Промышленное производство
Промышленный Интернет вещей | Промышленные материалы | Техническое обслуживание и ремонт оборудования | Промышленное программирование |
home  MfgRobots >> Промышленное производство >  >> Industrial programming >> Язык C

Ввод-вывод в C: stdio.h, потоки stdin/stdout/stderr, функции getchar/putchar, gets/puts, scanf/printf

Концепция потоков (streams)

В C все устройства ввода-вывода представлены как потоки байтов. Три стандартных потока открываются автоматически при запуске программы:

ПотокФайловый указательУстройство по умолчаниюНазначение
Стандартный вводstdin (FILE*)КлавиатураЧтение данных
Стандартный выводstdoutЭкран (терминал)Вывод результатов
Стандартный вывод ошибокstderrЭкран (терминал)Вывод диагностики/ошибок

stdin, stdout, stderr — макросы, расширяющиеся в выражения типа FILE*. Определены в <stdio.h>.

Буферизация

Управление: setbuf(), setvbuf(), fflush() (принудительный сброс).

Симвловой ввод-вывод

int getchar(void)

Читает один символ из stdin. Возвращает int (символ как unsigned char или EOF — обычно -1).

int c;
while ((c = getchar()) != EOF) {
    putchar(c); // эхо
}

int putchar(int c)

Пишет символ (младший байт c) в stdout. Возвращает записанный символ или EOF при ошибке.

Строчный ввод-вывод

char *fgets(char *s, int n, FILE *stream) — РЕКОМЕНДУЕТСЯ

Читает до n-1 символов или до \n (включительно) или EOF. Добавляет \0. Возвращает s или NULL (EOF/ошибка).

char line[256];
while (fgets(line, sizeof(line), stdin)) {
    // line содержит \n в конце (если поместилось)
    fputs(line, stdout);
}

int fputs(const char *s, FILE *stream)

Пишет строку s (без автоматического \n) в поток. Возвращает неотрицательное при успехе, EOF при ошибке.

gets() — УДАЛЕНА В C11 (ОПАСНА!)

Не проверяет границы буфера → переполнение. Никогда не используйте. Замените на fgets().

Форматированный ввод-вывод: scanf / printf

printf — форматированный вывод

int printf(const char *format, ...);
int fprintf(FILE *stream, const char *format, ...);
int sprintf(char *buf, const char *format, ...);
int snprintf(char *buf, size_t n, const char *format, ...); // БЕЗОПАСНЫЙ!

Основные спецификаторы формата

СпецификаторТип аргументаВывод
%d, %iintЗнаковое десятичное
%uunsigned intБеззнаковое десятичное
%ld, %lldlong, long longДлинные знаковые
%zusize_tРазмер (беззнаковый)
%fdouble (float промоутится)Фиксированная точка: 123.456
%e, %EdoubleНаучная: 1.23e+02
%g, %GdoubleКратчайшее из %f/%e
%cint (char)Символ
%sconst char*Строка (до \0)
%pvoid*Указатель (hex)
%%—Литерал %

Флаги, ширина, точность

%10d      // ширина 10, выравнивание вправо
%-10d     // ширина 10, выравнивание влево
%010d     // ширина 10, заполнение нулями
%.2f      // 2 знака после запятой
%10.2f    // ширина 10, 2 знака после запятой
%.*f      // точность из аргумента: printf("%.*f", 3, 1.23456) → "1.235"
%*d       // ширина из аргумента

scanf — форматированный ввод

int scanf(const char *format, ...);
int fscanf(FILE *stream, const char *format, ...);
int sscanf(const char *str, const char *format, ...);

Важные правила scanf

Примеры scanf

int a; float b; char name[50];
scanf("%d %f", &a, &b);           // два числа
scanf("%49s", name);              // слово (до пробела), макс 49 символов
scanf(" %49[^\n]", name);         // строка до \n (пробел перед % съедает \n от прошлого ввода)
int n; scanf("%d%n", &a, &n);     // %n — записывает число прочитанных символов

Бинарный ввод-вывод

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);

Читают/пишут блоки памяти (массивы, структуры). Возвращают число прочитанных/записанных элементов.

struct Record { int id; double val; } rec;
fwrite(&rec, sizeof(rec), 1, fp); // запись структуры
fread(&rec, sizeof(rec), 1, fp);  // чтение

Внимание: бинарные файлы непереносимы (endianness, padding, размер типов). Для переносимости используйте сериализацию (JSON, protobuf, свой формат).

Работа с файлами (кратко, подробнее в следующей статье)

FILE *fp = fopen("file.txt", "r"); // "r", "w", "a", "r+", "w+", "a+", "rb", "wb"...
if (!fp) { perror("fopen"); return 1; }

// чтение/запись через fgetc, fgets, fscanf, fprintf, fread, fwrite...

fclose(fp); // обязательно! сбрасывает буферы, закрывает дескриптор

Обработка ошибок

Пример: копирование файла с буферизацией

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {
    if (argc != 3) {
        fprintf(stderr, "Usage: %s  \n", argv[0]);
        return 1;
    }
    FILE *in = fopen(argv[1], "rb");
    if (!in) { perror(argv[1]); return 1; }
    FILE *out = fopen(argv[2], "wb");
    if (!out) { perror(argv[2]); fclose(in); return 1; }

    char buf[4096];
    size_t n;
    while ((n = fread(buf, 1, sizeof(buf), in)) > 0) {
        if (fwrite(buf, 1, n, out) != n) {
            perror("write error");
            break;
        }
    }
    if (ferror(in)) perror("read error");

    fclose(in);
    fclose(out);
    return 0;
}

Язык C

  1. Понимание ключевых слов и идентификаторов C#: правила, списки и лучшие практики
  2. Основы ввода-вывода в C#: Console.WriteLine, ReadLine и форматирование
  3. Классы и объекты в C#: Фундаменты надёжного ООП
  4. Освоение ввода и вывода в C++: практическое руководство
  5. Ввод-вывод в C: scanf() и printf() — подробное руководство
  6. Мастерство ввода-вывода и импорта модулей в Python: Практическое руководство
  7. Ввод и вывод в Java: печать, чтение и форматирование данных
  8. Потоки в C++: cout, cin, cerr, clog — практическое руководство
  9. Константы и литералы в C: целочисленные, вещественные, символьные, строковые и определение констант
  10. Константы и литералы в C#: типы, правила и лучшие практики