当前位置:编程学习 > C/C++ >>

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

 

揭开C++I/O的神秘面纱

 

 

 

C++通过流(stream)机制来提供比C更先进的输入输出方法。每个流都有一个相关联的源和目的。包括控制台流、文件流、字符串流等。

 

 

 

1.控制台流<iostream>:

 

流输出:cout<< ,可输出包含int、指针、double、字符、string等类型。

 

输出流方法:

 

put() 和write()是原始的输出方法。这二个方法风别接受一个字符或字符数组,而不是取已经定义了某种输出行为的对象或者变量。传递给这二个方法的数据按照原来的格式输出,没有进行任何专门的格式化或者处理。转义字符(如\n)仍然按照正确的形式输出,但不会发生多态输出。

 

flush():向输出流写数据时,流不必立即把数据写到目的中。大部分的输出流都会进入缓冲区(buffer),或者累积数据,而不是数据一到来就写出。当下列条件之一发生时,流会刷新输出(flush),或者写出累积数据:

 

        a.到达一个标记,比如endl标记。

 

        b.流超出了作用域,因此被撤销。

 

        c.对应的输入流请求输入(也就是说,利用cin输入时,cout会刷新输出)。

 

        d.流缓冲区已满。

 

        e.明确告诉流要刷新输出其缓冲区。就是flush()方法。

 

            cout<<”abc”;

 

            cout.flush();

 

        不是所有的输出流都会缓冲。比如,cerr流就没有对其输出进行缓冲。

 

 

 

处理输出错误:输出错误可能会在各种情况下产生。可能你试图向不存在或者已经指定为只读的文件写入数据。可能一个磁盘错误阻止了写操作成功执行,或者由于某种原因控制台进入了锁定状态。等等。可以调用方法good()来来确定流是否是好的。

 

cout.flush();

 

if(cout.good())

 

  cout<<”cout good!”<<endl;

 

使用good()能够很容易地获取关于流有效性的基本信息,但是它不能告诉你为什么流是不可用的。方法bad(),它提供了更多的信息,如果放回true,表示发生了一个致命的错误(不同于诸如文件结束等非致命错误)。还有一个方法fail(),如果最近的操作失败,它返回true,意味着下一个操作也会失败。

 

cout.flush();

 

if(cout.fail())

 

cerr<<”unable to flush to standard out”<<endl;

 

要重置流的错误状态,使用clear()方法

 

cout.clear();

 

这里讨论的几种方法也适合其他流。

 

 

 

输出控制符:C++的流不仅可以识别数据,还可以识别出控制符(manipulator),这些控制符是一些对象,它们可以改变流的行为,而不是为流提供数据,或者除了提供数据之外还可以改变流的行为。比如endl控制符,它封装了数据与行为。它告诉流输出一个回车符并刷新输出其缓冲区。

 

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

 

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

 

     c.setprecision。设置输出小数时的小数位数。这是一个参数化的控制符,可以接受一个参数。

 

     d.setw。设置输出数值数据时的字段宽度。这是一个参数化的控制符。

 

     e.setfill。数字宽度小于指定的宽度时,这个控制符可以指定填充空位的字符。。这是一个参数化的控制符。

 

     f.Showpoint和noshowpoing。对于没有小数部分的浮点数或者双精度数,分别表示显示和不显示小数点。

 

流也可以通过一些与之等效的方法来提供同样的功能,比如setPrecision()。

 

 

 

流输入:cin>> 它之后捕获第一个空白符之前的字符。

 

注意,即使cout没有使用endl或flush()明确刷新缓冲区,文本仍然会写到控制台上,因为使用cin就会立刻刷新输入cout缓冲区。

 

输入方法:

 

get(),此方法允许从流输入原始数据。仅仅返回流中的下一个字符。经常用于避免使用>>操作符时发生的自动词法分析。

 

下面可以读入有几个单词组成的字符串:

 

string readName(istream & inStream)

 

{

 

   string name;

 

   while(inStream.good())

 

   {

 

     int text = inStream.get();

 

     if(next == EOF)  break;

 

     name += next;

 

   }

 

return  name;

 

}

 

首先,函数的参数是istream的引用,而不是其const引用,因为从流中读取数据的方易做图改变所读取的具体流(会改变流的位置),所以它不是const方法。因此不能对const引用调用这些方法。第二,get()返回值存储在int中,而不是char中,因为get可以返回特殊的非字符值,比如EOF(文件结束)。会隐性转换为char。

 

另一个版本:

 

string readName(istream & inStream)

 

{

 

   string name;

 

char   text;

 

   while inStream.get(text))

 

   {

 

     name += next;

 

   }

 

   return name;

 

}

 

 

 

unget():对于大部分目的而言,理解输入流的正确方法是把它看作是单向的清洗槽。数据落入其中并进入变量。方法unget会打破这种模型,它允许把数据推回到清洗槽中。以此unget会引起流后退一个位置,其本质是把最后一个字符读回到流中。

 

char ch1,ch2,ch3;

 

cin>>ch1>>ch2>>ch3;

 

cin.unget();

 

char ch4;

 

cin>>ch4;

 

//ch4==ch3

 

 

 

putback():就向unget一样,允许在流中后退一个字符。二者的区别在于,putback取流中要后退的字符作为参数。

 

char ch1;

 

cin>>ch1;

 

cin.putback(ch1);

 

//ch1是输入流中得下一个字符。

 

 

 

peek():允许预览下一个值。

 

int next = cin.peek();

 

if(isdigit(next) code;

 

else othercode;

 

 

 

getline():从流中读入一行不超过指定值的数据。

 

char buffer[max+1];

 

cin.getline(buffer,max);

 

getline方易做图删除换行字符。所得到的字符串不包括换行字符。而get方易做图把换行字符留在输入流中。

 

还有一个getline方法可以用于C++字符串。

 

string myStr;

 

std::getline(cin,myStr);

 

 

 

处理输入错误:不光有前面的good()之类的方法,还有一个eof()方法,它用来判断是否到了流的结尾(文件结尾)。是,返回true,否则,返回false。

 

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

 

#include<iostream>

 

#include<fstream>

 

#include<string>补充:软件开发 , C++ ,

CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,