Базовый ввод / вывод

Примеры программ предыдущих разделов обеспечивали небольшое взаимодействие с пользователем, если оно вообще было. Они просто печатали простые значения на экране, но стандартная библиотека предоставляет множество дополнительных способов взаимодействия с пользователем через свои функции ввода / вывода. В этом разделе представлено краткое введение в некоторые из наиболее полезных.

C ++ использует удобную абстракцию, называемую потоками, для выполнения операций ввода и вывода в последовательных средах, таких как экран, клавиатура или файл. потокэто объект, в котором программа может вставлять или извлекать символы в / из. Нет необходимости знать подробности о носителях, связанных с потоком или о любых его внутренних спецификациях. Все, что нам нужно знать, это то, что потоки являются источником / назначением символов и что эти символы предоставляются / принимаются последовательно (т. Е. Один за другим).

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

поток описание
cin стандартный поток ввода
cout стандартный выходной поток
cerr стандартный поток ошибок (выход)
clog стандартный каротажный (выходной) поток

Мы рассмотрим только более подробно coutи cin(стандартные выходные и входные потоки); cerrи clogтакже являются выходными потоками, поэтому они, по существу, работают cout, с той лишь разницей, что они идентифицируют потоки для определенных целей: сообщения об ошибках и протоколирование; которые, во многих случаях, в большинстве настроек среды, на самом деле делают то же самое: они печатаются на экране, хотя они также могут быть индивидуально перенаправлены.

Стандартный вывод (cout)

В большинстве программных сред стандартным выховом по умолчанию является экран, а объект потока C ++, определенный для доступа к нему cout.

Для форматированных операций вывода coutиспользуется вместе с оператором вставки , который записывается как <<(т.е. два знака «меньше»).

1
2
3
cout << "Output sentence"; // prints Output sentence on screen
cout << 120;               // prints number 120 on screen
cout << x;                 // prints the value of x on screen  

<<Оператор вставляет данные , которые следуют за ним в поток , который предшествует ему. В приведенных выше примерах он вставил литеральную строку Output sentence, число 120и значение переменной xв стандартный выходной поток cout. Обратите внимание, что предложение в первом выражении заключено в двойные кавычки ( "), потому что это строковый литерал, а в последнем x– нет. В этом заключается двойное цитирование; когда текст заключен между ними, текст печатается буквально; когда их нет, текст интерпретируется как идентификатор переменной, и вместо этого его значение печатается. Например, эти два предложения имеют очень разные результаты:

1
2
cout << "Hello";  // prints Hello
cout << Hello;    // prints the content of variable Hello 

Несколько операций вставки (<<) могут быть скованы в одном выражении:

cout << "This " << " is a " << "single C++ statement";

Этот последний оператор напечатает текст This is a single C++ statement. Вставка цепочек особенно полезна для смешивания литералов и переменных в одном утверждении:

cout << "I am " << age << " years old and my zipcode is " << zipcode;

Если предположить , что возрастные переменный содержит значение 24 и почтовый индекс переменного содержит 90064, выход предыдущего оператора будет:

I am 24 years old and my zipcode is 90064
Что соиЬ не делает автоматически добавлять разрывы строк в конце концов, если не указано сделать это. Например, введите следующие два утверждения cout:
cout << «Это предложение»;
cout << «Это еще одно предложение»;

Вывод будет в одной строке, без разрывов между ними. Что-то вроде:

This is a sentence.This is another sentence.
Чтобы вставить разрыв строки, должен быть вставлен символ новой строки в точном положении, в котором должна быть разбита строка. В C ++ может быть указан символ новой строки \n(т. Е. Символ обратной косой черты, за которым следует строчный регистр n). Например:

1
2
cout << "First sentence.\n";
cout << "Second sentence.\nThird sentence.";

Это дает следующий результат: в качестве альтернативы манипулятор также может использоваться для разрыва линий. Например:

First sentence.
Second sentence.
Third sentence.

endl

1
2
cout << "First sentence." << endl;
cout << "Second sentence." << endl;

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

First sentence.
Second sentence.

endl'\n'coutendl'\n'

Стандартный ввод (cin)

В большинстве программных сред стандартный ввод по умолчанию – это клавиатура, а объект потока C ++, определенный для доступа к нему cin.

Для форматированных операций ввода cinиспользуется вместе с оператором извлечения, который записывается как >>(т. Е. Два знака «больше»). За этим оператором следует переменная, в которой хранятся извлеченные данные. Например:

1
2
int age;
cin >> age;

Первый оператор объявляет переменную intвызываемого типа age, а вторая – извлекает из cinзначения, которое будет храниться в нем. Эта операция заставляет программу ждать ввода cin; Как правило, это означает, что программа будет ждать ввода пользователем некоторой последовательности с клавиатуры. В этом случае обратите внимание, что символы, введенные с помощью клавиатуры, передаются только программе, когда нажата клавиша ENTER(или RETURN). Как только инструкция с операцией извлечения cinбудет достигнута, программа будет ждать столько, сколько потребуется, пока не будет введен какой-либо ввод.

Операция извлечения cinиспользует тип переменной после>>оператора, чтобы определить, как он интерпретирует символы, считываемые с ввода; если это целое число, ожидаемый формат представляет собой серию цифр, если строка содержит последовательность символов и т. д.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// i/o example

#include <iostream>
using namespace std;

int main ()
{
  int i;
  cout << "Please enter an integer value: ";
  cin >> i;
  cout << "The value you entered is " << i;
  cout << " and its double is " << i*2 << ".\n";
  return 0;
}
Введите целочисленное значение: 702
Введенное вами значение - 702, а его двойное значение - 1404.

Как вы можете видеть, извлечение из них, cinпохоже, делает задачу ввода ввода из стандартного ввода довольно простым и понятным. Но этот метод также имеет большой недостаток. Что происходит в приведенном выше примере, если пользователь вводит что-то другое, которое невозможно интерпретировать как целое? В этом случае операция извлечения не выполняется. И это, по умолчанию, позволяет программе продолжить работу без установки значения переменной i, создавая неопределенные результаты, если значение iиспользуется позже.

Это очень плохое поведение программы. Ожидается, что большинство программ будут вести себя ожидаемым образом независимо от того, что пользователь вводит, обрабатывая неверные значения соответствующим образом. Только очень простые программы должны полагаться на значения, извлеченные непосредственно из cinбез дальнейшей проверки. Немного позже мы увидим, какstringstreams могут использоваться для лучшего контроля над пользовательским вводом.
Выделения cinмогут также быть закодированы, чтобы запросить более одного значения в одном заявлении:

cin >> a >> b;

Это эквивалентно:

1
2
cin >> a;
cin >> b;

В обоих случаях пользователь должен ввести два значения: одно для переменной aи другое для переменной b. Любой вид пространства используется для разделения двух последовательных операций ввода; это может быть либо пробел, либо вкладка, либо символ новой строки.

cin и strings

Оператор извлечения может использоваться cinдля получения строк символов так же, как и для основных типов данных:

1
2
string mystring;
cin >> mystring;

Однако cinизвлечение всегда учитывает пробелы (пробелы, вкладки, новые строки …) как завершение извлекаемого значения и, таким образом, извлечение строки означает всегда извлекать одно слово, а не фразу или целое предложение.

Чтобы получить всю строку cin, существует функция, вызываемая getline, которая принимает stream ( cin) как первый аргумент, а строковая переменная – как вторая. Например:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// cin with strings
#include <iostream>
#include <string>
using namespace std;

int main ()
{
  string mystr;
  cout << "What's your name? ";
  getline (cin, mystr);
  cout << "Hello " << mystr << ".\n";
  cout << "What is your favorite team? ";
  getline (cin, mystr);
  cout << "I like " << mystr << " too!\n";
  return 0;
}
Как вас зовут? Гомер Симпсон
Привет, Гомер Симпсон.
Какая твоя любимая команда? Изотопы
Мне тоже нравятся изотопы!

Обратите внимание, что в обоих вызовах getlineмы использовали один и тот же строковый идентификатор ( mystr). То, что программа делает во втором вызове, просто заменяет предыдущий контент на новый, который вводится.

Стандартное поведение, которое большинство пользователей ожидают от консольной программы, состоит в том, что каждый раз, когда программа запрашивает пользователя для ввода, пользователь вводит это поле, а затем нажимает ENTER(или RETURN). Другими словами, ввод, как правило, ожидается в терминах строк на консольных программах, и этого можно добиться, используя getlineдля получения ввода от пользователя. Поэтому, если у вас нет веской причины, вы всегда должны использовать getlineвходные данные в своих консольных программах вместо того, чтобы извлекать их cin.

stringstream

Стандартный заголовок <sstream>определяет вызываемый тип, stringstreamкоторый позволяет обрабатывать строку как поток и, таким образом, позволяет выполнять операции извлечения или вставки из строк в строку так же, как они выполняются cinи cout. Эта функция наиболее полезна для преобразования строк в числовые значения и наоборот. Например, чтобы извлечь целое число из строки, мы можем написать:

1
2
3
string mystr ("1204");
int myint;
stringstream(mystr) >> myint;

Это объявляет a stringс инициализированным значением "1204"и переменной типа int. Затем третья строка использует эту переменную для извлечения из stringstreamпостроенной из строки. Этот кусок кода хранит числовое значение 1204в вызываемой переменной myint.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// stringstreams
#include <iostream>
#include <string>
#include <sstream>
using namespace std;

int main ()
{
  string mystr;
  float price=0;
  int quantity=0;

  cout << "Enter price: ";
  getline (cin,mystr);
  stringstream(mystr) >> price;
  cout << "Enter quantity: ";
  getline (cin,mystr);
  stringstream(mystr) >> quantity;
  cout << "Total price: " << price*quantity << endl;
  return 0;
}
Ввод цен: 22.25
Введите количество: 7
Общая стоимость: 155.75

В этом примере мы косвенно получаем числовые значения из стандартного ввода : вместо непосредственного извлечения числовых значений cinмы получаем строки из него в строковый объект ( mystr), а затем извлекаем значения из этой строки в переменные priceи quantity. Как только это числовые значения, на них могут выполняться арифметические операции, такие как их умножение для получения общей цены.

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

Залишити відповідь