[英]C - Segmentation fault with strtok()
我试图从控制台获取日期,然后分别获取月,日和年。
const size_t max = 11;
void getDate(Date * d){
char line[max];
printf("\t Insert the date in the american format (mm/dd/yyyy): ");
fgets(line, max, stdin);
d->month = atoi(strtok(line, "/"));
d->day = atoi(strtok(NULL, "/"));
d->year = atoi(strtok(NULL, " "));
}
我只执行一次就不会出错。 当我尝试一次获取2个日期时出现细分错误错误。
Date d1, d2;
getDate(&d1);
getDate(&d2);
而给我错误的那一行是d->day = atoi(strtok(NULL, "/"));
在第二次执行期间。
问题是您对fgets()
。 它没有返回您第二次认为的结果。
第一次, fgets()
用"10/23/2014\\0"
填充line[]
,一切都很好。
然而,在第二时间通过,ENTER键仍处于stdin
的输入缓冲器,因为第一fgets()
没有在任何房间line[]
读它,因此第二个fgets()
填充line[]
用"\\n\\0"
而无需等待新的用户输入。 因此,对strtok(line, "/")
的第一次调用返回"\\n"
( atoi()
转换为0),然后对strtok(NULL, "/")
的下一次调用失败并返回NULL,这导致atoi()
。
增加数组的大小,以便每次调用fgets()
都会读取ENTER 。 我还建议您使用sscanf()
代替atoi(strtok())
:
const size_t max = 16;
void getDate(Date * d)
{
char line[max];
printf("\t Insert the date in the american format (mm/dd/yyyy): ");
fgets(line, max, stdin);
if (sscanf(line, "%d/%d/%d", &(d->month), &(d->day), &(d->year)) != 3)
d->month = d->day = d->year = 0;
}
或者,添加一些额外的验证以确保正确读取日期:
const size_t max = 16;
void getDate(Date * d)
{
char line[max];
int consumed;
printf("\t Insert the date in the american format (mm/dd/yyyy): ");
fgets(line, max, stdin);
while (1)
{
if (sscanf(line, "%d/%d/%d%n", &(d->month), &(d->day), &(d->year), &consumed) == 3)
{
if (consumed == strlen(line))
break;
}
printf("\t Invalid input. Insert the date in the american format (mm/dd/yyyy): ");
fgets(line, max, stdin);
}
}
您将在输入缓冲区中保留新行。 发生这种情况是因为您的数组仅接受max
字符,并将换行符留在缓冲区中。
读取数组后,可以增加数组的大小或清除缓冲区。
您还应该检查每个strtok()调用的返回值,以检测调用是否成功。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.