C++学习之七、揭开C++I/O的神秘面纱 (二)

2014-11-24 12:34:44 · 作者: · 浏览: 6
lse。

下段程序使用了从流中读取数据和处理错误的常用模式。

#include

#include

#include

using namespace std;

int main()

{

int sum = 0;

if(!cin.good())

{

cout<<”Standard input is in a bad state!”<

exit(1);

}

int number;

while(true)

{

cin>>number;

if(cin.good())

sum += number;

else if(cin.eof()) break;

else

{

cin.clear();

string badToken;

cin>>badToken;

cerr<<”WARNING:Bad input encounter:”<

}

}

cout<<”The sum is :”<

return 0;

}

输入控制符:

a.oolalpha和noboolalpha,告诉流把bool类型的值输入为true或false(boolalpha)和1或0(noboolalpha)。默认为noboolalpha。

b.hex、oct、dec。分别以十六进制、八进制、十进制读取数字。

c.skipws和noskipws。告诉流在做词法分析时,忽略空白符或者把空白符读入作为一个空白符token。

d.ws。这是一个便利控制符,它只会忽略流中当前位置的一串空白。

2. 输入与输出对象

可以通过操作符重载,来控制输入输出对象的信息。

3. 字符串流

字符串流提供了一种对string应用流语义的方法。采用这种方法,可以有一个表示文本数据的内存中流。如果多个线程都向同一个字符串提供数据,或者需要把一个string传递给不同的函数,而同时还要维护当前的读取位置,在这样一些应用中,这种方法就很有用。因为流有内置的词法分析功能,所以字符串流对于解析文本也很有用。

类ostringstream和istringstream分别用于向字符串写数据和从字符串读数据。它们都在头文件中定义的。分别继承了ostream和istream同样的行为。

4. 文件流 见C++文件操作学习

补充:

seek()函数:可以移动到输入或输出流的任意位置。输入流为seekg(),输出流为seekp()。每种类型的流都有二个查找方法。可以在流中查找绝对位置或相对位置。位置以字节为单位。

移动到流的开始位置:ios_base::beg

移动到流的结束位置:ios_base::end

移动到流的中间常量:ios_base::cur

带一个参数:

outStream.seekp(ios_base::beg)或inStream.seekg(ios_base::beg)

带二个参数(第一个参数表示要移多少位置,第二个参数表示移动的起点):

移动到相对于流的开头的第二个字符:

outStream.seekp(2, ios_base::beg);

移动到相对于流的倒数的第二个字符:

isStream.seekg(-2,ios_base::end);

tell()函数:查询流的当前位置,返回ios_base::pos_type。输入流为tellg(),输出流为tellp()。

5. 链接流

可以在任何输入流与输出流之间建立链接。从而提供一种“一旦访问就刷新输出”的行为。换句话说,从输入流请求数据时,与其链接的输出流会自动刷新输出。这个行为可以用于所有的流,但是对于可能相互依赖的文件流尤其有用。

流链接用方法tie()来实现。要把输出流绑定到一个输入流上,可以在输入流上调用tie(),并把输出流的地址传递给它。要断开这个链接,传递NULL即可。

下面这段程序把一个文件的输出流绑到了另一个文件的输入流上。也可以把它绑定到同一个文件的输入流上,不过要同时读写一个文件,双向I/O可能更好。

#include

#include

#include

using namespace std;

int main()

{

ifstream inFile(“input.txt”);

ofstream outFile(“output.txt”);

inFile.tie(&outFile);

outFile<<”Hello there!”;

string text;

inFile>>text;

return 0;

}

方法flush()是在ostream基类上定义的,所以也可以把一个输出流绑定到另一个输出流上。

outFile.tie(&antherOutFile);

这种关系表示,每次向一个文件写数据时,就会向另一个文件写入已经发送的缓冲数据。可以使用这种机制保持二个相关文件之间的同步。

6. 双向流

前面一直把输入流,输出流最为独立的二个类来讨论的。实际上还有一种流可以同时进行输入输出。双向流可以同时作为输入流输出流操作。双向流是iostream的子类,所以也是istream和ostream的子类。

通过stringstream类,也可以一双向方式访问字符串流。

双向流对于读位置和写位置分别有单独的指针。在读操作与写操作之间切换时,需要查找正确的位置。

7. 国际化

宽字符:把字符看做是一个字节的问题就是,并不是所有编程语言和字符集都能用8为二进制为或1个字节来表示。幸运的是,C++提供了宽字符,wchar_t。它会像char一样工作,唯一区别的是字符串和字符直接量都有一个前缀字母L,来指示应该使用宽字符编码。

wchar_t letter = L’m’;

string有wstring,ofstream有wofstream,cin、cout、cerr有wcin、wcout、wcerr。等等。

非西方字符集:Unicode编码。可以查看相关资料。

本地化环境与方面:各国之间表示数据的唯一差别就是字符集。但是即使使用同一个字符集的国家之间也有差别,比如美国与英国之间类似日期和货币之类的。

标准C++提供了一种内置机制,他可以把特定地方的数据分组到一个本地化环境中。本地化环境是特定位置相关设置的集合。各个设置称为一个方面(facet)。C++还提供了定制或者增加方面的方法。

下面把美国英语本地化环境(en_US)附加到宽字符控制台输出流上。

wcout.imbue(locale(“en_US”));

默认的本地化环境不是美国英语,而是经典本地化环境,它使用ANSI C的约定。

比如,如果根本没有设置本地化环境,或者设置默认的本地化环境,并且要输出一个数字,那么输出时不带任何标点。

wcout.imbue(locale(“C”));

wcout<<32767<

32767

但是如果使用的本地化环境是美国英语,数字就会用美