cpp

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

Выводить данные на консоль мы научились, теперь рассмотрим объекты и функции, предназначенные для получения данных от пользователя. Для ввода данных в языке C++ предназначен объект cin (console input — ввод с консоли), объявленный в файле iostream. Объект cin позволяет ввести данные любого встроенного типа, например, число, символ или строку. В этом разделе мы рассмотрим лишь основные возможности этого объекта, так как для понимания всех возможностей требуется знание принципов объектно-ориентированного программирования (ООП). В последующих главах мы вернемся к изучению объекта cin.

Прежде чем использовать объект cin необходимо подключить файл iostream с помощью директивы #include:

#include <iostream>

Ввод числа

В качестве примера использования объекта cin произведем суммирование двух целых чисел, введенных пользователем (листинг 2.6).

Листинг 2.6. Суммирование двух введенных чисел

#include <iostream>
#include <clocale>

int main() {
   std::setlocale(LC_ALL, "Russian_Russia.1251");
   int x = 0, y = 0;
   std::cout << "x = ";  // Вывод подсказки
   std::cout.flush();    // Сброс буфера вывода
   std::cin >> x;        // Ввод числа
   std::cout << "y = ";  // Вывод подсказки
   std::cout.flush();    // Сброс буфера вывода
   std::cin >> y;        // Ввод числа
   std::cout << "Сумма равна: " << x + y << std::endl;
   return 0;
}

В первой строке производится подключение заголовочного файла iostream, а во второй — файла clocale. Далее внутри функции main() с помощью функции setlocale() настраивается локаль, а затем объявляются две локальные переменные: x и y. Ключевое слово int в начале строки означает, что объявляются целочисленные переменные. При объявлении переменным сразу присваивается начальное значение (0) с помощью оператора =. Если значение не присвоить, то переменная будет иметь произвольное значение, так называемый «мусор». Как видно из примера, на одной строке можно объявить сразу несколько переменных, разделив их запятыми.

В следующей строке с помощью объекта cout выводится подсказка для пользователя ("x = "). Благодаря этой подсказке пользователь будет знать, что от него требуется. Далее идет вызов метода flush() объекта cin, который сбрасывает данные из буфера потока вывода stdout в консоль. Если буфер вывода принудительно не сбросить, пользователь может не увидеть подсказку вообще.

После ввода числа и нажатия клавиши <Enter> значение будет присвоено переменной x. Ввод значения производится с помощью объекта cin. После названия объекта указывается оператор >>, который как бы указывает направление ввода. При разработке собственных объектов можно перегрузить этот оператор и тем самым управлять вводом. После оператора >> передается название переменной, в которой будут сохранены введенные данные. Так как объекты cout и cin объявлены в пространстве имен std, название пространства имен необходимо указать перед объектами.

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

x = 10
y = 20
Сумма равна: 30

При вводе данных производится попытка преобразования к типу переменной. В нашем примере строка "10" будет преобразована в число 10, а строка "20" — в число 20. Однако, пользователь вместо числа может ввести все что угодно, например, строку не содержащую число. В этом случае преобразование закончится неудачей, переменной не будет присвоено значение, а введенное значение останется в буфере и будет автоматически считано следующей операцией ввода. Проверить отсутствие ошибки при преобразовании можно с помощью метода good() объекта cin. Прототип метода:

bool good() const;

Метод good() возвращает логическое значение true (Истина), которое соответствует числу 1, если ошибок не произошло, или значение false (Ложь), соответствующее числу 0, в противном случае. Вывести сообщение об ошибке и прервать выполнение программы можно так:

std::cout << "x = ";  // Вывод подсказки
std::cout.flush();    // Сброс буфера вывода
std::cin >> x;        // Ввод числа
if (std::cin.good() == false) {
   std::cout << "Error" << std::endl;
   return 1; // Выходим из функции main()
}

В этом примере для проверки условия используется оператор ветвления if. После названия оператора внутри круглых скобок указывается проверяемое выражение. Если выражение возвращает логическое значение true (Истина), то будут выполнены инструкции внутри фигурных скобок. Если выражение возвращает значение false (Ложь), то инструкции внутри фигурных скобок игнорируются и управление передается инструкции, расположенной сразу после закрывающей фигурной скобки. Проверка значения, возвращаемого методом good(), осуществляется с помощью оператора ==. При ошибке метод good() вернет значение false, следовательно, условие false == false будет истинным. В этом случае выводим сообщение об ошибке и выходим из функции main() (и, следовательно, из программы), возвращая значение 1.

Обратите внимание на то, что оператор проверки на равенство содержит два символа =. Указание одного символа = является логической ошибкой, так как этот оператор используется для присваивания значение переменной, а не для проверки условия. Использовать оператор присваивания внутри логического выражения допускается, поэтому компилятор не выведет сообщение об ошибке (но возможно выведет предупреждение), однако программа может выполняться некорректно. Подобную ошибку часто допускают начинающие программисты. Например, в следующем примере вместо проверки равенства числу 11, производится операция присваивания:

int x = 10;
if (x = 11) {
   std::cout << "x == 11" << std::endl;
}

Любое число не равное 0 трактуется как логическое значение true, поэтому производится проверка условия true == true, которое является истинным. Проверка соответствия условия значению true производится по умолчанию.

Прерывать выполнение программы в случае ошибки мы научились, теперь рассмотрим возможность обработки ошибки (листинг 2.7). Дадим пользователю три попытки ввода, прежде чем досрочно завершим программу.

Листинг 2.7. Обработка ошибок ввода

#include <iostream>
#include <clocale>
#include <cstdio>

int main() {
   std::setlocale(LC_ALL, "Russian_Russia.1251");
   int x = 0, y = 0, count = 1;
   bool flag = false;
   // Получаем первое число
   do {
      std::cout << "x = ";
      std::cout.flush();
      std::cin >> x;
      if (!std::cin.good()) { // Проверяем успешность ввода
         std::cout << std::endl << "Вы ввели не число" << std::endl;
         ++count;
         if (count > 3) {
            std::cout << "Вы сделали три ошибки" << std::endl;
            return 1;
         }
         std::cin.clear();               // Сбрасываем флаг ошибки
         // Очищаем буфер
         int ch = 0;
         while ((ch = std::cin.get()) != '\n' && ch != EOF);
      }
      else flag = true;
   } while (!flag);
   // Получаем второе число
   flag = false;
   count = 1;
   do {
      std::cout << "y = ";
      std::cout.flush();
      std::cin >> y;
      if (!std::cin.good()) { // Проверяем успешность ввода
         std::cout << std::endl << "Вы ввели не число" << std::endl;
         ++count;
         if (count > 3) {
            std::cout << "Вы сделали три ошибки" << std::endl;
            return 1;
         }
         std::cin.clear();               // Сбрасываем флаг ошибки
         // Очищаем буфер
         int ch = 0;
         while ((ch = std::cin.get()) != '\n' && ch != EOF);
      }
      else flag = true;
   } while (!flag);
   // Выводим результат
   std::cout << "Сумма равна: " << x + y << std::endl;
   return 0;
}

В этом примере внутри функции main() объявляются четыре локальные переменные: x, y, count и flag. Переменные x, y и count являются целочисленными, а переменная flag имеет логический тип bool. Тип bool позволяет хранить в переменной только два значения: true (Истина) и false (Ложь). Значение true соответствует числу 1, а значение false — числу 0. В переменной flag мы будем сохранять текущий статус обработки ошибок, а в переменной count — количество допущенных ошибок подряд.

При возникновении ошибки ее необходимо обработать, а затем вывести повторный запрос на ввод числа. Вполне возможно эту процедуру нужно будет выполнить несколько раз. Причем количество повторов заранее неизвестно. Для выполнения одних и тех же инструкций несколько раз предназначены циклы. В нашем примере используется цикл do...while. Инструкции внутри фигурных скобок будут выполняться до тех пор, пока логическое выражение после ключевого слова while является истинным. Проверка условия производится после выполнения инструкций внутри фигурных скобок, поэтому инструкции выполняются минимум один раз. Обратите внимание на логическое выражение !flag. Восклицательный знак, расположенный перед переменной, инвертирует значение. Например, если переменная содержит значение true, то выражение !true вернет значение false. Так как проверка значения на истинность производится по умолчанию, выражение может не содержать операторов сравнения.

Внутри цикла выводим подсказку пользователю с помощью объекта cout, сбрасываем буфер вывода, а затем получаем значение с помощью объекта cin и сохраняем его в переменной. Далее проверяем наличие ошибки с помощью метода good() объекта cin. Если произошла ошибка, то выводим сообщение Вы ввели не число. Количество попыток мы отслеживаем с помощью переменной count. На начальном этапе она имеет значение 1. Если пользователь не ввел число, то увеличиваем значение на 1 с помощью инструкции:

++count;

Если пользователь допустил три ошибки подряд (переменная count будет содержать значение больше 3), то выводим сообщение Вы сделали три ошибки и выходим из функции main(), вызвав оператор return.

Так как ошибка была обработана необходимо сбросить флаг ошибки. Для этого предназначен метод clear() объекта cin:

void clear(iostate state=goodbit);

В прототипе параметру state присвоено начальное значение, поэтому, если значение по умолчанию устраивает, параметр можно не указывать:

std::cin.clear();

Сбросить флаг ошибки не достаточно, так как ошибочное значение по-прежнему находится в буфере. Если буфер не очистить, то значение будет автоматически передано следующей операции ввода, что породит повторную ошибку. Проигнорировать значение, расположенное в буфере, позволяют следующие инструкции:

int ch = 0;
while ((ch = std::cin.get()) != '\n' && ch != EOF);

Выполнение инструкций в цикле while продолжается до тех пор, пока логическое выражение внутри круглых скобок истинно. Внутри круглых скобок на каждой итерации цикла выполняется получение одного символа из потока ввода с помощью метода get(). Далее производится сравнение полученного символа с символом перевода строки \n и концом потока. Если полученный символ не равен символу перевода строки и не достигнут конец потока, то получаем следующий символ. Цикл выполняется до тех пор, пока не встретится символ перевода строки, который является маркером конца данных в буфере. В итоге буфер ввода будет очищен от ошибочных данных и мы можем запросить данные повторно.

Обычно в цикле while после круглых скобок указываются фигурные скобки, внутри которых размещаются инструкции, выполняемые несколько раз. Если инструкция одна, то фигурные скобки можно не указывать. Нам не нужно вообще выполнять какие-либо инструкции, поэтому мы воспользовались пустой инструкцией, состоящей из точки с запятой.

Очистить буфер можно также с помощью метода ignore() объекта cin. Прототип метода:

istream &ignore(streamsize n=1, int_type delim=EOF);

Первый параметр задает максимальное количество считываемых из буфера символов (по умолчанию один символ). Второй параметр задает символ-разделитель. Если символ-разделитель встретится раньше, чем будет считано указанное количество символов, то считывание прекращается. Метод возвращает ссылку на поток. Пример:

std::cin.ignore(255, '\n');

В этом примере очистка выполняется пока не будет считано 255 символов, либо пока не встретится символ перевода строки \n. Символ перевода строки также удаляется из буфера. Проблема этого способа заключается в том, что мы не знаем сколько символов нужно удалить из буфера. Число 255 — это всего лишь произвольное значение, которого может быть недостаточно. Чтобы полностью очистить буфер ввода можно в первом параметре указать максимальное значение для типа streamsize:

// #include <limits>
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

После очистки буфера проверяется значение переменной flag. Так как значение переменной является ложным, цикл будет выполнен еще раз.

Если ошибки нет, выполняются инструкции, расположенные после ключевого слова else. В нашем случае переменной flag присваивается значение true. Это значение является условием выхода из цикла.

Далее таким же способом получаем второе число. Так как в предыдущем цикле значения переменных flag и count были изменены, перед циклом производим восстановление первоначальных значений. Иначе выход из цикла произойдет даже в случае ошибки. Если второе число успешно получено, производим вывод суммы чисел.

После объекта cin можно указать сразу несколько переменных, разделив их операторами >>. В этом случае при вводе все значения можно указать на одной строке. Между собой значения должны разделяться пробелами, табуляцией или символом перевода строки. Эти символы не будут присвоены переменным. Например, программу суммирования двух целых чисел можно записать так:

std::setlocale(LC_ALL, "Russian_Russia.1251");
int x = 0, y = 0;
std::cin >> x >> y;
std::cout << "Сумма равна: " << x + y << std::endl;

При вводе строки "10 20" число 10 будет присвоено переменной x, а число 20 — переменной y. Пробел игнорируется.

Ввод символа

Получить символ можно двумя способами. Первый способ ничем не отличается от ввода числа, только при объявлении переменной указывается тип char:

std::setlocale(LC_ALL, "Russian_Russia.1251");
char ch = 0;
std::cout << "ch = ";              // Вывод подсказки
std::cout.flush();                 // Сброс буфера
std::cin >> ch;                    // Получение символа
std::cout << ch << std::endl;      // Вывод символа
std::cout << static_cast<int>(ch)
          << std::endl;            // Вывод кода символа

В этом примере для получения кода символа мы выполнили приведение переменной ch к типу int с помощью оператора static_cast. Формат оператора:

static_cast< Тип_результата > (<Выражение или переменная>)

Второй способ заключается в использовании метода get() объекта cin. Прототипы метода:

int get();
istream &get(char &ch)

Первый прототип возвращает целочисленный код символа:

std::setlocale(LC_ALL, "Russian_Russia.1251");
int ch = 0;
std::cout << "ch = ";              // Вывод подсказки
std::cout.flush();                 // Сброс буфера
ch = std::cin.get();               // Получение символа
std::cout << ch << std::endl;      // Вывод кода символа
std::cout << static_cast<char>(ch)
          << std::endl;            // Вывод символа

Второй прототип записывает введенный символ в переменную ch и возвращает ссылку на поток ввода:

std::setlocale(LC_ALL, "Russian_Russia.1251");
char ch = 0;
std::cout << "ch = ";              // Вывод подсказки
std::cout.flush();                 // Сброс буфера
std::cin.get(ch);                  // Получение символа
std::cout << ch << std::endl;      // Вывод символа
std::cout << static_cast<int>(ch)
          << std::endl;            // Вывод кода символа
Обратите внимание

Ввод строки

Числа и символы мы вводить научились, теперь попробуем ввести строку:

// #include <process.h>
system("chcp 1251"); // Смена кодировки консоли
std::setlocale(LC_ALL, "Russian_Russia.1251");
char str[255] = {0};
std::cout << "Введите строку: ";
std::cout.flush();
std::cin >> str;
std::cout << '\'' << str << '\'' << std::endl;

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

Далее объявляется символьный массив, состоящий из 255 символов. Строки в языке C++ представляют собой последовательность (массив) символов, последним элементом которого является нулевой символ ('\0'). Обратите внимание на то, что нулевой символ (нулевой байт) не имеет никакого отношения к символу '0'. Коды этих символов разные. Затем выводится подсказка пользователю и сбрасывается буфер. Далее объекту cin передается указатель на первый элемент массива str. Если в окне консоли ввести строку "Hello, world!" и нажать клавишу <Enter>, то массив str будет содержать значение "Hello,\0". Фрагмент "world!" останется в буфере, так как символ пробела является символом-разделителем.

Чтобы получить определенное количество символов необходимо воспользоваться методом getline() объекта cin. Прототипы метода:

istream &getline(char *str, streamsize count);
istream &getline(char *str, streamsize count, char delim);

В первом параметре задается указатель на строку, а во втором параметре максимальное количество символов. В параметре delim можно дополнительно указать символ-ограничитель. Метод, соответствующий первому прототипу, производит считывание count-1 символов. Если раньше встретится символ перевода строки (\n), то считывается фрагмент до этого символа. Символ перевода строки считывается, но не записывается в массив. В конец массива автоматически вставляется нулевой символ. В качестве значения метод возвращает ссылку на поток ввода. Пример использования метода getline() приведен листинге 2.8.

Метод, соответствующий второму прототипу, производит считывание count-1 символов. Если раньше встретится символ delim, то считывается фрагмент до этого символа. Символ delim считывается, но не записывается в массив. В конец массива автоматически вставляется нулевой символ. В качестве значения метод возвращает ссылку на поток ввода.

Количество записанных в массив символов можно получить с помощью метода gcount() объекта cin. Прототип метода:

streamsize gcount() const;

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

#include <iostream>
#include <clocale>
#include <process.h>

int main() {
   system("chcp 1251"); // Смена кодировки консоли
   std::setlocale(LC_ALL, "Russian_Russia.1251");
   char str[255] = {0};
   std::cout << "Введите строку: ";
   std::cout.flush();
   std::cin.getline(str, 255);
   std::cout << '\'' << str << '\'' << std::endl;
   std::cout << std::cin.gcount() << std::endl;
   return 0;
}

Ввод данных в языке 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++ (Qt Creator и MinGW)
Учебник C++ (Qt Creator и MinGW) в формате PDF

Помощь сайту

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

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

cpp