【输入、输出和文件】——C++ Prime Plus CH17

本文详细探讨了C++中的输入输出机制,包括流的概念、缓冲区的使用、iostream文件的组织,以及如何使用cout进行格式化输出和错误处理。文章还介绍了cin进行输入的机制,包括流状态的影响和异常处理。最后,文章涵盖了文件输入输出的基本操作,如打开模式、流状态检查和文件操作。通过对标准输入输出的深入理解,开发者可以更好地控制C++程序的交互和数据处理。
摘要由CSDN通过智能技术生成

1.C++输入和输出概述

1.1流和缓冲区

C++程序把输入和输出看作字节流。输入时,程序从输入流中抽取字节;输出时,程序将字节插入到输出流中。输入流中的字节可能来自键盘,也可能来自存储设备或其他程序。输出流中的字节可以流向屏幕、打印机、存储设备或其他程序。输入流和输出流均需要两个连接,文件端部提供了流的来源,程序端连接将流与程序进行连接。

使用缓冲区可以高效的处理输入和输出。C++程序通常在用户按下回车键时刷新输入缓冲区;在用户发送换行符时刷新输出缓冲区。

1.2流、缓冲区和iostream文件

iostream文件中包含了一些专门设计用来实现、管理流和缓冲区的类。

streambuf类为缓冲区提供了内存、缓冲区和管理缓冲区的办法;

ios_base类表示流的一般特征,如是否可读取、是二进制流还是文本流;

ios类基于ios_base,包括了一个指向streambuf对象的指针成员;

ostream从ios派生出来,提供了输出方法;

istream从ios派生出来,提供了输入方法;

iostream基于ostream和istream类,继承了输入和输出方法。

要使用这些工具,必须使用适当的类对象,例如,使用cout(ostream对象)来处理输出。创建一个这样的对象将打开一个流,自动创建缓冲区,并将其与流关联起来,同时使得能够使用类成员函数。

cin对象对应于标准输入流,默认情况下,这个流被关联到标准输入设备(通常为键盘)。

cout对象对应于标准输出流,默认情况下,这个流被关联到标准输出设备(通常为显示器)。

cerr对象对应于标准错误流,可用于显示错误消息。默认情况下,这个流被关联到标准输出设备(通常为显示器),这个流没有被缓冲。

clog对象对应于标准错误流,可用于显示错误消息。默认情况下,这个流被关联到标准输出设备(通常为显示器),这个流被缓冲。

对象代表流:创建一个对象,该对象包含了有关的所有数据成员。例如cout对象凭借streambuf对象的帮助,管理着流中的字节流。

1.3重定向

重定向使得能够该百年标准输入和标准输出。将输入输出和文件联系起来,而不是屏幕键盘。重定向用于不同的操作系统中的输入输出。对标准输入重定向并不会影响cerr或clog,错误信息依然会被显示到显示器上。如果重定向没有起作用,则选定的消息会被显示到屏幕上,如果程序输出被重定向到一个文件,第一条消息(被选定)将被发送到文件,而第二条消息(被选定)将发送到屏幕。

2.使用cout进行输出

ostream类最重要的任务之一是将数值类型(如int、float等)转换为以文本形式表示的字符流。需要将数据内部表示(二进制位模式)转换为由字符字节组成的输出流。

2.1重载的<<运算符

<<也叫插入运算符,是被重载的左移运算符。对于 char(unsigned signed ) 、short(unsigned signed) 、int(unsigned、signed)、float、double (long)、long(unsigned、long、 unsigned long long)数据类型都进行了左移运算符的重载,所以cout可以直接进行输出。

2.1.1输出和指针

ostream为下面的指针类型定义了插入运算符函数:

const signed char*、const unsigned char*、const char*、void*.

C++输出字符串(指针的方式来输出的),方法使用字符串中的终止空字符来确定何时停止显示字符。对于其它类型的指针,C++将其对应于void*,并打印地址的数值表示。要获得字符串地址,必须将其强制转换为void*类型。

2.1.2拼接输出

插入运算符的返回类型都是ostream&,返回掉队该运算符的对象,所以可以进行拼接输入,前几章重定向<<也是模仿了该技术。

2.2其他ostream方法

2.2.1put()

该方法用于显示字符,原型为:

ostream & put(char);

和运算符函数一样,该函数也返回一个指向调用对象的引用,可以用它拼接输出:

cout.put('w').put('I') ;

在原型何时的情况下,可以将数值型参数(int)用于put(),函数原型自动将参数转换为正确char值。

cout.put(65);
cout.put(66.3);

2.2.2write()

该方法用于显示字符串,该函数需要两个参数,第一个参数显示了字符串的地址,第二个参数指出要显示多少个字符串。cout.write()调用返回cout对象,可以将输出拼接起来,write()方法并不会在遇到空白字符时自动停止打印字符,而只是打印指定数目的字符,即使超过字符串的边界。

write()方法也可用于数值数据,将数字的地址强制转换为cahr*,这不会将数字转换为相应的字符,而是传输内存中存储的位表示,将把被个字节作为ASCII码进行解释。

#include<iostream>
using namespace std;
int main()
{
	const char* s1= "Hello,my sweetheart!";
	const char s2[] = "I been waiting for you all day.";
	char ch = 'p';
	cout.write(s2, strlen(s2));
	cout << endl;
	for (int i = 0; i < strlen(s1); i++)
	{
		cout.write(s1, i);
		cout << endl;
	}
		
	cout.put(ch).put(ch + 1);
	cout << 'o';
	return 0;
}

2.3刷新输出缓冲区

通常,缓冲区位512字节或其整倍数,在屏幕输出时,程序不必等到缓冲区被填满。将换行符发送到缓冲区后,将刷新缓冲区;程序期待输入,将导致它立刻显示cout信息,即使输出字符串中没有换行符,否则程序将等待输入,而无法通过cout信息来提示用户。

如果不能实现在希望的时刻刷新输出,可以使用endl、flush两个控制符来强制刷新,flush刷新缓冲区,endl刷新缓冲区并且插入换行符。

cout<<"Hello"<<endl;
cout<<"Hello"<<flush;

或者
flush(cout);

2.4用cout进行格式化

ostream插入运算将值转换为文本格式。在默认情况下,格式化值的方式如下:

1.char值,如果代表可打印字符,作为一个字符显示在宽度为一个字符的字段中;

2.数值整型,将以十进制方式显示在刚好容纳该数字及符号的字段中;

3.字符串被显示在宽度等于该字符串长度的字段中;

4.浮点类型被显示为6位,末尾的0不显示(显示位数与存储精度无关)。数字以定点表示法还是科学计数法取决于它的值(指数大于等于6或小于等于-5,将使用科学计数法表示)。字段宽度将刚好容纳数字和负号。

因为每个值的显示宽度都等于它的长度,因此必须在显式地在值之间提供空格;否则,相邻地值将不会被分开。

2.4.1修改显示时使用的计数系统

要控制整数以十进制、十六进制还是八进制显示,可以使用dec、hex、和oct控制符。下面地函数调用将cout对象的计数格式状态设置为十六进制:

hex(cout);

完成上述设置后,程序将以十六进制形式打印整数,直到将格式状态设置为其他选项为止。控制符不是函数,因此不需要通过对象调用。

通常的使用方式为:

cout<<hex;   等价于hex(cout);
#include<iostream>
using namespace std;
int main()
{
	const char* s1 = "Hello,my sweetheart!";
	const char s2[] = "I been waiting for you all day.";
	char ch = 'p';
	cout.write(s2, strlen(s2));
	cout << endl;
	for (int i = 0; i < strlen(s1); i++)
	{
		cout.write(s1, i);
		cout << endl;
	}

	cout.put(ch).put(ch + 1);
	cout << 'o';
	return 0;
}

 

2.4.2调整字段宽度

可以使用width成员函数将长度不同的数字放到宽度相同的字段中,所以必须使用对象来调用它,该方法的原型是:

int width();

int width(int i);

第一种格式返回字段宽度的当前设置;第二种格式将字段宽度设置为i个空格,并返回以前的字段宽度值。这使得能够保存以前的值,以便以后恢复宽度值时使用。width()方法只影响将显示的下一个项目,然后字段恢复默认值。 

C++永远不会截短数据,如果试图在字段宽度为2的字段中打印字段为7的值,C++将增宽字段。

#include<iostream>

using namespace std;
int main()
{
	cout << "Enter an interger:";
	int n;
	cin >> n;

	
	cout << "n";
	cout.width(8);
	cout<<"n * n\n";
	cout << n;
	cout.width(8);
	cout<< n * n << endl;
	cout << hex;
	cout << n;
	cout.width(8);
	cout << n * n << endl;
	cout << oct;
	cout << n;
	cout.width(8);
	cout << n * n << endl;
	cout << dec;
	cout << n;
	cout.width(8);
	cout << n * n << endl;

	return 0;
}

我们可以看到,值在字段中右对齐,cout通过加入空格来填满整个字段。 

2.4.3填充字符

在默认情况下,cout用空格填充字段中未被使用的部分,可以用fill()成员函数来改变填充字符。下面的函数调用将填充字符改为星号:

cout.fill('*');

新的填充字符将一直有效,直到更改它为止。

#include<iostream>

using namespace std;
int main()
{
	cout << "Enter an interger:";
	int n;
	cin >> n;

	cout.fill('-');
	cout << "n";
	cout.width(8);
	cout<<"n*n"<<endl;
	cout << n;
	cout.width(8);
	cout<< n * n << endl;
	cout << hex;
	cout << n;
	cout.width(8);
	cout << n * n << endl;
	cout << oct;
	cout << n;
	cout.width(8);
	cout << n * n << endl;
	cout << dec;
	cout << n;
	cout.width(8);
	cout << n * n << endl;

	return 0;
}

 

2.4.4设置浮点数的显示精度

浮点数精度的含义取决于输出模式。在默认情况下,它指的是显示的总位数。在定点模式和科学模式下,精度指的是小数点后面的位数。C++默认的精度为6位(末尾的0不显示)。precision成员函数使得能够选择其他值。下面语句将cout的精度设置为2:

cout.precision(2);

新的精度设置将一直有效,直到被重新设置。

#include<iostream>
using namespace std;

int main()
{
	float price1 = 20.40;
	float price2 = 1.9 + 8.0 / 9.0;

	cout << "$1:" << price1 << endl;   //这里的0不显示
	cout << "$2:" << price2<< endl;

	cout.precision(2);
	cout << "$1:" << price1 << endl;
	cout << "$2:" << price2 << endl;
	return 0;
}

 

2.4.5打印末尾的0和小数点

iostream系列类没有提供专门用于完成这项任务的函数,但ios_base类提供了一个set()函数,能够控制多种格式化特性。下面的函数调用使cout显示末尾小数点:

cout.setf(ios_base::showpoint);

使用默认的浮点格式,上述语句将导致末尾的0被显示出来。如果使用默认精度(6位)时,cout将不会将2.0显示为2.0,而是显示2.00000.

ios_base::showpoint;showpoint是ios_base类声明中定义的类级静态变量。

#include<iostream>
using namespace std;

int main()
{
	float price1 = 20.40;
	float price2 = 1.9 + 8.0 / 9.0;

	cout.setf(ios_base::showpoint);
	cout << "$1:" << price1 << endl;   //这里的0不显示
	cout << "$2:" << price2<< endl;

	cout.precision(2);
	cout << "$1:" << price1 << endl;
	cout << "$2:" << price2 << 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值