- •Функции стандартного ввода/вывода
- •Примечание
- •Примечание
- •9.2.2 Ввод/вывод с использованием разных классов
- •Пространства имен
- •Работа с классом fstream
- •Is_open() — если файл открыт, то функция возвращает true, иначе - false;
- •Работа с классом ofstream
- •Работа с классом ifstream
- •Работа с бинарным файлом
- •Общие положения
- •Стандартный ввод cin
Работа с бинарным файлом
Такие файлы, в отличие от потоковых, создаются в определенной логической структуре и поэтому должны читаться в переменную той же структуры. Пример программы приведен в листинге 9.14, результат работы программы показан на рис. 9.10.
Листинг 9.14
// 40.срр : Defines the entry point for the console application.
#include "stdafx.h"
#include <iostream> //for cin, cout
#include <fstream>
#include <conio.h>
#include <stdio.h>
void _tmain()
{
using namespace std; /*используется стандартное пространство имен*/
/*данные о сотрудниках*/
struct Blocknotes
{
char name[30];
char phone[15];
int age;
}b[2]={
"Smit", "123456", 45,
"Kolly", "456789", 50
}; //инициализация массива структур
//запись данных в файл
ofstream FILE;
FILE.open("Block", ios::binary);
for(int i=0; i<2; i++)
FILE.write((char *)&b[i], sizeof(b[i]));
FILE.close();
//чтение данных из файла
ifstream FILE1;
FILE1.open("Block", ios::binary);
Blocknotes bb[2];
int i=0;
while(!FILE1.eof())
{
if(i==2)
goto m;
FILE1.read((char *)&bb[i], sizeof(bb[i]));
cout << "string" << i << " " << bb[i].name <<" " << bb[i].phone << " " << bb[i].age << endl;
i++;
}
m: FILE1. close ();
system("DEL BLOCK");
_getch();
}
Рис. 9.10. Результат работы программы листинга 9.14
Пояснений требуют следующие моменты:
запись FILE.write((char *)&b[i], sizeof(b[i]));
Здесь для записи используется функция буферизированного вывода write(). где первым аргументом является указатель на структуру, из которой мы должны записывать данные. Этот указатель равен адресу структуры, т. е. &b[i]. Но в потоке все данные хранятся побайтно, поэтому тип указателя char (здесь идет принудительное преобразование типа). Второй аргумент— длина записи, она определяется стандартной функцией sizeof();
system ("DEL BLOCK ") ; — этой функцией удаляется рабочий файл;
оператор goto применен для подстраховки от превышения индекса массива bb[].
9.2.3 Стандартный ввод/вывод в C++
Общие положения
Стандартный ввод/вывод является частным случаем файлового ввода/вывода. При файловом вводе/выводе мы объявляли экземпляры соответствующих поточных классов, а затем пользовались методами и операциями: << , >>. Но как мы видели в начале этой главы, классы istream, ostream, лежащие в основе поточных классов, содержат стандартные объекты-экземпляры классов с именами cout (экземпляр класса для стандартного ввода), cin (экземпляр класса для стандартного вывода) и сегг (экземпляр класса для стандартного вывода сообщений об ошибках).
При запуске любой программы на языке C++ эти стандартные потоки определены (открыты) и по умолчанию назначены на стандартное вводное устройство — клавиатуру (cin), на стандартное выводное устройство — экран (cout и сегг). Причем все эти устройства синхронно связаны с соответствующими указателями stdin, stdout, stderr. Так что работа со стандартным вводом/выводом сводится к тому, что вместо задаваемых пользователем имен экземпляров соответствующих классов задаются имена стандартных экземпляров классов: cin, cout. Открывать ничего не надо, надо только использовать операции <<, >> и операции форматирования. Если мы пишем имена переменных, из которых выводятся или в которые вводятся данные, то по умолчанию для ввода/вывода используются определенные форматы. Например, запишем:
cout << i;
В этом случае значение i выведется на экран в формате, определенном по умолчанию для типа i и в минимальном поле.
Запишем:
cin >> i >> j >> s;
где i, j, s описаны, соответственно, как int, float, char. В записи не видно форматов, но при вводе значений этих переменных с клавиатуры (после ввода каждого значения надо нажимать <Enter>) их форматы будут учтены.
Стандартный вывод cout
Объект cout направляет данные в буфер-поток, связанный с объектом stdout, объявленным в файле stdio.h. По умолчанию стандартные потоки С и C++ синхронизированы.
При выводе данные могут быть отформатированы с помощью функций-членов класса или манипуляторов. Их перечень приводится в табл. 9.2.
Примечание
Манипуляторы, начинающиеся с "no" (noshowpos и т. п.), имеют обратное действие по отношению к манипуляторам с такими же именами, но без приставки "no". В графе "Описание" у таких манипуляторов проставлены пробелы.
Таблица 9.2. Манипуляторы и функции стандартного ввода/вывода в C++
Манипуляторы |
Функции-члены класса |
Описание |
showpos |
setf(ios::showpos) |
Выдает знак плюс у выводимых положительных чисел |
noshowpos |
unsetf(ios::showpos) |
|
showbase |
setf(ios::showbase) |
Выдает базу системы счисления в выводимом числе в виде префикса |
noshowbase |
unsetf(ios::showbase) |
|
uppercase |
setf(ios::uppercase) |
Заменяет символы нижнего регистра на символы верхнего регистра в выходном потоке |
nouppercase |
unsetf(ios::uppercase) |
|
showpoint |
setf(ios::showpoint) |
Создает символ десятичной точки в сгенерированном потоке с плавающей точкой (в выводимом числе) |
noshowpoint |
unsetf(ios::showpoint) |
|
boolalpha |
setf(ios::boolalpha) |
Переводит булевый тип в символьный |
noboolalpha |
unsetf(ios::boolalpha) |
|
unitbuf |
setf(ios::unitbuf) |
Сбрасывает буфер вывода после каждой операции вывода |
nounitbuf |
unsetf(ios::unitbuf) |
|
internal |
setf(ios::internal, ios::adjustfield) |
Добавляет символы-заполнители к определенным внутренним позициям выходного потока (речь идет о выводе числа в виде потока символов). Если такие позиции не определены, поток не изменяется |
left |
setf(ios::left, ios :: adjustfield) |
Добавляет символы-заполнители с конца числа (сдвигая число влево) |
right |
setf(ios::right,ios:: adjustfield) |
Добавляет символы-заполнители с начала числа (сдвигая число вправо) |
dec |
setf(ios::dec, ios:: basefield) |
Переводит базу вводимых или выводимых целых чисел в десятичную (введенные после этого манипулятора данные будут выводиться как десятичные) |
hex |
setf(ios::hex,ios:: basefield) |
Переводит базу вводимых или выводимых целых чисел в шестнадцатеричную (введенные после этого манипулятора данные будут выводиться как шестнадцатеричные) |
oct |
setf(ios::oct,ios:: basefield) |
Переводит базу вводимых или выводимых целых чисел в восьмеричную (введенные после этого манипулятора данные будут выводиться как восьмеричные) |
fixed |
setf(ios::fixed, ios :: floatfield) |
Переводит выход с плавающей точкой в выход с фиксированной точкой |
scientific |
setf(ios::scientific, ios:: floatfield) |
Выдает числа с плавающей точкой в виде, используемом в научных целях: например, число 23450000 будет записано как: 23.45е6 |
|
setbase(int base) |
Преобразует ввод целых чисел в тип base, где параметр base может быть одним из чисел 8, 10 или 16 |
fill(с) |
setfill(char_type c) |
Задает символ заполнения при выводе данных |
precision(n) |
setprecision(int n) |
Задает точность вывода данных (количество цифр после точки) |
setw(int n) |
width(n) |
Задает ширину поля для выводимых данных (количество символов) |
endl |
|
Вставляет символ новой строки ('\n') в выходную последовательность символов и сбрасывает буфер ввода |
ends |
|
Вставляет символ '\0' в выходную последовательность символов |
flush |
flush( ) |
Сбрасывает буфер вывода |
ws |
|
Задает пропуск пробелов при вводе |
Значения по умолчанию:
precision() —6;
width() —0;
fill() — пробел.
В листинге 9.15 приведен пример программы с применением объекта cout (все пояснения можно найти в комментариях). Результат работы программы представлен на рис. 9.11.
Листинг 9.15
// 41.срр : Defines the entry point for the console application.
#include "stdafx.h"
#include <iostream>
#include <iomanip> //включение манипуляторов
#include <conio.h>
// cout example
void _tmain()
{
using namespace std;
int i;
float f;
cout << "Enter i and f >" << endl;
//чтение целого числа и числа с плавающей точкой с устройства stdin
cin >> i >> f;
//вывод целого и переход на новую строку
cout << i << endl;
//вывод числа с плавающей точкой и переход на новую строку
cout << f << endl;
//вывод в шестнадцатеричной системе
cout << hex << i << endl;
//вывод в восьмеричной и десятичной системах
cout << oct << i << dec << i << endl;
//вывод i с указанием его знака
cout << showpos << i << endl;
//вывод i в шестнадцатеричной системе
cout << setbase(16) << i << endl;
/*вывод i в десятичной системе и дополнение справа символом @ до ширины в 20 символов (заполнение начинается от правой границы к левой). Если вы вводите, например, 45, то выведется 45@@@@@@@@@@@@@@@@@@*/
cout << setfill('@') << setw(20) << left << dec << i;
cout << endl;
//вывод того же результата в том же формате, но с использованием функций вместо манипуляторов cout.fill('@');
cout.width(20);
cout.setf(ios::left, ios::adjustfield);
cout.setf(ios::dec, ios::basefield);
cout << i << endl;
//вывод f в научной нотации с точностью 10 цифр
cout << scientific << setprecision(10) << f << endl;
//изменение точности до 6 цифр
cout.precision(6);
//вывод f и возврат к нотации с фиксированной точкой
cout << f << fixed << endl;
_getch();
} // _tmain()
Рис. 9.11. Результат работы программы листинга 9.15