C/C++有以下几种流对象的:

型别                名称                          作用

istream                cin                           从input通道读入数据

ostream              cout                          将数据写到标准output通道

ostream              cerr                          将错误信息写到标准error通道

ostream              clog                          将日志信息写到标准logging通道

wistream            wcin                          从input通道读入宽字符数据

wostream          wcout                        将宽字符数据写到标准output通道

wostream          wcerr                         将宽字符错误信息写到标准error通道

wostream          wclog                         将宽字符日志信息写到标准logging通道

注意,以上对象均是全局对象这意味着在多线程环境中使用它们时要非常小心,尤其是最常用的标准输入输出流(cin和cout)。

stream维护着一种状态,标志I/O是否成功,并且能够指明失败的原因。

stream定义了一些类型为iostate的产生过户来反映stream的状态。

这些状态(iostate类型)是ios_base的成员:

static const iostate badbit,eofbit,failbit,goodbit;

其意义如下:

badbit           毁灭性的错误,未定义的(不确定的)状态

eofbit             遇到end-of-file

failbit             错误,某个I/O操作未成功

goodbit         一切都好,没有其他状态位被设立

其中,failbit和badbit的却别在于:

failbit表示某项操作未能完成,单stream大体OK,通常是读入格式错误,如要读一个int值,输入的却是字符串(通常是可以挽回的)。

badbit表示因不明原因丢失或损坏数据,如将stream定位于文件起始端的前方(通常是不可挽回的)。

注意,通常eofbit和failbit同时出现,因为在end-of-file之后读取操作也会失败!

这些状态的常量定义域ios_base类里,并非全局的,因此使用的时候需要加上域作用符(ios_base或者其子类),如:

std::ios_base::eofbit,std::ios::eofbit ///(ios派生自ios_base)

C++还定义了一些处理stream状态的成员函数:

good()                             若stream正常无误则返回true(表示goodbit成立)

eof()                                若遇到end-of-file则返回true(表eofbit成立)

fail()                                若发生错误则返回true(表failbit||badbit成立)

bad()                               若发生毁灭性错误则返回true(表badbit成立)

rdstate()                          返回当前stream已设立的所有标志

clear()                              返回当前stream所有标志

clear(state)                       返回当前stream所有标志后,设立state

setstate(state)                  追加标志state

后三个常用于异常处理。

关于4个状态标志的解释:

1.输入(输出)对象中的流状态成员标记了输入(输出)流当前的状况,当eofbit、badbit、failbit三个标记位均为0时表示流状态正常。

2.一但某个或几个标记位被设置,表示对象的流状态出现相应状况,流将对后面的输入(输出)关闭,直到标记位被清除。

3.只有在流状态良好(goodbit)的情况下,if或者while对该输入(输出)对象的判断才能是true。

if(cin>>input)    cout<<input<<endl;else    cout<<"input   error"<<endl;if(!cin)    cou<<"input   error"<<endl;else    cout<<input<<endl;//第一次代码结束if(cin>>input)    cout<<input<<endl;else    cout<<"input   error"<<endl;if(!cin)    cou<<"input   error"<<endl;else    cout<<input<<endl;//重复代码结束

如果输入567a,输出是:

567

567

input   error

input   error

过程:第一次">>"操作符截取了输入的"567",此时流状态正常;第二次时,">>"抽取的"a"与int类型不匹配,此时cin的failbit标志位置1,goodbit标志位置0,且在恢复之前,流将对后面的输入关闭。

在例3.5中,代码如下:

View Code

#include<pthread.h>#include<iostream>#include<unistd.h>

using namespace std;

void *thread(void *arg){    cout << "in thread, tid = " << pthread_self() << endl;

    sleep(60);

return (void *)12;}

int main(){    pthread_t tid;if(pthread_create(&tid, NULL, thread, 0) != 0)    {    cout << "pthread_create error" << endl;return 0;    }

    pthread_cancel(tid);

int *r;    pthread_join(tid, (void**)&r);

    cout << PTHREAD_CANCELED << endl;    cout << r << endl;

    cout << "in main thread, tid = " << pthread_self() << endl;return 0;}

某些环境下,由于两个线程的竞争会使cout出错(failbit和badbit)。解决方法:

1.加互斥量,同步对cout的访问。对本例不太适用,原因:"pthread_cancel()"且两个进程的推进顺序具有随机性,仅仅简单的加锁非但不能解决问题,而且可能造成死锁(除非进行更精确的控制,但这无疑增大了开销,且降低线程间的并行性)。另一篇文章“printf和cout的线程安全问题”(http://blog.csdn.net/hujiao199/article/details/5002474)也进行了加锁,但cout冲突访问依然存在。凡是在临界区中可能导致线程中途退出,从而不能解锁的都不适用。"Linux学习之互斥量的封装二:封装临界区"提供了一种可靠的临界区类,保证了程序在异常终止和中途退出的情况下也能正确解锁。当仅使用该方法依然不能解决3.5的问题,需要配合操作流状态的函数(把状态标志置为正常)才行。
2.如上所述,用printf或其他线程安全的函数取代cout进行输出。经测试,此方法对例3.5有效。

3.在子线程中cout前忽略PTHREAD_CANCELE信号,cout后再恢复。对3.5这种子线程业务逻辑简单的可行,但对业务逻辑复杂的子线程,一样不容易进行控制(线程推进顺序的随机性)。

最后,记一下"endl"、"\n"和"flush":(本段来自"详解flush函数——endl控制符和'\n'换行符的区别":http://hi.baidu.com/tachun/blog/item/30b1ce0f9b849a2d6159f3e6.html)

首先,标准输入输出流(cin和cout)都是带有缓冲的。endl控制符和’ \n’换行符都可以将光标移动到输出设备中下一行的开头处。但是,endl控制符还有另外的用途。

当程序向输出设备中输出数据时,输出的数据先被存放在计算机缓冲区(Buffer)内。当缓冲区存满时,这些数据才真正地输出到输出设备。但是,如果输出的字符序列中出现了 endl控制符,那么缓冲区内的所有数据将立即输出到输出设备,而无论缓冲区是否已经存满。因此,endl控制符的作用是将光标移动到输出设备中下一行开头处,并且清空缓冲区。很有可能出现在程序终止时,并没有输出所有的输出数据的情况。这是因为在程序终止时,缓冲区并不一定是满的,所以也就没有将缓冲区中的数据写到输出设备。

  在C++中,可以使用flush函数来清空缓冲区,即使缓冲区中的数据不是满的。与endl控制符不同的是,flush函数并不是把光标移到下一行的开头处

  使用flush函数的语法是:

  ostreamVar.flush();//cout.flush();

  与endl一样,flush可以作为控制符使用。在这种情况下,flush使用在输出语句中,并不加括号。例如,下面的语句将数据从缓冲区写到标准输出设备:

  cout<<flush;

考虑一个典型应用:在同一行等待用户输入:

  cout<<”enter an integer:”<<flush;

在这种情况下,文字行“enter an integer:”,即使在缓冲区数据没有存满时也会立即被输出到标准输出设备上。而且,在输出这行文本后,光标将停留在分号的下一个位置上。用户将在分号后面输入数字。

关于"stream的状态标志和处理状态的函数"的详细资料,参看"C I-O流事态符号位"http://blog.sina.com.cn/s/blog_6ac2c3a70100utbx.html

"C++之stream异常"http://hi.baidu.com/nicker2010/blog/item/41a400f8daaf440c6c22eb5f.html

转载于:https://www.cnblogs.com/lq0729/archive/2011/10/20/2219009.html

C/C++的流(stream)对象相关推荐

  1. 如何将struct System.Byte byte []转换为C#中的System.IO.Stream对象?

    如何将struct System.Byte byte[]转换为C#中的System.IO.Stream对象? #1楼 查看MemoryStream类. #2楼 您正在寻找MemoryStream.Wr ...

  2. C语言ftell()函数(返回文件当前位置)(返回给定流 stream 的当前文件位置)

    C 标准库 - <stdio.h> 描述 C 库函数 long int ftell(FILE *stream) 返回给定流 stream 的当前文件位置. 声明 下面是 ftell() 函 ...

  3. c语言fgetc()函数(从指定的流 stream 获取下一个字符(一个无符号字符),并把位置标识符往前移动)

    C 标准库 - <stdio.h> 文章目录 描述 声明 参数 返回值 实例 描述 C 库函数 int fgetc(FILE *stream) 从指定的流 stream 获取下一个字符(一 ...

  4. C语言fputs()函数(把字符串写入到指定的流 stream (文件指针)中)

    C 标准库 - <stdio.h> 注意:fgets和fputs是字符串读写,fread和fwrite是数据块读写 文章目录 描述 声明 参数 返回值 实例 描述 C 库函数 int fp ...

  5. C语言函数fscanf()(从流 stream 读取格式化输入)(如果成功,返回成功匹配和赋值的个数;否则返回EOF)(分隔符:space、Tab、Enter)

    C 标准库 - <stdio.h> 文章目录 描述 声明 参数 返回值 实例1 实例2 实例3 注意(分隔符:space.Tab.Enter) 换行格式化输入示例(暂时只能弄英文字符,中文 ...

  6. C语言rewind()函数(设置文件位置为给定流 stream 的文件的开头)(回到文件开头重读)

    C 标准库 - <stdio.h> 文章目录 描述 声明 参数 返回值 实例 描述 C 库函数 void rewind(FILE *stream) 设置文件位置为给定流 stream 的文 ...

  7. Java19-day10【标准输入输出流、字节字符打印流、对象序列化-反序列化流、serialVersionUIDtransient、Properties】

    视频+资料[链接:https://pan.baidu.com/s/1MdFNUADVSFf-lVw3SJRvtg   提取码:zjxs] Java基础--学习笔记(零起点打开java世界的大门)--博 ...

  8. Java 方法、 流(Stream)、文件(File)和IO 总结

    这里只总结几个要点. 1. 方法的命名规则 1.方法的名字的第一个单词应以小写字母作为开头,后面的单词则用大写字母开头写,不使用连接符.例如:addPerson. 2.下划线可能出现在 JUnit 测 ...

  9. Node.js: 认识流stream

    流是Node.js中一个非常重要的概念, 也是Node.js之所以适用于I/O密集型场景的重要原因之一. 流是Node.js移动数据的方式,流可以是可读的和/或可写的.在Node.js中很多模块都使用 ...

最新文章

  1. 使用intellij idea制作可执行jar文件
  2. 【青少年编程】全国青少年软件编程等级考试大纲与说明(Scratch)
  3. 中英文论文高效排版插件一一 Tip ( Text Image P rocessing )
  4. oracle导入substring,java中substring()和oracle中substr()区别
  5. java jar 配置文件路径_java jar 配置文件的相对路径问题
  6. 背包问题学习笔记(二)
  7. mermaid流程图工具_Markdown高级使用之流程图
  8. php java memcached_php-memcached详解
  9. mysql中如何计算同比环比_vnpy中如何计算MACD指标
  10. 基于Cohesie单元的二维水力压裂
  11. 想要Linux上云?如何实现Linux工作流上云部署
  12. SPAMS稀疏建模工具箱
  13. 3dmax修改器堆栈的妙用
  14. 微服务化之无状态化和容器化
  15. 英语常用缩写(Abbreviations) ---一般常用缩写
  16. 深信服上网行为管理如何配置双因素/双因子(2FA)身份认证
  17. IT十年人生过客-十五-回京
  18. 计算机专业的职业探索,职业教育计算机教学的探索
  19. 读书有益——》《让我留在你身边》
  20. linux网卡驱动程序分析

热门文章

  1. 第三周 分队列 mooc 翁恺 c语言
  2. 初一辍学学php能行吗_那些初中就辍学的小姑娘现在过得如何了?
  3. ssh 远程登录_C.4 彻底解决-新版本Sentaurus TCAD的SSH远程登录问题!!!
  4. 6.5版本虚拟机的封装
  5. 阅读软件怎么添加书源_相册视频制作软件怎么用?怎么添加滤镜?
  6. print('HelloWorld'),Python为你打开一扇门。
  7. Linkswap宣布为DigiByte启动RenVM桥接器
  8. SAP License:SAP 系统参数设置
  9. 企业税银数据深度分析(上)
  10. 谈谈线下消费分期的风险点