Массив не сбрасывается правильно, при использовании memset - PullRequest
1 голос
/ 21 апреля 2019

Когда я беру вейл из stdin, который слишком велик для c, сброс происходит не так, как ожидалось. Пользователю будет предложено ввести код, но после ввода появится дополнительная новая строка, где требуется ввод, чем проверка длины не удалась.

void clear(void) {    
    while (getchar() != '\n')
        ;
}

int add_flight(code_t codes[], int lf) {
    char c[MAX_CODE_LEN + 1];
    int s = 0;
    while (s == 0) {
        printf("Enter code>\n");
        if (fgets(c, sizeof c, stdin)) {
            printf("%s", c);
            if ('\n' == c[0]) {
                printf("Invalid input\n");
            } else if (c[sizeof c - 1] == '\0' && c[sizeof c - 2] != '\n') {
                clear();
                printf("Invalid input\n");
                memset(c, 0, sizeof c);
            } else {
                strcpy(codes[lf].id, c);
                s = 1;
                break;
            }
        }
    }
    return 0;
}

Любая помощь будет принята с благодарностью.

1 Ответ

3 голосов
/ 21 апреля 2019

В вашем коде есть несколько проблем:

  • функция clear не проверяет конец файла, вызывая бесконечный цикл, если стандартный ввод закрыт без завершающей строки, как это было быслучай перенаправления ввода из пустого файла.
  • тест на слишком длинные строки ввода некорректен: последний символ массива не определен, если ввод не заполняет массив.Вы должны проверить, если strlen(c) == sizeof(c) - 1 после удаления завершающего символа новой строки.
  • c является очень запутанным именем для массива char.Это имя обычно используется для int для получения байтового значения.Назовите массив buf для лучшей читаемости.
  • memset бесполезен, так как вы собираетесь читать новую строку в массив.
  • определение code_t отсутствует.Если размер его id члена массива не меньше, чем MAX_CODE_LEN + 1, поведение будет неопределенным.
  • Кроме того, вы копируете завершающий символ новой строки в codes[lf].id, что, вероятно, неверно.
  • , если id определено для хранения MAX_CODE_LEN символов, т.е. char id[MAX_CODE_LEN + 1]; для дополнительного нулевого терминатора, buf должен иметь один дополнительный байт для новой строки, набранной пользователем, следовательно, char buf[MAX_CODE_LEN + 2];

Вот модифицированная версия:

int clear(void) {
    int c;   
    while ((c = getchar()) != EOF && c != '\n')
        continue;
    return c;
}

int add_flight(code_t codes[], int lf) {
    char buf[MAX_CODE_LEN + 2];

    for (;;) {
        printf("Enter code>\n");
        if (fgets(buf, sizeof buf, stdin)) {
            printf("%s", buf);
            /* remove the trailing newline if present */
            size_t len = strlen(buf);
            if (len > 0 && buf[len - 1] == '\n')
                buf[--len] = '\0';
            if (len == sizeof(buf) - 1) {
                /* line too long: consume the rest of the input line */
                printf("Invalid input\n");
                if (clear() == EOF)
                    break;
            } else if (len == 0) {
                /* empty line */
                printf("Invalid input\n");
            } else {
                strcpy(codes[lf].id, buf);
                return 1;  // return success
            }
        } else {
            break;
        }
    }
    return 0;  // premature end of file: return failure
}
...