我对C很新,我正在编写一些代码,允许用户以dd / mm / yyyy或dd-mm-yyyy的形式输入日期。我无法弄清楚如何让scanf忽略破折号或斜线,但不是两者。在输入斜杠后我需要代码识别负数。目前,该计划只是认为它是一个破折号并忽略它。
int dd1, mm1, yyyy1;
char str [3];
scanf("%d %[-/] %d %[-/] %d", &dd1, str, &mm1, str, &yyyy1);
任何帮助将不胜感激!
答案 0 :(得分:2)
你可以阅读输入并随后用sscanf()
解析它
示例程序:
#include <stdio>
int main(void)
{
char buf[256];
int dd1, mm1, yyyy1;
printf("input date: ");
// this is normally a function for file operations, but if you define stdin,
// the standard input, as file pointer it reads keyboard input
fgets(buf, 256, stdin);
if(sscanf(buf, "%d-%d-%d", &dd1, &mm1, &yyyy1) != 3)
{
if(sscanf(buf, "%d/%d/%d", &dd1, &mm1, &yyyy1) != 3)
{
printf("Wrong format!\n");
}
else
{
printf("format with /\n");
}
}
else
{
printf("Format with -\n");
}
}
好的,首先你用fgets()阅读你的输入。它将从标准输入(这是你的键盘)最大读取255个字节并且安全地进入我称为&#34; buf&#34;的数组中。然后我们使用sscanf()来&#34;分析&#34;输入。 sscanf()
返回成功分配的变量的数量,因为您希望从字符串中读取3个数字,每个返回值不同于3表示错误/错误输入。第一次sscanf()
使用 - 和第二次sscanf()
检查日期格式,并使用 /
答案 1 :(得分:1)
阅读(潜在的恶意)用户输入的经典方式包括3个步骤:
I / O:
char buffer[100];
if (fgets(buffer, sizeof buf, stdin) == NULL) Handle_EOForIOerror();
解析
int dd1, mm1, yyyy1;
// check the result of `sscanf()`
if (sscanf(buffer, "%2d/%2d/%4d", &dd1, &mm1, &yyyy1) != 3) ||
sscanf(buffer, "%2d-%2d-%4d", &dd1, &mm1, &yyyy1) != 3)) FormatError();
范围验证
if (dd1 < 1 || dd1 > 31 || mm1 < 1 || mm1 > 12 || ...) Handle_RangeError();
其他检查包括
1)寻找尾随垃圾
int n;
if (sscanf(buffer, "%2d/%2d/%4d %n", &dd1, &mm1, &yyyy1, &n) != 3) ||
sscanf(buffer, "%2d-%2d-%4d %n", &dd1, &mm1, &yyyy1, &n) != 3))FormatError();
if (buffer[n] != '\0') TrailingJunkDetected();
2)if (!valid_date(yyyy1, mm1, dd1)) ...
答案 2 :(得分:1)
对不起前一件事感到抱歉。
如果您不想使用中间存储空间,可以让您的程序说出“嘿!”首先,我想要一个数字,然后是一个字符,然后是另一个数字,然后是一个字符,最后是另一个数字。&#34;这正是你的日期字符串格式化的方式。
还有两个条件是,您希望两者之间的两个字符彼此相同,也可以是短划线或斜线。这就是你如何做到的:
int dd1, mm1, yyyy1;
char sep1, sep2;
if ( scanf( "%d%c%d%c%d", &dd1, &sep1, &mm1, &sep2, &yyyy1 ) == 5 && sep1 == sep2 && ( sep1 == '/' || sep1 == '-' ) )
printf( "Day: %d\nMonth: %d\nYear: %d", dd1, mm1, yyyy1 );
else {
// invalid syntax
}
正如我上面描述的那样,它要求一个整数,然后是字符,整数,字符和整数。如果它无法完成所有这些,那么它将不会返回5(scanf
返回它填充的变量数)。接下来要检查两个分隔符是否相同;最后,分隔符必须是破折号或斜线。
只需将其作为替代方案,总会有另一种方法。
答案 3 :(得分:0)
你可以试试这个:
scanf(" %3d%1[/-]%3d%1[/-]%5d", ...);
因为这些字段宽度仅指定最大宽度,而不指定最小宽度,所以它们不能用于区分输入与窄字段。因此,如果您想严格限制输入格式为dd/mm/yyyy
或dd-mm-yyyy
,则需要在scanf()
成功返回后进行更多语法检查。
这是一个测试程序:
#include <stdio.h>
int
main(void)
{
int yy, mm, dd;
char del1[2], del2[2];
const char *dates[] = {
/* well formed */
"28-03-2014",
"-28-03-2014",
"28--03-2014",
"28-03--2014",
"28/03/2014",
"-28/03/2014",
"28/-03/2014",
"28/03/-2014",
/* ill formed */
"28-3-2014",
"8-03-2014",
"28-03-14",
"28-03/2014",
"28/03-2014",
"28 03 2014",
NULL,
};
for (size_t i = 0; dates[i]; i++) {
int ret = sscanf(dates[i], " %3d%1[/-]%3d%1[/-]%5d", &dd, del1, &mm, del2, &yy);
if (ret != 5 || del1[0] != del2[0]) {
fprintf(stderr, "%s : syntax error\n", dates[i]);
continue;
}
printf("del = %c, yy = %d, mm = %d, dd = %d\n", del1[0], yy, mm, dd);
}
return 0;
}