Ввод данных в языке C

Язык C++ поддерживает также операции ввода из языка C, объявленные в файле stdio.h. В языке C++ вместо этого файла лучше подключить файл cstdio:

#include <cstdio>

Для ввода одного символа предназначена функция getchar(). Прототип функции:

#include <cstdio> /* или #include <stdio.h> */
int getchar(void);

В качестве значения функция возвращает код введенного символа. Чтобы символ был считан, необходимо после ввода символа нажать клавишу <Enter>. Если было введено несколько символов, то будет считан первый символ, а остальные останутся в буфере. Ключевое слово void внутри круглых скобок означает, что функция не принимает никаких параметров. Пример получения символа:

std::setlocale(LC_ALL, "Russian_Russia.1251");
int ch = 0;
std::printf("ch = ");          // Вывод подсказки
std::fflush(stdout);           // Сброс буфера
ch = std::getchar();           // Получение символа
std::printf("%d\n", ch);       // Вывод кода
std::printf("%c\n", (char)ch); // Вывод символа
Обратите внимание

Для ввода строки предназначена функция gets(), однако применять ее в программе не следует, так как функция не производит никакой проверки длины строки, что может привести к переполнению буфера. Лучше получать строку посимвольно с помощью функции getchar() или воспользоваться функцией fgets(). Прототип функции fgets():

#include <cstdio> /* или #include <stdio.h> */
char *fgets(char *buf, int maxCount, FILE *stream);

В качестве параметра stream указывается стандартный поток ввода stdin. Считывание производится до первого символа перевода строки или до конца потока или пока не будет прочитано maxCount–1 символов. Содержимое строки buf включает символ перевода строки. Исключением является последняя строка. Если она не завершается символом перевода строки, то символ добавлен не будет. Если произошла ошибка или достигнут конец потока, то функция возвращает нулевой указатель. Пример получения строки приведен в листинге 2.9.

Листинг 2.9. Ввод строки

#include <cstdio>
#include <cstring>
#include <clocale>
#include <process.h>
#include <cwchar>

int main() {
   system("chcp 1251"); // Смена кодировки консоли
   std::setlocale(LC_ALL, "Russian_Russia.1251");
   char buf[256] = "", *p = NULL;
   std::printf("Введите строку: ");
   std::fflush(stdout);              // Сброс буфера вывода
   p = std::fgets(buf, 256, stdin);
   if (p) {
      // Удаляем символ перевода строки
      size_t len = std::strlen(buf);
      if (len != 0 && buf[len - 1] == '\n') {
         buf[len - 1] = '\0';
      }
      // Выводим результат
      std::printf("Вы ввели: '%s'\n", buf);
   }
   else std::puts("Возникла ошибка");
   return 0;
}

В первой строке подключается заголовочный файл cstdio, в котором объявлены функции, предназначенные для ввода и вывода данных, во второй строке — файл cstring, в котором объявлена функция strlen(), возвращающая длину строки, в третьей строке — файл clocale, в котором объявлена функция setlocale(), в четвертой строке — файл process.h, в котором объявлена функция system(), а в пятой строке — файл cwchar.

Внутри функции main() сначала изменяется кодировка консоли и настраивается локаль. Строка, которую мы получим, по умолчанию будет в кодировке консоли (например, в кодировке windows-866 или какой-либо другой). Чтобы получить строку в кодировке windows-1251, мы в начале программы передаем команду смены кодировки chcp 1251 функции system().

Далее объявляется символьный массив buf, состоящий из 256 символов, а также указатель p на тип char и ему присваивается значение NULL. То, что переменная p является указателем, говорит символ * перед ее именем при объявлении. Значением указателя является адрес данных в памяти компьютера. Указатель, которому присвоено значение NULL, называется нулевым указателем. Такой указатель ни на что не указывает, пока ему не будет присвоен адрес.

В следующей строке выводится подсказка пользователю, а последующая инструкция сбрасывает буфер вывода. Далее мы получаем строку из стандартного потока ввода stdin. Поток указывается в третьем параметре функции fgets(). В первом параметре передается адрес символьного массива buf, а во втором — его размер. Если в процессе выполнения функции fgets() возникнет ошибка, то функция вернет нулевой указатель. В этом случае мы выводим сообщение Возникла ошибка. Если ошибка не возникла, то удаляем символ перевода строки, который был добавлен в символьный массив. Для этого с помощью функции strlen() получаем длину строки и сохраняем ее в переменной len. Затем проверяем значение последнего символа в строке. Если этот символ \n, то заменяем его нулевым символом. В противном случае ничего не заменяем. После замены выводим полученную строку в окно консоли.

Обратите внимание на два момента. Во-первых, размер символьного массива и длина строки это разные вещи. Размер массива — это общее количество символов, которое может хранить массив. Длина строки — это количество символов внутри символьного массива до первого нулевого символа. В следующем примере массив содержит 256 символов, а длина строки внутри него составляет всего три символа плюс нулевой символ:

char buf[256] = "abc";
std::cout << buf << std::endl;              // abc
std::cout << sizeof(buf) << std::endl;      // 256
std::cout << std::strlen(buf) << std::endl; // 3

Во-вторых, нумерация элементов массива начинается с 0, а не с 1. Поэтому последний символ имеет индекс на единицу меньше длины строки. Для доступа к отдельному символу нужно указать индекс внутри квадратных скобок:

char buf[256] = "abc";
std::cout << buf[0] << std::endl;           // a
std::cout << buf[1] << std::endl;           // b
std::cout << buf[2] << std::endl;           // c
std::cout << buf[std::strlen(buf) - 1]
          << std::endl;                     // c

Для получения и автоматического преобразования данных в конкретный тип (например, в целое число) предназначена функция scanf(). При вводе строки функция не производит никакой проверки длины строки, что может привести к переполнению буфера. Обязательно указывайте ширину при использовании спецификатора %s (например, %255s). Прототип функции:

#include <cstdio> /* или #include <stdio.h> */
int scanf(const char *format, ...);

В первом параметре указывается строка специального формата, внутри которой задаются спецификаторы, аналогичные применяемым в функции printf(), а также некоторые дополнительные спецификаторы. В последующих параметрах передаются адреса переменных. Функция возвращает количество произведенных присваиваний. Пример получения целого числа:

// #include <clocale>
std::setlocale(LC_ALL, "Russian_Russia.1251");
int x = 0;
std::printf("Введите число: ");
std::fflush(stdout);               // Сброс буфера вывода
int status = std::scanf("%d", &x); // Символ & обязателен!!!
if (status == 1) {
   std::printf("Вы ввели: %d\n", x);
}
else {
   std::puts("Ошибка при вводе числа");
}
std::printf("status = %d\n", status);

Обратите внимание на то, что перед названием переменной x указан символ &. В этом случае передается адрес переменной x, а не ее значение. При вводе строки символ & не указывается, так как название переменной без квадратных скобок является ссылкой на первый элемент массива. Пример ввода строки:

// #include <process.h>
system("chcp 1251"); // Смена кодировки консоли
// #include <clocale>
std::setlocale(LC_ALL, "Russian_Russia.1251");
char str[256] = "";
std::printf("Введите строку: ");
std::fflush(stdout);                   // Сброс буфера вывода
int status = std::scanf("%255s", str); // Символ & не указывается!!!
if (status == 1) {
   std::printf("Вы ввели: '%s'\n", str);
}
else {
   std::puts("Ошибка при вводе строки");
}

Обратите внимание: чтобы получить строку в кодировке windows-1251, мы вначале указываем нужную кодировку с помощью функции system(). Если кодировку не указать, то мы получим строку в кодировке консоли (по умолчанию в консоли используется кодировка windows-866). Далее мы настраиваем локаль, чтобы не было проблем при работе с русскими буквами. Не забудьте подключить заголовочные файлы process.h и clocale, в которых содержатся объявления функций system() и setlocale().

Считывание символов производится до первого символа-разделителя, например, пробела, табуляции или символа перевода строки. Поэтому после ввода строки "Hello, world!" переменная str будет содержать лишь фрагмент "Hello,", а не всю строку.

Следует учитывать, что функции getchar() и scanf() применяются в языке C. Хотя их можно использовать и в языке C++, тем не менее для ввода данных стоит отдать предпочтение объекту cin. Описание функций getchar() и scanf() приведено в этой книге лишь для того, чтобы вы могли разобраться в чужом коде.

Учебник C++ (MinGW-W64)
Учебник C++ (MinGW-W64) в формате PDF

Помощь сайту

ЮMoney (Yandex-деньги): 410011140483022

ПАО Сбербанк:
Счет: 40817810855006152256
Реквизиты банка:
Наименование: СЕВЕРО-ЗАПАДНЫЙ БАНК ПАО СБЕРБАНК
Корреспондентский счет: 30101810500000000653
БИК: 044030653
КПП: 784243001
ОКПО: 09171401
ОКОНХ: 96130
Скриншот реквизитов