繁体   English   中英

C-使用strtok()的分段错误

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM