【问题标题】:Issue with learning C scanf function when program is run (no errors during compile) C programming absolute beginners guide Chapter 8程序运行时学习C scanf函数的问题(编译期间没有错误)C编程绝对初学者指南第8章
【发布时间】:2025-11-25 01:15:01
【问题描述】:

我从书中逐字输入了以下代码:

// Ex program #2 from Ch 8 of ABGTC
// File Ch8Ex2.c

// This is a sample program that asks users for some basic data and prints it on screen in order to show what was entered

#include <stdio.h>

main()
{
    float cost;
    char topping[24];
    int slices;
    int month, day, year;

    // The first scanf will look for a floating-point variable, the cost of a pizza
    // If the user doesn't enter a $ before the cost, it could cause problems

    printf("How much does a pizza cost in your area? Enter as $XX.XX\n");
    scanf(" $%f", &cost);

    // The pizza topping is a string, so your scanf doesn't need an &

    printf("What is your favorite one-word pizza topping?\n");
    scanf(" %s", topping);

    printf("How many slices of %s pizza can you eat in one sitting?", topping);
    scanf(" %d", &slices);

    printf("What is today\'s date (enter it in XX/XX/XX format).\n");
    scanf(" %d/%d/%d", &month, &day, &year);

    printf("\n\nWhy not treat yourself to a dinner on %d/%d/%d", month, day, year);
    printf("\nand have %d slices of %s pizza!\n", slices, topping);
    printf("It will only cost you $%.2f!\n\n\n", cost);

    return 0;
}

编译时出现零错误(使用代码:块,如书中推荐和使用的那样);然而,一旦我运行程序,在输入请求的用户数据的第一位(一片披萨的价格,假设我说它是 03.45)后,程序就会打印出来:

"What is your favorite one-word pizza topping?"
"How many slices of 03.45 pizza can you eat in one sitting?"

感觉就像是跳过了 printf "What is your favorite...." 后面的 scanf 行,不仅提示了 "How many slices...." 后面的 printf 行,而是插入了 03.45 作为应该由用户在上一行输入的字符数组/字符串值。

我尝试了一些不同的调整,但我终其一生都无法弄清楚我做错了什么。有任何想法吗?

【问题讨论】:

  • 您显示的源代码真的是正在运行的代码吗?如果您看到输出,它与代码应该执行的操作不对应(将价格打印为字符串?)。程序的 full 输出是什么?程序的实际输入是什么?
  • 我展示的源代码实际上是正在运行的代码。我可以说它不对应。以下是我运行程序时发生的情况:“你所在地区的比萨饼要多少钱?”这是第一个问题,我输入 03.45 并回车。然后我在屏幕上看到以下内容:“你最喜欢的单字披萨配料是什么?” “你一次可以吃多少片03.45披萨?”是不是更详细一点?
  • 您缺少前导“$”。您必须输入如下内容:$03.45,正如问题所问(输入为 $XX.XX)
  • ^ 这就是整个问题.....哦,天哪,哈哈哈,谢谢 Amadeus!
  • @GuyWantingBoat:你能接受其中一个答案吗?

标签: c printf scanf


【解决方案1】:

问题是我在输入回复时没有使用 $。在回答第一个问题“您所在地区的比萨饼要多少钱?输入 $XX.XX”时,我的回答是 03.45,而我应该回答 $03.45,因为 scanf 是 $%f。从 "$%f" 中删除 $ 并使其余部分保持不变仍然会产生最终打印函数中所需的结果。

希望这可以帮助其他人使用这本书!

【讨论】:

    【解决方案2】:

    您没有检查scanf() 的返回值。 scanf() 返回正确解析和存储的输入数。

    在失败的情况下,例如不匹配格式字符串" $%f" 的缺失$,有问题的输入将保留在标准输入中,并将在下次调用scanf() 或任何其他输入函数时读取。

    您可以通过使用fgets() 读取输入并使用sscanf() 解析它来更正程序,直到执行正确的转换或到达文件末尾。

    请注意,您应该保护格式%s以防止缓冲区溢出:将要读取的最大字符数传递为scanf(" %23s", topping);

    这是一个例子:

    #include <stdio.h>
    
    int main(void) {
        char line[80];
        float cost;
        char topping[24];
        int slices;
        int month, day, year;
    
        for (;;) {
            printf("How much does a pizza cost in your area? Enter as $XX.XX\n");
            if (!fgets(line, sizeof line, stdin))
                return 1;
            if (sscanf(line, "$%f", &cost) == 1)
                break;
            printf("invalid input\n");
        }
    
        for (;;) {
            printf("What is your favorite one-word pizza topping?\n");
            if (!fgets(line, sizeof line, stdin))
                return 1;
            if (sscanf(line, "%23s", topping) == 1)
                break;
            printf("invalid input\n");
        }
    
        for (;;) {
            printf("How many slices of %s pizza can you eat in one sitting?\n", topping);
            if (!fgets(line, sizeof line, stdin))
                return 1;
            if (sscanf(line, "%d", &slices) == 1)
                break;
            printf("invalid input\n");
        }
    
        for (;;) {
            printf("What is today\'s date (enter it in XX/XX/XX format).\n");
            if (!fgets(line, sizeof line, stdin))
                return 1;
            if (sscanf(line, "%d/%d/%d", &month, &day, &year) == 3)
                break;
            printf("invalid input\n");
        }
    
        printf("\n\nWhy not treat yourself to a dinner on %d/%d/%d\n",
               month, day, year);
        printf("and have %d slices of %s pizza!\n", slices, topping);
        printf("It will only cost you $%.2f!\n\n\n", cost);
    
        return 0;
    }
    

    【讨论】:

      【解决方案3】:

      将浮点变量作为输入后,您缺少flush 标准输入。

      只需使用下面给出的以下代码即可解决您的问题。

      #include <stdio.h>
      
      main()
      {
          float cost;
          char topping[24];
          int slices;
          int month, day, year;
      
          printf("How much does a pizza cost in your area? Enter as $XX.XX\n");
          scanf(" $%f", &cost);
      
          fflush(stdin);    //Just add this line here and your problem is solved.
      
          printf("What is your favorite one-word pizza topping?\n");
          scanf(" %s", topping);
      
          printf("How many slices of %s pizza can you eat in one sitting?\n", topping);
          scanf(" %d", &slices);
      
          printf("What is today\'s date (enter it in XX/XX/XX format).\n");
          scanf("%d/%d/%d", &month, &day, &year);
      
          printf("\n\nWhy not treat yourself to a dinner on %d/%d/%d", month, day, year);
          printf("\nand have %d slices of %s pizza!\n", slices, topping);
          printf("It will only cost you $%.2f!\n\n\n", cost);
      
          return 0;
      }
      

      【讨论】:

      • 是的,它可以工作,但是用fflush() 刷新输入流在 Posix 和 C 中仍然是未定义的行为。但是您可以刷新输出流。我不知道为什么所有的书都用scanf()作为例子,scanf()即使你知道自己在做什么,也是一个真正的痛苦。
      • 好的,这解决了我之前遇到的问题,但是现在当程序打印披萨的成本(最终的 printf 函数)时,它说它将花费 0.00 美元,它应该说什么用户输入是(例如 03.45)。另外,由于我正在学习 C。 fflush(stdin) 是什么意思?它有什么作用?
      • @GuyWantingBoat 该程序对我来说运行良好。如果用户输入是 03.45,它正在打印 $03.45
      • @VastalSura Amadeus 在对上述问题的评论中解决了这个问题。这更多是用户错误的问题,但从“$%f”中删除 $ 基本上可以完全避免错误。
      • @GuyWantingBoat 关于fflush(stdin); 至于 fflush(stdin),人们之所以称之为 fflush(stdin),是因为某些函数,尤其是 scanf,有时会使输入处于反直觉状态。例如,假设您调用 scanf("%d", &n) 然后调用 fgets(buf, 100, stdin),期望输入形式为: 10 line 那么事实证明,您将得到一个空行fgets 是因为 scanf 在读取 10 后没有将您移过 '\n'。由于这种问题,人们使用 fflush(stdin)。继续...