Способы ввода/вывода в С++
Содержание:
Введение
Абсолютно любому приложению, написанному на любом языке программирования, необходимо взаимодействие как с пользователем, так и с окружающей средой. В противном случае полезность приложения сводится к нулю. Обычно, взаимодействие осуществляется посредством ввода-вывода информации.
Конечно, существует большое множество приложений, которые не используют ввод-вывод с помощью консоли или файла. Примером таких приложений могут стать программы для осуществления низкоуровненного взаимодействия с аппаратной частью или периферией (драйвера).
В большинстве языков программирования операции по вводу-выводу встроены в сам язык. Примером таких языков будет 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 направляет данные в буфер-поток, связанный с объектом 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 |
Задает пропуск пробелов при вводе |
Пример программы с применением объекта cout приведен в Исходном коде №5. Результат работы представлен на рисунке 3.
Исходный код № 5.
#include <vcl.h>
#include <iostream>
#include <conio.h>
#include <iomanip>
#include <stdio.h>
int main()
{
using namespace std;
int i;
float f;
cout << "Pleace enter i and f >" << endl;
cin >> i >> f;
cout << i << endl;
cout << f << endl;
cout << hex << i << endl;
cout << oct << i << dec << i << endl;
cout << showpos << i << endl;
cout << setbase(16) << i << endl;
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;
cout << scientific << setprecision(10) << f << endl;
cout.precision(6);
cout << f << fixed << endl;
getch();
}
Рисунок 3.
Объект (экземпляр класса) cin управляет вводом из буфера ввода, связанного с объектом stdin, объявленным в файле stdio.h. По умолчанию стандартные потоки в языках С и С++ синхронизированы. При вводе используется часть тех функций и манипуляторов, которые определены для cout. Это такие манипуляторы, как dec, hex, oct, ws и др.[7]
Пример программы с использованием объекта cin приведен в Исходном коде №6. Результат работы представлен на рисунке 4.
Исходный код №6.
#include <vcl.h>
#include <iostream>
#include <conio.h>
#include <iomanip>
#include <stdio.h>
void main()
{
using namespace std;
int i;
float f;
char c;
cout << "Please enter i,f,c and then input the string >" << endl;
cin >> i >> f >> c;
cout << i << endl << f << endl << c << endl;
char p[50];
cin >> ws >> p;
cout << p << endl;
cin.seekg(0);
cin.getline(p,50);
cout << p << endl;
getch();
}
Рисунок 4.
Заключение
Специалисты C++ рекомендуют использовать для ввода-вывода только потоки STL и отказаться от использования традиционного ввода-вывода в духе C. Однако, ничего не мешает, по крайней мере пока, использовать традиционную систему ввода-вывода. Более того, предусмотрена специальная функция для синхронизации ввода-вывода, выполненного посредством потоков и посредством старых функций.
Какой механизм использовать – вопрос предпочтений программиста, если работодателем явно непредписанно использование конкретного механизма. В любом случае для физического ввода-вывода используются вызовы операционной системы. Всё остальное – обёртка, набор более или менее удобных функций, или классов для взаимодействия с ОС.
Библиография
- Стивен Прата. Язык программирования C++. Лекции и упражнения — М.: Вильямс, 2017. Стр:968.
- Стивен Прата. Язык программирования C++. Лекции и упражнения — М.: Вильямс, 2017. Стр:969
- Липпман С., Лажойе Ж., Му Б. Язык программирования C++. Базовый курс – Вильямс, 2014. Стр:399
- Стивен Прата. Язык программирования C++. Лекции и упражнения — М.: Вильямс, 2017. Стр:973
- Мейерс С. Эффективное использование C++. 55 верных советов улучшить структуру и код ваших программ: Пер. с англ. — 3-е изд. — М.: ДМК пресс, 2006.
- Стивен Прата. Язык программирования C++. Лекции и упражнения — М.: Вильямс, 2017. Стр:975
- Стивен Прата. Язык программирования C++. Лекции и упражнения — М.: Вильямс, 2017. Стр:975
- Организационные аспекты закупки и поставки товаров в коммерческие предприятия (ИП Красильникова Э.В.)
- Юридическая ответственность (Особенности позитивной юридической ответственности )
- Законность и правопорядок (Гарантии законности и правопорядка: понятие и виды)
- Сущность и содержание основных проблем психологии эмоции (Аутогенная тренировка)
- Стресс на рабочем месте: причины, диагностика, создание системы профилактических мероприятий (Общая характеристика стресса)
- Особенности профессиональной мотивации служащих организации (Российская модель мотивации персонала)
- Понятие правового отношения (Содержание правоотношения)
- Понятие социального обслуживания (Правовые основы системы социального обслуживания )
- Оборотные активы предприятия (на примере АО «Колос»)(Понятие, классификация и состав оборотных активов предприятия)
- Основные функции в системе менеджмента (ООО «Продуктовый двор»)
- Технология «клиент-сервер» (Определение «Клиент-Сервера»)
- Разработка регламента выполнения процесса « Движение библиотечного фонда»