Добавлен: 04.04.2023
Просмотров: 283
Скачиваний: 1
Введение
Абсолютно любому приложению, написанному на любом языке программирования, необходимо взаимодействие как с пользователем, так и с окружающей средой. В противном случае полезность приложения сводится к нулю. Обычно, взаимодействие осуществляется посредством ввода-вывода информации.
Конечно, существует большое множество приложений, которые не используют ввод-вывод с помощью консоли или файла. Примером таких приложений могут стать программы для осуществления низкоуровненного взаимодействия с аппаратной частью или периферией (драйвера).
В большинстве языков программирования операции по вводу-выводу встроены в сам язык. Примером таких языков будет Pascal и Basic, в них присутствуют соответствующие операторы PRINT, write in они в ходят в так называемы словари языков. В языке C или C++ отсутствуют операции ввода и вывода, встроенных в сам язык. В ключевых словах мы сможем найти for и if, но ничего что могло относится к вводу или выводу. Это предоставило свободу разработчикам компиляторов в проектировании функций ввода-вывода. Для организации ввода-вывода С++ полагается на решения из языка C, Это решение представляет собой набор классов определенных в заголовочных файлах iostream, fstream. [1]
В стандартном языке C++ используется два метода ввода-вывода информации:
- Традиционная система ввода-вывода, которая была унаследована от языка C;
- С помощью STL потоков (Standart Template Library). [2]
1. Ввод и вывод в языке С++
В С++ ввод-вывод реализован с помощью поточных классов, которые содержат данные и методы работы с файлами для ввода-вывода информации. Поточные классы берут свое начало и наследуют функционал от класса IOS. Для написания программы с использование ввода/вывода на языке программирования C++ необходимо выполнить в программе:
#include <fstream>
Класс fstream происходит от двух классов ostream и istream.
Ввод и вывод в С++ организован с помощью так называемых поточных классов, содержащих данные и методы работы с файлами по вводу/выводу. Поточные классы происходят от общего предка – класса ios и потому наследуют его функциональность. Чтобы начать писать программу с использованием ввода/вывода на языке С++, следует обязательно выполнить в программе:
#include <fstream>[3]
Класс fstream предназначен для осуществления чтения и записи в одном конкретном файле и является потомком классов istream и ostream. Эти же классы являются родителями классов ifstream и оfstream.
Классы istream, ostream имеют экземпляры cin, cerr, count, благодаря им осуществляется стандартный ввод/вывод. Ввод осуществляется устройства ввода - клавиатура, а выводится на устройство вывода – экран.
Следовательно, включение в программу класса fstream окажется достаточным для организации файлового и стандартного ввода/вывода.
Для работы с файлом его необходимо открыть – связать с специальной структурой, в которой задаются все необходимые характеристики файла. Данная связь выполняется с помощью функции open. Данная функция входит в классы, отвечающие за ввод/вывод: fstream, istream, ostream.[4]
Поэтому, чтобы выполнить такую функцию, следует сначала создать экземпляр соответствующего класса, чтобы получить доступ к этой функции.
Для записи в файл, необходимо создать экземпляр класса ostream exp и выполнить функцию exp.open()
В скобках указываются параметры этой функции: имя открываемого файла и способ открытия файла со сведениями о работе с файлом чтение или запись.
После открытия файла для чтения или записи, экземпляром exp класса ostream можно произвести запись. Для этого необходимо использовать операции включения извлечений (<<). Разберем пример:
exp << "test for C++" << i << j << endl;
Переменные:
i – int i указатель на целочисленное значение;
j - float j указатель на значения с плавающей точкой;
endl – конец ввода и переход на новую строку;
По окончанию работы с файлом его необходимо закрыть. Это разорвёт связь с структурой, с которой был связан файл при открытии. Данная процедура позволит другим файлам открываться. Для закрытия используется метод close(). Для примера, приведенного выше: exp.close().[5]
2. Файловый ввод/вывод с использованием разных классов
Поточные классы – это поставщики инструментов для работы с файлами. В поточных классах хранятся:
- структуры, обеспечивающие открытие/закрытие файлов;
- функции (методы) открытия/закрытия файлов;
- другие функции и данные, обеспечивающие собственно ввод/вывод.
При использовании поточных классов языка С++ в основной программе требуется писать директиву:
using namespace::std;
В противном случае программа не пройдет компиляцию. В исходном коде №1 приводится пример использования директив пространства имен. Результат выполнения данного исходного кода показан на Рисунок 1.
Исходный код №1.
#include <vcl.h>
#include <iostream>
#include <conio.h>
namespace F
{
float x = 190;
}
namespace G
{
using namespace F;
float y = 7.0;
namespace INNER_G
{
float z = 25.01;
}
}
int main()
{
using namespace G;
using namespace G::INNER_G;
float x = 49.4;
std::cout << "x = " << x << std::endl;
std::cout << "y = " << y << std::endl;
std::cout << "z = " << z << std::endl;
getch();
return 0;
}
Рисунок 1.
std::cout – это стандартный вывод. Здесь показано, что объект cout принадлежит пространству имен std.
2.1. Работа с классом fstream
Члены этого класса позволяют открыть файл, записать в него данные, переместить указатель позиционирования в файле (указатель, показывающий, на каком месте в файле мы находимся) в то или иное место, прочитать данные.
Этот класс имеет следующие основные функции (методы):
open() – открывает файл;
close() – закрывает файл;
is_open() – если файл открыт, то возвращает true, иначе — false;
rdbuf() – выдает указатель на буфер ввода/вывода.
Формат функции open(): open(char* file_name, open_mode);
где file_name – имя открываемого файла, open_mode – способ открытия файла. Способ открытия файла задается значением перечислимой переменной: enum open_mode {app, binary, in, out, trunc, ate}; Эта переменная определена в базовом классе ios, поэтому обращение к перечислимым значениям в классе fstream, с экземпляром которого мы работаем, должно идти с указанием класса-родителя: ios::app, ios::binary и т. д.
Назначение способов открытия файла:
app – открыть файл для дозаписи в его конец;
binary – открыть файл в бинарном виде (такие файлы были записаны по определенной структуре данных и поэтому должны читаться по этой же структуре);
in — открыть файл для чтения;
out – открыть файл для записи в его начало. Если файл не существует, он будет создан;
trunc – уничтожить содержимое файла, если файл существует (очистить файл);
ate – установить указатель позиционирования файла на его конец.
При задании режимов открытия файла можно применять оператор логического ИЛИ (|), чтобы составлять необходимое сочетание режимов открытия. Приведем пример программы работы с классом fstream (Исходный код № 2). Результат работы показан на рисунке 2.
Исходный код № 2.
#include <iostream>
#include <conio.h>
#include <fstream>
#include <stdio.h>
int main()
{
using namespace std;
fstream inout;
inout.open("fstream.out", ios_base::in | ios_base::out | ios_base::trunc);
inout << "This is work for Kyrsovaya 1" << endl;
inout << "This is work for Kyrsovaya 2" << endl;
inout << "This is work for Kyrsovaya 3" << endl;
char p[100];
inout.seekg(0);
inout.getline(p, 100);
cout << endl << "String1 :" << endl;
cout << p;
fstream::pos_type pos = inout.tellg();
inout.getline(p, 100);
cout << endl << "String2 :" << endl;
cout << p;
inout.getline(p, 100);
cout << endl << "String3 :" << endl;
cout << p;
inout.seekp(pos);
inout << "This is work for Kyrsovaya 4" << endl;
inout << "This is work for Kyrsovaya 5" << endl;
inout.seekg(0);
cout << endl << endl << inout.rdbuf();
inout.close();
getch();
}
Рисунок 2.
2.2. Работа с классом ofstream
Класс ofstream предназначен для организации работ по выводу (записи) в файл с помощью методов этого класса:
open() – открывает файл для записи в него информации;
is_open() – возвращает true, если файл открыт, и false – в противном случае;
put() – записывает в файл один символ;
write() – записывает в файл заданное число символов;
skeep() – перемещает указатель позиционирования в заданное место файла;
tellp() – выдает текущее значение указателя позиционирования;
close() – закрывает файл;
rdbuf() – выдает указатель на буфер вывода (этот буфер находится в структуре, с которой связывается файл при его открытии).
В исходном коде №3 приведен пример использования класса ofstream.
Исходный код №3.
ofstream FILE;
FILE.open("test.txt");
if(FILE == NULL) return(0);
for(int i = 0; i < 2; i++)
FILE << "string " << i << endl;
FILE.close();
2.3. Работа с классом ifstream
Класс ifstream предназначен для организации работ по вводу (чтению) из файла с помощью методов этого класса:
open() – открывает файл для чтения из него информации;
is_open() – возвращает true, если файл открыт, и false – в противном случае;
get() – читает из файла один символ;
read() – читает из файла заданное число символов;
eof() – возвращает ненулевое значение, когда указатель позиционирования в файле достигает конца файла;
peek() – выдает очередной символ потока, но не выбирает его (не сдвигает указатель позиционирования данного в файле);
seekg() – перемещает указатель позиционирования в заданное место файла;
tellg() – выдает текущее значение указателя позиционирования;
close() – закрывает файл;
rdbuf() – выдает указатель на буфер ввода (этот буфер находится в структуре, с которой связывается файл при его открытии).
Пример использования класса приведен в исходном коде №4.
Исходный код №4.
ifstream FILE;
char p[100];
FILE.open("test.txt");
if(FILE == NULL) return(0);
while(!FILE.eof())
{
FILE >> p;
cout << p << endl;
}
FILE.close();
Стандартный ввод/вывод в С++
Стандартный ввод/вывод является частным случаем файлового ввода/вывода. При файловом вводе/выводе мы объявляли экземпляры соответствующих поточных классов и затем пользовались методами и операциями << и >>. Но классы istream, ostream, лежащие в основе поточных классов, содержат стандартные объекты-экземпляры классов с именами cout (экземпляр класса для стандартного ввода), cin (экземпляр класса для стандартного вывода) и сerr (экземпляр класса для стандартного вывода сообщений об ошибках).
При запуске любой программы на языке С+ + эти стандартные потоки определены (открыты) и по умолчанию назначены на стандартное вводное устройство — клавиатуру (cin), на стандартное выводное устройство — экран (cout и cerr). Причем все эти устройства синхронно связаны с соответствующими указателями stdin, stdout, stderr. Так что работа со стандартным вводом/выводом сводится к тому, что вместо задаваемых пользователем имен экземпляров соответствующих классов задаются имена стандартных экземпляров классов: cin, cout. Открывать ничего не нужно, надо только использовать операции <> и операции форматирования. Если мы пишем имена переменных, из которых выводятся или в которые вводятся данные, то по умолчанию для ввода/вывода используются определенные форматы. Например, запишем:
cout << i;
В этом случае значение i выведется на экран в формате, определенном по умолчанию для типа i и в минимальном поле.
Запишем:
cin >> i >> j >> s;
где i, j, s описаны соответственно как int, float, char. В записи мы не видим форматов, но при вводе значений этих переменных с клавиатуры (после ввода каждого значения надо нажимать клавишу ) их форматы будут учтены.
Объект cout
Объект cout направляет данные в буфер-поток, связанный с объектом stdout, объявленным в файле stdio.h. По умолчанию стандартные потоки С и С++ синхронизированы. При выводе данные могут быть отформатированы с помощью функций-членов класса или манипуляторов. Перечень их приведен в таблице 1.[6]
Таблица 1.
|
Манипуляторы |
Функции-члены класса |
Описание |
|
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.45e6 |
|
fill(c) |
setfill(char_type c) |
Задает символ заполнения при выводе данных |
|
precision(n) |
setprecision(int n) |
Задает точность вывода данных (количество цифр после точки) |
|
setw(int n) |
width(n) |
Задает ширину поля для выводимых данных (количество символов) |
|
endl |
Вставляет символ новой строки ('\n') в выходную последовательность символов и сбрасывает буфер ввода |
|
|
ends |
Вставляет символ '\0' в выходную последовательность символов |
|
|
flush |
flush() |
Сбрасывает буфер вывода |
|
ws |
Задает пропуск пробелов при вводе |