使用带有%i的scanf捕获日期时的问题(mm dd yyyy)

时间:2013-05-10 01:17:04

标签: c date printf scanf

我正在编写一个计算两个日期之间经过天数的程序。为此,我必须在如下定义的结构中将日期作为整数输入:

struct date {
    int month;
    int day;
    int year;
};

现在,我已经想出了如何运行我的程序,但是当月或日是单个数字时,用户无法以(mm dd yyyy)格式输入日期,这真让我烦恼。让我告诉你我的代码(请不要介意调试printf语句):

printf("Enter your start date (mm dd yyyy)\n");
scanf("%i %i %i", &startDate.month, &startDate.day, &startDate.year);
// DEBUG printf("Start date = %i/%i/%i\n", startDate.month, startDate.day, startDate.year);
// DEBUG printf("start date month = %i", startDate.month);

printf("Enter your end date (mm dd yyyy)\n");
scanf("%i %i %i", &endDate.month, &endDate.day, &endDate.year);
// DEBUG printf("End date = %i/%i/%i\n", endDate.month, endDate.day, endDate.year);

如果用户输入:

08 08 2004

然后将开始日期记录为

0/8/0

这等于用户输入的前三位数字。好的,我明白了。我也明白用户可以输入“8 8 2004”并且程序运行良好......但我相信编程是关于细节的,而且这个是一个bugger。任何人都可以帮我解决这个问题吗?

1 个答案:

答案 0 :(得分:6)

使用%i转换说明符会导致scanf()解析输入,就像调用strtol()一样,0作为基本参数。因此,由于080开头,8不是xX,因此它将08视为八进制序列。但是,由于8不是有效的八进制数,它会在那里停止,第一个数字的结果为0

然后第二个数字得到8,因为它是由空格分隔的。跳过空格,第三个数字再次将08解析为八进制,导致第三个数字为08未被解析。

使用2004来解析十进制数字。

%d

如评论中所述,scanf() should generally be avoided。作为替代方案,您可以先使用scanf("%d %d %d", &startDate.month, &startDate.day, &startDate.year); 检索整行输入,然后使用fgets()进行解析。这允许更好的错误恢复,因为错误可以由导致错误的行诊断,并且也可以优雅地跳过该行。 sscanf()用于结构化输入,只能让您大致了解扫描错误发生的位置。并且,错误导致输入卡住,有时会导致调试会话混乱。