Какую библиотеку использовать для cin и cout в qt линукса

Обновлено: 07.07.2024

Этот раздел является переводом туториала C++ Language

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

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

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

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

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

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

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

Оператор << вставляет данные, которые следуют за ним, в поток, который предшествует ему. В примере выше, он вставляет строковый литерал Output sentence, число 120 и значение переменной x в стандартный поток вывода cout. Заметьте, что предложение в первом выражении заключено в двойные кавычки, потому что оно является строковым литералом, в отличие от x. Когда текст заключен в двойные кавычки, он печатается как литерал; если кавычек нет, текст интерпретируется как идентификатор переменной и вместо текста печатается значение переменной. Например, такие два выражения приведут к совершенно различным результатам:

Можно использовать несколько операций вставки в одном выражении:

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

Допустим, переменная age содержит значение 24, а переменная zipcode содержит 90064, результатом предыдущего выражения будет:

I am 24 years old and my zipcode is 90064

Чего не делает cout автоматически - не добавляет разрывы строк в конце выражения, если это не указано. Например, возьмем следующие два выражения, вставляемые в cout:

cout << "This is a sentence.";
cout << "This is another sentence.";

Вывод будет представлять одну строку без каких-либо разделителей. Что-то вроде:

This is a sentence.This is another sentence.

Чтобы вставить разрыв строки, символ новой строки должен быть вставлен точно в ту позицию, в которой должна быть разбита строка. В C++ символ новой строки может быть указан как \n (т.e. символ обратной косой черты, за которым следует строчная n). Например:

Результатом будет следующий вывод:

First sentence.
Second sentence.
Third sentence.

Также для разрыва строки можно использовать манипулятор endl. Например:

First sentence.
Second sentence.

Манипулятор endl создает символ новой строки, что эквивалентно вставке символа '\n', однако он имеет дополнительное поведение: буфер потока (если таковой имеется) очищается, что означает, что вывод запрашивает физическую запись на устройство, если ее еще не было. Это затрагивает в основном полностью буферизованные потоки, а cout (в общем случае) не является полностью буферизованным потоком. Тем не менее, вообще-то неплохо использовать endl только тогда, когда очистка потока необходима, а '\n' в противном случае. Операция очистки приводит к определенным накладным расходам и на некоторых устройствах это может вызвать задержку.

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

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

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

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

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

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

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

Извлечением из cin можно запрашивать более одного элемента в одном выражении:

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

cin и строки

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

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

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

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

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

stringstream

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

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

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

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

Поточный ввод-вывод в C++ выполняется с помощью функций сторонних библиотек. В С++, как и в С, нет встроенных в язык средств ввода-вывода.

В С для этих целей используется библиотека stdio.h .
В С++ разработана новая библиотека ввода-вывода iostream , использующая концепцию объектно-ориентированного программирования:

Библиотека iostream определяет три стандартных потока:

Для их использования в Microsoft Visual Studio необходимо прописать строку:

Для выполнения операций ввода-вывода переопределены две операции поразрядного сдвига:

  • >> получить из входного потока
  • << поместить в выходной поток

Вывод информации

cout << значение;

Здесь значение преобразуется в последовательность символов и выводится в выходной поток:

Возможно многократное назначение потоков:
cout << 'значение1' << 'значение2' << . << 'значение n';

int n;
char j;
cin >> n >> j;
cout << "Значение n равно" << n << "j=" << j;

Ввод информации

cin >> идентификатор;

При этом из входного потока читается последовательность символов до пробела, затем эта последовательность преобразуется к типу идентификатора, и получаемое значение помещается в идентификатор:

Возможно многократное назначение потоков:
cin >> переменная1 >> переменная2 >>. >> переменнаяn;

При наборе данных на клавиатуре значения для такого оператора должны быть разделены символами (пробел, \n, \t ).

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

Для ввода текста до символа перевода строки используется манипулятор потока getline() :

Манипуляторы потока

Функцию - манипулятор потока можно включать в операции помещения в поток и извлечения из потока (<<, >>).

В С++ имеется ряд манипуляторов. Рассмотрим основные:

Пример Программа ввода-вывода значения переменной в C++

Та же программа, написанная на языке Си

Пример Использование форматированного вывода

Еще один пример использования форматированного вывода: для t∈[0;3] с шагом 0,5 вычислить значение y=cos(t).

Являясь студентом, постоянно пишу на C++. До этого использовал MinGW под Windows, но недавно решил вернуться на Arch, в связи с чем логично стал использовать gcc.

Раньше для вывода я просто использовал std::wcout, вызывая при этом setlocale(LC_ALL, "Russian") в начале программы и предваряя все строковые литералы буквой "L".
Всё прекрасно работало, как вывод русского текста, так и вывод чего-либо ещё.

Но сейчас, на Linux'е, я столкнулся с двумя проблемами:
1) Русский текст выводится вопросительными знаками. При том, что в системе установлена локаль ru_RU.UTF-8 и консоль поддерживает вывод русских букв;
2) По окончанию программы выводится какой-то мусор, выглядящий как символ % на сером фоне. Лечится с помощью cout << endl, но всё равно непонятно, откуда он берётся.

Подскажите, пожалуйста, как решить первую проблему и в чём причина второй?

Что за текст? Он, часом, не достался в наследство от винды и не пребывает в какой-нибудь cp1251?

По окончанию программы выводится какой-то мусор, выглядящий как символ % на сером фоне
Аналогично - не остался ли там в наследство от винды какой-нибудь '\r'?
в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик
Никак нет.
Вывожу строковый литерал либо строку считанную со входного потока.
Строковый литерал впечатан в исходный код, который набран в текстовом редакторе в самом Arch'е в UTF-8.

// Arch, ru_RU.UTF-8, edited in nano, pocessed in xfce4-terminal :

$ c++ first.cpp -o first.exe
$ ./first.exe
Программирование
$

Опа, действительно.
Я писал std::wcout << L"кириллица", а не как Вы. Написал как у Вас - действительно, работает.
Любопытно, Вы не объясните, почему?
Ведь текст всё же в UTF-8, стало быть выводить его нужно в соответствующий поток, нет?

Вообще, это несколько неожиданно для меня, попробовал сейчас следующее:


- работает!
Но разве обычный char пригоден для хранения символов в UTF-8. UPD
С "мусором" разобрался, выведя cat'ом исходный текст программы и заметив в конце вывода то же самое. Сменил zsh на дефолтный bash - исчезло.
Очевидно, какая-то ерунда с конфигурацией zsh. :\ . Раньше для вывода я просто использовал std::wcout, вызывая при этом setlocale(LC_ALL, "Russian") в начале программы.
Указывать следует либо корректную локаль (например, "ru_RU.UTF8"), либо пустую строку для автоопределения. Несуществующие локали, вроде вашей, формально приводят к неопределённому поведению, на практике работают как синоним "C".
Правильный код (только ключевые строки):
Но разве обычный char пригоден для хранения символов в UTF-8.

Символов - нет. Байтов - да. Если так делать, то один символ может занять больше одного байта. И кстати, не путайте UTF-8 и Unicode.

Строки вида L"" хранят данные в каком-либо внутреннем представлении юникода, обычно UCS2 или UCS4, а wcout перекодирует текст в установленную локалью кодировку (возможно, UTF-8, а возможно, что-то однобайтовое).

Строки вида "" хранят набор байтов (NUL-terminated), в той кодировке, в которой они были введены в исходниках. cout выводит их без перекодирования и не оглядываясь на локаль. Если кодировка исходников и кодировка терминала совпадают, вывод будет правильным. Иначе - нет.

UPD
С "мусором" разобрался, выведя cat'ом исходный текст программы и заметив в конце вывода то же самое. Сменил zsh на дефолтный bash - исчезло.
Очевидно, какая-то ерунда с конфигурацией zsh. :\
zsh так уведомляет пользователя, что запущенная программа вывела незавершённую строку (без "\n" в конце). Для удобства. Поправлю, что L"" и std::wcout работают с wide-char — wchar_t — для windows это обычно 2 байта и UCS2 (до Win2000 включительно) или UTF-16 (WinXP+), для Linux — 4 байта и UTF-32. Указывать следует либо корректную локаль (например, "ru_RU.UTF8"), либо пустую строку для автоопределения.

В смысле, в Linux? Или вообще?
Поскольку, когда я компилировал свой код в Windows, я поначалу тоже полагал, что нужно передать что-то вроде "utf-8", а оказалось, что рабочим является именно тот вариант, что я привёл.

И я правильно, понял, что вариант, приведённый Женей, хоть и является рабочим, но, вообще говоря, не является "хорошим", поскольку слабо переносим, да и вообще не гарантирует корректного вывода?

Указывать следует либо корректную локаль (например, "ru_RU.UTF8"), либо пустую строку для автоопределения.
В смысле, в Linux? Или вообще?
Поскольку, когда я компилировал свой код в Windows, я поначалу тоже полагал, что нужно передать что-то вроде "utf-8", а оказалось, что рабочим является именно тот вариант, что я привёл.

Пример относится к Linux (точнее, к GNU, т.к. ядро тут ни при чём), а всё остальное - к стандарту. Набор локалей в каждой системе может быть свой. Единственный надёжный вариант - использовать автоопределение.

И я правильно, понял, что вариант, приведённый Женей, хоть и является рабочим, но, вообще говоря, не является "хорошим", поскольку слабо переносим, да и вообще не гарантирует корректного вывода?
Да, он будет работать только если кодировка исходников и кодировка терминала совпадают. Лучше делать так, как я написал. А ещё лучше - использовать что-нибудь вроде gettext для многоязычности (в исходнике всё на английском, а переводы берутся из отдельных файлов). Выбор между "быстро" и "хорошо" - за вами. недавно решил вернуться на Arch, в связи с чем логично стал использовать gcc.

"в связи с чем логично использовать" . Clang

Но разве обычный char пригоден для хранения символов в UTF-8.

"обычный char" замечательно пригоден для хранения символов UTF-8 . и не только для хранения, но и для ввода, и для вывода . и не только UTF-8, а и UTF-16, и UTF-32, если захотите. - обычный char тупо хранит численные значения байт за байтом.

Но обычный char абсолютно непригоден для операций с контекстом строки: поиск, замещение и т.д. . начиная с простейшей strlen() которая станет врать

И вот тут у вас есть на выбор 2-альтернативы (для хранения):

- использовать "широкие" символы wchar_t, которые являются (по POSIX) прямым изображением UNICODE кодировки UTF-32, и, естественно, каждый символ занимает 4 байта; для них есть все эквиваленты строчных функций: strchr() -> wcschr() и т.д. + операции: wcout << . , wcin >> .

- многобайтные представления, которые хоть и загружены в char[], но содержимое представлено именно в кодировке UTF-8 (т.е. тоже UNICODE, но в другой кодировке); они непригодны для непосредственной обработки строковыми функциями, но для них есть функции преобразований (mbtowc(), wctomb(), mblen(), mbrtowc(), wcrtomb(), mbrlen() и т.д.), для преобразования в wchat_t[] и обратно.

В этом уроке мы подробнее поговорим о std::cout , который мы использовали в нашей программе «Hello world!» для вывода в консоль текста «Hello world!». А также узнаем, как получить данные от пользователя, которые мы будем использовать, чтобы сделать наши программы более интерактивными.

Библиотека ввода/вывода

Библиотека ввода/вывода (библиотека io) является частью стандартной библиотеки C++, которая имеет дело с базовым вводом и выводом. Мы будем использовать функции этой библиотеки для получения ввода с клавиатуры и вывода данных в консоль. Буквы io в iostream означают «input/output» (ввод/вывод).

Чтобы использовать функции, определенные в библиотеке iostream , нам нужно включить заголовочный файл iostream в начало любого исходного файла, который использует содержимое, определенное в iostream , например:

std::cout

Библиотека iostream содержит несколько предопределенных переменных, которые мы можем использовать. Одной из наиболее полезных является std::cout , которая позволяет нам отправлять данные в консоль для печати в виде текста. cout означает «character output» (вывод символов).

Вспомним нашу программу Hello world :

В эту программу мы включили iostream , чтобы у нас был доступ к std::cout . Внутри нашей функции main() мы используем std::cout вместе с оператором вставки ( << ) для отправки текста « Hello world! » в консоль для печати.

std::cout может печатать не только текст, но и числа:

Это дает результат:

Его также можно использовать для вывода значений переменных:

Это дает результат:

Чтобы напечатать несколько элементов в одной строке, для объединения (связывания) нескольких частей выводимых данных, оператор вставки ( << ) можно использовать несколько раз в одном выражении. Например:

Эта программа печатает:

Вот еще один пример, в котором мы печатаем и текст, и значение переменной в одном выражении:

Эта программа печатает:

std::endl

Как вы думаете, что напечатает следующая программа?

Результат может вас удивить:

Отдельные выражения вывода не приводят к отдельным выводимым строкам в консоли.

Если мы хотим выводить в консоль отдельные выводимые строки, нам нужно указать консоли, когда необходимо переместить курсор на следующую строку.

Один из способов сделать это – использовать std::endl . При выводе с помощью std::cout , std::endl выводит в консоль символ новой строки (заставляя курсор переместиться в начало следующей строки). В этом контексте endl означает «end line» (конец строки).

Совет

В приведенной выше программе второй std::endl технически не нужен, так как программа сразу же после этого завершается. Однако он служит двум полезным целям: во-первых, он помогает указать, что строка вывода является «законченной мыслью». Во-вторых, если мы позже захотим добавить дополнительные выражения вывода, нам не нужно будет изменять существующий код. Мы можем просто добавить новые выражения.

Использование std::endl может быть немного неэффективным, поскольку фактически выполняет две задачи: перемещает курсор на следующую строку и «очищает» вывод (обеспечивает немедленное отображение на экране). При записи текста в консоль с использованием std::cout , std::cout обычно всё равно очищает вывод (а если нет, это обычно не имеет значения), поэтому наличие очистки от std::endl редко бывает важным.

Этот код напечатает:

Лучшая практика

Предупреждение

std::cin

std::cin – еще одна предопределенная переменная, определенная в библиотеке iostream . В то время как std::cout выводит данные в консоль с помощью оператора вставки ( << ), std::cin (что означает «character input», «ввод символов») считывает ввод с клавиатуры с помощью оператора извлечения ( >> ). Для дальнейшего использования входные данные должны быть сохранены в переменной.

Попробуйте скомпилировать эту программу и запустить ее самостоятельно. Когда вы запустите программу, строка 6 напечатает «Enter a number: ». Когда код дойдет до строки 10, ваша программа будет ждать, пока вы введете данные. После того, как вы введете число (и нажмете клавишу Enter ), введенное вами число будет присвоено переменной x . Наконец, в строке 11 программа напечатает «You entered », а затем число, которое вы только что ввели.

Например (я ввел 4):

Если ваш экран закрывается сразу после ввода числа, обратитесь к уроку «0.8 – Несколько основных проблем C++» для решения этой проблем.

Лучшая практика

Существуют споры о том, нужно ли инициализировать переменную непосредственно перед тем, как передать ей значение, предоставленное пользователем, через другой источник (например, std::cin ), поскольку значение, предоставленное пользователем, просто перезапишет значение инициализации. В соответствии с нашей предыдущей рекомендацией о том, что переменные всегда следует инициализировать, лучше всего сначала инициализировать переменную.

Мы обсудим, как std::cin обрабатывает недопустимые входные данные в следующем уроке (7.16 – std::cin и обработка недопустимых входных данных).

Для продвинутых читателей

Библиотека ввода/вывода C++ не позволяет принимать ввод с клавиатуры без нажатия пользователем клавиши Enter . Но если вам это нужно, то вам придется использовать стороннюю библиотеку. Для консольных приложений мы рекомендуем библиотеку pdcurses. Многие графические пользовательские библиотеки имеют для этого свои собственные функции.

Резюме

Программисты-новички часто путают std::cin , std::cout , оператор вставки ( << ) и оператор извлечения ( >> ). Вот простой способ запомнить:

  • std::cin и std::cout всегда идут в левой части выражения;
  • std::cout используется для вывода значения (cout = character output);
  • std::cin используется для получения входного значения (cin = character input);
  • << используется с std::cout и показывает направление движения данных (если std::cout представляет консоль, выходные данные перемещаются из переменной в консоль). std::cout << 4 перемещает значение 4 в консоль;
  • >> используется с std::cin и показывает направление движения данных (если std::cin представляет клавиатуру, входные данные перемещаются с клавиатуры в переменную). std::cin >> x перемещает значение, введенное пользователем с клавиатуры, в x .

Небольшой тест

Вопрос 1

Рассмотрим следующую программу, которую мы использовали выше:

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

Запустите эту программу несколько раз и опишите, что произойдет, если вместо этого вы введете следующие типы входных данных:

а) Буква, например, h .

б) Число с дробной частью. Попробуйте числа с дробными составляющими меньше 0,5 и больше 0,5 (например, 3,2 и 3,7).

Дробная составляющая опущена.

в) Небольшое отрицательное целое число, например -3.

Всё прекрасно работает.

г) Слово, например «Hello».

д) Действительно большое число (минимум 3 миллиарда).

Вы получаете, казалось бы, случайное число.

Последнее предложение может быть особенно неожиданным. Попробуйте! Это происходит потому, что x может содержать числа только до определенного размера. После этого он «переполняется». Мы обсудим переполнение в следующем уроке.

Читайте также: