我对C还很陌生,我正在编写一些代码,允许用户以dd/mm/yyyy或dd-mm-yyyy的形式输入日期。我不知道如何让scanf忽略破折号或斜线,但不能同时忽略两者。输入斜线后,我需要代码来识别负数。目前,程序只是认为这是一个破折号,并忽略了它
int dd1, mm1, yyyy1;
char str [3];
scanf("%d %[-/] %d %[-/] %d", &dd1, str, &mm1, str, &yyyy1);
任何帮助都将不胜感激!
您只需读取输入,然后使用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个字节,并将其安全地放入我称为"buf"的数组中。然后我们使用sscan((来"分析"输入。sscanf()
返回成功分配的变量数,因为您希望从字符串中读取3个数字,每个与3不同的返回值都表示错误/错误输入。第一个sscanf()
用-检查日期格式,第二个sscanf()
用/检查日期格式
对之前的事情感到抱歉。
如果你不想使用中间存储器,你可以让你的程序说"嘿!首先,我想要一个数字,然后是一个字符,然后是另一个数字、一个字符、最后是一个数字。"这正是你的日期字符串的格式。
还有两个条件,即,您希望中间的两个字符彼此相同,并且可以是短划线或斜杠。这就是你可以做到的:
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: %dnMonth: %dnYear: %d", dd1, mm1, yyyy1 );
else {
// invalid syntax
}
正如我上面描述的那样,它要求一个整数,然后是一个字符、整数、字符和整数。如果它不能得到所有这些,那么它就不会返回5(scanf
返回它填充的变量数(。接下来要检查两个分隔符是否相同;最后,分隔符必须是短划线或斜线。
只要把它作为一种替代,总会有另一种方法。
读取(潜在敌对(用户输入的经典方法包括3个步骤:
- I/O
- 正在分析
- 范围验证
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] != ' ') TrailingJunkDetected();
2( if (!valid_date(yyyy1, mm1, dd1)) ...
你可以试试这个:
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 errorn", dates[i]);
continue;
}
printf("del = %c, yy = %d, mm = %d, dd = %dn", del1[0], yy, mm, dd);
}
return 0;
}