C中的Scanf / Printf ......这里发生了什么?

时间:2016-09-04 09:44:10

标签: c arrays variables printf scanf

我是自学C,目前正在学习Scanf和Printf功能。

我调整了这个程序来测试自己:

char topping[24];
int slices;
int  day, year;
float cost;
char month[10];

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

printf("What is your favorite one-word pizza topping?\n");
scanf(" %s",topping);
printf("How many slices of %s pizza, topping can you eat in one sitting\n",topping);
scanf(" %d", &slices);

printf(" What is today's date (enter in the following format 1-Jan-2016 )\n");
scanf(" %d-%s-%d", &day, month, &year);
printf("\nWhy not treat yourself to dinner on %d-%s-%d and have %d slices of %s pizza ? It will only cost you %.2f", day, month, year,slices, topping,cost);

练习的目的是让我掌握对scanf功能的理解以及如何理解"他们可以。

我的测试程序运行良好...除了年变量的输出。

为什么年份变量输出会乱七八糟,我该如何解决?

谢谢。

1 个答案:

答案 0 :(得分:5)

这就是问题所在。 %s说明符表示读取任何字符直到下一个空格。因此,在%d-匹配1-后,%s匹配Jan-2016。然后下一个%d失败,因为没有什么可以匹配。

首先,您应该始终检查scanf的返回值,以便了解是否存在匹配的失败。例如,在这种情况下:

if ( 3 != scanf(" %d-%s-%d", &day, month, &year) )
{
    printf("Matching failure occurred.\n");
    // do something else...
}
else
{
     printf("Why not treat yourself...

其次,要真正避免这个问题。您可以看到,scanf功能非常有限。要使用其他分隔符而不是空格,可以使用scanset说明符%[.....]代替:

scanf(" %d-%9[^-]-%d", &day, month, &year)

(使用相同的错误检查)。 scanset说明符表示读取与[]内的字符匹配的任何字符(可能包括空格),但^表示与下一个字符不匹配。因此,这将在下一个-之前读取所有内容。我还添加了9以避免溢出大小为9+1的缓冲区。

当然这意味着如果这个人从不输入另一个-,那么该程序就会变得有些奇怪。您可以通过使格式字符串越来越复杂来解决此问题;或者您可以使用fgets读取整行,然后将sscanf函数与上述字符串一起使用。这将记录此人在键入另一个-之前按Enter键的情况。

事实上,事实证明,一次读取整行通常是一个好主意,然后返回并处理该行。

在某个阶段,你会厌倦scanf有多糟糕,并制作自己的解析器。