Скачать презентацию Потоки в С В языке Си нет Скачать презентацию Потоки в С В языке Си нет

Лекция6. Потоки_в_С++.ppt

  • Количество слайдов: 36

Потоки в С++ Потоки в С++

В языке Си++ нет особых операторов для ввода или вывода данных. Вместо этого имеется В языке Си++ нет особых операторов для ввода или вывода данных. Вместо этого имеется набор классов, стандартно поставляемых вместе с компилятором, которые и реализуют основные операции ввода-вывода. Библиотека классов для ввода-вывода решает две задачи. Вопервых, она обеспечивает эффективный ввод-вывод всех встроенных типов и простое, но тем не менее гибкое, определение операций ввода-вывода для новых типов, разрабатываемых программистом. Во-вторых, сама библиотека позволяет при необходимости развивать её и модифицировать.

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

Стандартные потоки iostream. h l cout, cin и cerr cout - стандартный вывод, cin Стандартные потоки iostream. h l cout, cin и cerr cout - стандартный вывод, cin – стандартный ввод, cerr – стандартный поток сообщений об ошибках. l cout и cerr выводят на терминал и принадлежат к классу ostream, cin имеет тип istream и вводит с терминала. l

Основные классы потоков ios — базовый класс потоков; istream — класс входных потоков; ostream Основные классы потоков ios — базовый класс потоков; istream — класс входных потоков; ostream — класс выходных потоков; iostream — класс двунаправленных потоков; istrstream — класс входных строковых потоков; ostrstream — класс выходных строковых потоков; strstream — класс двунаправленных строковых потоков; ifstream — класс входных файловых потоков; ofstream — класс выходных файловых потоков; fstream — класс двунаправленных файловых потоков; streambuf — буферизация потоков.

Вывод осуществляется с помощью перегруженной операции >>, ввод с помощью операции <<. cout << Вывод осуществляется с помощью перегруженной операции >>, ввод с помощью операции <<. cout << "Пример вывода: " << 34; int x; cin >> x;

Форматирование функции-члены; l флаги; l манипуляторы l Форматирование функции-члены; l флаги; l манипуляторы l

Класс ios class ios { // набор форматирующих методов public: int width(int w); // Класс ios class ios { // набор форматирующих методов public: int width(int w); // установить поле width int width() const; char fill(char); // установить символ заполнения char fill() const; // вернуть символ заполненияlong flags(long f); long flags() const; long setf(long setbits, long field); long setf(long); long unsetf(long); int precision(int); // установить точность для float int precision() const; //. . . };

Примеры: форматирующие методы #include <iostream. h> void main() { double values[] = { 1. Примеры: форматирующие методы #include void main() { double values[] = { 1. 23, 35. 36, 653. 7, 4358. 24 }; for( int i = 0; i < 4; i++ ) { cout. width(10); cout. width( 10 ); cout << values[i] << 'n'; cout. fill( '*' ); } cout << values[i] << endl; } 1. 23 35. 36 653. 7 4358. 24 ******1. 23 *****35. 36 *****653. 7 ***4358. 24

Форматирующие флаги // Класс ios const int my_io_options = enum { ios: : left|ios: Форматирующие флаги // Класс ios const int my_io_options = enum { ios: : left|ios: : oct|ios: : showpoint|ios: : fixed; skipws = 0 x 0001, //пропуск пробелов cout. flags(my_io_options); left = 0 x 0002, //выравнивание right = 0 x 0004, internal = 0 x 0008, cout. setf(ios: : scientific, ios: : floatfield); dec = 0 x 0010, //система счисления cout. setf(0, ios: : floatfield); // вернуться oct = 0 x 0020, к стандартному hex = 0 x 0040, cout. setf(ios: : hex, ios: : basefield); showbase = 0 x 0080, //показать основание с. с. showpoint = 0 x 0100, //нули в конце uppercase = 0 x 0200, //большие буквы для основания showpos = 0 x 0400, scientific = 0 x 0800, //научная форма числа fixed = 0 x 1000, //с фиксир. точкой unitbuf = 0 x 2000, //сброс в выходной поток stdio = 0 x 4000 }; static const long basefield; // dec | oct | hex static const long adjustfield; // left | right | internal static const long floatfield; // scientific | fixed

Манипуляторы – это объекты особых типов, которые управляют тем, как ostream или istream обрабатывают Манипуляторы – это объекты особых типов, которые управляют тем, как ostream или istream обрабатывают последующие аргументы. Некоторые манипуляторы могут также выводить или вводить специальные символы. endl при выводе перейти на новую строку; ends вывести нулевой байт (признак конца строки символов); flush немедленно вывести и опустошить все промежуточные буферы; dec выводить числа в десятичной системе (действует по умолчанию); oct выводить числа в восьмеричной системе; hex выводить числа в шестнадцатеричной системе счисления; setw (int n) установить ширину поля вывода в n символов (n – целое число); setfill(int n) установить символ-заполнитель; этим символом выводимое значение будет дополняться до необходимой ширины; setprecision(int n) установить количество цифр после запятой при выводе вещественных чисел; resetiosflags( long l. Flags ); Сбросить флаги ввода-вывода setiosflags( long Установить флаги ввода. вывода

Примеры: манипуляторы #include “iostream” #include “iomanip” void main() { double values[] = { 1. Примеры: манипуляторы #include “iostream” #include “iomanip” void main() { double values[] = { 1. 23, 35. 36, 653. 7, 4358. 24 }; char *names[] = { "Zoot", "Jimmy", "Al", "Stan" }; for( int i = 0; i < 4; i++ ) cout << setw( 6 ) << names[i] << setw( 10 ) << values[i] << endl; } Zoot 1. 23 Jimmy 35. 36 Al 653. 7 Stan 4358. 24 setw и width не отсекают данные при выводе

int x = 53; cout << int x = 53; cout << "Десятичный вид: " << dec << x << endl << "Восьмеричный вид: " << oct << x << endl << "Шестнадцатеричный вид: " << hex << endl ; double x; // вывести число в поле общей шириной // 6 символов (3 цифры до запятой, // десятичная точка и 2 цифры после запятой) cout << setw(6) << setprecision(2) << x << endl; int x; // ввести шестнадцатеричное число cin >> hex >> x; Манипулятор ws переключает вводимый поток в такой режим, при котором все пробелы (включая табуляцию, переводы строки, переводы каретки и переводы страницы) будут вводиться. По умолчанию эти символы воспринимаются как разделители между атрибутами ввода.

Флаги: выравнивание double values[ ] = { 1. 23, 35. 36, 653. 7, 4358. Флаги: выравнивание double values[ ] = { 1. 23, 35. 36, 653. 7, 4358. 24 }; char *names[ ] = { "Zoot", "Jimmy", "Al", "Stan" }; for ( int i = 0; i < 4; i++ ) cout << setiosflags( ios: : left ) << setw( 6 ) << names[i] << resetiosflags( ios: : left ) << setw( 10 ) << values[i] << endl; Zoot Jimmy Al Stan 1. 23 35. 36 653. 7 4358. 24

Точность double values[] = { 1. 23, 35. 36, 653. 7, 4358. 24 }; Точность double values[] = { 1. 23, 35. 36, 653. 7, 4358. 24 }; char *names[] = { "Zoot", "Jimmy", "Al", "Stan" }; for ( int i = 0; i < 4; i++ ) cout << setiosflags(ios: : left) << setw( 6 ) << names[i] << resetiosflags( ios: : left ) << setw( 10 ) << setprecision( 1 ) << values[i] << endl; Zoot 1 Jimmy 4 e+001 Al 7 e+002 Stan 4 e+003 Добавить перед циклом cout << setiosflags(ios: : fixed); Zoot 1. 2 Jimmy 35. 4 Al 653. 7 Stan 4358. 2 Заменить ios: : fixed flag на ios: : scientific Zoot 1. 2 e+000 Jimmy 3. 5 e+001 Al 6. 5 e+002 Stan 4. 4 e+003

Создание собственных манипуляторов без аргументов #include <iostream. h> ostream& myhex( ostream& os ) { Создание собственных манипуляторов без аргументов #include ostream& myhex( ostream& os ) { return os << “My text: ”<

Операции << и >> для потоков В классах iostream операции >> и << определены Операции << и >> для потоков В классах iostream операции >> и << определены для всех встроенных типов языка Си++ и для строк (тип char*). Если мы хотим использовать такую же запись для ввода и вывода других классов, определенных в программе, для них нужно определить эти операции. class String { public: String() { str=new char[1]; str[0]=0; } friend ostream& operator<<(ostream& os, const String& s); friend istream& operator>>(istream& is, String& s); private: char* str; int length; }; ostream& operator<<(ostream& os, const String& s) { os << s. str; return os; } istream& operator>>(istream& is, String& s) { // длина строк не более char tmp[1024]; is >> tmp; if (s. str != 0) { delete [] s. str; } s. length = strlen(tmp); s. str = new char[s. length + 1]; if (s. str == 0) { // обработка ошибок s. length = 0; return is; } strcpy(s. str, tmp); String x; . . . cin >> x; cout << "this is a string: " << x;

#include “iostream” class Date { int mo, da, yr; public: Date( int m, int #include “iostream” class Date { int mo, da, yr; public: Date( int m, int d, int y ) { mo = m; da = d; yr = y; } friend ostream& operator<< ( ostream& os, Date& dt ); friend istream& operator>> ( istream& is, Date& dt ) }; ostream& operator<< ( ostream& os, Date& dt ) { os << dt. mo << '/' << dt. da << '/' << dt. yr; return os; } istream& operator>> ( istream& is, Date& dt ) { is >> dt. mo >> dt. da >> dt. yr; return is; } void main() { Date dt( 5, 6, 92 ); cout << dt; cin >> dt; }

Дополнительные функции ostream и istream class ostream : public virtual ios { //. . Дополнительные функции ostream и istream class ostream : public virtual ios { //. . . public: ostream& flush(); //вывести из потока //позиционирование потока ostream& seekp(streampos); ostream& seekp(streamoff, seek_dir); // вернуть текущую позицию streampos tellp(); //. . . }; class istream : public virtual ios { //. . . public: int peek(); //след. символ ввода // вернуть считанный символ в поток istream& putback(char c); istream& seekg(streampos); istream& seekg(streamoff, seek_dir); streampos tellg(); //. . . }; istream& putback(char ch ); #include using namespace std; int main( ) { char c[10], c 2, c 3; c 2 = cin. get( ); c 3 = cin. get( ); cin. putback( c 2 ); cin. getline( &c[0], 9 ); cout << c << endl; } Input q w aaaaaa Output q aaaaaa

#include <iostream. h> class Complex { double re, im; public: Complex(double r, double i): #include class Complex { double re, im; public: Complex(double r, double i): re(r), im(i){} friend istream & operator >> ( istream & is, Complex &c); friend ostream & operator << ( ostream & os, const Complex &c); }; istream & operator >> ( istream & is, Complex &com) { int main() { double r, i; Complex a 1(0, 0); r = i = 0; for ( int i = 0; i < 5; i++ ) { char c = 0; cin >> a 1; is >> c; if (cin. good() ) if ( c =='(') cout << a 1; { is >> r>> c; else { if ( c==', ') is >> i >> c; Восстанавливает cin. clear(); if ( c != ')') is. clear(ios: : failbit); состояние потока cout << "Errorn"; } } else { is. putback(c); } is >> r; return 0; } } if ( is ) com = Complex(r, i); return is; }; ostream & operator <<( ostream & os, const Complex &c) { os << '(' << c. re <<', ' << c. im << ')'; return os;

Состояние потоков Методы класса ios для проверки состояния потока: class ios { public: int Состояние потоков Методы класса ios для проверки состояния потока: class ios { public: int eof() const; // дошли до конца файла int fail() const; // следующая операция // будет неудачна int bad() const; // поток испорчен int good() const; // следующая операция будет // успешной void clear(int _i) // очистка всех битов // состояния //. . . }; Значения, обозначающие эти состояния: class ios { public: enum io_state { goodbit=0, eofbit=1, failebit=2, badbit=4, }; //. . . }; Проверить состояние потока можно следующим образом: switch (cin. rdstate()) { case ios: : goodbit: // последняя операция cin была успешной break; case ios: : eofbit: // конeц файла break; case ios: : failebit: // некоторый анализ ошибки break; case ios: : badbit: // cin возможно испорчен break; }

Ввод-вывод файлов Класс ofstream (вывод) l Класс ifstream (ввод) l Класс fstream (двунаправленный файловый Ввод-вывод файлов Класс ofstream (вывод) l Класс ifstream (ввод) l Класс fstream (двунаправленный файловый поток). l Эти классы являются производными от классов istream, ostream и iostream соответственно, поэтому они наследуют перегруженные операции << и >>, флаги форматирования, манипуляторы, методы, состояние потоков и т. д.

Файлы По способу доступа файлы можно разделить на: l l последовательные, чтение и запись Файлы По способу доступа файлы можно разделить на: l l последовательные, чтение и запись производятся с начала байт за байтом, файлы с произвольным доступом, допускающие чтение и запись в указанную позицию. Допустимые операции с файлами: создание потока; l открытие потока и связывание его с файлом; l обмен (ввод/вывод); l уничтожение потока; l закрытие файла. Конструкторы без параметров создают объект соответствующего класса, не связывая его с файлом Конструкторы с параметрами создают объект соответствующего класса, открывают файл с указанным именем и связывают файл с объектом: l ifstream(const char *name, int mode = ios: : in); ofstream(const char *name, int mode = ios: : out | ios: : trunc); fstream(const char *name, int mode = ios: : in | ios: : out);

Режимы открытия файла ios: : app при записи данные добавляются в конец файла, даже Режимы открытия файла ios: : app при записи данные добавляются в конец файла, даже если текущая позиция была перед этим перемещена; ios: : ate при создании потока текущая позиция помещается в конец файла; однако, в отличие от режима app, запись ведется в текущую позицию; ios: : in поток создается для ввода; если файл уже существует, он сохраняется; ios: : out поток создается для вывода (режим по умолчанию); ios: : trunc если файл уже существует, его прежнее содержимое уничтожается, и длина файла становится равной нулю; режим действует по умолчанию, если не заданы ios: : ate, ios: : app или ios: : in; ios: : binary ввод-вывод будет происходить в двоичном виде, по умолчанию используется текстовое представление данных; ios: : nocreate Если файл не существует, выдать ошибку ios: : noreplace Если файл существует, выдать ошибку

Запись чтение в/из файл(а) #include <fstream. h> #include <string. h> int main(){ // Запись Запись чтение в/из файл(а) #include #include int main(){ // Запись в файл ofstream out(“test"); if(!out) { //проверка создания файла cout << "Cannot open file 'test' for writing" << endl; return 1; } char *str[ ] = {"This is the first line. ", "This is the second line. ", "This is the third line. "}; for (int i = 0; i<3; ++i){ out. write(str[i]. strlen(str[i])); out. put('n'); } out. close(); // Чтение из файла ifstream in(“test", ios: : in|ios: : nocreate); if(!in) { //проверка на открытие файла cout << "Cannot open file 'test' for reading" << endl; return 1; } char check_str[3][60]; for (i = 0; i<3; ++i){ in. get(check_str[i], 60); in. get(); } for (i = 0; i<3; ++i) cout << check_str[i] << endl; in. close(); return 0; }

Файлы со смешанными данными int main(){ char ch; ofstream out(“test Файлы со смешанными данными int main(){ char ch; ofstream out(“test"); if(!out) { cout << "Cannot open file 'test' for writing" << endl; return 1; } char str[80], *p; out << 123 << "this is a test" << 23; out << "Hello there!" << 99 << "bye" << endl; out. close(); // Чтение файла ifstream in('test", ios: : i n | ios: : nocreate); if(!out) { cout << "Cannot open file 'test' for reading" << endl; return 1; } do{ p = str; ch = in. peek(); // выяснение типа символа if(isdigit(ch)){ while(isdigit(*p = in. get())) p++; in. putback(*p); // возврат в поток *р = ''; //конец строки cout << "Number: " << atoi(str); } else if(isalpha(ch)){ while(isalpha(*p = in. get())) p++; in. putback(*p); // возврат в поток *р = ''; cout << "String: " << str: } else in. get(); // пропуск cout << endl; } while(!in. eof()); in. close(); return 0; }

Текстовые файлы #include <fstream. h> int main(){ char text[81], buf[81]: cout << Текстовые файлы #include int main(){ char text[81], buf[81]: cout << "Введите имя файла: "; cin >> text; ifstream f(text, ios: : in|ios: : nocreate); if (!f){ cout << "Ошибка открытия файла"; return 1; } while (!f. eof()){ f. getline(buf, 81); cout << buf << endl; } return 0; }

Вывод/ввод в файловый поток #include <fstream. h> void main(void) { //вывод в файл 3 Вывод/ввод в файловый поток #include void main(void) { //вывод в файл 3 текстовые строки ofstream book_file("bookinfo. dat"); book_file << "Учимся программировать на языке C++, " << "Вторая редакция" << endl; book_file << "Jamsa Press" << endl; book_file << "22. 95" << endl; } #include #include void main() { // чтение из файла 3 -х текстовых строк ifstream input_file("bookinfo. dat") ; char one[64], two[64], three[64]; input_file >> one; input_file >> two; учимся input_file >> three; программировать cout << one << endl; cout << two << endl; на cout << three << endl; } #include #include void main(void) { ifstream input_file("bookinfo. dat"); char one[64], two[64], three [64] ; input_file. getline(one, sizeof(one)) ; input_file. get line(two, sizeof(two)); input_file. getline(three, sizeof(three)) ; cout << one << endl; cout << two << endl; cout << three << endl; }

Вывод/ввод в файловый поток #include <iostream. h> #include <fstream. h> void main() { //чтение Вывод/ввод в файловый поток #include #include void main() { //чтение по 1 символу из файла ifstream input_file("bookinfo. dat "); char letter; while (! input_file. eof()) { //пока не конец файла letter = input_file. get(); cout << letter; } } #include #include void main(void) { //чтение по 1 слову ifstream input_file("bookinfo. dat"); char word[64] ; while (! input_file. eof()) { //пока не конец файла input_file >> word; cout << word << endl; }}

Двоичные файлы Данные можно вывести в двоичный поток с помощью методов write или put: Двоичные файлы Данные можно вывести в двоичный поток с помощью методов write или put: ostream& write(const char* pch, int n. Count); ostream& put(char ch); Метод write выводит указанное количество байтов (n. Count), расположенных в памяти, начиная с адреса pch. Метод put выводит один байт. Для того чтобы переместить текущую позицию, используется метод seekp: ostream& seekp(streamoff off, ios: : seek_dir dir); streampos tellp(); Первый аргумент – смещение позиции в байтах. Второй аргумент определяет, откуда отсчитывается смещение; он может принимать одно из трех значений: ios: : beg смещение от начала файла ios: : cur смещение от текущей позиции ios: : end смещение от конца файла

Двоичные файлы Чтение из файла производится методами read или get: istream& read(char* pch, int Двоичные файлы Чтение из файла производится методами read или get: istream& read(char* pch, int n. Count); istream& get(char& rch); l Метод read вводит указанное количество байтов (n. Count) в память, начиная с адреса pch. Метод get вводит один байт. l Так же, как и для вывода, текущую позицию ввода можно изменить с помощью метода seekg() l Получить текущую позицию можно с помощью метода tellg() l По завершении выполнения операций с файлами надо закрыть файлы с l помощью close или просто уничтожить объект . #include int iarray[2] = { 99, 10 }; void main() { ofstream os( "test. dat" ); os. write( (char *) iarray, sizeof( iarray ) ); }

Вывод/ввод массивов и структур #include <iostream. h> #include <fstream. h> void main() { //запись Вывод/ввод массивов и структур #include #include void main() { //запись структуры в файл struct employee { char name[64]; int age; float salary; } worker = { "Джон Дой", 33, 25000. 0 }; ofstream emp_file("employee. dat") ; // запись в файл структуры emp_file. write((char *) &worker, sizeof(employee)); } #include #include void main() { //чтение структуры из файла struct employee { char name [64] ; int age; float salary; } worker; ifstream emp_file("employee. dat"); emp_file. read((char *) &worker, sizeof(employee)); cout << worker. name << endl; cout << worker. age << endl; cout << worker. salary << endl; }

Проверка ошибок файловых операций #include <iostream. h> #include <fstream. h> void main() { char Проверка ошибок файловых операций #include #include void main() { char line[256] ; ifstream input_file("bookinfo. dat") ; if (input_file. fail()) cerr << "Ошибка открытия bookinfo. dat" << endl; else { while ((! input_file. eof()) && (! input_file. fail())) { input_file. getline(line, sizeof(line)) ; if (! input_file. fail()) cout << line << endl; } } }

#include using namespace std; void fchar(char" src="https://present5.com/presentation/-76845397_338592073/image-34.jpg" alt="Копирование файлов #include "stdafx. h" #include #include using namespace std; void fchar(char" /> Копирование файлов #include "stdafx. h" #include #include using namespace std; void fchar(char * name_in, char * name_out) { ifstream in(name_in); ofstream out(name_out); char ch; if ( in && out) while ( in. get(ch)) out. put(ch); } void fline(char * name_in, char * name_out) { ifstream in(name_in); ofstream out(name_out); char buf[200]; while ( in && out) { in. getline(buf, sizeof(buf)); out<< buf << endl; } } void fbinary(char * name_in, char * name_out) { ifstream in(name_in, ios: : binary); ofstream out(name_out, ios: : binary); char buf[200]; while ( in && out) { in. read(buf, sizeof(buf)); out. write(buf, in. gcount()); } } void fbuf(char * name_in, char * name_out) { ifstream in(name_in, ios: : binary); ofstream out(name_out, ios: : binary); streambuf *sb = in. rdbuf(); out<< sb; void main() { // in >> out. rdbuf(); fchar("d 1. txt", "d 2. txt") // out << in. rdbuf(); fline("d 1. txt", "d 3. txt") } fbinary("d 1. txt", "d 4. tx fbuf("d 1. txt", "d 5. txt"); }

Перегрузка файловых потоков для пользовательских типов #include <iostream. h> #include <fstream. h> class Date Перегрузка файловых потоков для пользовательских типов #include #include class Date { int mo, da, yr; public: Date() { mo = 0; da = 0; yr = 0; } Date( int m, int d, int y ) { mo = m; da = d; yr = y; } friend ofstream& operator<< ( ofstream& os, Date& dt ); friend ifstream& operator>> ( ifstream& is, Date& dt ); }; ofstream& operator<< ( ofstream& os, Date& dt ) { os << dt. mo << " " << dt. da << " " << dt. yr; return os; } ifstream& operator>> ( ifstream& is, Date& dt ) { is >> dt. mo >> dt. da >> dt. yr; return is; } void main() { Date dt( 5, 6, 92 ); ofstream os("s 1. txt"); os << dt; os. close(); Date dt 1; ifstream is("s 1. txt"); is >> dt 1; is. close(); }

Строковые потоки l Класс strstream Функция split_numbers выделяет числа из строки, состоящей из нескольких Строковые потоки l Класс strstream Функция split_numbers выделяет числа из строки, состоящей из нескольких чисел, разделенных пробелом, и печатает их по одному на строке. #include void split_numbers(const char* s) { Объект iostr автоматически выделяет память, и при выходе из функции split_numbers, когда объект уничтожается, память будет освобождена. strstream iostr; iostr << s << ends; int x; while (iostr >> x) // конец файла это 0 байт cout << x<< endl; } int main(){ split_numbers("123 34 56 932"); return 1; }