Скачать презентацию Ввод вывод и файлы Для реализации операций ввода-вывода Скачать презентацию Ввод вывод и файлы Для реализации операций ввода-вывода

Ввод, вывод.ppt

  • Количество слайдов: 119

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

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

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

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

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

Потоки, буферы и файл iostream Включение заголовочного файла iostream (бывшего iostream. h) предоставляет в Потоки, буферы и файл iostream Включение заголовочного файла iostream (бывшего iostream. h) предоставляет в ваше распоряжение несколько классов, предназначенных для реализации и управления потоками и буферами. Ввод-вывод в С++98 определяет шаблоны классов для поддержки как данных char, так и данных wchar_t. Ввод-вывод в С++11 добавляет специализации charl 6_t и char 32_t. Используя средство typedef, C++ делает специализацию char этих шаблонов подобной традиционным, нешаблонным реализациям ввода-вывода.

 • Класс streambuf предоставляет память для буфера, а также и методы для его • Класс streambuf предоставляет память для буфера, а также и методы для его заполнения, доступа к содержимому, очистки буфера и управления памятью буфера. • Класс ios_base представляет общие свойства потока, такие как признак того, открыт ли поток для чтения, и является он бинарным или текстовым. • Класс ios базируется на ios_base и включает член-указатель на объект класса streambuf. • Класс ostream является производным от ios и предоставляет методы вывода. • Класс istream является производным от ios и предоставляет методы ввода. • Класс iostream базируется на классах istream и ostream и потому наследует как методы ввода, так и методы вывода.

Включение в программу файла iostream автоматически создает восемь потоковых объектов • Объект сіn соответствует Включение в программу файла iostream автоматически создает восемь потоковых объектов • Объект сіn соответствует стандартному потоку ввода. По умолчанию этот поток ассоциируется со стандартным устройством ввода — обычно клавиатурой. Объект wcin работает с типом wchar_t. • Объект cout соответствует стандартному потоку вывода. По умолчанию этот поток ассоциируется со стандартным устройством вывода — обычно монитором. Объект wcout работает с символами типа wchar_t. • Объект сегг соответствует стандартному потоку ошибок, который можно использовать для отображения сообщений об ошибках. По умолчанию этот поток ассоциируется со стандартным устройством вывода — обычно монитором — и данный поток не буферизуется. Объект wcerr работает с типом wchar_t. • Объект clog также соответствует стандартному потоку ошибок. По умолчанию этот поток ассоциируется со стандартным устройством вывода — обычно монитором

Когда в файле iostream объявляется объект cout для программы, этот объект получает члены данных, Когда в файле iostream объявляется объект cout для программы, этот объект получает члены данных, содержащие информацию относительно вывода: • ширина поля для отображения данных, • количество знаков после десятичной точки, • основание системы счисления для отображения целочисленных данных • адрес объекта streambuf, описывающего буфер, который используется выходным потоком. Оператор, подобный показанному ниже, помещает символы из строки "Bjarne free" в управляемый объектом cout буфер посредством указанного объекта streambuf: cout « "Bjarne free"; Класс ostream определяет функцию operator<< (), используемую в этом операторе, а также поддерживает данные-члены cout с множеством других методов класса Вывод из буфера направляется в стандартный вывод — обычно монитор — предоставленный операционной системой.

Вывод с помощью cout Одной из наиболее важных задач, стоящих перед классом оstream, является Вывод с помощью cout Одной из наиболее важных задач, стоящих перед классом оstream, является преобразование числовых типов, таких как int или float, в поток символов, который представляет значения в текстовой форме. Таким образом, класс ostream транслирует внутреннее представление данных в виде двоичных битовых последовательностей в выходной поток символьных байтов. Для выполнения такой трансляции в классе ostream предусмотрено несколько методов.

Перегруженная операция вставки << Операция вставки перегружена для применения со всеми базовыми типами C++: Перегруженная операция вставки << Операция вставки перегружена для применения со всеми базовыми типами C++: • unsigned char • short • unsigned short • int • unsigned int • long • unsigned long • long (C++11) • unsigned long (C++11) • float • double • long double

Например, выражение cout << 88 соответствует следующему прототипу метода: ostream & operator<<(int) ; Такой Например, выражение cout << 88 соответствует следующему прототипу метода: ostream & operator<<(int) ; Такой прототип указывает, что функция operator<<() принимает один аргумент типа int. Это соответствует параметру 88 в предыдущем операторе. Прототип указывает также, что функция возвращает ссылку на объект ostream. Это свойство позволяет группировать вывод, как показано в следующем примере: cout << "I'm feeling sedimental over " << boundary << "n";

Класс ostream определяет функции операции вставки для следующих типов указателей: • const signed char Класс ostream определяет функции операции вставки для следующих типов указателей: • const signed char * • const unsigned char * • const char * • void * Все следующие операторы с cout отображают строки: char name[20] = "Dudly Diddlemore"; char * pn = "Violet D'Amore"; cout « "Hello!"; cout « name; cout « pn;

C++ интерпретирует указатель любого другого типа как void * и выводит числовое представление адреса. C++ интерпретирует указатель любого другого типа как void * и выводит числовое представление адреса. Если требуется получить адрес строки, необходимо выполнить приведение к другому типу: int eggs = 12; char * amount = "dozen"; cout << &eggs; // выводит адрес переменной eggs cout << amount; // выводит строку "dozen" cout << (void *) amount; // выводит адрес строки "dozen"

Другие методы ostream Класс ostream предоставляет метод put() для отображения символов и метод write() Другие методы ostream Класс ostream предоставляет метод put() для отображения символов и метод write() для отображения строк. Метод put() имел следующий прототип: ostream & put(char); cout. put(‘W’) ; // отображение символа W cout. put('I'). put('t'); // отображение строки //It с помощью двух вызовов функции put() cout. put(65); // отображает символ А cout. put(66. 3) ; // отображает символ В

Метод write() записывает целую строку и имеет следующий шаблонный прототип: basic_ostream<char. T, traits>&write(const char_type* Метод write() записывает целую строку и имеет следующий шаблонный прототип: basic_ostream&write(const char_type* s, streamsize n) ; for (i = 1; i <= len; i + + ) { cout. write (state 2, i); cout « endl; }

Метод write () можно также использовать с числовыми данными. В этом случае ему нужно Метод write () можно также использовать с числовыми данными. В этом случае ему нужно передать адрес числа, приведя его тип к char *: long val = 560031841; cout. write ( (char *) &val, sizeof (long)); Это не ведет к трансляции числа в корректные символы; вместо этого такой вызов передает битовое представление хранящихся в памяти данных. Однако write() обеспечивает компактный, аккуратный способ сохранения числовых данных в файле.

Очистка выходного буфера Поскольку буфер класса ostream управляется объектом cout, вывод не отправляется по Очистка выходного буфера Поскольку буфер класса ostream управляется объектом cout, вывод не отправляется по назначению немедленно. Вместо этого он накапливается в буфере до тех пор, пока не заполнит его. Затем программа очищает буфер, отправляя его содержимое по назначению и освобождая буфер для приема новых данных. Как правило, размер буфера составляет 512 байт или же кратное этому значению число.

В случае экранного вывода программе не обязательно дожидаться заполнения буфера. Например, отправка символа перевода В случае экранного вывода программе не обязательно дожидаться заполнения буфера. Например, отправка символа перевода строки обычно ведет к очистке буфера. Кроме того большинство реализаций C++ очищают буфер, когда ожидается ввод. Предположим, что имеется следующий код: cout « "Enter a number: "; // вывод приглашения на ввод числа float num; cin » num; Тот факт, что программа ожидает ввода, заставляет ее отобразить сообщение cout (т. е. очистить буфер от сообщения "Enter a number: ") немедленно, даже несмотря на то, что строка вывода не содержит символа новой строки. Не будь этой функциональной особенности, программе пришлось бы ожидать ввода, не выдав пользователю приглашения на ввод посредством сообщения cout.

Если используемая реализация не очищает буфер вывода, когда требуется, это можно сделать принудительно с Если используемая реализация не очищает буфер вывода, когда требуется, это можно сделать принудительно с помощью одного из двух манипуляторов. Манипулятор flush просто очищает буфер, а манипулятор endl очищает буфер и вставляет символ перевода строки. Эти манипуляторы применяются так же, как имена переменных: cout « "Hello, good-looking! " « flush; cout « "Wait just a moment, please. " « endl; Фактически манипуляторы являются функциями. Например, буфер cout можно очистить, вызвав функцию flush() непосредственно: flush(cout); Однако класс ostream перегружает операцию << так, что следующее выражение замещается вызовом функции flush(cout): cout « flush

Форматирование с помощью cout Операции вставки в ostream преобразуют значения в текстовую форму. По Форматирование с помощью cout Операции вставки в ostream преобразуют значения в текстовую форму. По умолчанию они форматируют значения следующим образом. • Значение типа char, если оно представляет печатаемый символ, отображается как символ в поле шириной в один символ. • Целочисленные типы отображаются как десятичные целые в поле с шириной, достаточной для отображения числа и знака минус (если таковой присутствует). • Строки отображаются в поле ширины, равной длине строки.

Поведение по умолчанию для отображения чисел с плавающей точкой изменилось. • Новый стиль. Типы Поведение по умолчанию для отображения чисел с плавающей точкой изменилось. • Новый стиль. Типы с плавающей точкой отображаются в поле общей шириной в шесть разрядов, за исключением завершающих нулей, которые не отображаются. Число отображается либо в форме записи с фиксированной точкой, либо в экспоненциальной форме записи, в зависимости от значения числа. В частности, экспоненциальная запись используется, если порядок равен 6 или больше либо равен -5 или меньше. Ширина поля выбирается такой, чтобы вместить все цифры и знак минус, если он присутствует. Поведение по умолчанию соответствует использованию функции fprintf() из стандартной библиотеки С со спецификатором %g.

 • Старый стиль. Типы с плавающей точкой отображаются в виде значений с шестью • Старый стиль. Типы с плавающей точкой отображаются в виде значений с шестью разрядами после десятичной точки, за исключением завершающих нулей, которые не отображаются. Число отображается либо в форме записи с фиксированной точкой, либо в экспоненциальной форме записи в зависимости от значения числа. Ширина поля выбирается такой, чтобы вместить все цифры и знак минус, если он присутствует.

Изменение основания системы счисления Класс ostream унаследован от класса ios, который, в свою очередь, Изменение основания системы счисления Класс ostream унаследован от класса ios, который, в свою очередь, унаследован от ios_base. Класс ios_base хранит информацию, описывающую состояние формата. Например, определенные биты в одном члене класса определяют используемое основание системы счисления, в то время как другие — ширину поля. Применяя манипуляторы, можно управлять основанием системы счисления, используемым для отображения целочисленных значений. С помощью функций-членов ios_base можно управлять шириной поля и количеством знаков после запятой.

Следующий вызов функции устанавливает для объекта cout шестнадцатеричную систему счисления: hex(cout); После этого программа Следующий вызов функции устанавливает для объекта cout шестнадцатеричную систему счисления: hex(cout); После этого программа будет выводить целые значения в шестнадцатеричной форме до тех пор, пока не будет установлено другое основание. Хотя в действительности манипуляторы являются функциями, обычно их используют следующим образом: cout « hex; cout « oct; cout « dec;

Настройка ширины полей Для размещения чисел различной длины в полях постоянной ширины можно воспользоваться Настройка ширины полей Для размещения чисел различной длины в полях постоянной ширины можно воспользоваться функцией-членом width. Этот метод имеет следующие прототипы: int width(); int width(int i) ; Первая форма возвращает текущую установку ширины поля. Вторая устанавливает ширину поля равной і пробелам и возвращает предыдущее значение ширины.

cout « '#'; cout. width(12); cout << 12 << cout « '#'; cout. width(12); cout << 12 << "#" << 24 << "#n"; Оператор вывода создает следующую строку вывода: # 12#24# Значение 12 помещается у правого края поля шириной в 12 символов. Это называется выравниванием по правому краю. После этого ширина поля возвращается в значение по умолчанию, и два символа # и значение 2 4 выводятся в полях, ширина которых равна длине этих элементов вывода.

Символы-заполнители По умолчанию cout заполняет неиспользуемые части поля пробелами. Для изменения этого можно воспользоваться Символы-заполнители По умолчанию cout заполняет неиспользуемые части поля пробелами. Для изменения этого можно воспользоваться функцией-членом fill(). Например, следующий вызов изменяет символ-заполнитель на звездочку: cout. fill(‘*’); В отличие от ширины поля, новый символзаполнитель остается в действии до тех пор, пока он не будет заменен.

Установка точности отображения чисел с плавающей точкой Смысл точности чисел плавающей точкой зависит от Установка точности отображения чисел с плавающей точкой Смысл точности чисел плавающей точкой зависит от режима вывода. В режиме по умолчанию она означает общее количество отображаемых разрядов. Точность по умолчанию, применяемая в C++ равна 6. (Но завершающие нули отбрасываются. ) Функция-член precision() позволяет выбрать другие значения. Например, следующий оператор устанавливает точность вывода cout в 2: cout. precision(2);

Вывод завершающих нулей и десятичных точек Класс ios_base предоставляет функцию setf () (т. е. Вывод завершающих нулей и десятичных точек Класс ios_base предоставляет функцию setf () (т. е. set flag), управляющую некоторыми средствами форматирования. Этот класс также определяет несколько констант, которые могут использоваться в качестве аргументов этой функции. Например, следующий вызов функции вынуждает cout отображать завершающие десятичные точки: cout. setf(ios_base: : showpoint);

В формате с плавающей точкой, используемом по умолчанию, это также обеспечивает отображение завершающих нулей. В формате с плавающей точкой, используемом по умолчанию, это также обеспечивает отображение завершающих нулей. То есть вместо отображения значения 2. 00 в виде 2, cout будет его отображать как 2. 00000, если по умолчанию действует точность равная 6.

Дополнительные сведения о setf() Класс ios_base имеет защищенный член данных, в котором отдельные биты Дополнительные сведения о setf() Класс ios_base имеет защищенный член данных, в котором отдельные биты (в данном контексте — флаги) управляют различными аспектами форматирования, такими как основание системы счисления и признак необходимости отображения завершающих нулей. Включение флага называется установкой флага (или бита) и означает установку его значения в 1.

Константы форматирования ios_base: : boolalpha Ввод и вывод значений типа bool, таких как true Константы форматирования ios_base: : boolalpha Ввод и вывод значений типа bool, таких как true и false iosbase: : showbase Использование при выводе префиксов основания C++ (0, 0 х) iosbase: : showpoint Отображение завершающей десятичной точки iosbase: : uppercase Использование прописных букв для шестнадцатеричного вывода и экспоненциальной записи iosbase: : showpos Использование символа + перед положительными числами

cout << cout << "Today's water temperature: "; cout. setf(ios_base: : showpos); // показывать знак плюс cout << temperature << endl; cout << "For our programming friends, that'sn"; cout << hex << temperature << endl; // использование //шестнадцатеричного представления cout. setf(ios_base: : uppercase); // применение прописных // символов в шестнадцатеричном представлении cout. setf(ios_base: : showbase); // использование префикса // ОХ для шестнадцатеричных значений cout « "orn"; cout << temperature << endl; cout « "How " « true « " ! oops — How "; cout. setf(ios_base: : boolalpha); cout « true « " !n" ;

Today's water temperature: +63 For our programming friends, that's 3 f or 0 X Today's water temperature: +63 For our programming friends, that's 3 f or 0 X 3 F How 0 X 1! oops — How true!

Аргументы функции setf (long, long) Аргументы функции setf (long, long)

// Использовать выравнивание влево, показать знак плюс, показать завершающие нули с точностью, равной 3 // Использовать выравнивание влево, показать знак плюс, показать завершающие нули с точностью, равной 3 cout. setf(ios_base: : left, ios_base: radjustfield); cout. setf(ios_base: : showpos); cout. setf(ios_base: : showpoint); cout. precision (3); // Использовать экспоненциальную запись и сохранить старые установки формата ios_base: : fmtflags old = cout. setf (ios_base: : scientific, ios_base: : floatfield);

// Переключиться на внутреннее выравнивание cout. setf(ios_base: : internal, ios_base: radjustfield); // Восстановить стиль // Переключиться на внутреннее выравнивание cout. setf(ios_base: : internal, ios_base: radjustfield); // Восстановить стиль отображения значений с плавающей точкой, заданный по умолчанию cout. setf(old, ios_base: : floatfield); // Использовать выравнивание по правому краю и форму записи с фиксированной точкой cout. setf(ios_base: : right, ios_base: : adjustfield); cout. setf(ios_base: : fixed, ios_base: : floatfield);

Стандартные манипуляторы cout « left « fixed; Стандартные манипуляторы cout « left « fixed;

Заголовочный файл iomanip При установке некоторых значения форматирования, таких как ширина поля, использовать средства Заголовочный файл iomanip При установке некоторых значения форматирования, таких как ширина поля, использовать средства ios t re am неудобно. Для упрощения задачи C++ предлагает дополнительные манипуляторы в заголовочном файле iomanip.

Три наиболее часто используемые из них функции — это setprecision() для установки точности, setfill() Три наиболее часто используемые из них функции — это setprecision() для установки точности, setfill() для установки символа-заполнителя setw() для установки ширины поля. В отличие от ранее рассмотренных манипуляторов, эти принимают аргументы. Манипулятор setprecision() принимает целочисленный аргумент, задающий точность, setfill() принимает аргумент типа char, указывающий символ-заполнитель, a setw() принимает целочисленный аргумент, устанавливающий ширину поля.

#include <cmath> #include <iostream> #include <iomanip> int main () { using namespace std; cout #include #include #include int main () { using namespace std; cout << fixed << right; // Использование новых стандартных манипуляторов cout << setw(6) << "N" <

Ввод с помощью сіn Объект сіn представляет стандартный ввод в виде потока байтов. Обычно Ввод с помощью сіn Объект сіn представляет стандартный ввод в виде потока байтов. Обычно этот поток символов генерируется клавиатурой. При вводе последовательности символов 2011 объект сіn извлекает эти символы из входного потока. Этот ввод может являться частью строки, значением типа int, типа float или какого-либо иного типа. Таким образом, извлечение символов из потока предполагает также преобразование типа. Объект сіn на основании типа переменной, предназначенной для приема значения, должен применять свои методы для преобразования последовательности символов в значения соответствующего типа.

Обычно сіп используют следующим образом: cin » value_holder; Здесь value_holder идентифицирует область памяти, в Обычно сіп используют следующим образом: cin » value_holder; Здесь value_holder идентифицирует область памяти, в которую помещается ввод. Это может быть именем переменной, ссылкой, разыменованным указателем либо членом структуры или класса. То, как сin интерпретирует ввод, зависит от типа данных value_holder. Класс istream, определенный в заголовочном файле iostream, перегружает операцию извлечения >> для распознавания следующих базовых типов:

 • signed char & • unsigned char & • short & • unsigned • signed char & • unsigned char & • short & • unsigned short & • int & • unsigned int & • long & • unsigned long & • long & (C++11) • unsigned long & (C++11) • float & • double & • long double & Их называют функциями форматированного ввода, потому что они преобразуют входные данные в соответствии с переменной назначения.

Типичная функция операции имеет прототип следующего вида: istream & operator» (int &) ; И Типичная функция операции имеет прототип следующего вида: istream & operator» (int &) ; И аргумент, и возвращаемое значение являются ссылками. При наличии аргумента-ссылки (см. главу 8) оператор, подобный показанному ниже, вынуждает функцию operator>> () работать с самой переменной staf f_size, а не с ее копией, как это имеет место при использовании обычного аргумента: сіn » staff_size; Поскольку тип аргумента является ссылкой, сіn в состоянии непосредственно модифицировать значение переменной, применяемой в качестве

Предположим, что staf f_size имеет тип int. В этом случае компилятор сопоставляет сіn » Предположим, что staf f_size имеет тип int. В этом случае компилятор сопоставляет сіn » staff_size; со следующим прототипом: istream & operator>>(int &) ; Затем функция, соответствующая прототипу, считывает поток символов, отправляемый программе — например, символы 2, 3, 1, 8 и 4. Для систем, использующих двухбайтный тип int, функция преобразует эти символы в двухбайтное двоичное представление целочисленного значения 23184. С другой стороны, если бы переменная staff_size имела тип double, объект сіn использовал бы operator>> (double &), чтобы преобразовать этот же ввод в восьмибайтное представление значения с плавающей точкой 23184. 0.

Вместе с сіn можно применять манипуляторы hex, oct и dec для указания того, что Вместе с сіn можно применять манипуляторы hex, oct и dec для указания того, что вводимое целое должно интерпретироваться в шестнадцатеричном, восьмеричном или десятичном формате. Например, следующий оператор приводит к тому, что ввод 12 или 0 x 12 воспринимается как шестнадцатеричное значение 12, или десятичное 18, a ff или FF считывается как десятичное 255: cin >> hex;

Класс istream также перегружает операцию извлечения >> для типов указателей на символы: • signed Класс istream также перегружает операцию извлечения >> для типов указателей на символы: • signed char * • unsigned char * Для аргументов этих типов операция извлечения считывает следующее слово из входного потока и помещает его по указанному адресу, добавляя нулевой символ для ограничения строки.

Предположим, что имеется следующий код: // Вывод приглашения на ввод имени cout « Предположим, что имеется следующий код: // Вывод приглашения на ввод имени cout « "Enter your first name: n"; char name[20] ; // Ввод имени cin » name; Если вы ответите на запрос вводом Liz, то операция извлечения поместит символы Liz в массив name. Идентификатор name, будучи именем массива типа char, действует как адрес первого элемента массива и имеет тип char * (указатель на массив типа char).

Каждая операция извлечения возвращает ссылку на вызывающий объект, позволяет выполнять конкатенацию ввода, подобно тому, Каждая операция извлечения возвращает ссылку на вызывающий объект, позволяет выполнять конкатенацию ввода, подобно тому, как это делается в отношении вывода: char name[20]; float fee; int group; cin >> name >> fee >> group; Здесь, к примеру, объект cin, возвращенный операцией cin » name, становится тем объектом, который принимает fee.

Восприятие ввода операцией cin » Различные версии операции извлечения одинаково воспринимают входной поток. Они Восприятие ввода операцией cin » Различные версии операции извлечения одинаково воспринимают входной поток. Они опускают пробельные символы (пробелы, символы новой строки и табуляции) до тех пор, пока не встретят непробельный символ. Это справедливо даже для односимвольных режимов (когда аргумент имеет тип char, unsigned char или signed char), но не относится к функциям символьного ввода языка С В односимвольных режимах операция >> считывает символ и присваивает его указанному целевому объекту. В других режимах она считывает один элемент данных указанного типа. То есть она читает все, начиная с начального символа, отличного от пробельного, вплоть до первого символа, не соответствующего целевому типу.

Например, рассмотрим следующий код: int elevation; cin >> elevation; Предположим, вы вводите следующие символы: Например, рассмотрим следующий код: int elevation; cin >> elevation; Предположим, вы вводите следующие символы: -123 Z Операция прочитает символы -, 1, 2 и 3, потому что они являются допустимыми составляющими целого числа. Но символ Z таковым не является, поэтому последним принятым символом ввода будет 3. Символ Z останется во входном потоке, и следующий оператор сin начнет чтение с этой позиции. Тем временем, операция преобразует последовательность символов -123 в целое значение и присвоит его переменной elevation.

Другие методы класса istream Методы get (char &) и get (void) обеспечивают односимвольный ввод Другие методы класса istream Методы get (char &) и get (void) обеспечивают односимвольный ввод без пропуска пробельных символов. Когда метод get () вызываются с аргументом типа char или вообще без аргументов, он извлекает следующий символ ввода, даже если это пробел, знак табуляции или символ новой строки. Версия get (char & ch) присваивает введенный символ своему аргументу, а версия get (void) просто использует введенный символ, преобразованный в целочисленный тип (обычно — int), в качестве своего возвращаемого значения.

int ct = 0; char ch; cin. get (ch) ; while (ch != 'n') int ct = 0; char ch; cin. get (ch) ; while (ch != 'n') { cout « ch; ct++; cin. get(ch); } cout « ct « endl;

int ct = 0; char ch; cin » ch; while (ch != ' n') int ct = 0; char ch; cin » ch; while (ch != ' n') // ОТРИЦАТЕЛЬНЫЙ РЕЗУЛЬТАТ ПРОВЕРКИ { cout « ch; ct++; cin » ch; } cout « ct « endl;

Функция-член get (void) также считывает пробельные символы, но использует свое возвращаемое значение для передачи Функция-член get (void) также считывает пробельные символы, но использует свое возвращаемое значение для передачи ввода в программу. Поэтому ее можно использовать следующим образом: int ct = 0; char ch; ch = cin. get(); // использование возвращаемого значения while (ch != 'n') { cout « ch; ct++; ch = cin. get () ; } cout « ct « endl;

Какую форму односимвольного ввода предпочесть? Что следует использовать при наличии выбора между >>, get Какую форму односимвольного ввода предпочесть? Что следует использовать при наличии выбора между >>, get (char &) и get (void) ? Сначала нужно решить, требуется ли пропускать пробелы при вводе. Если пропуск пробелов допустим (или даже удобен), нужно использовать операцию извлечения >>. Если требуется, чтобы программа обрабатывала каждый символ, нужно применять один из методов get().

Строковый ввод: getline (), get () Функция-член getline (), и строчноориентированная версия get () Строковый ввод: getline (), get () Функция-член getline (), и строчноориентированная версия get () считывают строки, и обе они имеют одинаковую сигнатуру: istream & get(char *, int, char); istream & get (char *, int); istream & getline(char *, int, char); istream & getline(char *, int);

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

Функция cin. get () прекращает считывание ввода в массив после получения 49 символов или, Функция cin. get () прекращает считывание ввода в массив после получения 49 символов или, по умолчанию, после получения символа перевода строки — в зависимости от того, что произойдет раньше. Основное различие между get () и getline () в том, что get () оставляет символ перевода строки во входном потоке, делая его доступным для следующей операции ввода, в то время как getline () отбрасывает символы новой строки из входного потока.

Другие методы класса istream Другие методы istream, помимо уже описанных, включают read(), peek(), gcount Другие методы класса istream Другие методы istream, помимо уже описанных, включают read(), peek(), gcount () и putback (). Функция read () считывает заданное количество байтов и сохраняет их в указанном месте. Например, следующие операторы считывают 144 символа из стандартного ввода и помещают их в массив gross. char gross[144] ; cin. read(gross, 144);

В отличие от getline () и get (), метод read () не добавляет нулевой В отличие от getline () и get (), метод read () не добавляет нулевой символ к вводу и, следовательно, не преобразует ввод в строковую форму. Метод read () не предназначен для клавиатурного ввода. Вместо этого чаще всего он применяется в сочетании с функцией write () класса ostream для файлового ввода и вывода. Возвращаемым типом этого метода является istream &, поэтому к его значению можно применять конкатенацию следующим образом: char gross[144]; char score[20]; cin. read(gross, 144). read(score, 20);

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

char great_input[80]; char ch; int i = 0; while ( (ch = cin. peek char great_input[80]; char ch; int i = 0; while ( (ch = cin. peek () ) !='. '&& ch !='n ') cin. get(great_input[i++ ]) ; great_input [i] = ' '; Вызов cin. peek () выбирает следующий входной символ и присваивает ch. Затем условие цикла while удостоверяется, что значение ch не является ни точкой, ни символом новой строки. Если это так, цикл считывает символ в массив и обновляет его индекс. Когда цикл прерывается, точка или символ новой строки остаются во входном потоке в позиции первого символа, который будет считан следующей операцией ввода. Затем код добавляет нулевой символ к массиву, превращая его в строку.

Метод gcount () возвращает количество символов, прочитанных последним методом неформатированного извлечения. Это подразумевает символы, Метод gcount () возвращает количество символов, прочитанных последним методом неформатированного извлечения. Это подразумевает символы, считанные методом get (), get line () , ignore () или read(), но не операцией извлечения (>>), которая форматирует ввод в соответствии с определенными типами данных.

Функция putback () вставляет символ обратно в строку ввода. При этом вставленный символ становится Функция putback () вставляет символ обратно в строку ввода. При этом вставленный символ становится первым символом, читаемым следующим оператором ввода. Метод putback () принимает один аргумент char, представляющий вставляемый символ, и возвращает тип istream &, что позволяет осуществлять конкатенацию вызова с другими методами istream.

#include <iostream> int main () { char ch; while(cin. get(ch) ) // завершение по #include int main () { char ch; while(cin. get(ch) ) // завершение по достижении EOF { if (ch != '#') cout « ch; else { cin. putback(ch); // повторная вставка символа break; } }

if (!cin. eof()) { cin. get(ch); cout « endl << ch << if (!cin. eof()) { cin. get(ch); cout « endl << ch << " is next input character. n"; } else { cout « "End of file reached. n"; // достигнут конец файла std: : exit(0); }

while(cin. peek() !='#') // while(cin. peek() !='#') // "заглядывание" вперед { cin. get (ch); cout « ch; } if (!cin. eof ()) { cin. get(ch); cout « endl << ch << " is next input character. n"; } else cout « "End of file reached. n"; // достигнут конец файла return 0; }

Файловый ввод и вывод Пакет классов ввода-вывода C++ управляет файловым вводом и выводом в Файловый ввод и вывод Пакет классов ввода-вывода C++ управляет файловым вводом и выводом в основном так же, как он делает это со стандартным вводом и выводом. Чтобы записывать в файл, надо создать объект ofstream и использовать такие его методы, как операция вставки << или write(). Чтобы читать из файла, надо создать объект ifstream и применить методы istream наподобие операции извлечения >> и get().

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

Чтобы помочь в решении этих задач, в C++ определено несколько новых классов в заголовочном Чтобы помочь в решении этих задач, в C++ определено несколько новых классов в заголовочном файле fstream, включая класс ifstream для файлового ввода и класс ofstream для файлового вывода. В C++ также определен класс fstream для одновременного файлового ввода и вывода. Эти классы являются производными от классов, определенных в заголовочном файле iostream, поэтому объекты новых классов могут использовать методы, которые уже были изучены ранее.

Простой файловый вводвывод Предположим, программа должна выполнять запись в файл. Понадобится предпринять следующие действия. Простой файловый вводвывод Предположим, программа должна выполнять запись в файл. Понадобится предпринять следующие действия. 1. Создать объект ofstream для управления выходным потоком. 2. Ассоциировать этот объект с конкретным файлом. 3. Использовать объект так же, как нужно было бы использовать cout.

Нужно начать с подключения заголовочного файла fstream. Его подключение в большинстве, хотя и не Нужно начать с подключения заголовочного файла fstream. Его подключение в большинстве, хотя и не во всех реализациях, автоматически подключает файл iostream, поэтому явное подключение iostream не обязательно. Затем нужно объявить объект типа ofstream: ofstream fout; Именем объекта может быть любое допустимое в C++ имя, такое как fout, Оut. File, cgate или didi.

Затем этот объект нужно ассоциировать с конкретным файлом. Это можно сделать с помощью метода Затем этот объект нужно ассоциировать с конкретным файлом. Это можно сделать с помощью метода open(). fout. open("jar. txt"); // связывание fout с файлом jar. txt Эти два шага (создание объекта и ассоциация файла с ним) можно совместить в одном операторе, используя другой конструктор: ofstream fout("jar. txt"); // создание объекта fout и его ассоциирование с файлом jar. txt

После этого fout можно будет использовать таким же образом, как и cout. Например, если После этого fout можно будет использовать таким же образом, как и cout. Например, если требуется поместить слова Dull Data в этот файл, это можно сделать следующим образом: fout « "Dull Data"; Действительно, поскольку ostream — это базовый класс для ofstream, можно применять все методы ostream, включая разнообразные операции вставки, а также методы форматирования и манипуляторы.

Такое открытие файла для вывода создает новый файл, если файла с указанным именем не Такое открытие файла для вывода создает новый файл, если файла с указанным именем не существует. Если же файл с этим именем существовал ранее, то действие по его открытию усекает его так, чтобы вывод начинался в пустой файл.

Действия для выполнения чтения из файла во многом подобны тем, которые необходимы для выполнения Действия для выполнения чтения из файла во многом подобны тем, которые необходимы для выполнения записи в файл. 1. Создать объект ifstream для управления входным потоком. 2. Ассоциировать этот объект с конкретным файлом. 3. Использовать объект так же, как нужно было бы использовать сin.

Нужно подключить заголовочный файл fstream. Затем объявить объект ifstream и ассоциировать его с именем Нужно подключить заголовочный файл fstream. Затем объявить объект ifstream и ассоциировать его с именем файла. // Два оператора ifstream fin; // создать объект fin типа ifstream fin. open("jellyjar. txt") ; // открытие файла jellyjar. txt для чтения // Один оператор ifstream fis("jamjar. dat") ; // создание объекта fis и его ассоциирование с файлом jamjar. txt

Затем объект fin или fis можно использовать почти так же, как сіn. char ch; Затем объект fin или fis можно использовать почти так же, как сіn. char ch; fin » ch; // считывание символа из файла jellyjar. txt char buf[80]; fin » buf; // считывание слова из файла fin. getline(buf, 80); // считывание строки из файла string line; getline(fin, line); // считывание из файла в строковый объект

Ввод, как и вывод, также буферизуется, поэтому создание объекта ofstream, такого как fin, создает Ввод, как и вывод, также буферизуется, поэтому создание объекта ofstream, такого как fin, создает входной буфер, которым управляет объект fin. . Соединение с файлом закрывается автоматически, когда объекты ввода и вывода уничтожаются, например, по завершении программы. Кроме того, соединение с файлом можно закрыть явно, используя для этого метод close (): fout. close (); fin. close ();

#include <iostream> // для многих систем не требуется #include <fstream> #include <string> int main #include // для многих систем не требуется #include #include int main () { using namespace std; string filename; cout « "Enter name for new file: "; // запрос имени нового файла cin >> filename;

// Создание объекта выходного потока для нового файла и назначение ему имени fout ofstream // Создание объекта выходного потока для нового файла и назначение ему имени fout ofstream fout(filename. c_str()); fout << "For your eyes only!n"; // запись в файл cout « "Enter your secret number: "; // вывод на экран float secret; cin » secret; fout << "Your secret number is " « secret « endl; fout. close ();

// Создание объекта входного потока и назначение ему имени fin ifstream fin(filename. c_str ()) // Создание объекта входного потока и назначение ему имени fin ifstream fin(filename. c_str ()) ; cout << "Here are the contents of " « filename « " : n" ; char ch; while (fin. get(ch)) // чтение символа cout « ch; // и его вывод на экран cout << "Donen"; fin. close () ; return 0; }

Проверка потока и is_open() Классы файловых потоков C++ наследуют член, описывающий состояние потока, от Проверка потока и is_open() Классы файловых потоков C++ наследуют член, описывающий состояние потока, от класса ios_base. Этот член, как упоминалось ранее, хранит информацию, отражающую состояние потока — о том, что все в порядке, что достигнут конец файла, о том, произошел ли сбой операции ввода-вывода, и т. д. Если все в порядке, состояние потока равно нулю

Например, попытка открытия для ввода несуществующего файла устанавливает флаг failbit. Поэтому можно было бы Например, попытка открытия для ввода несуществующего файла устанавливает флаг failbit. Поэтому можно было бы выполнить проверку следующим образом: fin. open(argv[file]); if (fin. fail()) // попытка открытия не удалась { }

Поскольку объект if stream, подобно is t ream, преобразуется в тип bool, когда ожидается Поскольку объект if stream, подобно is t ream, преобразуется в тип bool, когда ожидается именно этот тип, можно было бы использовать следующий код: fin. open(argv[file]) ; if (!fin) // попытка открытия не удалась { }

Однако новые реализации C++ предлагают лучший способ проверки того, открыт ли файл — метод Однако новые реализации C++ предлагают лучший способ проверки того, открыт ли файл — метод is_open(). if (!fin. is_open()) // попытка открытия не удалась { }

Открытие нескольких файлов Если требуется, чтобы два файла были открыты одновременно, нужно создать отдельный Открытие нескольких файлов Если требуется, чтобы два файла были открыты одновременно, нужно создать отдельный поток для каждого файла. Например, программа, которая сравнивает два отсортированных файла и отправляет результат в третий, должна создать два объекта ifstream для двух входных файлов и один объект ofstream — для выходного файла. Количество файлов, которые можно открыть одновременно, зависит от операционной системы.

Однако можно запланировать последовательную обработку файлов. Можно открыть единственный поток и по очереди ассоциировать Однако можно запланировать последовательную обработку файлов. Можно открыть единственный поток и по очереди ассоциировать его с каждым из файлов. При этом ресурсы компьютера используются экономнее, чем при открытии отдельного потока для каждого файла. Чтобы применить такой подход, нужно объявить объект ifstream без его инициализации, а затем с помощью метода open() ассоциировать поток с файлом.

ifstream fin; // создание потока конструктором по умолчанию fin. open( ifstream fin; // создание потока конструктором по умолчанию fin. open("fat. txt"); // ассоциирование потока с файлом fat. txt. . . // выполнение каких-либо действий fin. close (); // разрыв связи потока с файлом fat. txt fin. clear(); // сброс fin (может не требоваться) fin. open("rat. txt"); // ассоциирование потока с файлом rat. txt fin. close();

Обработка командной строки Аргументы командной строки — это параметры, вводимые в командной строке после Обработка командной строки Аргументы командной строки — это параметры, вводимые в командной строке после команды. Например, чтобы подсчитать количество слов в некоторых файлах в системе Unix или Linux, в приглашении командной строки понадобится ввести следующую команду: wc report 1 report 2 report 3

Можно использовать следующий заголовок int main(int argc, char *argv[]) Аргумент argc представляет количество аргументов Можно использовать следующий заголовок int main(int argc, char *argv[]) Аргумент argc представляет количество аргументов в командной строке. Счетчик включает имя самой команды. Переменная argv — это указатель на char. argv можно трактовать как массив указателей на аргументы командной строки, причем argv[0] указывает на первый символ строки, содержащей имя самой команды, argv [1] — указатель на первый символ строки, содержащей первый аргумент и т. д.

wc report 1 report 2 report 3 В этом случае argc будет равно 4, wc report 1 report 2 report 3 В этом случае argc будет равно 4, argv[0] — wc, argv[1] — report 1 и т. д. Следующий цикл будет выводить каждый аргумент командной строки в отдельной строке экрана: for (int i = 1; i < argc; i++) cout « argv[i] « endl;

Многие интегрированные среды разработки IDE для Windows имеют опцию, позволяющую передавать им аргументы командной Многие интегрированные среды разработки IDE для Windows имеют опцию, позволяющую передавать им аргументы командной строки. Многие IDE-среды в Windows могут генерировать исполняемые файлы, которые запускаются в режиме командной строки Windows.

#include <iostream> #include <fstream> #include <cstdlib> // для exit() int main(int argc, char * #include #include #include // для exit() int main(int argc, char * argv[]) { using namespace std; if (argc ==1) // выход при отсутствии аргументов { cerr « "Usage: " « argv[0] « " filename[s]n"; exit(EXIT_FAILURE);

ifstream fin; // открытие потока long count; long total = 0; char ch; for ifstream fin; // открытие потока long count; long total = 0; char ch; for (int file = 1; file < argc; file++) { fin. open(argv[file]); // подключение потока к argv[file] if (!fin. is_open()) { cerr « "Could not open " « argv[file] « endl; //не удается открыть файл fin. clear (); continue; }

count = 0; while (fin. get (ch) ) count++; cout « count « count = 0; while (fin. get (ch) ) count++; cout « count « " characters in " « argv[file] « endl; // количество символов в файле total += count; fin. clear(); // требуется для некоторых реализаций fin. close(); // отключение от файла } cout « total « " characters in all filesn"; // количество символов во всех файлах return 0;

$ a. out Usage: a. out filename[s] $ a. out paris rome 3580 characters $ a. out Usage: a. out filename[s] $ a. out paris rome 3580 characters in paris 4886 characters in rome 8466 characters in all files $

Режимы файла Режим файла описывает, как файл будет использоваться: для чтения, записи, добавления информации Режимы файла Режим файла описывает, как файл будет использоваться: для чтения, записи, добавления информации и т. п. При ассоциировании потока с файлом либо инициализацией объекта файлового потока именем файла, либо с помощью метода open (), можно указать второй аргумент, описывающий режим файла: ifstream fin("banjo", mode 1); // конструктор с аргументом режима ofstream fout(); fout. open("harp", mode 2); // open() с аргументом режима

Константы режима файла Константы режима файла

Метод open() и конструктор ifstream в качестве значения по умолчанию для аргумента режима используют Метод open() и конструктор ifstream в качестве значения по умолчанию для аргумента режима используют ios_base: : in (открыть для чтения), а метод open() и конструктор ofstream в качестве значения по умолчанию применяют ios_base: : out | ios_base: : trunc (открыть для чтения и усечь файл). Если требуется сохранить содержимое файла и добавить новую информацию в его конец, можно воспользоваться режимом ios_base: : app ofstream fout("bagels", ios_base: : out | ios_base: : app);

Стандарт C++ определяет части файлового ввода -вывода в терминах их эквивалентов из стандарта ввода-вывода Стандарт C++ определяет части файлового ввода -вывода в терминах их эквивалентов из стандарта ввода-вывода ANSI С. Оператор C++ вроде ifstream fin(filename, c++mode); реализуется, как если бы он использовал функцию fopen() из С: fopen(filename, cmode);

Бинарные файлы Сохранять данные в файле можно в текстовом или в бинарном формате. Текстовая Бинарные файлы Сохранять данные в файле можно в текстовом или в бинарном формате. Текстовая форма означает хранение всех данных — даже чисел — в виде текста. Например, сохранение значения 2. 324216 е+07 в текстовой форме означает сохранение 13 символов, используемых для записи этого числа. Это требует преобразования внутреннего компьютерного представления числа с плавающей точкой в символьную форму, что и делает операция вставки «. С другой стороны, бинарный формат означает хранение внутреннего компьютерного представления значения.

Каждый формат обладает своими преимуществами. Текстовый формат легко читать. С ним можно использовать обычный Каждый формат обладает своими преимуществами. Текстовый формат легко читать. С ним можно использовать обычный редактор или текстовый процессор для чтения и редактирования текстового файла. Текстовый файл несложно передать из одной системы в другую. Бинарный формат более точен для представления чисел. Он позволяет избежать ошибок, связанных с преобразованием или округлением. Сохранение данных выполняется быстрее. К тому же, в зависимости от природы данных, обычно бинарный формат требует меньше места.

const int LIM = 20; struct planet { char name[LIM] ; double population; double const int LIM = 20; struct planet { char name[LIM] ; double population; double g; }; planet p 1; Сохранение в текстовом формате: ofstream fout("planets. dat", ios_base: : out | ios_base: : app); fout « p 1. name « " " « p 1. population « " " « p 1. g « "n";

Сохранение в бинарной форме: ofstream fout( Сохранение в бинарной форме: ofstream fout("planets. dat", ios_base: : out | ios_base: : app I ios_base: : binary); fout. write( (char *) &p 1, sizeof p 1) ; Этот код сохраняет всю структуру как единое целое, используя внутреннее компьютерное представление данных.

fout. write((char *)&p 1, sizeof p 1); Этот оператор вынуждает программу обратиться к адресу fout. write((char *)&p 1, sizeof p 1); Этот оператор вынуждает программу обратиться к адресу структуры р1 и скопировать 36 байт (значение выражения sizeof p 1), начиная с указанного адреса, в файл, подключенный к fout. Чтобы восстановить информацию из файла, нужно использовать соответствующий метод read() с объектом ifstream: ifstream fin("planets. dat", ios_base: : in | ios_base: : binary); fin. read((char *) &p 1, sizeof p 1) ; Этот код копирует sizeof p 1 байт из файла в структуру р1.

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

Напишите программу, которая копирует клавиатурный ввод (вплоть до эмулируемого конца файла) в файл, имя Напишите программу, которая копирует клавиатурный ввод (вплоть до эмулируемого конца файла) в файл, имя которого передано в командной строке.