АвтоАвтоматизацияАрхитектураАстрономияАудитБиологияБухгалтерияВоенное делоГенетикаГеографияГеологияГосударствоДомДругоеЖурналистика и СМИИзобретательствоИностранные языкиИнформатикаИскусствоИсторияКомпьютерыКулинарияКультураЛексикологияЛитератураЛогикаМаркетингМатематикаМашиностроениеМедицинаМенеджментМеталлы и СваркаМеханикаМузыкаНаселениеОбразованиеОхрана безопасности жизниОхрана ТрудаПедагогикаПолитикаПравоПриборостроениеПрограммированиеПроизводствоПромышленностьПсихологияРадиоРегилияСвязьСоциологияСпортСтандартизацияСтроительствоТехнологииТорговляТуризмФизикаФизиологияФилософияФинансыХимияХозяйствоЦеннообразованиеЧерчениеЭкологияЭконометрикаЭкономикаЭлектроникаЮриспунденкция

Стандартные потоки ввода – вывода

Читайте также:
  1. Ввода (поступления)
  2. Внешние устройства — для ввода и вывода информации.
  3. ВНУТРЕННИЕ МАТЕРИАЛЬНЫЕ ПОТОКИ
  4. Временные русловые потоки.
  5. Выбор ячеек КРУ ввода.
  6. Глава 4 Невозможное возможно, или нестандартные методы
  7. Грузопотоки на карьерах.
  8. ДЕНЕЖНЫЕ ПОТОКИ
  9. Замыкание множества функциональных зависимостей. Аксиомы Армстронга (с доказательством). Расширенный набор правил вывода Дейта (с выводом).
  10. Инструкция для онлайн-ввода по 9 волне по проекту 7402.
  11. Информационные потоки в логистической системе
  12. Інфологічна модель представляє інформаційні потоки, сутності й зв'язку даної предметної області. Вона може бути представлена у вигляді ER-Моделі й реляційної схеми.

Итак, файл iostream.h содержит описание соответствующих классов и содержит определение объектов класса - стандартных потоков ввода – вывода:

cin -объект класса istream, связанный со стандартным буферизированным входным потоком (клавиатура)

cout -объект класса ostream, связанный со стандартным буферизированным выходным потоком (обычно экран дисплея)

cerr - объект ostream класса, связанный со стандартным небуферизированным выходным потоком (обычно экраном дисплея), в который направляются сообщения об ошибках

clog - объект ostream класса, связанный со стандартным буферизированнымвыходным потоком (обычно экраном дисплея), в который направляются сообщения об ошибках.

При включении в программу файла iostream.h автоматически создаютсяи доступныэти стандартные объекты – потоки, по умолчанию связанные с клавиатурой и с экраном дисплея. При желании можно разорвать эту связь и связать потоки с тем или иным файлом.

В том же файле для этих объектов (потоков) определены операции ввода и вывода данных, которыми являются перегруженные для данных потоковых классов сдвиговые операции >> и <<:

Операция ввода >> называется извлечением (чтением) данных из потока.

Операция вывода << называется включением (записью) данных в поток.

Такую роль конструкции >> и << играют только, если слева от них находятся объекты соответствующих классов:

Например,

cin >> имя переменной базового типа

cout << выражение базового типа

cerr << выражение базового типа

clog << выражение базового типа

Рассмотрим процесс ввода-вывода данных подробнее.

Внешнее (визуальное) представление данных не похоже на те внутренние коды, которые используются для их хранения внутри ЭВМ.

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

Поток при вводе и при выводе – это последовательность байтов (двоичных кодов фиксированной длины).

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

При вводе выполняется преобразование символов из потока (с клавиатуры) в двоичные коды внутреннего представления данных, при этом происходит автоматическое распознавание типов вводимых данных.

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

При выводе байты (коды) потока преобразуются в последовательность символов, выводимых на экран.

В языке Си необходимо с помощью средств форматирования указать правила преобразования и форму представления вводимой и выводимой информации.

В С++ имеется новый механизм автоматического распознавания типов вводимых и выводимых данных.

Операции ввода (>>) и вывода (<<) перегружены так, что при той же форме они выполняются по-разному в зависимости от типа правого операнда.

Операция вывода <<

Операция вывода должна уметь распознавать тип выводимых данных.

Операция вывода перегружена, она применима в той же форме к данным типа: char, unsigned shot, singed shot, unsigned int, singed int, unsigned long, singed long, float, double, long double, char*, void*.

Операция определена только для двух указателей, и этого достаточно т.к. все указатели, отличные от char*, автоматически приводятся к типу void*.

Операция ввода >>

Подобная ситуация и при вводе данных. Операция извлечения >> перегружена, т.е. с одинаковым обозначением существуют три по-разному выполнимые операции:

1) для целых чисел, 2) для вещественных чисел и 3) для строк

Все они по умолчанию игнорируют ведущие пробелы, и считывание идет до пробела или до первого недопустимого символа.

Чтение начинается с первого не пробельного символа и для чисел заканчивается при появлении нечислового символа

Для целых читаются также следующие символы +, -, и при 0x - A, a,B, b, C, c D, d, E,e, F,f

Для вещественных чисел читаются символы +, -, E, e, и точка.

Для строк чтение происходит до первого пробельного символа.

Напр., название инструмента char line [40]

cin>>line

С клавиатуры набирается название отбойный молоток <enter>

В line считается только первое слово и вместо пробела заносится нулевой код ‘\0’.

 

Таким образом, объекты cin и cout с операциями >> и <<, знают, как выполнять ввод-вывод значений различных типов.

 

При организации выводимых выражений следует учитывать низкий приоритет сдвиговых операций, т.к. операции ввода-вывода имеют тот же приоритет:

cout<< a+ b+ c;

cout << (a + b < c); cout << (7<<1);

 

cout << (x<0? –x: x);

 

Выражения с операциями >> и << должны возвращать значение (любая операция должна возвращать значение).

В соответствии с описанием перегрузок этих операций в файле iostream.h значением выражения

cout<< выражение

является ссылка на поток cout (фактически сам поток) и к результату операции включения как к объекту cout опять можно применить операцию включения <<. Аналогично и с операцией извлечения из потока cin >> (или ввода данных).

Позволительно при одном обращении к потоку несколько раз применять операции ввода (исключения из потока) и вывода (включения в поток):

 

cout << … << … << «\n Cтроковое значение \t «<<…;

 

int i, j, k;

cin >> i >> j >> k;

 

Значения для этих переменных во входном потоке должны разделяться обобщенными пробелами 1 2 3 < enter> либо 1 < enter>

2< enter>

3 < enter>

Можно ввести и больше данных, но почитается столько, сколько надо:

1 2 3 4 5 6 < enter>

 

Извлечение из потока cin происходит после сигнала от клавиши enter.

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

При вводе вещественных значений допустимы все формы их записи и с фиксированной точкой и с плавающей точкой. Если затем мы выведем значение переменной. Оно будет выведено по возможности с фиксированной точкой и по умолчанию будет использовано 7 цифр. Исключение составляют очень большие и очень маленькие числа.

float a; cin >> a; cout <<”a=”<< a;

1.23456789 a=1.234568

0.123456789e+1 a=1.234568

123456789 a= 1.234567e+08

0.0000000000112345678 a=1.123457e-11

 

В операции ввода - вывода целых чисел данные можно представлять в восьмеричном и шестнадцатеричном виде. В каком бы виде данные не вводились, по умолчанию они всегда выводятся в десятеричном виде. Также, если в операторе вывода стоят восьмеричные или шестнадцатеричные константы, выведутся десятеричные величины:

 

cout << 077777 << ««<< -0x7fff 32767 -32767

 

Ввод значений должен соответствовать диапазону значений данного типа. Например, если вводится слишком большое для данного типа значение данное не будет введено целиком, а будет обрезано в соответствии с внутренним представлением данного типа.

Значения указателей (адреса) выводятся в шестнадцатеричном формате, как было рассмотрено выше.

Вывод (ввод) данных числовых массивов производится поэлементно

float A[3];

for (int i=o; i<3; i++) { cin>> A [i]; cout << A[i] << ««;}

cout<< A - выведется значение указателя - адрес

cin>> A // Ошибка на этапе компиляции!

 

Имя массива – константный указатель. Вводить с клавиатуры значение константного указателя нельзя. Но ввести значение символьного массива – строку, используя указатель – имя массива можно.

 

Ввод – вывод символьных массивов:

char H [ ] = «Миру – мир»

cout << H; - выведется строка

char * ph =H;

cin>>ph; вводится новое значение с клавиатуры

cout << ph - выведется строка

сout << (void*) ph - выведется значение указателя – адреса

строки

сhar name[20]; cin >> name; - ввод строки.

 

 

Форматирование данных при обмене с потоками

При применении операций ввода – вывода к стандартным потокам по умолчанию устанавливаются стандартные форматы внешнего представления пересылаемых данных.

Например, при выводе данные занимают ровно столько позиций, сколько надо для их представления.

Форматы представления могут быть изменены программистом с помощью:

1) флагов форматирования класса ios

2) компонентных функций для управления форматами класса ios

3) с помощью манипуляторов потоков без параметров и с параметрами

Флаги

 

Флаги – представляют собой отдельные фиксированные биты чисел типа long. Эти фиксированные биты входят в компонент класса ios типа long:

 

long x_flags; // переменная, представляющая флаги – форматы

//наследуется всеми производными потоковыми классами

//флаги наследуются всеми потоками

 

Эта переменная анализируется при обменах, ее значение влияет на преобразование информации.

 

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

 

Компонентные функции класса ios: flags() и setf() предназначены для проверки значений флагов, для их установки и для их сбрасывания в исходные умалчиваемые значения.

Флаги могут обрабатываться как по отдельности, так и группами, когда отдельные флаги связаны побитовой логической операцией – дизъюнкцией (‘ | ’).

 

Рассмотрим флаги:

 

skipws = 0x0001 - пропуск (игнорирование) при операции извлечении из

потока обобщенные пробельные символы (действует

по умолчанию)

 

left =0x0002 – вывод с левым выравниванием

 

right = 0x0004 – вывод с правым выравниванием

 

internal=0x0008 - принятый в качестве заполнителя символ помещается

между числом и знаком числа или признаком системы

счисления.

 

 

dec = 0x0010 - десятичная система счисления

oct = 0x0020 - восьмеричная система счисления

hex = 0x0040 - шестнадцатеричная система счисления

 

showbase =0x0080 - выводить признак системы счисления (0x и 0);

 

showpoint = 0x0100 – печатать обязательно десятичную точку и следующие

за ней нули, даже для числа имеющего нулевую

дробную часть;

 

uppercase = 0x0200 – при выводе чисел использовать буквы верхнего

регистра (0X, E, ABCDEF)

 

scientific = 0x0800 – представление чисел в формате с плавающей точкой

мантисса имеет одну ненулевую цифру перед точкой

 

fixed = 0x1000 - представление в формате с фиксированной точкой,

причем количество цифр после запятой определяется

заданной по умолчанию точностью;

 

unitbuf = 0x2000 – очищает все потоки (сбрасывает содержимое буферов)

после каждого вывода

 

и т. д.

 

Можно использовать имена флагов, естественно с указанием их принадлежности классу ios (ios::left) или непосредственно значения флагов

Как установить и проверить значения флагов рассмотрим ниже.

 

Компонентные функции класса ios для форматирования

 

char fill (); – возвращает символ заполнения пустых позиций вывода

char fill (char);– замещает символ заполнения пустых позиций вывода,

возвращает предыдущий символ заполнения

Значение символа (кода символа) заполнения хранится в

компонентной переменной класса int x_fill

 

long flags (); – возвращает текущий набор битов флагов форматирования

 

long flags (long);– устанавливает флаги в соответствии со значением

параметра, возвращает предыдущее значение флагов

 

int precision (); -возвращает текущее значение точности вывода

вещественных чисел

int precision (int n); - устанавливает по значению параметра

точность представления вещественных чисел, т.е.

количество цифр дробной части при выводе,

передает значение в переменную int x_precision,

возвращает предыдущее значение точности

 

long setf (long); - устанавливает набор флагов в соответствии с параметром,

возвращает значение старого набора;

long setf (long setbits, long field); - устанавливает флаги в соответствии со

значением параметра setbits; биты, которые дает параметр

field,сбрасываются и устанавливаются новые биты.

 

int width (); - возвращает текущее значение ширины поля вывода

 

int width (int); - устанавливает значение ширины поля вывода, в

соответствие со значением параметра, значение

сохраняется в переменной int x_width, функция

возвращает старое значение

 

и т. д.

 

 

В классе ios имеются три компонента – статические константы (общие для всех объектов класса (обращение: ios:: имя), объединяющие несколько флагов

static const long adjustfield; // left |right | internal

static const long basefield; // dec | oct | hex

static const long floatfield; // scientific | fixed

Используются в качестве второго параметра в функции setf () для сбрасывания флагов.

 

 

Обращения к функциям

void main()

{clrscr();

cout.width(15); // ширины вывода

cout.fill('*'); // установка символа заполнителя

cout.setf(ios::internal); // заполнить между знаком и значением

cout<<-5.35<<endl; // -**********5.35

cout.setf(ios::left,ios::adjustfield); //сбросили правое выравнивание,

//установили левое

cout.width(15);

cout<<-32767<<endl; //-32767*********

cout.setf(ios::hex,ios::basefield); //сбросили старую систему, установили

// новую систему счисления

cout.width(15);

cout<<32767<<endl; // 7fff***********

cout.setf(0x0200|0x0080); //показать признаки системы и верхн. рег.

cout.width(15);

cout<<32767<<endl; // 0X7FFF*********

cout.setf(ios::right,ios::adjustfield); // правое выравнивание

cout.width(15);

cout<<32767<<endl; // *********0X7FFF

cout.fill('.');

cout.setf(ios::internal,ios::adjustfield);

cout.width(15);

cout<<32767<<endl; // 0X………7FFF

cout.fill('+');

cout.setf(ios::right,ios::adjustfield);

cout.width(15);

cout<<32767<<endl; // +++++++++0X7FFF

 

}

 

Манипуляторы

Более простой способ форматирования – это использования манипуляторов.

Манипуляторы – это специальные функции позволяющие изменять флаги потока.

Имена манипулятора, если манипулятор без параметров, и вызовы функции-манипулятора с параметрами можно использовать в качестве правого операнда операции ввода-вывода.

Манипуляторы можно включать в цепочки включений в поток и извлечений из потока.

Манипуляторы изменяют состояние потока.

 

Манипуляторы без параметров

 

dec - действует при вводе и выводе, устанавливает флаг десятичной

системы

hex - действует при вводе и выводе, устанавливает флаг

шестнадцатеричной системы

oct - действует при вводе и выводе, устанавливает флаг восьмеричной

системы

 

endl - действует только при выводе, обеспечивает включение в поток

символа новой строки и сбрасывает буфер

ends - действует только при выводе, обеспечивает включение в поток

нулевого признака конца строки

flush - действует только при выводе, обеспечивает сбрасывание буфера

ws - действует только при вводе, обеспечивает извлечение из входного

потока пробельных символов (пробел, ' \t’, ‘\v’, ‘\n’, ‘\r’, ‘\f’)

hex, oct, dec изменяют состояние потока до следующего явного изменения

 

Манипуляторы с параметрами (определены в файле iomanip.h)

 

setbase (int n) - устанавливает основание системы счисления

 

cout << setbase (8) << 255 <<setbase (16) << 255 377 ff

 

resetiosflags (long L) -сбрасывает отдельные флаги

 

setiosflags (long L) - устанавливает отдельные флаги

 

cout<<setw(5)<< setiosflags(ios::left)<<5<<»\n»<<setw(5)<<

 

resetiosflags(ios::left) <<5; 5

 

setfill(int n) - значение параметра – код заполнителя

 

for (int i=0; i<3; i++) cout <<setfill(46)<<setw(5+i)<<i+1<<»\n»;

….1

…..2

……3

 

setprecision(int n) -определяет точность представления числа при вводе –

вывода вещественного числа, количество цифр

дробной части

for(int i =0; i< 4; i++) cout<<setprecicion(i)<<1.2345<<»\n» 1.2345

1.2

1.23

1.234

 

setw(int n) - параметр задает поле вывода

При использовании манипулятора setw как и член – функции width необходимо указывать требуемую ширину отдельно для каждого выводимого значения.

 

cout << setiosflags(ios::scientific)<< 0.000123; 1.23e-04

 

cout << setiosflags(ios::fixed)<< 0.000123; 0.000123

 

Ввод-вывод для типов, определенных пользователем

 

Необходимо расширить действие операций >>и << на данные производного типа.

Это делается с помощью операций – функций (перегрузка операций). Первый параметр операции - функции ссылка на объект класса (поток). Второй параметр - ссылка на объект желаемого типа для ввода или сам желаемый тип для вывода.

Тип возвращаемого результата – ссылка на объект класса, т. е. на поток

 

Пример Вывод структуры

#include <iostream.h>

struct st // объявлена структура

{char* name; long sh, cen;}zap1 ={ «ножницы», 1756, 43};

st A [5];

// перегрузка операции включения в поток:

ostream& operator << (ostream& out, st& zap) //операция- функция для

//вывода структуры на экран

{ out << «\n»<<zap.name<<»» << zap.sh<<» «<< zap.cen

return out; }

 

/*Эквивалентно было написать:

{ return cout << «\n»<<zap.name<<»» << zap.sh<<» «<< zap.cen;} */

 

// Перегрузка операции извлечения из потока:

istream& operator >> (istream& in, st & zap) //операция функция для ввода

// с клавиатуры структуры

{ in >> zap.name >> zap. sh >> zap.cen; return in;}

// вводятся три значения через <enter

/* Или эквивалентно:

{ return in >> zap.name >> zap. sh >> zap.cen;} */

 

… void main()

{ … for(int I=0; I<5; I++) {cin>> A[I]; cout<< A[I];}

cout<<zap1<<A[0];…

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

Функции для обмена с потоком

Кроме операций включения >> в поток и извлечения <<из потока имеются альтернативные компонентные функции ввода – вывода.

Функции вывода

В классе выходного потока определены две функции для двоичного вывода данных в стандартный поток:

ostream & ostream::put(char c);

 

ostream & ostream::write (const signed char * array, int n);

 

ostream & ostream::write (const unsigned char * array, int n);

 

Функция put (‘ ‘) помещает в выходной поток (объект для которого она вызвана) символ – параметр:

cout.put(‘ X’) (аналогично cout<<’X’;)

Первый параметр функции write - указатель array на символьный массив на участок оперативной памяти из которого извлекаются побайтно данные для вывода в поток, параметр n определяет количество выводимых байт.

 

Флаги форматирования и компонентные функции для форматирования не применимы к функциям put и write. Т.е. в отличии от операции включения в поток << эти функции не обеспечивают форматного вывода, напр., символ выводится всегда в одну позицию потока.

Функции put и write возвращают указатель на объект (поток), поэтому из них также можно составлять цепочки вывода

 

char mas[] =”Миру-мир”;

int r = sizeof (mas) -1;

cout.put(‘\n’). write (mas, r). put(‘!’). put(‘\n’);

 

//Миру-мир!

Функции чтения

Если надо прочитать строку символов, содержащую пробелы, то с помощью операции это сделать не просто – каждое чтение выполняется до пробела, а ведущие левые пробелы игнорируются.

Это легко можно сделать с помощью функций класса istream – функций бесформатного двоичного чтения.

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

 

Двоичное чтение – это чтение любой информации как последовательность байт. Данные читаются без преобразования.

Напр., если во входном потоке находится представление вещественного числа 1.7E-2, то оно будет воспринято как последовательность из шести байт, и читать эту последовательность с помощью функций двоичного ввода можно только в символьный массив из 7 символов.

1) istream & get (signed char* array, int n, char=’\n’);

2) istream & get (unsigned char* array, int n, char=’\n’);

Функции извлекают последовательность n-1 байтов из потока и переносят их в символьный массив (буфер), задаваемый первым параметром. Затем в массив помещается концевой символ ‘\0’.

Если раньше встретился ограничительный символ – третий параметр, то чтение прекращается, сам ограничитель не извлекается из потока, в формируемую строку не переносится, а помещается концевой символ ‘\0’.

Таким образом, массив должен иметь длину не менее n символов. Если встретился EOF, то он воспринимается как ограничительный символ.

 

3) istream & get (signed char & c);

 

4) istream & get (unsigned char & c);

 

Извлекают один символ из потока и присваивают его параметру

 

5) int get ();– Возвращает код извлеченного символа, если поток пуст

возвращает код конца файла.

 

 

6) istream & getline (signed char* array, int n, char=’\n’);

 

7) istream & getline (unsigned char* array, int n, char=’\n’);

 

Аналогичны первым двум функциям, но удаляется из входного потока и символ ограничитель.

 

8) int peek();

Возвращает код очередного символа потока (или EOF, если поток пуст)

 

char ch; while(cin.peek()!= ‘\n’) { cin.get(ch); cout.put (ch);}

 

9) istream & putback(char);– помещает символ в поток, он и будет

следующим читаемым символом

 

 

10) istream & ignore (int n=1, int m = EOF); - позволяет проигнорировать

n символов потока, m -символ ограничитель.

 

11) istream & read (signed char* array, int n);

 

12) istream & read (unsigned char* array, int n);

 

Считывают из потока n символов в массив array

 

13) istream & seekg (long pos); -устанавливает позицию чтения

 

14) istream & seekg (long pos, seek_dir dir);

где параметр dir принимает значение из перечисления

enum seek_dir {ios:: beg, ios::cur, ios::end}

pos - относительная величена смещения (в байтах) указателя во

входном потоке, относительно трех ориентиров.

15) ostream & seekp(long pos); - устанавливает позицию записи в поток

16) ostream & seekp(long pos, ios:: beg)

15) long tellg(); - определяет текущую позицию чтения

16) long tellp(); определяет текущую позицию записи

Строковые потоки (обмены в оперативной памяти)

Классы istrstream, ostrstream, strstream предназначены для создания потоков, связанных с участками основной памяти. Такие участки определяются часто как символьные массивы. Объекты (потоки) названных классов называют строковыми потоками.

Определение:

Определяется строковый поток и одновременно связывается с участком ОП с помощью конструктора с параметром (по правилу создания объекта с помощью вызова конструктора с параметрами)

 

<Имя класса> < имя потока(объекта)> (параметры конструктора)

 

Входные строковые потоки (из которых читают) создаются с помощью вызова следующего конструктора

 

istrstream in (char *str);

параметр str указывает на существующий участок памяти

Пример: char buf [80];

istrstream in (buf);

 

Входной строковый поток in связан с участком памяти, выделенным под массив buf. Теперь используя поток in и операцию >> можно из массива buf считывать значения, в какие либо данные.

 

Пример:

#include <strstrea.h>

void main()

// выделяем область памяти для обмена

{char*stroka=”1436.7 Auda!”

istrstream instr (stroka);

char mas[10];

float b;

instr>> b>> mas; //распаковка строки

cout << b << “ “ << mas << endl;

}

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

char * stroka = “ 1917 \t – год революции “

istrstream instr (stroka);

char array [80];

instr.getline (array, sizeof(array), ‘\0’);

cout<<array;…

 

1917 - год революции

 

Безымянные входные потоки – это создание безымянного объекта

Вызывается конструктор без имени

char* stroka = “ … “

char array [50];

istrstream (stroka)>>array; // введет до первого пробела

… istrstream (stroka).getline(array, 50, ‘\0’)// введет всю строку опять с ее

//начала

 

 

Выходные строковые потоки (связывается с участком ОП для вывода данных) создается вызовом конструктора с параметрами

 

ostrstream outstr (char*str, int n, int mod)

 

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

ios:: out

- строковый поток создается для вывода, запись информации ведется с начала строки, выбирается по умолчанию.

ios::ate (ios:: app)

- позиция записи в месте нахождения символа ‘\0’(продолжение записи)

Пример безымянного выходного строкового потока

#include < strstrea.h>

void main()

{ char buf [80];

char al [ ]=«\nБез включения разделителей «

char ol [ ] =«текст\n\»сливается\».\n»

ostrstream (buf, sizeof(buf)).write(al, sizeof(al));

ostrstream (buf, sizeof(buf), ios:: ate).write(ol, sizeof(ol));

cout << buf<<endl;

 

Без включения разделителей текст

«сливается».

Функция write() вызывается для безымянного потока. Запись идет в массив buf[ ]. Вывод в строку с помощью write идет подряд и без форматирования. Строка al записывается в buf[ ] вместе с пробелами и признаками конца строки. Байтовый ноль в строку переносится. Т.к. длина строки меньше длины буфера, то буфер не заполнится целиком. При создании второго безымянного потока с помощью конструктора, в качестве третьего параметра указывается флаг ios:: ate, что означает, что поток открыт для дополнения. Последняя запись в поток осуществляется, начиная с позиции символа ‘\0’ предыдущей записи, туда адресуется строка ol. Т.е. в buf[ ] запишется результат конкатенации строк, который и выведется на экран последним оператором.

 

Используем для вывода операцию включения в поток <<.

Будем использовать для разнообразия именованный поток.

 

…{

ostrstream outstr(stroka, sizeof(stroka), ios::out | ios::ate) // мода для до-

//полнения строки

outstr<<”\nБез включения разделителей»

<<«текст\n\»сливается\».\n»

<< 12345<<-4.67<<+1.456<<ends;…

cout<< stroka;}

 

Без включения разделителей текст

«сливается».

12345-4.67 1.456

 

При создании потока (для дополнения) указатель потока устанавливается на начало потока, а затем перемещается на длину каждой новой записи без промежутков. При использовании операции включения в поток << даже

байтовый ноль ’\0’ в строку-буфер не переносится и его надо добавлять явно, если надо использовать буфер потока(stroka) в качестве строки. Числовая информация, включаемая в поток, форматируется, средства изменения форматов были рассмотрены выше.

Знак “+” заменяется пробелом.

Двунаправленные потоки

Конструктор строковых потоков для чтения и для записи имеет вид:

 

strstream outstr (char*buf, int n, int mod)

 

buf – указатель на участок памяти (буфер потока);

n – размер в байтах участка памяти

 

Третий параметр – это дизъюнкция флагов

ios:: in ios::out – определяет направление потока

ios::ate ios app –влияют на размещение указателя позиции чтения или записи в буфере.

Пример 1:

#include <strstrea.h>

void main ()

{ char buf [100];

char s [80];

 

// объявляем двунаправленный строковый поток, связанный с массивом buf[]

strstream iostr (buf, sizeof(buf), ios:in |ios::out);

iostr<< “Строковый поток связан с участком ОП.” <<ends;

//позиция записи сместилась в конец потока, позиция чтения на начале //потока

iostr>>s; cout<<’\n’<< s; // читает до пробела

iostr>>s; cout<<’\n’<< s; // читает следующее слово

// установим позицию чтения на начало потока и прочитаем весь буфер

iostr.seekg (0L, ios::beg);

iostr.getline(s, sizeof(s), ‘\0’); // копирование из буфера потока buf в s

cout<<’\n’<<s;

Результат:

Строковый

Поток

Строковый поток связан с участком ОП.

Пример 2:

#include <strstrea.h>

#include<conio.h>

char link[200]; // массив для буфера

 

strstream obmen (link, sizeof(link), ios::in |ios::out);// определение

//двунаправленного потока

 

struct elem { int nk, nl; float nz;}; // определена структура

 

strstream &operator >> (strstream & in, elem & el)// перегрузка операции

{in >> el.nk >> el. nl >>el.nz; return in;} //ввода

 

 

ostream &operator << (ostream & out, elem & el)// перегрузка операции

{ out << el.nk <<"\t " << el. nl << "\t " <<el.nz<<"\n"; return out;}

// вывода

 

// функция чтения из потока

void res(void)

{ elem elz; //объявлена структура

int num;

obmen >> num;

cout << num<<'\n';

for(int i=0; i< num; i++) { obmen >> elz; cout<<elz;}

}

void main()

{clrscr();

// char buffer [180];

elem arel[5]={{ 1, 2,3.45}, {3, 4, 4.56},

{5, 6, 5.7}, {7, 8, 7.7 },

{ 9, 10, 7.7}};

int k=5;

obmen << k<<" ";

for(int i=0; i< 5; i++)

obmen << arel[i];

obmen<<ends;

res ();

}

Результат:

1 2 3.45

3 4 4.56

Перегрузка операции включения << для базового потока класса ostream наследуется производным классом strstream для строковых потоков. Поэтому дополнительно для строковых потоков перегружать эту операцию не надо.

 

Работа с файлами

Информация во внешней памяти сохраняется в виде файлов – именованных участков внешней памяти (жесткого диска, гибкой дискеты, электронного виртуального диска). Файлы позволяют сохранять информацию при отключении компьютера (в отличие от ОП). Под файлом понимают также логическое устройство – потенциальный источник или приемник информации.

В файлы можно как помещать данные, так и извлекать их из файлов. Такие действия имеют общее название ввод-вывод.

Функции С++ позволяют читать данные из файлов в ОП, получать их с устройств (напр. с клавиатуры), и записывать данные из ОП в файл или выводить их на различные устройства, напр. на экран или на принтер.

 

Средства ввода-вывода языка С++ можно разделить на три группы:

0 ввод-вывод верхнего уровня – потоковый

а) библиотека функций Си - интерфейс в файле stdio.h

б) библиотека классов С++ -интерфейс в файле fstream.h

1 ввод-вывод нижнего уровня (системный ввод- вывод)-файл io.h

2 ввод-вывод для консоли и портов – интерфейс в файле conio.h

 

Библиотека ввода-вывода С++ включает средства для работы с последовательными файлами, представляющими собой именованную последовательность байтов, имеющую начало и конец. Чтение из файла или запись в файл ведутся байт за байтом, позиции в файле, откуда производится чтение, или куда ведется запись, определяются указателем позиции файла. Указатель позиции записи или чтения устанавливается либо автоматически, либо с помощью функций управления положением его можно установить на нужный байт.

 

 

Ввод-вывод нижнего уровня

 

Функции ввода – вывода низкого уровня позволяют пользоваться средствами ввода-вывода операционной системы непосредственно.

При этом не выполняется буферизация и форматирование данных при обмене.

При низкоуровневом открытии файла с ним связывается целое значение - дескриптор файла (логический номер файла, идентификатор файла), которое назначается операционной системой.

Дескриптор файла характеризует его размещение во внутренних файловых таблицах операционной системы.

Основные функции нижнего уровня:

0 open() / close() – открыть / закрыть файл

1 creat() – создать файл

2 read ()/ write() – читать / писать данные

3 eof () – проверить достижение конца файла

4 lseek() – изменить текущую позицию в файле

5 tell () – получить значение текущей позиции в файле

 

Текстовой и бинарный файлы

 

Текстовой файл представляет собой последовательность символьных строк переменной длины, разделенных комбинацией символов “перевод каретки” (символ с кодом 13) и символ “перевод строки” (символ с кодом 10).

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

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

Кроме того в текстовом режиме при чтении из файла два символа CR (0x0D-конец строки – код 13) и LF (0x0A- переход к началу строки – код 10) преобразуются в один символ новой строки ‘\n’.

При записи в текстовой файл символ новой строки преобразуется в два символа CR и LF.

 

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

 

Создание файла

(на нижнем уровне)

 

Функция по заданному имени (path) создает новый файл или очищает и подготавливает к работе уже существующий файл.

 

int creat (const char *path, int mode); // прототип в файле < io.h >

 

Параметр mode определен в файле <sys\stat.h>

равен: S_IWRITE - для записи

S_IREAD - для чтения

S _IREAD | S_IWRITE - для записи и чтения

 

Файл создается для работы в режиме обмена либо текстовом (по умолчанию) либо бинарном.

Таким образом файл может создаваться для текстового режима обмена данными или для двоичного. Для установления режима обмена при создании файла надо глобальной системной переменной _fmode, определенной в файлах fcntl.h и stdlib.h надо задать соответствующее значение:

#include < fcntl.h>

_fmode = O_BINARY // по умолчанию O_TEXT

 

Функция creat() возвращает индивидуальный логический номер файла, идентификатор файла, дескриптор файла при создании файла и –1 при неуспешном завершении.

Пример использования функции:

# include <iostream.h>

#include <io.h>

#include<sys\stat.h>

… int fd;

fd = creat (“ examp.cpp”, S_WRITE);

if(fd = = -1) cout<<”Ошибка”…

По умолчанию создастся текстовой файл.

 

Открытие и закрытие файлов

 

int open (const char *path, int mode); // прототип в файле < io.h >

 

int fd=open(имя файла, флаги); // вызов функции

 

Первый параметр задает имя файла

Параметр mode определяет режим открытия файла, представляет результат битовой дизъюнкции флагов обмена, определенных в файлах <sys\stat.h> или

fcntl.h:

O_APPEN – открыть для дополнения;

O_BINARY – открыть в бинарном режиме;

O_CREAT – создать и открыть новый файл;

O_EXCL – в сочетании с O_CREAT создает только новый файл, если

файл существует, он не стирается, выводится сообщение об

ошибке;

O_RONLY – открыть только для чтения;

O_RDWR – открыть и для чтения и для записи;

O_TEXT – открыть в текстовом режиме;

O_TRUNC - открыть существующий файл и стереть его содержимое;

O_WRONLY- открыть только для записи.

 

Режим открытия должен устанавливаться явно, т.к. умолчания нет.

Вызов функции creat () эквивалентен вызову:

 

open(имя файла,O_CREAT|O_TRUNC|O_WRONLY).

 

Для закрытия файлов функция:

int close(дескриптор файла)

Возвращает 0 при успешном закрытии и -1 в случае ошибки.

 

Чтение и запись данных

 

int read(int fd, char* buffer, unsigned int count)

 

– читает count байт из файла, с дескриптором fd в буфер buffer.

Возвращает число байт, помещенных в буфер;

0 – при достижении конца файла; - 1 – при возникновении ошибки чтения.

Чтение идет с текущей позиции в файле. В текстовом режиме идет преобразование двух символов к одному ‘\n’ и в возвращаемом значении вместо двух символов учитывается один.

 

int write(int fd, char* buffer, unsigned int cout)

 

- записывает count байт из буфера buffer в файл, открытый с дескриптором fd.

Запись идет с текущей позиции. Возвращает количество реально записанных байтов, в текстовом режиме это количество будет превышать количество реально записанных байтов за счет преобразования ‘\n’ в CR и LF.

Возвращает –1 при ошибке записи (напр. нет места на диске).

Копирование файла

void main()

{ int fdin, fdout, n;

char buf[512]; // размер стандартного буфера – размер кластера

if(fdin =open(“f1.dat”, O_RDONLY) = = -1) {cout<<”Ошибка 1”; exit(1);}

if(fdout =open(“f2.dat”, O_WRONLY|O_CREAT|O_TRUNC) = = -1) {cout<<”Ошибка 2”; exit(1);}

while (n=read(fdin, buf, 512)>0)

write(fdout, buf, n);

}

Произвольный доступ к файлу

 

При необходимости файл можно читать не последовательно, а в произвольном порядке. Функция для изменения текущей позиции чтения/ записи в файле:

long lseek(int fd, long offset, int origin)

 

Изменяет позицию в файле с дескриптором fd относительно origin на offset байт.

Параметр origin задает точку отчета:

SEEK_SET = = 0 - начало файла

SEEK_CUR = = 1 - текущая позиция

SEEK_END = = 2 – конец файла.

Возвращает новую позицию в файле от начала, от нуля.

 

lseek(fd, 0L, SEEK_SET); -установка на начало

lseek(fd, 0L, SEEK_END); -установка на конец файла

 

Функция определяющая текущую позицию в файле

long tell(int fd);

 

read(fd, buf, sizeof (запись));

lseek(fd, - sizeof (запись),SEEK_CUR);

write(fd, buf, sizeof(запись));…

 

Полезные функции:

 

Как правило, параметру для дескриптора файла во всей литературе дают имя handle

1) long filelength (int handle);

 

- возвращает длину файла связанного с дескриптором handle в байтах.

… int n = filelength(fd) / sizeof(запись); … //количество записей в файле

 

2) int chsize (int handle, long size);

 

- изменяет длину файла, связанного с handle – усекает его или расширяет в зависимости от соотношения между size и первоначальной длины файла, size новая длина файла. При расширении новое место заполняется символами \0.

Возвращает 0, если изменение прошло успешно и –1, если нет.

 

3) int remove (const char*filename);

 

- уничтожает существующий на диске файл с именем filename, который перед удалением должен быть закрыт.

Возвращает 0, если удаление прошло успешно и –1, если нет.

 

4) int rename (const char*oldname, const char*newname)

 

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

Новое имя newname должно быть оригинально на диске.

Возвращает 0, если переименование прошло успешно и –1 -, если нет.

 

 

Потоковый ввод- вывод на базе библиотеки классов

 

Рассмотрим механизмы выполнения основных работ с файлами на базе связи файлов с потоками ввода-вывода.

Основные виды работ с файлами

1. создание файла;

2. создание потока;

3. открытие файла;

4. присоединение файла к потоку

5. обмены с файлом с помощью потока

6. отсоединение потока от файла

7. закрытие файла

 

 

Создание потоков

 

Потоки для работы с файлами – объекты следующих классов:

 

ofstream - для записи данных в файл

ifstream - для чтения данных из файла

fstream - для чтения и записи данных

 

Описание этих классов находится в файле < fstream.h>

 

Определение потоков - объектов классов

(первый способ – создание объекта с помощью конструктора по умолчанию)

 

ofstream Fout //выходной файловый поток

 

ifstream Fin //входной файловый поток

 

fstream Fio //входной выходной файловый поток

 

При таком создании под объекты выделяется память – это буфер обмена и инициируются переменные, характеризующие состояние потока

 

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

 

Создав файловый поток, нужно присоединить его к конкретному файлу с помощью компонентной функции open ().

 

Эта функция открывает файл (если он существует) или создает новый файл и связывает его с потоком

void open (const char* filename, int mode= умалчиваемые значения,

int protection= умалчиваемые значения)

 

Первый параметр – имя файла.

Второй - дизъюнкция флагов, определяющих режим работы с файлом

ios:: in = 0x01 // открыть только для чтения

 

ios:: out = 0x02 // открыть только для записи

 

ios:: ate = 0x04 // при открытии искать конец файла

 

ios:: app = 0x08 // дописывать данные в конец файла

 

ios::trunc= 0x10 //вместо существующего создать новый файл

 

ios::nocreate=0x20 //не открывать новый файл, (ошибка, если файл не

существует)

ios::noreplace=0x40 // не открывать существующий файл

 

ios::binary = 0x80 // открыть для двоичного обмена

 

Умалчиваемое значение параметра mode для потока класса ifstream равно

ios::in для потока класса ofstream равно ios::out.

 

Для третьего параметра, определяющего защиту, используется умалчиваемое значение, которое всегда устраивает пользователя.

Вызов компонентной функции осуществляется с помощью уточненного имени:

Имя объекта. вызов компонентной функции

 

Имя потока. open(имя файла, режим, защита)

 

Fout. open(“ D:\\ DATA\\work.dat») // по умолчанию ios::out, если файл не существует, он будет создан и присоединен к потоку Fout.

Применяя к потоку операцию включения Fout << …

или вызывая компонентные функции Fout.put(‘…’) или Fout.write(…), запись будет производиться в файл.

 

Fin.open(«result.txt») // по умолчанию ios::in, если файл не существует, то вызов функции приведет к ошибке. Существующий файл присоединяется к потоку Fin.

Применяя операцию извлечения Fin>>…, или вызывая компонентные функции Fin.get(…), Fin. getline(…), Fin.read(…)можно читать из файла

 

Fio.open(«change.dat», ios::out) // файл открыт для записи и будет иметь такую направленность до закрытия, потом его можно вновь открыть для считывания.

Для проверки удачности завершения open() существует перегруженная для классов потоков операция!. Если ошибок не было, то! имя потока выражение имеет нулевое значение, противном случае не нулевое.

(Если!поток равно нулю, то все хорошо, т.е. поток не должен быть нулевым)

if(! Fin) { cout<< «ошибка при открытии файла»<<endl; exit(1);}

 

Закрытие файла

 

имя файлового потока(присоединенного к файлу). close()

Чтобы изменить режим доступа к файлу, его надо закрыть и открыть вновь в нужном режиме.

 

 

Присоединение к потоку, используя дескриптор файла

 

Если файл был открыт с помощью функции creat(), то для присоединения к файловому потоку можно использовать компонентную функцию attach (), доставшуюся по наследству от базовых классов. Эта функция имеет параметром дескриптор открытого файла

 

… int descrip= creat («имя_файла», S_WRITE);

 

… ofstream Fout; //определение потока

Fout.attach (descript);// присоединение файла с дескриптором descript к

//потоку Fout

if(!Fout) { cerr<<»ошибка присоединения файла»; exit(1) }

 

 

Определение потоков - объектов классов с присоединением потока к физическому файлу

(второй способ – создание объекта с помощью конструктора с параметрами)

 

Первый параметр конструктора – имя физического файла, второй -мода.

ifstream input («filename.ext», ios::in)

 

ofstream output(«filename.out», ios::out)

 

fstream ioput («…»,ios:: out)

 

После можно писать в файл и читать из файла

input.read (buffer, number_of_buffer)

 

output.write(buffer, number_of_buffer)

 

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

 

Удобно использовать компонентную функцию этих классов

 

int eof()

Возвращает ненулевое значение, имеет место условие конца файла.

 

Перегрузка операций ввода – вывода

 

Пример функции записи в текстовой файл (напр. создание файла данных)

и чтения из текстового файла.

 

#include <fstream.h>

#include <iomanip.h>

ofstream fout;

ifstream fin;

struct st

{ char name [20]; long sh, cen;}zap[3]={ {"yy yyy", 1745,186},

{"oooo", 1234,78},

{"ddddddddd", 3421,96}};

//перегрузка

ofstream & operator << (ofstream& out, st zap2)

{ out <<setw(9)<<zap2.name <<" " <<zap2.sh<<" " << zap2.cen << "\n";

return (out);}

 

ifstream& operator >> (ifstream& fin, st& zap)

{ char ch[5];

fin.getline(zap.name,10); fin >> zap.sh >> zap.cen;

fin.getline(ch,5,'\n');

return fin;}

 

struct st zap1;

void main()

{

fout.open("\\myf");

for(int i=0; i< 3; i++)

fout<<zap[i];

fout.close();

fin.open("\\myf");

лев. выр. 10сс призн. сс.0 +

//cout << cout.setf(0x0002|0x0010|0x0080|0x0200|0x0400);

16сс

//cout << cout.setf(0x0002|0x0040|0x0080|0x0200);

 

for(int i=0; i<3; i++)

{fin>> zap1;

 

cout <<"\n"<< zap1.name << setw(15)<<zap1.sh <<setw(15)<<zap1.cen<<"\n"; }

 

fin.close();

}

/*

// запись и считывание в режиме бинарного обмена с использованием

перегруженных операций << и >>

 

#include <fstream.h>

#include <iostream.h>

#include <iomanip.h>

ofstream fout;

ifstream fin;

struct st

{ char name [20]; long sh,cen;}zap[3]={ {"yy yyy", 1745,186},

{"oooo", 1234,78},

{"ddddddddd",3421,96}};

 

ofstream & operator << (ofstream& out, struct st zap2)

{ out <<zap2.name<<’ ’<<zap2.sh<<" " <<zap2.cen<<" ";

return (out);}

 

ifstream& operator >> (ifstream& fin, struct st& zap)

{ fin.getline(zap.name,20,'\0'); fin >> zap.sh >> zap.cen;

return fin;}

 

struct st zap1;

void main()

{

fout.open("\\myf",0x80);

for(int i=0; i< 3; i++)

fout<<zap[i];

fout.close();

fin.open("\\myf",0x80);

 

for(int i=0; i<3; i++)

{ fin>> zap1;

cout <<setw(10)<< zap1.name << " "<<zap1.sh <<" "<<zap1.cen<<"\n";}

fin.close();

}

*/

//запись и чтение файла с помощью функций read и write

 

#include <fstream.h>

#include <iostream.h>

ofstream fout;

ifstream fin;

struct st { char* name; char* FIO; long sh, cen;}zap1,zap={ "rrrrr rrrrr",

"fff ff",1745,186};

void main()

{ st*p = &zap;

char *ss = (char*)p;

 

fout.open("\\myf",0x80);

 

fout.write(ss, sizeof(st));

fout.close();

fin.open("\\myf",ios::in|0x80);

fin.read((char*)&zap1,sizeof(st));

fin.close();

cout << zap1.name<<"\n"<<zap1.FIO<<"\n"<<zap1.sh<<"\n" <<zap1.cen;

}

 

Библиотека ввода-вывода Си (stdio.h)

 

Рассмотрим функции обмена верхнего уровня, которые обеспечивают

буферизацию данных при обмене с файлом.

Функции реализуют обмен с потоком-источником или приемником последовательности байт(в бинарном режиме) или последовательности строк (в текстовом режиме обмена)

Открытие файла

 

Объявляется указатель на структуру типа FILE, в которой должна будет содержаться информация о файле. Тип FILE определен в файле stdio.h

 

typedef struct

{shot level; // уровень буфера

unsigned flags; // флаг статуса файла

int fd; // дескриптор файла

…} FILE

 

Далее в программе должен быть объявлен указатель на структуру типа FILE (указатель на файловый поток):

#include<stdio.h>

FILE* F;

При открытии файла функцией fopen структуре типа FILE выделяется ОП, адрес которой, возвращает функция и происходит связь физического файла с указателем потока.

Прототип:

FILE* fopen (char *filename, char *type);

Вызов:

F = fopen (имя файла, режим открытия);

 

Параметр filename определяет полное имя физического файла

Параметр type определяет режим работы с файлом

«r» - чтение, файл должен быть создан

«w» - создание нового файла для записи

«a» -дополнение записи в конец файла

«+» -допускается чтение из файла и запись в файл

«wb» - запись в бинарный файл

«rb» -чтение из бинарного файла

и.т.д.

 

FILE *fid, frz, fin;

Fid= fopen («lr.dat», «r») - открыт для чтения

Frz=fopen(«lr.rez», «w») -открыт для вывода

Fin=fopen(«lr.res», «a+») - открыт для чтения и дополнения

 

При успешном выполнении функция возвращает указатель на FILE.

В противном случае возвращает NULL.

Закрытие файла

Функции закрытия файлового потока:

Прототипы:

int fclose(FILE* stream); int fcloseall();

вызов:

fclose(fid);

Возвращает 1-ая- 0 при успешном закрытии

2-ая –количество закрытых потоков

-1 при неуспешном закрытии.

 

Бесформатный ввод-вывод в текстовой файл

 

а) посимвольный, б) построчный

 

а)

Посимвольный ввод

int getchar(void), int fgetchar (void), -ввод символа с клавиатуры чтение из стандартного потока stdin

 

int getc (FILE*stream), int fgetc (FILE*stream) -ввод символа из входного

файла

int getch(void) – ввод символа с клавиатуры без эхопечати.

 

Посимвольный вывод

 

int putc (int c, FILE*stream); вывод символа в файл

int fputc(int c, FILE*stream);

 

void putch(int c), putchar(int c,) вывод символа на экран в стандартный поток stdout

 

б)

Построчный ввод – вывод

 

Ввод:

char* gets (char* string) – читает строку из стандартного потока до символа ‘\n’ и помещает ее по адресу параметра string, символ ‘\n’ не включается, результат дополняется символом ’\0’

 

char* fgets (char* string, int n, FILE*stream) – читает строку из файла

до 1) символа ‘\n’, который включается в строку

2) до конца файла

3) прочитано n-1 символ

результат дополняется символом ’\0’

Функции возвращают адрес строки string или NULL

 

Вывод:

int puts (char* string) – выводит строку string в стандартный поток stdout до символа ‘\0’ и помещает в довершение символ ‘\n’. После вывода строки курсор переместится на новую строку.

 

int fputs (char* string, FILE*stream) – выводит строку string в файловый поток stream до символа ‘\0’

Функции возвращают код последнего выведенного символа, или –1, если ошибка вывода.

 

Форматный ввод- вывод данных в текстовой файл

 

Функции ввода

int scanf (char*format [, arg, … ]);

int fscanf(FILE*stream, char*format [, arg, … ]);

 

И функции вывода

int printf(char*format [, arg, … ]);

int fprintf(FILE*stream, char*format [, arg, … ]);

 

Эти функции были рассмотрены ранее.

 

int sscanf (char*string, char*format [, arg, … ]);– читает даннае из строки

 

string, «распоковка» строки

 

 

int sprintf (char*string, char*format [, arg, … ]); - выводит данные в строку, расположенную в ОП. Функция преобразует данные – аргументы в символьный массив. Удобна при работе с графикой, когда нужно вывести на экран числа, а можно выводить только строки.

 

 

Функции printf () и scanf ()

- осуществляют форматированный вывод и ввод в стандартные потоки (по умолчанию на консоль)

- прототипы в файле STDIO.H

int printf (char * управляющая строка, arg…);

int scanf (char * управляющая строка, arg…);

1) первый параметр всегда символьная строка, содержащая некоторые символы и команды (спецификаторы) формата сообщающие какие данные надо вводить или как надо выводить аргументы.

Спецификаторы задаются с помощью знака % с буквами и цифрами

2) последующие параметры (их переменное число)- аргументы

для printf – это значения выражений, в частности числа, переменные, константы, строки.

для scanf – это список адресов переменных типы которых, указанных в строке формата для каждого аргумента последовательно (первый формат соответствует первому аргументу, второй – второму и т. д.)

printf

Функция printf() возвращает общее число выводимых значений при успешном выводе

Int result;

Result =printf (“ … \n”, …)

int

%d, %i – для вывода десятеричных значений;

%0 - в восьмеричном формате;

% x, % X –в шестнадцатеричном;

 

int v = 255;

printf (“ значение %d в восьмеричном формате %0\n”, v, v)

printf('' значение %d в шестн. формате %x и %X\n’’, v, v,v)

значение 255 в восьмеричном формате 377

значение 255 в шестн. формате ff и FF

unsigned int

%u unsigned int a = 42000

printf (“%u % d\n’’, a, a) 42000 -23536

 

long floatshot unsignedlong double

long int % ld % f % hu % lf

 

символы % и 0 и x,X

%% %#0 %#x %#X

char

% c printf (“ буква %c\n’’, ‘A’); буква А

printf (“ буква %c\n’’, 65); буква А

 

Вывод чисел с плавающей точкой в экспоненциальном виде: %e или %E

Float a=3.14159, b= 2.0031;

Printf (‘’ %e %E”, a, b)

3.14159e +00 2.0031E+00

на усмотрение машины %g

printf (“ %g\n’’, 0.1234); printf (“%g\n”,0.000001234)

0.1234 1.234e-06

Строки

%s char t [255]=” Pascal”;

printf (“ Название-%s\n”, t)

Название –


1 | 2 |

Поиск по сайту:



Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Студалл.Орг (0.3 сек.)