2016-10-08 14 views
5

Я тестировал эту структуру, и я получаю предупреждение об использовании gets. Кто-то упомянул вместо этого использовать fgets и заменить конец на '\0'. Любая рекомендация, как я могу изменить свой код, чтобы сделать это?Замена gets() с помощью fgets()

void regCars(Car reg[], int *pNrOfCars) { 
    char again[WORDLENGTH] = "yes", model[WORDLENGTH], tmp[WORDLENGTH]; 
    int year, milage; 

    while (strcmp(again, "yes") == 0) { 
     printf("Enter model:"); 
     gets(model); 
     printf("Enter Year:"); 
     gets(tmp); 
     year = atoi(tmp); 
     printf("Enter milage:"); 
     gets(tmp); 
     milage = atoi(tmp); 
     reg[*pNrOfCars] = createCar(model, year, milage); 
     (*pNrOfCars)++; 
     printf("Continue? (yes/no)"); 
     gets(again); 
    } 
} 

ответ

0

Вы можете написать служебную функцию mygets(), которая принимает 2 аргумента: указатель на массив назначения и его размер:

char *mygets(char *dest, size_t size) { 
    /* read a line from standard input and strip the linefeed if any */ 
    if (fgets(dest, size, stdin)) { 
     dest[strcspn(dest, "\n")] = '\0'); 
     return dest; 
    } 
    return NULL; 
} 

void regCars(Car reg[], int *pNrOfCars) { 
    char model[WORDLENGTH], tmp[WORDLENGTH]; 
    int year, milage; 

    for (;;) { 
     printf("Enter model:"); 
     if (!mygets(model, sizeof mode)) 
      break; 
     printf("Enter year:"); 
     if (!mygets(tmp, sizeof tmp)) 
      break; 
     year = atoi(tmp); 
     printf("Enter milage:"); 
     if (!mygets(tmp, sizeof tmp)) 
      break; 
     milage = atoi(tmp); 
     reg[*pNrOfCars] = createCar(model, year, milage); 
     (*pNrOfCars)++; 
     printf("Continue? (yes/no)"); 
     if (!mygets(tmp, sizeof(tmp)) 
      break; 
     if (strcmp(again, "yes") != 0) 
      break; 
    } 
} 

Обратите внимание, что вы можете факторизуются больше кода с prompt() функции, которая выводит вопрос и читает ответ:

char *prompt(const char *message, char *dest, size_t size) { 
    printf("%s ", message); 
    fflush(stdout); 
    /* read a line from standard input and strip the linefeed if any */ 
    if (fgets(dest, size, stdin)) { 
     dest[strcspn(dest, "\n")] = '\0'); 
     return dest; 
    } 
    return NULL; 
} 

void regCars(Car reg[], int *pNrOfCars) { 
    char model[WORDLENGTH], tmp[WORDLENGTH]; 
    int year, milage; 

    for (;;) { 
     if (!prompt("Enter model:", model, sizeof mode)) 
      break; 
     if (!prompt("Enter year:", tmp, sizeof tmp)) 
      break; 
     year = atoi(tmp); 
     if (!prompt("Enter milage:", tmp, sizeof tmp)) 
      break; 
     milage = atoi(tmp); 
     reg[*pNrOfCars] = createCar(model, year, milage); 
     (*pNrOfCars)++; 
     if (!prompt("Continue? (yes/no)", tmp, sizeof(tmp)) 
      break; 
     if (strcmp(again, "yes") != 0) 
      break; 
    } 
} 

также отметить, что эта функция должна принимать размер reg массив, чтобы прекратить запрашивать больше ввода, когда он заполнен. Как указано в настоящее время, он имеет тот же самый недостаток, что и gets(), неожиданный ввод приведет к неопределенному поведению.

+0

@Alex: вы не возражаете против голосования, который вы приняли? – chqrlie

0

Вобще, например

if (NULL != fgets(model, WORDLENGTH, stdin)) /* Read the string. */ 
{ 
    model[strcspn(model, "\r\n")] = '\0'; /* Cut off \n and/or \r, if any. */ 
} 
+0

Я думаю, что это будет делать это только для модели, если у меня есть умножение int и char, есть ли функция, которая может просматривать все из них и заменять \ n? – xxFlashxx

+0

@Alex: 'fgets()' (а также 'get() ') читает только« строки ». Для чтения «года» вы используете 'gets (tmp)', который можно заменить, как показано. – alk

+0

поэтому я вставляю оператор if сразу после fgets (model)? – xxFlashxx

1

Это немного Tricker, чем это выглядит. Не так много смысла, как только замена получает с помощью fgets(), если вы затем обрабатываете усеченную строку на слишком длинном вводе и обрабатываете ее как действительную. Вы просто заменили неопределенное поведение неправильным поведением.

if(fgets(line, sizeof(line), fp)) 
{ 
    if(!strchr(line, '\n')) 
    { 
     /* line is too long, what you do is up to you, but normally 
     we will discard it */ 
     int ch; 

     while((ch = fgetc(fp)) != EOF) 
     if(ch == '\n') 
      break; 

    } 
    else 
    { 
     /* line is a normal line with a trailing '\n' (gets trims the '\n')   */ 
    } 
} 
+0

Не нужно просто отбрасывать длинные строки ... и длинные строки встречаются довольно часто в текстовых файлах, написанных компьютерными программами. 'fgets()' может читать их ... для этого требуется больше вызовов и логики. – Peter

+0

Если допустимые строки не ограничены, функция fgets() не является вашей функцией ввода. Но, конечно, то, что означает длинная линия, определяется ситуацией, а иногда отбрасывать ее неправильно. Тем не менее, тихое усечение и оставление остатка неотличимы от полной линии. –