大纲 标准 I/O 流的介绍 I/O 流的概念 程序的输入指的是从输入文件将数据传送给程序,程序的输出指的是从程序将数据传送给输出文件。C++ 的输入输出包含以下三个方面的内容:
对系统指定的标准设备的输入和输出
:即从键盘输入数据,输出到显示器屏幕。这种输入输出称为标准的输入输出,简称 标准 I/O
。以外存磁盘文件为对象进行输入和输出
:即从磁盘文件输入数据,数据输出到磁盘文件。以外存文件为对象的输入输出称为文件的输入输出,简称 文件 I/O
。对内存中指定的空间进行输入和输出
:通常指定一个字符数组作为存储空间(实际上可以利用该内存空间存储任何信息)。这种输入和输出称为字符串输入输出,简称 串 I/O
。I/O 流类库的结构 在 C 语言中,用 printf
和 scanf
进行输入输出,往往不能保证所输入输出的数据是可靠的安全的。在 C++ 的输入输出中,编译系统对数据类型进行严格的检查,凡是类型不正确的数据都不可能通过编译。因此 C++ 的 I/O 操作是类型安全(Type Safe)的。C++ 的 I/O 操作是可扩展的,不仅可以用来输入输出标准类型的数据,也可以用于用户自定义类型的数据。C++ 通过 I/O 类库来实现丰富的 I/O 功能。这样使 C++ 的输人输出明显地优于 C 语言中的 printf
和 scanf
,但是也为之付出了代价,C++ 的 I/O 系统因此变得比较复杂,要掌握许多使用细节。C++ 编译系统提供了用于输入输出的 iostream
类库。iostream
这个单词是由 3 个部分组成的,即 i-o-stream
,意为输入输出流。在 iostream
类库中包含许多用于输入输出的类,如下图所示:
ios
是抽象基类,由它派生出 istream
类和 ostream
类,两个类名中第 1 个字母 i 和 o 分别代表输入(input)和输出(output)。istream
类支持输入操作,ostream
类支持输出操作,iostream
类支持输入输出操作。iostream
类是从 istream
类和 ostream
类通过多重继承而派生的类,其继承层次如下图所示:
iostream
类库中不同的类的声明被放在不同的头文件中,用户在自己的程序中用 #include
命令包含了有关的头文件,这就相当于在本程序中声明了所需要用到的类。可以换 — 种说法:头文件是程序与类库的接口。iostream
类库的接口分别由不同的头文件来实现,常用的头文件如下:
strstream
:用于字符串流 I/Ofstream
:用于实现文件的 I/O 操作iomanip
:在使用格式化 I/O 时,应包含此头文件iostream
:包含了对输入输出流进行操作所需的基本信息stdiostream
:用于混合使用 C 语言和 C++ 的 I/O 机制,例如希望将 C 语言程序转变为 C++ 程序在 iostream
头文件中定义的类有 ios,istream,ostream,iostream,istream_withassign,ostream_withassign,iostream_withassign
等。在 iostream
头文件中不仅定义了相关的类,还定义了 4 种标准 I/O 对象,如下所示:
<<
和 >>
本来在 C++ 中是被定义为左位移运算符和右位移运算符的,由于在 iostream
头文件中对它们进行了重载,使它们能用作标准类型数据的输入和输出运算符。所以,在使用到它们的程序中必须用 #include <iostream>
命令将其包含到程序中。在 iostream
中只对 <<
和 >>
运算符用于标准类型数据的输入输出进行了重载,但未对用户声明的类型数据的输入输出进行重载。如果用户声明了新的类型,并希望用 <<
和 >>
运算符对其进行输入输出,则需要按照 C++ 的运算符重载规则来做。
标准 I/O 流的使用 标准输入流的简单使用 标准输入流对象 cin
的常用函数如下:
cin.get()
,一次只能读取一个字符cin.get(一个参数)
,读一个字符cin.get(多个参数)
,可以读字符串cin.getline()
,读取整行字符串,包括读取空格字符cin.ignore()
,用于忽略或清除输入缓冲区中的一个或多个字符cin.putback()
,将数据放回缓冲区cin.peek()
,返回值是一个 char
型的字符,即指针指向的当前字符,但它只是观测指针停留在当前的位置并不后移;如果要访问的字符是文件结束符,则函数的返回值是 EOF
或者 -1
标准输入流的使用案例一 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 #include <iostream> using namespace std;void test01 () { char c = cin.get (); cout << "c = " << c << endl; c = cin.get (); cout << "c = " << c << endl; c = cin.get (); cout << "c = " << c << endl; c = cin.get (); cout << "c = " << c << endl; } void test02 () { char buffer[1024 ]; cin.get (buffer, 1024 ); cout << buffer << endl; char c = cin.get (); if (c == '\n' ) { cout << "换行符还在缓冲区" ; } else { cout << "换行符不在缓冲区" ; } } void test03 () { char buffer[1024 ]; cin.getline (buffer, 1024 ); cout << buffer << endl; char c = cin.get (); if (c == '\n' ) { cout << "换行符还在缓冲区" ; } else { cout << "换行符不在缓冲区" ; } } void test04 () { cin.ignore (); cin.ignore (2 ); char c = cin.get (); cout << "c = " << c << endl; } void test05 () { char c = cin.peek (); cout << "c = " << c << endl; c = cin.get (); cout << "c = " << c << endl; } void test06 () { char c = cin.get (); cin.putback (c); char buffer[1024 ]; cin.getline (buffer, 1024 ); cout << buffer << endl; }
标准输入流的使用案例二 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 #include <iostream> using namespace std;void input1 () { int number; cout << "请输入一个数字: " ; cin >> number; cout << "输入的数字是: " << number << endl; } void input2 () { char buf[1024 ]; cout << "请输入字符串: " ; cin >> buf; cout << "输入的字符串: " ; cout << buf << endl; } void input3 () { char ch; cout << "请输入字符串: " ; while ((ch = cin.get ()) != EOF) { cout << ch << " " ; } } void input4 () { char a, b, c; cout << "请输入字符串: " ; cin.get (a); cin.get (b); cin.get (c); cout << a << b << c; } void input5 () { char buf[256 ]; cout << "请输入字符串: " ; cin.getline (buf, 256 ); cout << buf << endl; } void input6 () { char buf1[256 ]; char buf2[256 ]; cout << "请输入字符串:" ; cin >> buf1; cin.ignore (2 ); cin.getline (buf2, 256 ); cout << buf1 << endl; cout << buf2 << endl; } void input7 () { char buf1[256 ]; char buf2[256 ]; cout << "请输入字符串:" ; cin >> buf1; cin.ignore (2 ); int num = cin.peek (); cout << num << endl; cin.getline (buf2, 256 ); cout << buf1 << endl; cout << buf2 << endl; } void input8 () { cout << "Please, enter a number or a word: " ; char c = std::cin.get (); if ((c >= '0' ) && (c <= '9' )) { int n; cin.putback (c); cin >> n; cout << "You entered a number: " << n << '\n' ; } else { char ch; cin.putback (c); cin.get (ch); cout << "You entered a character: " << ch << '\n' ; } }
标准输出流的简单使用 标准输出流对象 cout
的常用函数如下:
cout.flush()
cout.put()
cout.write()
cout.width()
cout.fill()
cout.setf()
标准输出流的使用案例一 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 #include <iostream> #include <cstring> #include <iomanip> using namespace std;void test01 () { cout.put ('a' ); } void test02 () { char buf[1024 ] = "hello world" ; cout.write (buf, strlen (buf)); } void test03 () { int number = 99 ; cout.width (20 ); cout.fill ('*' ); cout.setf (ios::left); cout.unsetf (ios::dec); cout.setf (ios::hex); cout.setf (ios::showbase); cout.unsetf (ios::hex); cout.setf (ios::oct); cout << number; } void test04 () { int number = 30 ; cout << setw (20 ) << setfill ('*' ) << setiosflags (ios::showbase) << setiosflags (ios::left) << hex << number; } int main () { cout << endl << "------- test01() -------" << endl; test01 (); cout << endl << "------- test02() -------" << endl; test02 (); cout << endl << "------- test03() -------" << endl; test03 (); cout << endl << "------- test04() -------" << endl; test04 (); return 0 ; }
程序运行输出的结果如下:
1 2 3 4 5 6 7 8 ------- test01() ------- a ------- test02() ------- hello world ------- test03() ------- 0143**************** ------- test04() ------- 0x1e****************
标准输出流的使用案例二 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 #include <iostream> #include <iomanip> using namespace std;void output1 () { cout.put ('h' ).put ('e' ).put ('l' ).put ('l' ).put ('o' ).put ('\n' ); } void output2 () { char * str = "hello world\n" ; cout.write (str, strlen (str)); } void output3 () { cout << "<Start>" ; cout.width (30 ); cout.fill ('*' ); cout.setf (ios::showbase); cout.setf (ios::internal); cout << hex << 123 << "<End>\n" ; } void output4 () { cout << "<Start>" << setw (30 ) << setfill ('*' ) << setiosflags (ios::showbase) << setiosflags (ios::internal) << hex << 123 << "<End>\n" ; } int main () { output1 (); output2 (); output3 (); output4 (); return 0 ; }
程序运行输出的结果如下:
1 2 3 4 hello hello world <Start>0x**************************7b<End> <Start>0x**************************7b<End>
文件 I/O 流的简单使用 以普通的方式读写文件 读写文件的使用案例一 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 #include <iostream> #include <fstream> using namespace std;void writeFile () { char *fname = "/tmp/file.txt" ; ofstream fout (fname) ; if (fout) { fout << "Hello World 1" << endl; fout << "Hello World 2" << endl; fout << "Hello World 3" << endl; fout.flush (); fout.close (); } } void writeFileAppend () { char *fname = "/tmp/file.txt" ; ofstream fout (fname, ios::app) ; if (fout) { fout << "What" << endl; fout.flush (); fout.close (); } } void readFile () { char ch; char *fname = "/tmp/file.txt" ; ifstream fin (fname) ; if (fin) { while (fin.get (ch)) { cout << ch; } fin.close (); } } int main () { writeFile (); readFile (); cout << "-----------------------" << endl; writeFileAppend (); readFile (); return 0 ; }
程序运行输出的结果如下:
1 2 3 4 5 6 7 8 Hello World 1 Hello World 2 Hello World 3 ----------------------- Hello World 1 Hello World 2 Hello World 3 What
读写文件的使用案例二 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 #include <iostream> #include <fstream> using namespace std;void test01 () { ofstream ofs; ofs.open ("/tmp/file.txt" , ios::out | ios::trunc); if (!ofs.is_open ()) { cout << "文件打开失败" << endl; return ; } ofs << "Hello World 1" << endl; ofs << "Hello World 2" << endl; ofs << "Hello World 3" << endl; ofs.flush (); ofs.close (); cout << "文件写入完成" << endl; } void test02 () { ifstream ifs; ifs.open ("/tmp/file.txt" , ios::in); if (!ifs.is_open ()) { cout << "文件打开失败" << endl; return ; } char buffer[1024 ]; while (ifs >> buffer) { cout << buffer << endl; } ifs.close (); } void test03 () { ifstream ifs; ifs.open ("/tmp/file.txt" , ios::in); if (!ifs.is_open ()) { cout << "文件打开失败" << endl; return ; } string line; while (getline (ifs, line)) { cout << line << endl; } ifs.close (); } void test04 () { ifstream ifs; ifs.open ("/tmp/file.txt" , ios::in); if (!ifs.is_open ()) { cout << "文件打开失败" << endl; return ; } char c; while ((c = ifs.get ()) != EOF) { cout << c; } ifs.close (); } int main () { cout << "------ test01() ------" << endl; test01 (); cout << "------ test02() ------" << endl; test02 (); cout << "------ test03() ------" << endl; test03 (); cout << "------ test04() ------" << endl; test04 (); return 0 ; }
程序运行输出的结果如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ------ test01() ------ 文件写入完成 ------ test02() ------ Hello World 1 Hello World 2 Hello World 3 ------ test03() ------ Hello World 1 Hello World 2 Hello World 3 ------ test04() ------ Hello World 1 Hello World 2 Hello World 3
以二进制的方式读写文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 #include <iostream> #include <fstream> using namespace std;class Teacher {public : Teacher () { age = 33 ; strcpy (name, "" ); } Teacher (int _age, char * _name) { age = _age; strcpy (name, _name); } void print () { cout << "age:" << age << ", name:" << name << endl; } private : int age; char name[32 ]; }; int main () { char * fname = "/tmp/file.dat" ; ofstream fout (fname, ios::binary) ; if (!fout) { cout << "打开文件失败" << endl; return 0 ; } Teacher t1 (23 , "Jim" ) ; Teacher t2 (26 , "Tom" ) ; fout.write ((char *)&t1, sizeof (Teacher)); fout.write ((char *)&t2, sizeof (Teacher)); fout.flush (); fout.close (); ifstream fin (fname) ; if (!fin) { cout << "打开文件失败" << endl; return 0 ; } Teacher tmp; fin.read ((char *)&tmp, sizeof (Teacher)); tmp.print (); fin.read ((char *)&tmp, sizeof (Teacher)); tmp.print (); fin.close (); return 0 ; }
程序运行输出的结果如下:
1 2 age:23, name:Jim age:23, name:Jim