Моя (очень простая) программа демонстрирует странное поведение, когда мой ввод fgets превышает указанный размер буфера - PullRequest
0 голосов
/ 16 января 2019

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

Я фиксирую идентификатор с помощью fgets, однако, когда я ввожу строку символов длиннее указанного размера буфера (здесь 10), моя программа, похоже, "вылетает". Он печатает следующие два printf в той же строке, пропуская ввод для первого, что, очевидно, нарушает программу.

Когда идентификатор, захваченный с помощью fgets, равен <= размеру буфера, он работает нормально. Немного смущен относительно того, в чем проблема. Я использую кодовые блоки с компилятором GNU GCC. </p>

Спасибо.

#include <stdio.h>

int main()
{
    // Initialize variables
    char ID[11];
    float hrs, sal;

    // Get Employee's ID from user input
    printf("Input the Employee's ID(Max. 10 chars): ");
    fgets(ID, sizeof(ID), stdin);

    // Get working hours as float from user input
    printf("Input the working hrs: ");
    scanf("%f", &hrs);

    // Get hourly salary as float from user input
    printf("Salary amount/hr: ");
    scanf("%f", &sal);

    // Print Employee's ID
    printf("Employee's ID: %s", ID);

    // Print wage based on hours worked and salary
    printf("Salary = U$ %.2f", sal * hrs);

    return 0;
}

Ответы [ 2 ]

0 голосов
/ 16 января 2019

Вы наблюдаете поведение, потому что, если символ новой строки не записывается в ID из-за отсутствия места, он остается во входном буфере, который последующие два вызова scanf() не используют из-за того, что строка спецификатора формата не читается белымпробел.

fgets() возвращается при вводе новой строки, и новая строка записывается в буфер.В этом случае вам необходим буфер из 12 символов - для размещения новой строки и нулевого терминатора.Хорошей идеей является также инициализация буфера нулями.

char ID[11] = {0} ;

После fgets() может потребоваться заменить символ новой строки на nul.

Чтобы заменить символ новой строки на nulили отбросьте данные входного буфера, где остается символ новой строки:

char* end = strrchr( ID, `\n` ) ;
if( end != NULL) 
{ 
    *end = `\0` 
}
else
{
    char c ;
    do
    {
        c = getchar() ;
    } while( c != '\n' && c != EOF ) ;
}
0 голосов
/ 16 января 2019

Причина в том, что остальная часть строки не извлекается fgets(), если она больше переданного буфера и, следовательно, остается во входном буфере вашего файлового потока stdin; впоследствии преобразования scanf() не удаются.

Вы должны обнаружить этот случай (например, проверив, является ли последний символ в вашей только что прочитанной строке не новой строкой) и очистить входной буфер до следующей новой строки, например, вызвав getchar() в цикл до новой строки (или EOF). Затем позвоните scanf().

Пример кода (непроверенный и EOF-проверка все еще отсутствует):

fgets(ID, sizeof(ID), stdin);
if (ID[strlen(ID)-1] != '\n') {
    while (getchar() != '\n')
        ;
}

И не забудьте проверить возвращаемые значения ваших вызовов scanf(), чтобы увидеть, удалось ли преобразование!

...