
- •Ввод-вывод в языке с
- •Потоковые функции
- •Открытие файлов и потоков
- •Переадресация ввода-вывода
- •Изменение буфера потока
- •Форматный вывод данных
- •Функция printf()
- •Поиск в файлах с помощью функций fseek( ), ftell( ) и rewind()
- •Синхронный и асинхронный ввод/вывод
- •3. Позиционирование указателя файла.
- •6. Запись данных в файл
- •Блокировка и разблокировка файла
- •Асинхронный режим чтения и записи файлов
- •Стандартные потоки cin, coutи cerr
- •Флаги и функции форматирования
- •Файловый ввод-вывод
- •Флаг Назначение
- •Файловый ввод
- •Файловый вывод
- •Вот результаты работы программы:
- •Двоичные файлы
- •Буферы потоков
Стандартные потоки cin, coutи cerr
Стандартным потокам языка С stdin, stdout и stderr, объявленным в файле STDIO.H, в C++ соответствуют объекты-потоки cin, cout, cerr и clog, подключаемые посредством файла IOSTREAM.
cin Объект класса istream, связанный со стандартным потоком ввода
cout Объект класса ostream, связанный со стандартным потоком вывода
cerr Объект класса ostream, не поддерживающий буферизацию и связанный со стандартным потоком ошибок
clog Объект класса ostream, поддерживающий буферизацию и связанный со стандартным потоком ошибок
Все они открываются автоматически во время запуска программы и обеспечивают интерфейс между программой и пользователем.
Операторы ввода (>>) и вывода (<<) данных
Ввод-вывод в C++ значительно усовершенствован и упрощен благодаря универсальным операторам >> (ввод) и << (вывод). Их универсальность стала возможной благодаря появившемуся в C++ понятию перегрузки операторов, которая заключается в создании функций, имена которых совпадают с именами стандартных операторов языка. Компилятор различает вызов настоящего и "функционального" операторов на основании типов передаваемых им операндов. Операторы >> и << перегружены таким образом, чтобы поддерживать все стандартные типы данных C++, включая классы. Рассмотрим пример вывода данных с помощью функции printf() в языке С:
printf("Целое числей.'/%d,, число с плавающей запятой: %f",ivalue, fvalue);
А теперь запишем это же выражение на C++:
cout<< "Целое число: " << ivalue<< ", число с плавающей запятой: " << fvalue;
Обратите внимание, что один и тот же перегруженный оператор используется для вывода данных трех разных типов: строк, целых чисел и чисел с плавающей запятой. Оператор << самостоятельно проанализирует тип данных и выберет подходящий формат их представления. Аналогично работает оператор ввода. Сравним два эквивалентных выражения на языках С и C++:
/* на языке С */
scanf("%d%f%c",&ivalue, &fvalue, &c);
// на языке С+.+ cin >> ivalue >> fvalue >> c;
Нет необходимости при вводе данных ставить перед именами переменных оператор взятия адреса &. В C++ оператор >> берет на себя задачу вычисления адреса, определения формата и прочих особенностей записи значения переменной.
Прямым следствием перегрузки является возможность расширения операторов << и >> для обработки данных нестандартных типов. Ниже показано, как перегрузить оператор вывода, чтобы он мог принимать данные нового типа tclient:
ostream& operator <<(ostream& osout, tclient client)
{
osout<< " " << client.pszname;
osout<< " " << client.pszaddress;
osout<< " " << client .pszphone;
}
Тогда для вывода содержимого структуры client на экран достаточно будет задать такое выражение:
cout << client;
Эффективность этих операторов объясняется компактностью поддерживающего их программного кода. При обращении к функциям типа printf() и scanf() задействуется большой объем кода, основная часть которого не используется при выполнении конкретной операции ввода или вывода данных. Даже если в языке С вы оперируете только целыми числами, все равно будет подгружаться весь код функции с блоками обработки данных самых разных типов. Напротив, в языке C++ реально подгружаться будут только те подпрограммы, которые необходимы для решения конкретной задачи.
В следующей программе оператор >> применяется для чтения данных различных типов:
// // insert. срр // Эта программа на языке C++ демонстрирует применение оператора >> для // ввода данных типа char, int и double, а также строк. //
#include <iostream > #define INUMCHARS. 45 #define INULL_CHAR 1
void main() {
char canswer;
int ivalue;
double dvalue;
char pszname [INUMCHARS + INULL_CHAR];
cout<< "Эта программа позволяет вводить данные различных типов.\n"; cout<< "Хотите попробовать? (Y— да, N — нет) ";
cin >> canswer;
if (canswer == 'У'){ cout << "\n"<< "Введите целое число: "; cin >> ivalue;
cout<< "\n\nВведите число с плавающей запятой: "; cin >> dvalue;
cout<< "\n\nВведите ваше имя: "; cin >> pszname; cout<< "\n\n"; } }
В данном примере оператор << используется в простейшем виде — для вывода текста приглашений. Обратите внимание, что оператор >> выглядит во всех случаях одинаково, если не считать имен переменных.
Теперь приведем пример программы, в которой оператор << применяется для вывода данных различных типов:
// // extract.срр // Эта программа на языке C++ демонстрирует применение оператора << для // вывода данных типа int, float, а также строк. //
#include <iostream >
void main ()
{
char description!] = "Магнитофон";
int quantity = 40;
float price = 45.67;
cout<< "Наименование товара: " << description<< endl;
cout<< "Количество на складе: " << quantity<< endl;
cout<< "Цена в долларах: " << price<< endl;
}
Программа выведет на экран следующую информацию:
Наименование товара: Магнитофон
Количество на складе: 40
Цена в долларах: 45.67
Здесь следует обратить внимание на манипулятор endl. Манипуляторами называются специальные функции, которые в выражениях с потоковыми объектами, такими как cout и cin, записываются подобно обычным переменным, но в действительности выполняют определенные действия над потоком. Манипулятор endl широко применяется при выводе данных в интерактивных программах, так как помимо записи символа новой строки он очищает буфер потока, вызывая "выталкивание" содержащихся в нем данных. Эту же операцию, но без вывода символа \n, можно выполнить с помощью манипулятора flush.
Рассмотрим некоторые особенности ввода-вывода строк:
// // string. срр // Эта программа на языке C++ иллюстрирует особенности // работы оператора >> со строками. //
#include <iostream.h> #define INUMCHARS 45 #define INULL_CHARACTER 1
void main (void) {
char ps zname[ INUMCHARS + INULL_CHARACTER] ;
cout<< "Введите ваше имя и фамилию: ";
cin >> pszname;
cout << "\n\nСпасибо, " << pszname;
В результате выполнения программы будет выведена следующая информация:
Введите ваши имя и фамилию: Александр Иванов
Спасибо, Александр
Почему не была выведена вся строка? Это связано с особенностью оператора >>: он прекращает чтение строки, как только встречает первый пробел, знак табуляции или символ новой строки (кроме ведущих). Поэтому в переменной pszname сохранилось только имя, но не фамилия. Чтобы решить эту проблему, следует воспользоваться функцией cin.get (), как показано ниже:
// // cinget.cpp // Эта программа на языке C++ демонстрирует применение оператора >> // совместно с функцией get()для ввода строк с пробелами. //
#include <iostream.h> #define.INUMCHARS 45 . j#define INULL_CHARACTER 1
void main(void)
char pszname[INUMCHARS + INULL CHARACTER];
cout<< "Введите ваше имя и фамилию: ";
cin.get(pszname, INUMCHARS);
cout << "\n\nСпасибо, " << pszname;
Теперь программа отобразит данные следующим образом:
Введите ваше имя и фамилию: Александр Иванов
Спасибо, Александр Иванов
Функция cin.get (), помимо имени переменной, принимающей данные, ожидает два дополнительных аргумента: максимальное число вводимых символов и символ, служащий признаком конца ввода. В качестве последнего по умолчанию используется символ \n. Функция cin.get() считывает все символы в строке, включая пробелы и знаки табуляции, пока не будет прочитано указанное число символов или не встретится символ-ограничитель. Если в качестве ограничителя необходимо, к примеру, использовать знак *, следует записать такое выражение:
cin.get(pszname, INUMCHARS, '*');