确保scanf仅读取dd.mm.yyyy

确保scanf仅读取dd.mm.yyyy,c,C,我正在寻找解决我问题的办法。 我想扫描一个日期(dd.mm.yyyy)。我需要确保,输入的格式只有0name,what);strcpy(temp->deadline,when);strcpy(temp->place,where);temp->next=pointer;`但我不能用3个整数来做这件事。'我必须把日期放在那之后'是什么意思?你现在是否也可以使用fgets而不是scanf,特别是因为这样可以防止缓冲区溢出

我正在寻找解决我问题的办法。 我想扫描一个日期(dd.mm.yyyy)。我需要确保,输入的格式只有0<天<31;0<13个月;2018年

对于任务的长度,我是这样做的:

printf("Please typ in the Task: \t");
scanf("%s", &what);
while (strlen(what) >= MAX) {
    clearScanf();
    printf("The task must contain a maximum of %d :\t", MAX - 1);
    scanf("%s", &what);
}
但我不知道如何确保我的

printf("Pls put in the Deadline (dd.mm.yyyy): \t");
scanf("%s", when);
不会接受字符,但仍在字符之间使用“.”

在scanf之后,我想通过以下方式将我的结构的一切都归还给我:

strcpy(temp->name, what);
strcpy(temp->deadline, when);
temp->next = pointer;

但是我不知道,如何将月、年、日分开还给你。

使用
scanf
+
sscanf

int day, month, year;
for(;;)                                        /* Infinite loop */
{
    scanf("%s", when);
    char temp;
    if(sscanf(when, "%2d.%2d.%4d%c", &day, &month, &year, &temp) != 4 ||
       temp != '\n')                           /* Check if no extra characters were typed after the date */
    {
        fputs("Invalid format!\n", stderr);
        clearScanf();                          /* Assuming this function of yours clears the stdin */
    }
    else if(!(0 < date && date <= 31) ||       /* Valid range checks */
            !(0 < month && month <= 12) ||
            !(0 < year && year <= 2018))
    {
        fputs("Invalid date!\n", stderr);
    }
    else
    {
        break;
    }
}
int日、月、年;
对于(;)/*无限循环*/
{
scanf(“%s”,何时);
焦炭温度;
如果(sscanf(当“%2d.%2d.%4d%c”、&日、月、年和温度)!=4||
temp!='\n')/*检查日期后是否键入了额外字符*/
{
fputs(“无效格式!\n”,标准格式);
clearcanf();/*假设您的此函数清除stdin*/
}

如果(!(0scanf
+
sscanf

int day, month, year;
for(;;)                                        /* Infinite loop */
{
    scanf("%s", when);
    char temp;
    if(sscanf(when, "%2d.%2d.%4d%c", &day, &month, &year, &temp) != 4 ||
       temp != '\n')                           /* Check if no extra characters were typed after the date */
    {
        fputs("Invalid format!\n", stderr);
        clearScanf();                          /* Assuming this function of yours clears the stdin */
    }
    else if(!(0 < date && date <= 31) ||       /* Valid range checks */
            !(0 < month && month <= 12) ||
            !(0 < year && year <= 2018))
    {
        fputs("Invalid date!\n", stderr);
    }
    else
    {
        break;
    }
}
int日、月、年;
对于(;)/*无限循环*/
{
scanf(“%s”,何时);
焦炭温度;
如果(sscanf(当“%2d.%2d.%4d%c”、&日、月、年和温度)!=4||
temp!='\n')/*检查日期后是否键入了额外字符*/
{
fputs(“无效格式!\n”,标准格式);
clearcanf();/*假设您的此函数清除stdin*/
}

否则如果(!(0
bool is_correctly_formatted(const char* s) {

    if(!isdigit(s[0])) return false;
    if(!isdigit(s[1])) return false;
    if('.' != s[2]) return false;
    if(!isdigit(s[3])) return false;
    if(!isdigit(s[4])) return false;
    if('.' != s[5]) return false;
    if(!isdigit(s[6])) return false;
    if(!isdigit(s[7])) return false;
    if(0 != s[8]) return false;

    return true;

}
然后,您可以像这样使用它:

#define MAX 8

int main(int argc, char** argv) {

    /* Space for MAX chars + line feed + terminal zero */
    char what[MAX + 1 + 1] = {0};

    /* Ensure that scanf reads in at most as many chars as can be safely written to `what` */
    char format[MAX + 2 + 1] = {0};
    snprintf(format, sizeof(format), "%%%ds", MAX + 1);

    do {
        printf("%s Please type in the Task: ", format);
        scanf(format, &what[0]);
        /* chomp the trailing '\n' */
        if(isspace(what[MAX + 1])) what[MAX + 1] = 0;
        printf("Entered %s\n", what);
    } while (! is_correctly_formatted(what));
}
这使你能够在你期望的事情上尽可能地灵活。你甚至可以求助于使用某种方法


注意:读取字符串将包含尾随换行符,因此您必须删除它…

编写您自己的格式检查函数:

bool is_correctly_formatted(const char* s) {

    if(!isdigit(s[0])) return false;
    if(!isdigit(s[1])) return false;
    if('.' != s[2]) return false;
    if(!isdigit(s[3])) return false;
    if(!isdigit(s[4])) return false;
    if('.' != s[5]) return false;
    if(!isdigit(s[6])) return false;
    if(!isdigit(s[7])) return false;
    if(0 != s[8]) return false;

    return true;

}
然后,您可以像这样使用它:

#define MAX 8

int main(int argc, char** argv) {

    /* Space for MAX chars + line feed + terminal zero */
    char what[MAX + 1 + 1] = {0};

    /* Ensure that scanf reads in at most as many chars as can be safely written to `what` */
    char format[MAX + 2 + 1] = {0};
    snprintf(format, sizeof(format), "%%%ds", MAX + 1);

    do {
        printf("%s Please type in the Task: ", format);
        scanf(format, &what[0]);
        /* chomp the trailing '\n' */
        if(isspace(what[MAX + 1])) what[MAX + 1] = 0;
        printf("Entered %s\n", what);
    } while (! is_correctly_formatted(what));
}
这使你能够在你期望的事情上尽可能地灵活。你甚至可以求助于使用某种方法


注意:读取的字符串将包含尾随换行符,因此您必须将其删除…

仅使用
scanf
无法做到这一点。您需要手动解析字符串,在无法解析输入时返回错误。仅使用
scanf
无法做到这一点。您需要手动解析字符串,在可以时返回错误“我无法分析输入。警告:
scanf
家族对它所接受的内容非常松散。如果我没记错的话,它也会接受像
3.4.-53
(我还没有测试过)这样的日期。”虽然这是我最初的想法,但如果用户输入,这将失败,例如,
19.08.2522
?好的,我需要将日期放在后面。现在,我这样做:'strcpy(temp->name,what);strcpy(temp->deadline,when);strcpy(temp->place,where);temp->next=pointer;`但是我不能用3个整数来做这件事。'我必须把日期放在那之后'是什么意思?你现在也可以使用
fgets
而不是
scanf
,特别是因为这样可以防止缓冲区溢出警告:
scanf
家族对它所接受的内容非常松散。如果我记得corre实际上,这也会接受像
3.4.-53这样的日期(虽然我还没有测试),虽然这是我最初的想法,但如果用户输入,这将失败,例如,
19.08.2522
?好的,我需要把日期放在后面。现在,我这样做:'strcpy(temp->name,what);strcpy(temp->deadline,when);strcpy(temp->place,where);temp->next=pointer;`但我不能用3个整数来做这件事。'我必须把日期放在那之后'是什么意思?你现在是否也可以使用
fgets
而不是
scanf
,特别是因为这样可以防止缓冲区溢出