2014-10-24 3 views
0

Я пытаюсь получить дату с консоли, а затем получаю месяц, день и год для работы с ними отдельно.C - Ошибка сегментации с 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, " ")); 
} 

У меня нет ошибки, выполняющей его только один раз. Я получаю ошибку ошибки сегментации, когда я пытаюсь получить две даты одновременно.

Date d1, d2; 
getDate(&d1); 
getDate(&d2); 

и линия, которая дает мне ошибку в d->day = atoi(strtok(NULL, "/")); во втором исполнении.

+13

Segfault - это не утечка памяти! –

+0

Как выглядит ваш вход? –

ответ

3

Проблема заключается в использовании вами fgets(). Он не возвращает то, что, по вашему мнению, он делает во второй раз.

Первый раз, fgets() заполняет line[]"10/23/2014\0" и все в порядке.

Тем не менее, второй раз до конца, ENTER ключ еще во входном буфере stdin «s, потому что первый fgets() не было комнаты в line[], чтобы прочитать его, так что второй fgets() заполняет line[] с "\n\0", не дожидаясь новый пользовательский ввод. Таким образом, первый вызов strtok(line, "/") возвращает "\n" (который atoi() преобразует в 0), затем следующий вызов strtok(NULL, "/") завершается с ошибкой и возвращает NULL, что вызывает atoi() для segfault.

Увеличьте размер вашего массива так, чтобы ENTER будет считываться по каждому звонку до fgets(). Я также предлагаю вам использовать 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); 
    } 
} 
1

Вы покидаете новую строку в буфере ввода. Это происходит потому, что ваш массив принимает только max символов и оставляет символ новой строки в буфере.

Вы можете увеличить размер массива или очистить буфер после его чтения.

Вы также должны проверить возвращаемое значение для каждого вызова strtok(), чтобы определить, был ли вызов успешным.

Смежные вопросы