C Academy · Урок

Распространённые ошибки ввода-вывода

Проблемы буфера и перевода строки

Урок 4 из 413 шагов

«Распространённые ошибки ввода-вывода» — бесплатный урок C Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения C Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс C Academy содержит 4 уроков всего.

Распространённые ошибки ввода-вывода

Ввод и вывод в C таят несколько классических ловушек. Знание этих ловушек сэкономит вам часы отладки.

#include <stdio.h>
int main(void) {
    printf("Let us study I/O pitfalls\n");
    return 0;
}

Оставшийся перевод строки

После scanf("%d", ...) клавиша Enter оставляет в буфере \n. Последующий %c считывает этот перевод строки вместо настоящего ввода.

#include <stdio.h>
int main(void) {
    char c = 'A';
    printf("Use a space before %%c to skip the leftover newline\n");
    printf("c = %c\n", c);
    return 0;
}

Исправление с помощью пробела

Запись scanf(" %c", &c) с пробелом в начале сообщает scanf, что сначала нужно пропустить пробельные символы.

#include <stdio.h>
int main(void) {
    char c = 'Z';
    printf("scanf(\" %%c\", &c) skips whitespace\n");
    printf("c = %c\n", c);
    return 0;
}

Забытый амперсанд

Передача переменной в scanf без & приводит к записи по неверному адресу и, скорее всего, к сбою.

#include <stdio.h>
int main(void) {
    int n = 9;
    printf("Always pass &n, not n, to scanf for an int\n");
    printf("n = %d\n", n);
    return 0;
}

Несоответствующие спецификаторы

Считывание double с помощью %f вместо %lf в scanf повреждает значение. Для вывода используется %f в обоих случаях, но для ввода спецификаторы различаются.

#include <stdio.h>
int main(void) {
    double d = 2.5;
    printf("scanf needs %%lf for double; printf uses %%f\n");
    printf("d = %.1f\n", d);
    return 0;
}

Буферизация вывода

Вывод может буферизоваться и не появляться сразу. Завершение строкой \n или вызов fflush(stdout) очищает буфер.

#include <stdio.h>
int main(void) {
    printf("Flushed by newline\n");
    fflush(stdout);
    return 0;
}

gets опасна

Старая функция gets не проверяла границы и удалена из современного C. Вместо неё используйте fgets.

#include <stdio.h>
int main(void) {
    char buf[10];
    /* fgets(buf, sizeof buf, stdin); */
    buf[0] = 'H'; buf[1] = 'i'; buf[2] = 0;
    printf("buf = %s\n", buf);
    return 0;
}

Переполнение буфера с %s

Обычный %s в scanf может записать данные за пределы небольшого массива. Ограничьте его ширину, например %19s.

#include <stdio.h>
int main(void) {
    char name[20];
    printf("Use %%19s to leave room for the null terminator\n");
    name[0] = 0;
    printf("name length cap protects buffer\n");
    return 0;
}

fgets сохраняет перевод строки

fgets сохраняет завершающий перевод строки. Часто его необходимо удалить.

#include <stdio.h>
#include <string.h>
int main(void) {
    char line[] = "hello\n";
    line[strcspn(line, "\n")] = 0;
    printf("[%s]\n", line);
    return 0;
}

Игнорирование возвращаемых значений

Если не проверять возвращаемое значение scanf, некорректный ввод незаметно проходит дальше. Всегда выполняйте проверку.

#include <stdio.h>
int main(void) {
    int n = 3;
    int items = 1;
    if (items != 1)
        printf("bad input\n");
    else
        printf("ok: %d\n", n);
    return 0;
}

Безопасная сборка всего вместе

Надёжный подход: считывайте данные с помощью fgets, разбирайте их с помощью sscanf и проверяйте результат.

#include <stdio.h>
int main(void) {
    char line[] = "123";
    int n;
    if (sscanf(line, "%d", &n) == 1)
        printf("parsed %d\n", n);
    return 0;
}

Быстрая проверка

Проверьте своё понимание проблем ввода-вывода.

Итоги: распространённые проблемы ввода-вывода

Вы научились избегать распространённых ошибок.

  • Оставшиеся переводы строк мешают %c; используйте пробел в начале
  • Всегда передавайте адреса с помощью &
  • Используйте %lf для считывания значений double
  • Предпочитайте fgets функции gets и ограничивайте ширину %s
  • Проверяйте возвращаемые значения и очищайте буфер вывода
Можно начать бесплатно

Изучай C с ИИ-репетитором — бесплатно

Пиши и запускай код прямо в браузере, получай мгновенную помощь от ИИ-репетитора 24/7 и продолжи учиться на сайте или в приложении.

Курсы
39
Уроки
144

Часто задаваемые вопросы

Урок «Распространённые ошибки ввода-вывода» бесплатный?

Да — полный текст урока «Распространённые ошибки ввода-вывода» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс C Academy, подпишись на CoddyKit PRO. Курс C Academy содержит 4 уроков всего.

Чему я научусь в уроке «Распространённые ошибки ввода-вывода»?

Проблемы буфера и перевода строки Ты практикуешь C Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать C Academy?

Предыдущий опыт не требуется. C Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.

Сколько времени занимает урок «Распространённые ошибки ввода-вывода»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке C Academy?

Да. Каждый урок C Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Спецификаторы формата printf
  2. scanf и ввод
  3. Ширина, точность и флаги
  4. Распространённые ошибки ввода-вывода
← Назад к C Academy