首页 > 代码库 > C++ Primer学习随便——第20章iostream
C++ Primer学习随便——第20章iostream
头文件 <iostream>
一. 对终端的操作
相关头文件#include <iostream>
1. 输入istream
2. 输出ostream
3. iostream继承istream和ostream 所以它具有输入输出功能。
为了方便这个库定义了下列三个标准流对象:
1. cin 代表标准输入istream类对象一般地cin使我们能够从用户终端读入数据。
2. cout 代表标准输出ostream类对象一般地cout使我们能够向用户终端写数据。
3. cerr 代表标准错误ostream类对象一般地cerr是导出程序错误消息的地方。
另外,输出主要由重载的左移操作符<< 来完成类似地输入主要由重载的右移操作符>>来完成。
Demo1:
#include <iostream>#include <string>int main() { string in_string; // 向用户终端写字符串 std::cout << "Please enter your name: "; // 把用户输入的读取到 in_string 中 std::cin >> in_string; if ( in_string.empty() ) // 产生一个错误消息输出到用户终端 std::cerr << "error: input string is empty!/n"; else std::cout << "hello, " << in_string << "!/n";}
二. 对文件的操作
相关头#include <fstream>
1. ifstream 从istream 派生把一个文件绑到程序上从文件读取数据用来输入。
2. ofstream 从ostream 派生把一个文件绑到程序上用来向文件写入数据。
3. fstream 从iostream 派生把一个文件绑到程序上用来输入和输出。
注:由于在fstream 头文件中也包含了iostream 头文件所以我们不需要同时包含这两个文
件C++对于文件的输入输出也支持同样的输入和输出操作符。
Demo2:
#include <fstream>#include <string>#include <vector>#include <algorithm>int main(){ string ifile; cout << "Please enter file to sort: "; cin >> ifile; // 构造一个 ifstream 输入文件对象 ifstream infile( ifile.c_str() ); if( ! infile ) { cerr << "error: unable to open input file: " << ifile << endl; return -1; } string ofile = ifile + ".sort"; // 构造一个 ofstream 输出文件对象 ofstream outfile( ofile.c_str() ); if( !outfile ) { cerr << "error: unable to open output file: " << ofile << endl; return -2; } string buffer; vector<string> text; int cnt = 1; while ( infile >> buffer ) { text.push_back( buffer ); cout << buffer << ( cnt++ % 8 ? " " : "/n" ); } sort( text.begin(), text.end() ); // ok: 把排序后的词打印到 outfile vector<string>::iterator iter = text.begin(); for ( cnt = 1; iter != text.end(); ++iter, ++cnt ) outfile << *iter << (cnt%8 ? " " : "/n" ); return 0;}
三. 对字符流操作
相关的头文件#include <sstream>
1 istringstream 从istream 派生从一个字符串中读取数据。
2 ostringstream 从ostream 派生写入到一个字符串中。
3 stringstream 从iostream 派生从字符串中读取或者写入到字符串中。
Demo3:
#include <sstream>string program_name( "our_program" );string version( "0.01" );// ...string mumble( int *array, int size ){ if ( ! array ) { ostringstream out_message; out_message << "error: " << program_name << "--" << version << ": " << __FILE__ << ": " << __LINE__ <<" -- ptr is set to 0; " << " must address some array./n"; // 返回底层 string 对象 return out_message.str();}
四. wchar_t型
支持wchar_t类型的流读写操作
wcin wcout wcerr wiostream 等等....
20.1 输出操作符<<
1. 支持所有的内置数据类型 包括string ,const char* 和complex。以及函数的调用。
2. endl等价于输出换行操作符,然后再刷新缓存区。cout << ‘/n‘ << flush;
3. <<可以连接使用,因为operator<<的返回值是ostream&。
4. cout << p << &i << endl;会输出指针的地址(p是int *,i是int)。如果是const char * pcStr不会输出指针地址值,
输出的是字符串。转换为cout << static_cast<void *>(const_cast<char *>(pcStr));
5. <<运算符的优先级高于?:所以和?:使用时注意加括号。
6. ostream_iterator和cout的使用。
Demo4:
#include <iostream>#include <algorithm>#include <vector>#include <string>string pooh_pals[] = {"Tigger", "Piglet", "Eeyore", "Rabbit"};int main(){ vector<string> ppals( pooh_pals, pooh_pals+4 ); vector<string>::iterator iter = ppals.begin(); vector<string>::iterator iter_end = ppals.end(); cout << "These are Pooh‘s pals: "; // 把每个元素拷贝到 cout ... ostream_iterator< string > output( cout, " " ); copy( iter, iter_end, output ); cout << endl;}
7. cout << 遇到‘/0’会定制输出。
20.2 输入操作符>>
1. while(cin >> 变量)的时候有两种情况会让循环停止(false):
(1) 读到文件结束在这种情况下我们已经正确地读完文件中所有的值。
(2) 遇到一个无效的值比如3.14159小数点是非法的1e-1字符文字e是非法的或者一般的任意字符串文字在读入一个无效值的
情况下istream对象被放置到一种错误的状态中并且对于值的所有读入动作都将停止。
2. 预定义的输入操作符可以接受任何的内置数据类型包括C 风格字符由以及标准库string和complex 类类型。
3. 缺省情况下输入操作符丢弃任何中间空白空格制表符换行符走纸以及回车。
Demo5:
#include <iostream>#include <string>int main(){ int item_number; string item_name; double item_price; cout << "Please enter the item_number, item_name, and price: " << endl; cin >> item_number; cin >> item_name; cin >> item_price; cout << "The values entered are: item# " << item_number << " " << item_name << " @$" << item_price << endl;}
4. 如果希望读入空白符号可以利用cin.get()方法一个个读入,或者设置skipws和noskipws选项(后面介绍)。
5. isream_iterator和cin关联使用。
Demo6:
#include <algorithm>#include <string>#include <vector>#include <iostream>int main(){ istream_iterator< string > in( cin ), eos ; vector< string > text ; // 从标准输入向 text 拷贝值 copy( in , eos , back_inserter( text ) ) ; sort( text.begin() , text.end() ) ; // 删除所有重复的值 vector< string >::iterator it ; it = unique( text.begin() , text.end() ) ; text.erase( it , text.end() ) ; // 显示结果 vector int line_cnt = 1 ; for ( vector< string >::iterator iter = text.begin(); iter != text.end() ; ++iter , ++line_cnt ) cout << *iter << ( line_cnt % 9 ? " " : "/n" ) ; cout << endl;}
20.2.1 字符串输入
1. setw函数:防止读入字符串益处(char[4],输入4个以上字节),while ( cin >> setw( bufSize ) >> buf )
这里bufSize是字符数组buf的长度setw()把长度等于或大于bufSize 的字符串分成最大长度为bufSize - 1的两个
或多个字符串,在每个新串的末尾放一个空字符为了使用setw()要求程序包含iomanip头文件#include <iomanip>。
2. 用string没有char *那些长度和内存溢出问题,更容易使用。
20.3 其他输入输出操作符
一. istream的成员get()一次读入一个字节。属于istream
1. get(char& ch)从输入流中提取一个字符包括空白字符并将它存储在ch中它返回被应用的istream对象。
与之对应的是ostream的put()方法,每次读入一个字节,然后返回ostream。
2. get()的第二个版本也从输入流读入一个字符区别是它返回该字符值而不是被应用的istream 对象它的返回类型
是int 而不是char 因为它也返回文件尾的标志end-of-file该标志通常用-1 来表示以便与字符集区分开为测试返回
值是否为文件尾我们将它与iostream 头文件中定义的常量EOF 做比较。
Demo7:
#include <iostream>int main(){ int ch; // 或使用: // while (( ch = cin.get() ) && ch != EOF) while (( ch = cin.get()) != EOF) cout.put(ch); return 0;}
3. get(char *sink, streamsize size, char delimiter=‘/n‘)
(1) sink 代表一个字符数组用来存放被读取到的字符。
(2) size 代表可以从istream 中读入的字符的最大数目。
(3) delimiter 表示如果遇到它就结束读取字符的动作delimiter 字符本身不会被读入而是留在istream 中作为istream 的
下一个字符一种常见的错误是在执行第二个get()之前忘了去掉delimiter。
二. ignore( streamsize length = 1, int delim = traits::eof )函数: 属于istream
我们用istream 成员函数ignore()来去掉delimiter
缺省情况下换行符被用作delimiter。
三. gcount()函数: 属于istream
它返回由最后的get()或getline()调用实际提取的字符数。
Demo8:
#include <iostream>int main(){ const int max_line = 1024; char line[ max_line ]; while ( cin.get( line, max_line )) { // 最大读取数量 max_line - 1, 也可以为 null int get_count = cin.gcount(); cout << "characters actually read: " << get_count << endl; // 处理每一行 // 如果遇到换行符 // 在读下一行之前去掉它 if ( get_count & max_line-1 ) cin.ignore(); }}
四. getline(char *sink, streamsize size, char delimiter=‘/n‘)属于istream
五. write( const char *sink, streamsize length )属于ostream
提供了另外一种方法可以输出字符数组”它不是输出直到终止空字符为止的所有字符“而是输出某个长度的字符序列包括内含的
空字符它的函数。length 指定要显示的字符个数write()返回当前被调用的ostream 类对象。
六. read( char* addr, streamsize size )属于istream
read()从输入流中提取size 个连续的字节并将其放在地址从addr 开始的内存中gcount()返回由最后一个read()调用提取的字
节数而read()返回当前被调用的istream 类对象。
Demo9:
#include <iostream>int main(){ const lineSize = 1024; int lcnt = 0; // 读入多少行 int max = -1; // 最长行的长度 char inBuf[ lineSize ]; // 读取 1024 个字符或者遇到换行符 while (cin.getline( inBuf, lineSize )) { // 实际读入多少字符 int readin = cin.gcount(); // 统计: 行数最长行 ++lcnt; if ( readin > max ) max = readin; cout << "Line #" << lcnt << "/tChars read: " << readin << endl; cout.write( inBuf, readin).put(‘/n‘).put(‘/n‘); } cout << "Total lines read: " << lcnt << endl; cout << "Longest line read: " << max << endl;}
七. getline( istream &is, string str, char delimiter );
这个getline()实例的行为如下读入最大数目为str::max_size-1 个字符如果输入序列超出这个限制则读操作失败
并且istream 对象被设置为错误状态否则当读到delimiter 它被从istream 中丢弃但没有被插入到string 中或遇
到文件结束符时输入结束。
八. putback( char c ); 将字符放回 iostream。
九. unget();往回重置下一个 istream 项。
十. peek(); 返回下一个字符或 EOF,但不要提取出来。
Demo10:
char ch, next, lookahead;while ( cin.get( ch )){ switch (ch) { case ‘/‘: // 是注释行吗? 用 peek() 看一看: // 是的? ignore() 余下的行 next = cin.peek(); if ( next == ‘/‘ ) cin.ignore( lineSize, ‘/n‘ ); break; case ‘>‘: // 查找 >>= next = cin.peek(); if ( next == ‘>‘ ) { lookahead = cin.get(); next = cin.peek(); if ( next != ‘=‘ ) cin.putback( lookahead );}
20.4 重载输出操作符<<
输出操作符是一个双目操作符它返回一个ostream 引用重载定义的通用框架如下
// 重载 output 操作符的通用框架
ostream&
operator <<( ostream& os, const ClassType &object )
{
// 准备对象的特定逻辑
// 成员的实际输出
os << // ...
// 返回 ostream 对象
return os;
}
注:因为第一个实参是一个ostream 引用所以输出操作符必须定义为非成员函数,当输出操作符要求访问非公有成员
时必须将它声明为该类的友元。
20.5 重载输入操作符>>
1 由于不正确的格式而导致失败istream 应该把状态标记为fail。setstate( ios_base::failbit )。
2 对于错误状态中的iostream 插入和提取操作没有影响。
Demo11:
#include <iostream>#include "WordCount.h"/* 必须修改 WordCount, 指定输入操作符为友元class WordCount { friend ostream& operator<<( ostream&, const WordCount& ); friend istream& operator>>( istream&, WordCount& );*/istream&operator>>( istream &is, WordCount &wd ){/* WordCount 对象被读入的格式: * <2> string * <7,3> <12,36> */int ch;/* 读入小于符号, 如果不存在 * 则设置 istream 为失败状态并退出 */if ((ch = is.get()) != ‘<‘ ){ is.setstate( ios_base::failbit ); return is;} // 读入多少个 int occurs; is >> occurs; // 取 >; 不检查错误 while ( is && (ch = is.get()) != ‘>‘ ); is >> wd._word; // 读入位置 // 每个位置的格式: < line, col > for ( int ix = 0; ix < occurs; ++ix ) { int line, col; // 提取值 while (is && (ch = is.get())!= ‘<‘ ); is >> line; while (is && (ch = is.get())!= ‘,‘ ); is >> col; while (is && (ch = is.get())!= ‘>‘ ); wd.occurList.push_back( Location( line, col )); } return is;}
20.6 文件输入和输出
包含头文件#include <fstream>
1. ofstream的构造函数要制定打开模式
输出模式ios_base::out 或附加模式ios_base::app 等等。在缺省情况下ostream文件以输出模式打开。
注:如果在输出模式下打开已经存在的文件则所有存储在该文件中的数据都将被丢弃如果我们希望增加而不是替换现
有文件中的数据则应该以附加模式打开文件于是新写到文件中的数据将添加到文件尾部在这两种模式下如果文件不存
在程序都会创建一个新文件。
2. 判断是否打开if (!outFile /*ofstream对象*/)
3. 因为ofstream派生于ostream,所以ofstream拥有ostream的操作,比如put()等等。
4. 自定义<<操作输入到ofstream中。
5. 用ifstream读入一个文件,派生于istream,所有拥有istream的操作,比如get()等等。
6. close()函数断开和文件的关联。
7. fstream派生于iostream,它具有对文件的读写操作。
8. seekg和seekp标记当前位置,g是在读文件中使用,p再写文件中使用。
注:第二个参数标示定位标记:
(1) ios_base::beg 文件的开始
(2) ios_base::cur 文件的当前位置
(3) ios_base::end 文件的结尾
9. tellg()或tellp()返回当前位置,g和p意义同seekg和seekp。返回值是ios_base::pos_type。
10. clear()函数:清除状态。
20.7 条件状态
一. 条件状态
1 如果一个流遇到文件结束符则eof()返回true。
2 如果试图做一个无效的操作比如seeking 重定位操作超出了文件尾则bad()返回true,一般地这表示该流由于某种
未定义的方式而被破坏了。
3 如果操作不成功比如打开一个文件流对象失败或遇到一种无效的输入格式则fail()
返回true 例如
ifstream iFile( filename, ios_base::in );
if ( iFile.fail() ) // 不能打开
error_message( ... );
4 如果其他条件都不为true 则good()返回true
二. 改变状态
1. clear()函数,状态变为显示。
2. setstate()函数,添加状态。参数设置为:
ios_base::badbit
ios_base::eofbit
ios_base::failbit
ios_base::goodbit
3. rdstate()获取成员状态,返回值ios_base::iostate。
20.8 string 流
1. 包括头文件#include <sstream>
2. str()返回与ostringstream 类对象相关联的string 对象。
20.9 格式状态
操 作 符 含 义
boolalpha 把true 和false 表示为字符串
*noboolalpha 把true 和false 表示为0 1
showbase 产生前缀指示数值的进制基数
*noshowbase 不产生进制基数前缀
showpoint 总是显示小数点
*noshowpoint 只有当小数部分存在时才显示小数点
Showpos 在非负数值中显示+
*noshowpos 在非负数值中不显示+
*skipws 输入操作符跳过空白字符
noskipws 输入操作符不跳过空白字符
uppercase 在十六进制下显示0X 科学计数法中显示E
*nouppercase 在十六进制下显示0x 科学计数法中显示e
*dec 以十进制显示
hex 以十六进制显示
oct 以八进制显示
left 将填充字符加到数值的右边
right 将填充字符加到数值的左边
Internal 将填充字符加到符号和数值的中间
*fixed 以小数形式显示浮点数
scientific 以科学计数法形式显示浮点数
flush 刷新ostream 缓冲区
ends 插入空字符然后刷新ostream 缓冲区
endl 插入换行符然后刷新ostream 缓冲区
ws 吃掉 空白字符
// 以下这些要求 #include <iomanip>
setfill(ch) 用ch 填充空白字符
setprecision(n) 将浮点精度设置为n
setw(w) 按照w 个字符来读或者写数值
setbase(b) 以进制基数b 输出整数值
注*表示缺省的流状态
20.10 强类型库
iostream库是强类型的例如试图从一个ostream 读数据或者写数据到一个istream都会在编译时刻被捕获到并标记为类型违例
C++ Primer学习随便——第20章iostream