输入输出流(一)

1、变量的三种命名方式

a. C风格类型

_int_number_of_student

b. 驼峰表示法

numberOfStudent,sizeOfString

c.匈牙利标注法

iNumberOfStudent,charName

2、引子

C++中的输入输出操作由“流”来处理;流:指数据从一个位置流向另一个位置;提取操作:从流中获取数据的操作;插入操作:向流中添加数据的操作;

流对象(iostream.h)

cin:用来处理标准输入,即键盘输入;cout:用来处理标准输出,即屏幕输出;cerr:用来处理标准出错信息;

数据输出cout

(1)作用:将数据输出到外设(如屏幕);

(2)格式:cout<< 表达式1〔<< 表达式2 << 表达式3 … << 表达式n〕;

int a=2,b=3;

char c='x';

cout<<"a="<<a<<'\t'<<"b="<<b<<'\n';

cout<<"c="<<c<<'\n';

数据输入cin

(1)作用:从外设(键盘)输入数据到变量

(2)格式:cin>> 变量名1 〔>> 变量名2 >>变量名3 … >>变量名n〕;

其中,“>>”称为提取运算符,表示将暂停程序执行,等待用户从键盘上输入相应的数据。

int i,j; 

cin>>i>>j;

(3)分隔符:空格或回车

(4)回车作用

①通知cin已输入一行数据,cin可从输入行提取输入数据,依次赋给变量;

②用作输入数据间的分隔符。

当cin遇到回车键时,若仍有变量没有得到数据,则继续等待用户输入新的一行数据。当cin遇到回车键时,输入行中的数据没有提取完,则可给其它变量赋值。

注意:

从键盘上输入数据的个数、类型、顺序,必须与cin列举的变量一一对应。

简单的输入/输出格式控制

C++中预定义了一些格式控制函数,可以直接嵌入到cin和cout中实现输入/输出数据格式的控制。使用这些格式控制函数时,必须在程序的开头包含iomanip.h文件,即增加一行:

#include <iomanip.h>

注意:

(1)当指明用一种进制输入/输出数据时,对其后的输入/输出均有效,直到指明又以另一种进制输入/输出为止;

(2)八进制或十六进制数的输入/输出,只能适用于整型数据,不适用于实型数据和字符型数据;

(3)域宽设置函数setw(int)仅对其后的一个输出项有效。

(4)实数的小数位数设置函数setprecision(int)对其后的所有输出项都有效,直到再一次设置为止。

即从键盘输入数据,输出到显示器屏幕。这种输入输出称为标准的输入输出,简称标准I/O。

C++的I/O操作是类型安全(type safe)的。C++的I/O操作是可扩展的,不仅可以用来输入输出标准类型的数据,也可以用于用户自定义类型的数据。

以外存文件为对象的输入输出称为文件的输入输出,简称文件I/O。

对内存中指定的空间进行输入和输出(通常指定一个字符数组作为存储空间,实际上可以利用该空间存储任何信息),这种输入和输出称为字符串输入输出,简称串I/O。

3、输入输出流

    C++的输入输出流是指由若干字节组成的字节序列,这些字节中的数据按顺序从一个对象传送到另一对象。在输入操作时,字节流从输入设备(如键盘、磁盘)流向内存,在输出操作时,字节流从内存流向输出设备(如屏幕、打印机、磁盘等)。流中的内容可以是ASCII字符、二进制形式的数据、图形图像、数字音频视频或其他形式的信息。实际上,在内存中为每一个数据流开辟一个内存缓冲区,用来存放流中的数据。流是与内存缓冲区相对应的,或者说,缓冲区中的数据就是流。

在C++中,输入输出流被定义为类。C++的I/O库中的类称为流类(stream class)。用流类定义的对象称为流对象。cout(cout是console output的缩写)和cin并不是C++语言中提供的语句,它们是iostream类的对象。

    头文件是程序与类库的接口,iostream类库的接口分别由不同的头文件来实现。与iostream类库有关的头文件,常用的有

iostream包含了对输入输出流进行操作所需的基本信息。

fstream用于用户管理的文件的I/O操作。

strstream用于字符串流I/O。

stdiostream用于混合使用C和C++的I/O机制时。

iomanip在使用格式化I/O时应包含此头文件。

    在iostream头文件中定义的类有ios,istream,ostream,iostream,istream _withassign, ostream_withassign,iostream_withassign等。

iostream.h包含了对输入输出流进行操作所需的基本信息。在iostream.h头文件中不仅定义了有关的类,还定义了4种流对象。

1)四个流对象

cin是istream的派生类istream_withassign的对象,它是从标准输入设备(键盘)输入到内存的数据流,称为cin流或标准输入流。cout是ostream的派生类ostream_withassign的对象,它是从内存输入到标准输出设备(显示器) 的数据流,称为cout流或标准输出流。cerr和clog作用相似,均为向输出设备(显示器) 输出出错信息。因此用键盘输入时用cin流,向显示器输出时用cout流。向显示器输出出错信息时用cerr和clog流。

在iostream头文件中定义以上4个流对象用以下的形式(以cout为例): 

ostream cout (stdout);

    在定义cout为ostream流类对象时,把标准输出设备stdout作为参数,这样它就与标准输出设备(显示器)联系起来,如

cout<<3;//就会在显示器的屏幕上输出3。

cout流在内存中对应开辟了一个缓冲区,用来存放流中的数据,当向cout流插入一个endl时,不论缓冲区是否已满,都立即输出流中所有数据,然后插入一个换行符,并刷新流(清空缓冲区)。

cerr流对象是标准错误流,被指定为与显示器关联。cerr与标准输出流cout的作用和用法差不多。但有一点不同: cout流通常是传送到显示器输出,但也可以被重定向输出到磁盘文件,而cerr流中的信息只能在显示器输出。cerr流中的信息是用户根据需要指定的。

clog(console log)流对象也是标准错误流,作用和cerr相同。区别: cerr不经过缓冲区,直接向显示器上输出信息,而clog中的信息存放在缓冲区中,缓冲区满后或遇endl时向显示器输出。

#include <iostream>

#include <string>

using namespace std;

int main()

{

float a,b,c,disc;

cout<<"Please input a,b,c:";

cin>>a>>b>>c;

if(a==0) cerr<<"a is equal to zero,error!"<<endl;

else if((disc=b*b-4*a*c)<0)

 cerr<<"disc=b*b-4*a*c<0"<<endl;

else {

 cout<<"x1="<<(-b-sqrt(disc))/(2*a)<<endl;

    cout<<"x2="<<(-b+sqrt(disc))/(2*a)<<endl;}

return 1;

}

2)格式输出

(1)使用控制符控制输出格式

  C++的I/O 系统定义了一些用来管理I/O 格式的控制函数。它们不在类的封装之内,表面上也不一定以函数调用的形式出现,因此它们被称为格式控制符,格式控制符包括有参和无参的控制符,分别在两个头文件中说明。

 定义在iostream.h 文件中的I/O 控制符有:

 endl 输出时插入换行符并刷新流

 ends 输出时在字符串后插入NULL 作为尾符

 flush 刷新,把流从缓冲区输出到目标设备

 ws 输入时略去空白字符

 dec 令I/O 数据按十进制格式

 hex 令I/O 数据按十六进制格式

 oct 令I/O 数据按八进制格式

 定义在iomanip.h 文件中的带参控制符有:

 setbase(int a)

 resetiosflags(long)

 setiosflags(long)

 setfill(char)

 setprecision(int)

 setw(int)

 这些格式控制符大致可以代替ios 的格式函数成员的功能,且使用比较方便。例如,为了把整数457 按16 进制输入,可有两种方式:

 int i=457;

 cout.setf(ios:hex,ios::basefield);

 cout<<i<<endl;或者:

 int i=457;

 cout<<hex<<i<<endl;

 由例中可以看出采用格式控制符比较方便,二者的区别主要为:

 (1) 用成员函数须增加限定前缀:“cout”,控制符是类外定义的无此要求。

 (2) 用格式成员函数时要单独成一语句,不能用I/O运算符“<<”和“>>”与数据的I/O 写到一起。如cout<<hex<<i<<endl;那样。

  从这个例中还发现,用标志状态字时,还要注意状态字的各个位对应的特征不是无关的。例如dec,hex,oct三者只能取其一,简单地用cin.setf(ios:dec)的形式可能出现问题:

 cout.setf(ios::dec);

 cout.setf(ios::oct);

  这两个函数调用之后,在两个特征位置都为1,但输出不可能既是十进制又是十六进制。为了解决集中互斥属性不能同时设置的问题,ios 类中又定义了公有的静态常量:

 static const long basefield //值为dec/oct/hex

 static const long adjustfield //值为left/right/intenal

 static const long floatfield //值为scientific/fixed

 其使用方法为:

 cout.setf(ios::scientific,ios::floatfield);

 其第二个参数保证设置为科学表示法,同时不设置为定点表示法。

 格式控制符的使用比较方便,但有些细节应在使用中注意。

fmtflags ios::flags(fmtflags newflags);

fmtflags ios::setf(fmtflags ored_flag);

fmtflags ios::unsetf(fmtflags clear_flag);

fmtflags ios::setf(fmtflags bits, fmtflags field);

fmtflags field用来保证同一种类型的值只设置一种,在设置新值时,先清除先前设置过的值。常用后三种

(1)有些控制符与对应的格式成员函数功能一致,例如:

 setiosflags(long)与函数long setf(long)的功能一致;

 resetiosflags(long)则与函数long unsetf(long)的功能一致。

(2) setfill(char),setw(int)和setprecision(int)是三个常用的有参控制符,

 其中:

 setw(n)为数据域宽。如果数据实际宽度小于n 则以填充字符填完;如果数据实际宽度大于n,则原数照常输出,并不删除任何一位,参数n 的缺省值为0。setw(n)的使用与函数width(n)除了上面讲的之外,还有一点不同即setw(n)的有效范围只涉及后面的一个I/O 数据,这与width(n)的情况不同,后者的设置一直保持到有新的设置为止。setprecision(n)与函数precision(n)的功能一致,缺省的精度值为n=6。setfill(c)与函数fill(c)的功能一致,缺省的填充字符为空格。

(2)用流对象的成员函数控制输出格式

        除了可以用控制符来控制输出格式外,还可以通过调用流对象cout中用于控制输出格式的成员函数来控制输出格式。流成员函数setf和控制符setiosflags括号中的参数表示格式状态,它是通过格式标志来指定的。格式标志在类ios中被定义为枚举值。因此在引用这些格式标志时要在前面加上类名ios和域运算符“::”。

在类ios 的说明中,列出下面一些用于格式控制的公有成员函数:

long flags(); //返回当前标志字

long flags(long); //设置标志字并返回

long setf(long); //设置指定的标志位

long unsetf(long); //清除指定的标志位

long setf(long,long); //设置指定的标志位的值

int width(); //返回当前显示数据的域宽

int width(int); //设置当前显示数据域宽并返回原域宽

char fill(); //返回当前填充字符

char fill(char); //设置填充字符并返回原填充字符

int precision(); //返回当前浮点数精度

int precision(int); //设置浮点数精度并返回原精度(指小数点后的位数)

 所涉及的标志字又称标志状态字,它是一个long 类型(长整型)的变量。状态字的各位都控制一定的I/O 特征,例如标识状态字的右第一位为1,则表示在输入时跳过空白符号。状态字的各位以枚举类型形式定义于ios 说明中:

 enum{

 skipws=0x0001 //输入时跳过空白

 left=0x0002 //左对齐输出

 right=0x0004 //右对齐输出

 internal=0x0008 //在符号位和基指示符后填充

 dec=0x0010 //十进制格式

 oct=0x0020 //八进制格式

 hex=0x0040 //十六进制格式

 showbase=0x0080 //输出标明基数说明

 showpoint=0x0100 //输出浮点数带小数点

 uppercase=0x0200 //十六进制大写输出

 showpos=0x0400 //输出正整数带+号

 scientific=0x0800 //输出浮点数用科学表示法

 fixed=0x1000 //输出浮点数以定点形式

 unitbuf=0x2000 //插入后刷新流缓冲区

 stdio=0x4000 //插入后刷新stdout 和stderr

 };

    cin.flags()返回当前的(键盘)输入流中的标志状态字,但它一般不单独使

用。

cin.flags(cin.flags()|ios::skipws);

这个函数的调用,其实参为两个状态字的“或”运算的结果。其功能是在原有的状态不变条件下,输入时跳过空白。

cout.flags(cout.flags()|ios::showbase);

此函数调用结果为要求输出时标明数制基数符,其它设置不变。如果要求不标明基数符,则需执行:

cout.flags(cout.flags()&~ios::showbase);

用setf 函数有时可能比较方便:

cin.setf(ios::skipws);

同样是要求输入时跳过空白。为了改变这一设置,令其输入时不跳过空白

可用下面的两种方式之一:

cin.unsetf(ios::skipws);或cin.setf(0,ios::skipws);

再如:cout.unsetf(ios::uppercase);可令十六进制数以小写字符输出,而

cout.setf(1,ios::uppercase);则可令其大写输出。

其余函数更为常用,同时也比较简单:

cout.width(12);设置数据宽度位12,

cout.precision(4);输出浮点数时小数点后取4 位,

cout.fill('#');要求输出中用‘#’填充空白。

例如:

#include <iostream>

#include <string>

using namespace std;

int main()

{

cout.setf(ios::scientific);

cout.setf(ios::showpos);

cout<<2345<<23.4567<<endl;

cout.precision(2);

cout.width(10);

cout<<2345<<23.4567<<endl;

cout.unsetf(ios::scientific);

cout.fill('#');

cout.width(8);

cout<<2345<<23.4567<<endl;

return 1;

}

当然了,还有用户自定义的格式控制符。

再举两个例子:

#include <iostream>
#include <string>
#include <iomanip>
using namespace std;
int main()
{
int a;
cout<<"input a:";
cin>>a;
cout<<"dec:"<<dec<<a<<endl;
cout<<"hex:"<<hex<<a<<endl;
cout<<"oct:"<<setbase(8)<<a<<endl;
char* pt="China";
cout<<setw(10)<<pt<<endl;
cout<<setfill('*')<<setw(10)<<pt<<endl;
double pi=22.0/7.0;
cout<<setiosflags(ios::scientific)<<setprecision(8);
cout<<"pi="<<pi<<endl;
cout<<"pi="<<setiosflags(ios::fixed)<<pi<<endl;
return 1;
}

#include <iostream>
#include <string>
#include <iomanip>
using namespace std;
int main()
{
int a=21;
cout.setf(ios::showbase);
cout.unsetf(ios::dec);
cout.setf(ios::hex);
cout<<"hex:"<<a<<endl;
char* pt="China";
cout.width(10);
cout<<pt<<endl;
cout.width(10);
cout.fill('*');
cout<<pt<<endl;
double pi=22.0/7.0;
cout.setf(ios::scientific);
cout<<"pi=";
cout.width(14);
cout<<pi<<endl;
return 1;
}

发布了208 篇原创文章 · 获赞 30 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/hopegrace/article/details/104219587