Scanf()不等待整数输入

时间:2018-08-24 12:31:44

标签: c scanf

我第二次在该程序中调用scanf,该函数不等待用户输入。我知道在使用char时,您必须在格式说明符(我已经尝试过)之前留一个空格,但无法弄清楚此int发生了什么。谢谢!

// Program to calculate the number of elasped days between two dates.

#include <stdio.h>

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

int valueofN (struct date d);
int f(int year, int month);
int g(int month);

int main (void)
{
    struct date date1, date2;

    printf("Enter the first date - dd:mm:yyyy : ");
    scanf("%i:%i:%i", &date1.day, &date1.month, &date1.year);

    printf("Enter the second date - dd:mm:yyyy : ");
    scanf("%i:%i:%i", &date2.day, &date2.month, &date2.year);

    // The line above here is where the problem lies ^^^^

    long int N1 = valueofN (date1);
    long int N2 = valueofN (date2);

    printf("Number of elasped days = %li\n", (N2 - N1));

    return 0;
}

// Functions

int valueofN (struct date d)
{
    int N;
    return N = (1461 * (f(d.year, d.month) / 4) + 153 * (g(d.month) / 5) +d.day);
}

int f(int year, int month)
{
    if (month <= 2)
        return (year - 1);
    else
        return year;
}

int g(int month)
{
    if (month <= 2)
        return (month + 13);
    else
        return (month + 1);
}

1 个答案:

答案 0 :(得分:1)

这归因于格式说明符%i

%d一起使用时,您可能不会观察到行为%iprintf()的任何差异,但是与scanf一起使用时,其意义显而易见,即{{1 }}根据一个前缀将一个整数值作为具有十进制,十六进制或八进制类型的整数值,这样 如果以%i开头,则为十六进制;如果以0x开头,则为八进制值。当您在0中使用%d时,它假定基数为10。

因此,您需要将scanf替换为%i

此外,请养成标准库阅读计划使用的功能手册页的习惯。 例如,scanf“转化” 部分指出,

  

i

     

匹配一个可选的带符号整数;下一个指针必须是指向int的指针。如果整数以0x或0X开头,则以16为基数;如果以0开头,则以8为基数;否则,以10为基数。仅使用与基数相对应的字符。

还在“返回值” 部分中指出,

  

返回值   这些函数返回成功匹配和分配的输入项目的数量,该数量可能少于所提供的数量,在早期匹配失败的情况下甚至为零。

     

如果在第一次成功转换或匹配失败发生之前达到输入结束,则返回EOF值。如果发生读取错误,也会返回EOF,在这种情况下,将设置流的错误指示符(请参见ferror(3)),并设置errno来指示错误。

%d获取返回值,并为意外返回添加一些错误处理,这将为您免除许多痛苦。

其他输入:

  1. 通常优选/建议使用动词(或动作)而不是没有意义的名称来命名您的函数。

例如,

scanf

如果我正在查看您的代码,则不知道此功能的作用。继续,以有意义的方式命名函数和其他变量。

  1. 使用兼容的数据类型

例如

int valueofN (struct date d);
int f(int year, int month);
int g(int month);

long int N1 = valueofN (date1); long int N2 = valueofN (date2); N1的数据类型为N2,而long int返回的是valueofN()。它是一种不同的数据类型,此代码不会立即造成危害,但这种做法可能会造成潜在的危害。

  1. 一些改进

int

应该是

int valueofN (struct date d)
{
    int N;
    return N = (1461 * (f(d.year, d.month) / 4) + 153 * (g(d.month) / 5)+ d.day);
}
  1. 更多改进:您应该始终验证用户输入的数据(除非您不知道上下限值)。例如,用户可以为int valueofN (struct date d) { return (int)(1461 * (f(d.year, d.month) / 4) + 153 * (g(d.month) / 5) +d.day); } 输入50。未验证。在输入阶段本身进行处理。养成习惯。