C scanf 未按预期工作(救命!)

标签 c string-formatting

正在开发一个程序,提示用户输入电话号码,然后使用 打印出来。而不是 - 因此,当我运行它时,它甚至不允许我输入任何内容,它只是运行并给我随机值。下面是完整的程序。

int item_number, year, month, day, first, middle, last;
//float unit_price;

printf("Enter item number: ");
scanf("%d", &item_number);

printf("Enter unit price: ");
scanf("%f", &unit_price);

printf("Enter purchase date (mm/dd/yyyy): ");
scanf("%d /%d /%d", &month, &day, &year);

printf("Item\t\tUnit\t\tPurchase\n\t\tPrice\t\tDate");
printf("\n%d\t\t$%6.2f\t\t%.2d/%.2d/%.2d\n", item_number, unit_price, month, day, year);

//here is the code that gives me the problem explained above.
//also if i comment the code above it works.
printf("Enter phone number [(xxx) xxx-xxxx] : ");
scanf("(%d) %d - %d", &first, &middle, &last);

printf("You entered %d.%d.%d", first, middle, last);

最佳答案

您遇到的问题,可能是新C程序员遇到的最常见问题之一——scanf使用不当。具体来说,当您尝试读取电话号码时,stdin 包含,例如:

    "\n(888) 555-1212"

('\n'是输入(mm/dd/yyyy)后按Enter的结果)

因此,在 stdin 中等待的输入匹配 "(%d...",并且 匹配失败结果。为什么?stdin中的字符开头有一个换行符"%d" < em>格式说明符(所有数字转换说明符)将跳过前导空格。

但是,前导空格并不在整数之前,而是在 "(" 之前,格式字符串不会跳过它。使用 scanf 时,格式字符串中的""(空格)将导致任意数量的空白字符被跳过/丢弃。正如 BLUEPIXY 正确指出的那样,您需要在格式字符串中的"("之前添加空格以具有scanf 忽略在 stdin 中等待的 '\n'

除此之外,您还会犯几乎所有新 C 程序员都会犯的同样的错误和误用 scanf -- 未能检查 返回scanf 返回基于格式字符串中的转换说明符发生的成功转换的数量。

至少,您必须检查 scanf 的返回(实际上是所有用户输入函数),以提供最低限度的验证,确保您确实在变量中存储了有效输入以继续进行在你的代码中。如果您未能检查返回结果,则您无法确信从那时起未定义的行为不会被调用。因此验证所有用户输入

将这些部分组合在一起的代码的最小重写将是:

#include "stdio.h"

int main (void) {

    int item_number, year, month, day, first, middle, last;
    float unit_price;

    printf("Enter item number: ");
    if (scanf ("%d", &item_number) != 1) {  /* validate item */
        fprintf (stderr, "error: invalid input (item_number)\n");
        return 1;
    }

    printf("Enter unit price: ");
    if (scanf ("%f", &unit_price) != 1) {   /* validate unit */
        fprintf (stderr, "error: invalid input (unit_price)\n");
        return 1;
    }

    printf("Enter purchase date (mm/dd/yyyy): ");
    /* validate date */
    if (scanf ("%d /%d /%d", &month, &day, &year) != 3) {
        fprintf (stderr, "error: invalid input (mm/dd/yyyy)\n");
        return 1;
    }

    printf ("\t\tUnit\t\tPurchase\nItem\t\tPrice\t\tDate");
    printf ("\n%d\t\t$%6.2f\t\t%.2d/%.2d/%.2d\n", 
            item_number, unit_price, month, day, year);

    printf ("Enter phone number [(xxx) xxx-xxxx] : ");
    /* validate phone */
    if (scanf (" (%d) %d - %d", &first, &middle, &last) != 3) {
        fprintf (stderr, "error: invalid input [(xxx) xxx-xxxx]\n");
        return 1;
    }

    printf ("You entered %d.%d.%d\n", first, middle, last);

    return 0;
}

示例使用/输出

$ ./bin/scanf_phone
Enter item number: 3
Enter unit price: 19.95
Enter purchase date (mm/dd/yyyy): 03/01/2017
                Unit            Purchase
Item            Price           Date
3               $ 19.95         03/01/2017
Enter phone number [(xxx) xxx-xxxx] : (800) 555-1212
You entered 800.555.1212

(注意我调整了格式,将Item放在第二行...)

仔细检查,并花时间去理解 man 3 scanf 。时间花得值。

关于C scanf 未按预期工作(救命!),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46535729/

相关文章:

c - 多次运行之间同一程序的不同缓存未命中计数

python - 'io.h' : No such file or directory during "pip install netifaces"

c - 存储类别之间有什么区别

string - Matlab字符到字符串的转换问题。使用什么功能?

c++ - 将 boost.log 与 printf 样式的宏一起使用

c - 为什么if条件不满足?

c - 如何优化我的 C 代码?

python - 如何将 float 格式化为整数?

python - 是否有与 fortran 可重复格式描述符等效的 python 版本?

date - 如何将毫秒转换为人类可读的形式?