我将以某种日期作为用户的输入,格式如下:mm / dd / yyyy。
如何确定用户仅输入数值,如果没有,则再次提示他输入有效日期。我已根据输入的值检查日期是否有效,但如果用户输入的值不是完全数字,则程序崩溃。
请帮忙......
守则:
int x=0;
printf("\nEnter the date of birth(mm/dd/yyyy):");
do
{
scanf("%d/%d/%d",&add.dob.month,&add.dob.day,&add.dob.year);
if((add.dob.month<13 && add.dob.month>0) && (add.dob.day>0 && add.dob.day<32) && (add.dob.year<2016))
{
x=1;
}
else
{
printf("\nThe above date of birth is invalid.\nEnter a valid date of birth(mm/dd/yyyy):");
}
}while(x!=1);
答案 0 :(得分:3)
有几个问题。如果使用scanf
检查其返回。除了数字有效性检查之外,还存在在用户输入除整数之外的事件时需要刷新输入缓冲区的问题。虽然有几种方法可以做到这一点,但保持您的方法的一种方法只是预先形成您正在进行的检查,然后使用第二个do/while
循环手动刷新输入缓冲区。您还可以转换逻辑并测试任何一个条件是否为真,强制另一个提示日期。如上所述,有很多方法可以解决这个问题。将此视为您收到的其他答案之一。
int c = 0; /* value to test for end of input buffer */
printf("\nEnter the date of birth(mm/dd/yyyy):");
while ((scanf("%d/%d/%d",&add.dob.month,&add.dob.day,&add.dob.year) != 3) ||
(add.dob.month < 1) ||
(add.dob.month > 12 ) ||
(add.dob.day < 1 ) ||
(add.dob.day > 31) ||
(add.dob.year < 1) ||
(add.dob.year > 2015))
{
printf("\nThe above date of birth is invalid.\nEnter a valid date of birth(mm/dd/yyyy):");
do { c = getchar(); } while (c != '\n' && c != EOF); /* flush input buffer */
}
如上所述,从stdin
读取信息的一种稍微强大的方法是使用fgets
或getline
将日期作为字符串读入缓冲区,然后解析来自缓冲区的月,日,年信息。这也可以通过多种方式完成。由于您最终将从字符转换为十进制,您也可以使用strtol
来解析和转换,而不是使用指针踩下字符串或使用strtok
或strsep
解析(因为每个都需要在分离后转换为十进制)。这是一个提供相当强大的解决方案的快速示例。除了mm-dd-yyyy
之外,它还允许将日期输入为mm.dd.yyy
或mm/dd/yyyy
:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <errno.h>
#define SZDATE 12
int main (void) {
int mm = 0; // month/day/year values
int dd = 0;
int yyyy = 0;
int gooddate = 0; // flag signifying valid date
char datestr[SZDATE] = {0}; // buffer to hold input string
char *p = NULL; // pointer to use with strtol
char *endptr = NULL; // end pointer for strtol
long val = 0; // long value for strtol
while (gooddate == 0)
{
printf("\nEnter the date of birth (mm/dd/yyyy): ");
/* read string with fgets */
fgets (datestr, SZDATE-1, stdin);
/* test sufficient length */
if (strlen (datestr) < 8) {
printf ("\n insufficient date length entered, try again.\n");
continue;
}
/* parse month value with strtol (with error checking) */
errno = 0;
val = strtol (datestr, &endptr, 10);
if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN))
|| (errno != 0 && val == 0)
|| (endptr == datestr)
|| (*endptr != '/' && *endptr != '-' && *endptr != '.')
|| (val < 1)
|| (val > 12)) {
printf ("\n invalid month entered, try again.\n");
continue;
}
mm = (int) val; /* set month on successful conversion */
p = ++endptr; /* set p to start of day, reset endptr */
endptr = NULL;
/* parse day value with strtol (with error checking) */
errno = 0;
val = strtol (p, &endptr, 10);
if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN))
|| (errno != 0 && val == 0)
|| (endptr == p)
|| (*endptr != '/' && *endptr != '-' && *endptr != '.')
|| (val < 1)
|| (val > 31)) {
printf ("\n invalid day entered, try again.\n");
continue;
}
dd = (int) val; /* set day on successful conversion */
p = ++endptr; /* set p to start of year, reset endptr */
endptr = NULL;
/* parse year value with strtol (with error checking) */
errno = 0;
val = strtol (p, &endptr, 10);
if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN))
|| (errno != 0 && val == 0)
|| (endptr == p)
|| (*endptr != '\n' && *endptr != 0)
|| (val < 1900)
|| (val > 2015)) {
printf ("\n invalid year entered, try again.\n");
continue;
}
yyyy = (int) val; /* set year on successful conversion */
gooddate = 1; /* set gooddate flag ending loop */
}
printf ("\n valid date is: %d/%d/%d\n\n", mm, dd, yyyy);
return 0;
}
仔细检查与strtol
次转化相关的检查。您可能想要添加更多内容。另外,尝试使用strtok
等进行解析并进行比较。这只是将读取视为字符串然后解析的一种方法。它可以通过许多不同的方式完成。
答案 1 :(得分:2)
您应该检查scanf
的返回值,看看它是否能够完成所有分配。如果没有,您需要在再次尝试之前使用用户的输入,否则您将尝试无限循环并且无法一遍又一遍地读取相同的输入。例如:
do {
printf("\nEnter the date of birth(mm/dd/yyyy): ");
fflush(stdout);
if (scanf("%d/%d/%d", &month, &day, &year) != 3) {
scanf("%*[^\n]"); // consume line from input, do not assign
} else if (month < 13 && month > 0 && day < 32 && day > 0 && year < 2016) {
break;
}
printf("Invalid date!\n");
} while (!feof(stdin));
另一方面,您缺少对日期有效性的检查,例如,用户仍然可以输入02/30 / -5。
编辑:参考下面评论中的讨论,这里对角落案件的处理很差;假设这是一个旨在始终在本地终端上交互运行的程序。为了正确处理输入,我强烈建议您从scanf
切换到fgets
(之后可能sscanf
)。然后应检查fgets
的返回值,并在那里处理错误,而不是可能有问题的feof
检查。当然,scanf
解决方案可以通过正确检查不同的返回值(例如EOF
)来变得更加迂腐,但我认为它不值得。
答案 2 :(得分:2)
您可以查看scanf()
的返回值,以测试三个输入的值是否为int
类型。
代码:
int returnval = scanf("%d/%d/%d",&input1, &input2, &input3);
if (returnval == 3)
{
//The input is correct.
}
else
{
printf("The input is not correct.");
//The input is not correct.
}
答案 3 :(得分:1)
要检查scanf的返回值,它将返回读取的输入数量 只需说输入1输入2和输入3是整数
int isValid = 0;
while (!isValid)
{
isValid = scanf("%d/%d/%d",&input1, &input2, &input3);
if(isValid != 3)
{
printf("\nThe above date of birth is invalid.\nEnter a valid date of birth(mm/dd/yyyy):");
}
else
{
// the user entered integers
if((add.dob.month<13 && add.dob.month>0) && (add.dob.day>0 && add.dob.day<32) && (add.dob.year<2016))
{
}
else
{
isValid = 0; // it didn't pass your date validation but it did pass integer validation
}
}
}
如果用户输入字符或字符串或任何非整数的内容,则scanf将返回0并且您可以使其循环。如果将if部分留空,我使用了非常糟糕的if / else,它会更好地否定每一个,但这是一个不同的故事。故事的道德只是检查scanf返回什么,如果它返回&gt; 1,用户输入数字,如果返回0,则他们尝试输入字母并且失败。
答案 4 :(得分:1)
您可以扫描输入,然后通过strtol()
之类的函数对其进行解析。
strtol()
会告诉您是否包含所有数字或混合数字。
这将为您节省一些麻烦,最后您需要做的就是检查数字边界。