C++从入门到精通(第5版)
上QQ阅读APP看书,第一时间看更新

2.5 数据输入与输出

在用户与计算机进行交互的过程中,数据输入与输出是必不可少的操作过程。计算机需要通过输入获取用户的操作指令,并通过输出显示操作结果。本节将介绍数据输入与输出的相关内容。

2.5.1 控制台屏幕

在NT内核的Windows操作系统中为保留DOS系统的风格,提供了控制台程序,单击系统的“开始”→“运行”命令,运行cmd.exe程序,可以启动控制台。在控制台中可以运行DIR、CD、DELETE等DOS系统中的文件操作命令,也可以启动Windows程序。控制台屏幕如图2.7所示。

使用Visual C++ 6.0创建的控制台程序都将运算结果输出到如图2.7所示的控制台屏幕上,它是程序显示输出结果的地方。

图2.7 控制台屏幕

2.5.2 C++语言中的流

在C++语言中,数据的输入和输出发生在标准输入/输出设备(键盘、显示器)、外部存储介质(磁盘)和内存的存储空间。对标准输入/输出设备的输入/输出简称标准I/O,对在外存磁盘上文件的输入/输出简称文件I/O,对内存中指定的字符串存储空间的输入/输出简称串I/O。

C++语言中把数据之间的传输操作称为流。C++中的流既可以表示数据从内存传送到某个载体或设备中,即输出流;也可以表示数据从某个载体或设备传送到内存缓冲区变量中,即输入流。C++中所有流都是相同的,但文件可以不同(文件流参见第16章)。使用流以后,程序用流统一对各种计算机设备和文件进行操作,使程序与设备、文件无关,从而提高了程序设计的通用性和灵活性。

C++语言定义了I/O类库供用户使用,标准I/O操作有4个类对象,分别是cin、cout、cerr和clog。其中cin代表标准输入设备键盘,也称cin流或标准输入流。cout代表标准输出显示器,也称cout流或标准输出流,当进行键盘输入操作时使用cin流,当进行显示器输出操作时使用cout流,当进行错误信息输出操作时使用cerr流或clog流。

C++的流通过重载运算符“<<”和“>>”执行输入和输出操作。输出操作是向流中插入一个字符序列,因此,在流操作中,将左移运算符“<<”称为插入运算符。输入操作是从流中提取一个字符序列,因此,将右移运算符“>>”称为提取运算符。

1.cout语句的一般格式
     cout<<表达式1<<表达式2<<…<<表达式n;

cout代表显示器,执行cout << x操作就相当于把x的值输出到显示器。

先把x的值输出到显示器屏幕上,在当前屏幕光标位置显示出来,然后cout流恢复到等待输出的状态,以便继续通过插入操作符输出下一个值。当使用插入操作符向一个流输出一个值后,再输出下一个值时将被放在上一个值的后面,所以为了让流中前后两个值分开,可以在输出一个值后接着输出一个空格,或一个换行符,或其他需要的字符或字符串。

一个cout语句可以分写成若干行,例如:

     cout<< "Hello World!" <<endl;

可以写成:

也可写成多个cout语句:

以上3种情况的输出均正确。

2.cin语句的一般格式
     cin>>变量1>>变量2>>…>>变量n;

cin代表键盘,执行cin>>x操作就相当于把键盘输入的数据赋值给变量。

当从键盘上输入数据时,只有当输入完数据并按下Enter键后,系统才把该行数据存入键盘缓冲区,供cin流顺序读取给变量。另外,从键盘上输入的每个数据之间必须用空格或Enter键分开,因为cin为一个变量读入数据时是以空格或Enter键作为其结束标志的。

当cin>>x操作中的x为字符指针类型时,则要求从键盘的输入中读取一个字符串,并把它赋值给x指向的存储空间,若x没有事先指向一个允许写入信息的存储空间,则无法完成输入操作。另外,从键盘上输入的字符串,其两边不能带有双引号定界符,若有则只作为双引号字符看待。对于输入的字符也是如此,不能带有单引号定界符。

cin相当于C库函数中的scanf,作用是将用户的输入赋值给变量。例如,下面的代码可将用户输入的数打印出来。

【实例2.3】 默写王之涣的《登鹳雀楼》。(实例位置:资源包\TM\sl\2\3)

使用cout向控制台输出唐朝诗人王之涣的《登鹳雀楼》,具体代码如下:

运行程序,将向控制台屏幕输出诗句,效果如图2.8所示。其中,endl用于向流的末尾部位加入换行符。

2.5.3 流操作的控制

图2.8 向控制台屏幕输出诗句

在头文件iomanip.h中定义了一些控制流输出格式的函数,默认情况下整型数按十进制形式输出,也可以通过hex将其设置为十六进制输出。

(1)long setf(long f); 根据参数f设置相应的格式标志,返回此前的设置。该参数f对应的实参为无名枚举类型中的枚举常量(又称格式化常量),可以同时使用一个或多个常量,每两个常量之间要用按位或操作符连接。如需要左对齐输出,并使数值中的字母大写,则调用该函数的实参为ios::left|ios::uppercase。

(2)long unsetf(long f); 根据参数f清除相应的格式标志,返回此前的设置。如果要清除此前的左对齐输出设置,恢复默认的右对齐输出设置,则调用该函数的实参为ios::left。

(3)int width(); 返回当前的输出域宽。若返回数值为0,则表明没有为刚才输出的数值设置输出域宽。输出域宽是指输出的值在流中占有的字节数。

(4)int width(int w); 设置下一个数据值的输出域宽为w,返回为输出上一个数据值规定的域宽,若无规定则返回0。注意,此设置不是一直有效,而只是对下一个输出数据有效。

(5)setiosflags(long f); 设置f对应的格式标志,功能与setf(long f)成员函数相同,当然,在输出该操作符后返回的是一个输出流。如果采用标准输出流cout输出,则返回cout。输出每个操作符后都是如此,即返回输出它的流,以便向流中继续插入下一个数据。

(6)resetiosflags(long f); 清除f对应的格式标志,功能与unsetf(long f)成员函数相同。输出后返回一个流。

(7)setfill(char c); 设置填充字符的ASCII码为c的字符。

(8)setprecision(int n); 设置浮点数的输出精度为n。

(9)setw(int w); 设置下一个数据的输出域宽为w。

数据输入/输出的格式控制还有更简便的形式,就是使用头文件iomainip.h中提供的操作符。使用这些操作符不需要调用成员函数,只要把它们作为插入操作符“<<”的输出对象即可。

 dec:转换为按十进制输出整数,是默认的输出格式。

 oct:转换为按八进制输出整数。

 hex:转换为按十六进制输出整数。

 ws:从输出流中读取空白字符。

 endl:输出换行符\n并刷新流。

 ends:输出一个空字符\0。

 flush:只刷新一个输出流。

【实例2.4】 控制打印格式。(实例位置:资源包\TM\sl\2\4)

本实例中,定义一个双精度类型的变量并赋值,利用各种格式打印数据,具体代码如下:

程序运行结果如图2.9所示。

【实例2.5】 变幻莫测的整数。(实例位置:资源包\TM\sl\2\5)

本实例中,定义一个整数变量并赋值,利用不同形式输出整型,具体代码如下:

程序运行结果如图2.10所示。

图2.9 控制打印格式

图2.10 整数输出

【实例2.6】 十六进制与十进制转换。(实例位置:资源包\TM\sl\2\6)

本实例中,定义两个整型变量,其中一个变量赋值为十六进制,另一个变量赋值为十进制。利用cout输出第一个变量十进制、十六进制,用cout输出第二个变量小写十六进制和大写十六进制。具体代码如下:

程序运行结果如图2.11所示。

【实例2.7】 控制输出精确度。(实例位置:资源包\TM\sl\2\7)

本实例中,定义一个整型变量并赋值,定义一个双精度变量并赋值,利用cout输出这两个不同精度的格式,具体代码如下:

程序运行结果如图2.12所示。

图2.11 输出十进制和十六进制

图2.12 控制输出精确度

【实例2.8】 千变万化的小数。(实例位置:资源包\TM\sl\2\8)

本实例中,定义两个单精度类型,用cout输出不同长度的小数,具体代码如下:

程序运行结果如图2.13所示。

C++语言中还保留着C语言的输出函数printf,使用printf可以将任意数量、类型的数据输出到屏幕中。printf函数的声明形式如下:

     printf("[控制格式]... [控制格式]...",数值列表);

printf是变参函数,数值列表中可以有多个数值,数值的个数不是确定的,每个数值之间用逗号运算符隔开;控制格式表示数值以哪种格式输出,控制格式的数量要与数值的个数一致,否则程序运行时会产生错误。

控制格式由“%+特定字符”构成,形式如下:

     %[*][域宽][长度]类型

“*”代表可以使用占位符,域宽表示输出的长度。如果输出的内容没有域宽长,用占位符占位;如果比域宽长,就按实际内容输出,以适应域宽。长度决定输出内容的长度,例如,%d代表以整型数据格式输出。常见的输出类型如表2.6所示。

表2.6 常见输出类型

(1)d格式符,以十进制形式输出整数。

 %d:按整型数据的实际长度输出。

 %*md:m用于指定输出字段的宽度,如果数据的位数小于m,用*指定的字符占位;如果*未指定用空格占位,若大于m,则按实际位数输出。

 %ld:输出长整型数据。

【实例2.9】 printf占位输出形式。(实例位置:资源包\TM\sl\2\9)

本实例中,使用printf格式输出函数,在格式符号中间加0做占位符,具体代码如下:

程序运行结果如图2.14所示。

图2.13 流输出小数控制

图2.14 输出占位符

(2)o格式符,以八进制形式输出整数。

 %o:按整型数据的实际长度输出。

 %*mo:m用于指定输出字段的宽度,如果数据的位数小于m,用*指定的字符占位;如果*未指定用空格占位,若大于m,则按实际位数输出。

 %lo:输出长整型数据。

(3)x格式符,以十六进制形式输出整数。

 %x:按整型数据的实际长度输出。

 %*mx:m用于指定输出字段的宽度,如果数据的位数小于m,用*指定的字符占位;如果*未指定用空格占位,若大于m,则按实际位数输出。

 %lx:输出长整型数据。

(4)s格式符,用来输出一个字符串。

 %s:将字符串按实际长度输出。

 %*ms:输出的字符串占m列,如果字符串本身长度大于m,则突破m的限制,将字符串全部输出;如果*未指定用空格占位,若字符串长度小于m,则左补空格。

 %-ms:如果字符串长度小于m,则在m列范围内,字符串向左靠,右补空格。

 %m.ns:输出占m列,但只取字符串中左端n个字符。这n个字符输出在m列的右侧,左补空格。

 %-m.ns:输出长整型数据。输出占m列,但只取字符串中左端n个字符。这n个字符输出在m列的左侧,右补空格。

【实例2.10】 截取helloworld。(实例位置:资源包\TM\sl\2\10)

本实例中,定义字符型指针(第7章详细介绍)用来保存字符串,利用printf函数格式输出字符串,代码如下:

程序运行结果如图2.15所示。

(5)f格式符,以小数形式输出实型数据。

 %f:不指定字段宽度,整数部分全部输出,小数部分输出6位。

 %m.nf:输出的数据占m列,其中有n位小数。如果数值长度小于m,则左端补空格。

 %-m.nf:输出的数据占m列,其中有n位小数。如果数值长度小于m,则右端补空格。

【实例2.11】 输出格式控制。(实例位置:资源包\TM\sl\2\11)

本实例中,定义一个单精度和一个双精度类型,利用printf格式输出不同形式,具体代码如下:

程序运行结果如图2.16所示。

图2.15 输出格式控制字符串输出

图2.16 输出格式控制

(6)e格式符,以指数形式输出实型数据。

 %e:不指定输出数据所占的宽度和小数位数。

 %m.ne:输出的数据占m位,其中有n位小数。如果数值长度小于m,则左端补空格。

 %-m.ne:输出的数据占m位,其中有n位小数。如果数值长度小于m,则右端补空格。

【实例2.12】 科学计数法输出。(实例位置:资源包\TM\sl\2\12)

本实例中,利用printf格式控制符%e,将小数用科学计数法输出,具体代码如下:

程序运行结果如图2.17所示。

图2.17 科学计数法输出

误区警示

一定要注意%x(%X、%#x、%#X),因为调试时经常要将内存中的二进制代码输出。这几种形式解释如下:

如果是x,输出的字母就是小写的;如果是X,输出的字母就是大写的;如果加一个“#”就会以标准的十六进制形式输出。建议最好是加一个“#”,否则如果输出的十六进制正好没有字母,就会被误认为是一个十进制数。

编程训练(答案位置:资源包\TM\sl\2\编程训练\)

【训练3】 控制台输出汉字 使用cout向控制台输出汉字“明日科技”。

【训练4】 地球的年龄有多大 地球的年龄约为45.5亿年,用科学计数法输出地球的年龄。