输入/输出流

流类简介

在C++的标准类库中,将与数据输入/输出相关的类统称为“流类".


image.png

istream类提供了流的大部分输入操作,对系统预定义的所有输入流重载提取运算符“>>”。ostream类对系统预定义的所有输出流重载插入运算符“<<”。
表7-1 常用I/O流类列表

类名 说明 包含文件
抽象流基类 ios 流基类 ios
输入流类 istream 通用输入流基类和其他输入流基类。cin是该类的对象 istream
ifstream 文件输入流类。用于从文件读取数据 fstream
输出流类 ostream 通用输出流基类和其他输出流基类。cout是该类的对象 ostream
ofstream 文件输出流类。用于向文件写入数据 fstream
输入输出流类 iostream 通用输入/输出流基类和其他输入/输出流基类 istream
fstream 文件输入/输出流类。既能从文件中读取数据,也能向文件中写入数据 fstream

常见的头文件有以下三个。

  • iostream
    包含操作所有输入/输出流所需的基本信息。
  • iomanip
    包含格式化I/O的带参数操纵符,可用于指定数据输入/输出的格式。
  • fstream
    包含处理文件的有关信息。

标准流对象

标准流对象是为用户提供的常用外设与内存之间通信的通道,对数据进行解释和传输,提供必要的数据缓冲等。

C++在头文件iostream中为用户预定义了4个标准流对象,分别是cin(标准输入流)、cout(标准输出流)、cerr(非缓冲错误输出流)和clog(缓冲错误输出流)。

重定向,是改变默认的输入来源,或改变默认的输出目的地。
重定向函数freopen的原型

FILE *freopen(const char *path,const char *mode,FILE *sream);

freopen()功能是将stream按mode指定的模式重定向到路径path指向的文件。

程序7-1 将标准输出cout重定向到文件

#include 
using namespace std;

int main()
{
    int x,y;
    cin>>x>>y;
    freopen("test.txt","w",stdout); //将标准输出重定向到文件test.txt
    if(y==0)        //除数为0则输出错误信息
        cerr<<"error."<>x;
        sum+=x;
    }
    cout<<"前10个整数的平均值 = "<<1.0*sum/10<

表7-2 ios中错误状态字

标识常量 含义
goodbit 0X00 流状态正常
eofbit 0X01 文件结束符
failbit 0X02 I/O操作失败,数据未丢失,可以恢复
badbit 0X04 非法操作,数据丢失,不可恢复

在ios类中还有几个与流状态相关的成员函数。

  • 返回流是否结束 int eof() const
    返回eofbit的值。
  • 返回流是否处于正常状态 int fail() const
    返回failbit状态
  • 判定流是否正常 int good() const;int operator void *();
  • 返回流是否处于失败状态 int bad() const; int operator void !();
  • 返回状态字 int rdstate() const;
    返回流的当前状态
  • 恢复状态字 void clear(int nStata = 0);

程序7-3 标准输入重定向为文件并判断文件状态

#include 
using namespace std;
int main()
{
    int x,count,sum = 0;
    freopen("input.dat","r",stdin); //将标准输入重定向到文件input.dat
    for(count=0;count<10;count++)
    {
        cin>>x;
        sum+=x;
        if(cin.eof()) break;
    }
    cout<<"前"<

程序7-4 将从键盘输入的数据进行累加

#include 
#include 
using namespace std;

int main()
{
    char ch;
    int sum = 0,count=0,x;
    cout<<"请输入整数(按Ctrl+Z退出)"<>x)       //使用组合键 结束输入
        {
            sum += x;       //计算累加和
            count++; 
        } 
        cout<<"确实要退出输入请按 Q";
        cin.clear();        //状态字清0,恢复流状态
        cin>>ch; 
    }while(toupper(ch)!='Q');
    cout<<"sum="<

控制I/0格式

c++进行I/O格式控制的方式一般有使用流操作符设置标志字调用成员函数

流操作符

表7-3 C++中常见数据类型的默认I/O格式

I/O的数据类型 默认的输入格式 默认的输出格式
short、int、long(signed、unsigned) 与整型常数相同 一般整数形式,负数前面有负号
float、double、long double 与浮点数相同 浮点或指数格式,取决于哪个更短
char(signed、unsigned) 第一个非空白字符 单个字符(无引号)
char *(signed、unsigned) 从第一个空白字符(空格、\t、\n等)开始到下一个空白字符结束 字符序列(无引号)
void * 无前缀的十六进制数 无前缀的十六进制数
Bool 将true或1识别为true,将false或0识别为false 1或0

C++在iostream中提供了一些常用的无参数的流操作符。
表7-4 iostream中常用流操作符

流操作符 作用 输入/输出
endl 输出一个新行符,并清空流 O
ends 输出字符串结束,并清空流 O
flush 清空流缓冲区 O
dec * 以十进制形式输入或输出整数 I/O
hex 以十六进制形式输入或输出整数 I/O
oct 以八进制形式输入或输出整数 I/O
ws 提取空白字符 O

注:“流操作符”栏中的星号“*”不是操作符的一部分,表示是默认设置。

在头文件iomanip中定义了一些用于格式控制的流操纵符。
表7-5 常用的用于格式控制的流操纵符

流操纵符 作用
fixed 以普通小数形式输出浮点数
scientific 以科学计数法形式输出浮点数
left 左对齐,即在宽度不足时将填充字符添加到右边
right 右对齐,即在宽度不足时将填充字符添加到左边
setbase(int b) 设置输出整数时的进制,b为8、10或16
setw(int w) 指定输出宽度为w个字符,或输入字符串时读入w个字符。一次有效
setfill(int c) 在指定输出宽度的情况下,输出的宽度不足时用ASCII码为c的字符填充(默认情况是用空格填充)
setprecision(int n) 设置输出浮点数的精度为n。在使用非fixed且非scientific方式输出的情况下,n即为有效数字最多的位数。如果有效数字位数超过n,则小数部分四舍五入,或自动变为科学计数法输出并保留一共n位有效数字;在使用fixed方式和scientific方式输出的情况下,n是小数点后面应保留的位数
setiosflags(fmtfalgs f) 通用操纵符。将格式标志f所对应的格式标志位置为1
resetiosflags(fmtfalgs f) 通用操纵符。将格式标志f所对应的格式标志位置为0(清除)
boolapha 把true和false输出为字符串
noboolalpha * 把true和false分别输出为1和0
showbase 输出表示数值进制的前缀
noshowbase * 不输出表示数值进制的前缀
showpoint 总是输出小数点
noshowpoint * 只有当小数部分存在时才显示小数点
showpos 在非负数值中显示+
noshowpos * 在非负数值中不显示+
skipws * 输入时跳过空白字符
noskipws 输入时不跳过空白字符
uppercase 十六进制数中使用'A'~'E'。若输出前缀,则前缀输出“0x”,科学计数法中输出’E‘
no uppercase * 十六进制数中使用'a'~'e'。若输出前缀,则前缀输出“0x”,科学计数法中输出’e‘
internal 数值的符号(正负号)在指定宽度内左对齐,数值右对齐,中间由填充字符填充

程序7-5 使用流操纵符控制整数输出

#include 
#include 
using namespace std;
int main()
{
    int n = 65535,m = 20;
    //1)分别输出一个整数的十进制、十六进制和八进制表示
    cout<<"1) "<

程序7-6 使用流操纵符控制浮点数输出

#include 
#include 
using namespace std;

int main()
{
    double x = 1234567.89,y = 1.23456789;
    //1)无格式控制时
    cout<<"无格式控制时: \t\t 1)x=("<

程序7-7 通过setw()控制输入格式

#include 
#include 
using namespace std;
int main()
{
    string s1,s2;
    cin>>setw(5)>>s1>>setw(3)>>s2;
    cout<<"s1="<

标志字

为满足不同用户对数据输入/输出格式的要求,C++提供了通过setiosflags()设置标志字进行格式控制的方式。setiosflags()是带参数的操纵符,在头文件iostream中,用以设置指定的标志,函数的参数为流的格式标志位。

表7-6 常见格式标志常量及含义

标志常量名 含义 输入/输出
ios::skipws 0X0001 跳过输入中的空白 I
ios::left 0X0002 按输出域左对齐,用填充字符填充右边 O
ios::right * 0X0004 按输出域右对齐,用填充字符填充左边 O
ios::internal 0X0008 在符号位或基数指示符后填入字符 O
ios::dec * 0X0010 转换为十进制基数形式 I/O
ios::oct 0X0020 转换为八进制基数形式 I/O
ios::hex 0X0040 转换为十六进制基数形式 I/O
ios::showbase 0X0080 在输出中显示基数指示符 O
ios::showpoint 0X00100 在浮点数时必须带小数点和尾部的0 O
ios::uppercase 0X00200 以大写字母表示十六进制数,科学计数法使用大写字母E O
ios::showpos 0X00400 正数前加”+“号 O
ios::scientific 0X00800 科学计数法显示浮点数 O
ios::fixed 0X001000 定点形式表示浮点数 O
ios::unitbuf 0X002000 插入操作后立即刷新流 O

程序7-8 通过setiosflags()设置标志字进行格式控制

#include 
#include 
using namespace std;

int main()
{
    double x = 12.34;
    cout<<"1)"<

调用cout的成员函数

ostream类提供了在cout中控制输出格式的成员函数,常见的有:

  • 设置和返回标志字 long flags(long 1Flags); long flags() const;
  • 设置标志位 long setf(long 1Flags);
  • 清除标志位 long unsetf(long 1Flags);
  • 设置和返回输出宽度 int width(int w); int width() const;
  • 设置填充字符 char fill(char cFill); char fill() const;
  • 设置数据显示精度 int precision(int np); int precision() const;

表7-7 ostream类的成员函数及与其作用相同的流操纵符

成员函数 作用相同的流操纵符
precision(int np) setprecision(np)
widh(int nw) setw(nw)
fill(char cFill) setfill(cFill)
setf(long IFlags) setiosflags(IFlags)
unsetf(long IFlags) resetiosflags(IFlags)

程序7-9 使用cout中的函数控制输出格式

#include 
using namespace std;
int main()
{
    double values[] = {1.23,20.3456,300.4567,4000.56789,50000.1234567};
    cout.fill('*');     //设置填充字符为星号*
    for(int i = 0;i

ostream类还有一些输出流的成员函数。

  • 字符插入 ostream &put(char c);
  • 数据块插入 ostream & write(const char *pch,int nCount);

程序7-10 使用cont()函数

#include 
using namespace std;
int main()
{
    char c = 'a',str[80] = "0123456789abcdefghijklmn";
    int x = 65;
    cout<<"cout.put('a'): ";cout.put('a');
    cout<<"\ncout.put(c+25): ";cout.put(c+25);
    cout<<"\ncout.put(x): ";cout.put(x);
    cout<<"\ncout.write(str,20): ";
    cout.write(str,20);
    return 0;
}

cout.put('a'): a
cout.put(c+25): z
cout.put(x): A
cout.write(str,20): 0123456789abcdefghij

调用cin的成员函数

get()函数

从输入流中读取一个字符(包括空白字符),返回值就是该字符的ASCII码。
程序7-11 采用EOF判断输入是否结束

#include 
using namespace std;
int main()
{
    int n = 0;
    char ch;
    while((ch = cin.get())!=EOF)
    {
        cout.put(ch);
        n++;
    }
    cout<<"输入字符共计: "<

getline()函数

从输入流中的当前字符开始读取bufSize-1个字符到缓冲区buf,或读到'\n'为止。

程序7-12 getline()函数功能演示

#include 
using namespace std;
int main()
{
    char buf[10];
    int i = 0;
    while(cin.getline(buf,10))      //若输入流的一行超过9个字符,则会报错
        cout<<++i<<":"<

eof()函数 bool eof();

用于判断输入流是否已经结束。

ignore()函数 istream & ignore(int n=1,int delim=EOF);

跳过输入流中的n个字符,或跳过delim及其之前的所有字符。

例如,现有若干电话号码。提取号码

Home: 12345678901
Tel:12345678019
Office:19876543210

程序7-13 从输入的字符串中提取电话号码

#include 
using namespace std;
int main()
{
    char str[30];
    while(!cin.eof())
    {
        cin.ignore(10,':'); //在cin流中跳过':'之前的全部字符
        if(!cin.eof())
        {
            cin>>str;
            cout<

peek()函数 int peek();

返回输入流中的当前字符,但是并不将该字符从输入流中取走——相当于只是”看了一眼“将要读入的下一个字符,因此叫”窥视“。

程序7-14 日期格式转换

#include 
#include 
#include 
using namespace std;

string Months[13] = {"","Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};//西文格式的月份

int main()
{
    char ch;
    int year,month,day;
    while((ch=cin.peek())!=EOF)
    {
        if(ch>='A'&&ch<'Z')
        {
            string sMonth;
            cin>>sMonth>>day>>year;     //接收:月、日、年
            //查找月份完成转换
            for(month=0;month<12&&sMonth!=Months[month];++month); 
        }
        else
        {
            cin>>year;
            cin.ignore()>>month;
            cin.ignore()>>day;
            //以上3条语句等价于:cin>>year>>ch>>month>>ch>>day; 
        }
        cin.ignore();   //跳过\n
        cout<

你可能感兴趣的:(输入/输出流)