【C++ Primer Plus学习记录】简单文件输入/输出

有时候,通过键盘输入并非最好的选择。例如,假设您编写了一个股票分析程序,并下载了一个文件,其中包含1000种股票的价格。在这种情况下,让程序直接读取文件,而不是手工输入文件中所有的值,将方便得多。同样,让程序将输出写入到文件将更为方便,这样可以得到有关结果的永久性记录。

1.文本I/O和文本文件

使用cin进行输入时,程序将输入视为一系列的字节,其中每个字节都被解释为字符编码。不管目标数据类型是什么,输入一开始都是字符数据------文本数据。然后,cin对象负责将文本转换为其他类型。

本章讨论的文件I/O相当于控制台I/O,因此仅适用于文本文件。要创建文本文件,用于提供输入,可使用文本编辑器,如DOS中的EDIT、Windows中的"记事本"和UNIX/Linux系统中的vi或emacs。也可以使用字处理程序来创建,但必须将文件保存为文本格式。

源代码文件就属于文本文件。

可以使用文本编辑器来查看通过文本输出创建的文件。

2.写入到文本文件中

下面来复习一些有关将cout用于控制台输出的基本事实,为文件输出做准备。

·必须包含头文件iostream。

·头文件iostream定义了一个用于处理输出的ostream类。

·头文件iostream声明了一个名为cout的ostream变量(对象)。

·必须指明名称空间std;例如,为引用元素cout和endl,必须使用编译指令using或前缀std::。

·可以结合使用cout和运算符<<来显示各种类型的数据。

文件输出与此及其相似。

·必须包含头文件fstream。

·头文件fstream定义了一个用于处理输出的ofstream类。

·需要声明一个或多个ofstream变量(对象),并以自己喜欢的方式对其进行命名,条件是遵守常用的命名规则。

·必须指明名称空间std;例如,为引用元素ofstream,必须使用编译指令using或前缀std::。

·需要将ofstream对象与文件关联起来。为此,方法之一是使用open()方法。

·使用完文件后,应使用方法close()将其关闭。

·可结合使用ofstream对象和运算符<<来输出各种类型的数据。

注意,虽然头文件iostream提供了一个预先定义好的名为cout的ostream对象,但您必须声明自己的ofstream对象,为其命名,并将其同文件关联起来。下面演示了如何声明这种对象:

cpp 复制代码
ofstream outFile;  //outFile an ofstream object
ofstream fout;     //fout an ofstream object 

下面演示了如何将这种对象与特定的文件关联起来:

cpp 复制代码
outFile.open("fish.txt");  //outFile used to write to the fish.txt file

char filename[50];
cin >> filename;   //user specifies a name
fout.open(filename);  //fout to read specified file

注意,方法open()接受一个C-风格字符串作为参数,这可以是一个字面字符串,也可以是存储在数组中的字符串。

下面演示了如何使用这种对象:

cpp 复制代码
double wt = 125.8;
outFile << wt;   //write a number to fish.txt

char line[81] = "Objects are closer than they apper.";
fout << line << endl;  //write a line of text

重要的是,声明一个ofstream对象并将其同文件关联起来后,便可以像使用cout那样使用它。所有可用于cout的操作和方法(如<<、endl和setf())都可用于ofstream对象(如前述示例中的outFile和fout)。

总之, 使用文件输出的主要步骤如下:

1.包含头文件fstream。

2.创建一个ofstream对象。

3.将该ofstream对象同一个文件关联起来。

4.就像使用cout那样使用该ofstream对象。

程序清单6.15中的程序演示了这种方法。它要求用户输入信息,然后将这些信息显示到屏幕上,再将这些信息写入到文件中。读者可以使用文本编辑器来查看该输出文件的内容。

cpp 复制代码
//6.15
#if 1
#include<iostream>
#include<fstream> //包含头文件fstream
using namespace std;

int main()
{
	char automobile[50];
	int year;
	double a_price;
	double d_price;

	ofstream outFile; //create object for output,声明一个文件输出对象
	outFile.open("carinfo.txt");//将上述对象与特定文件关联起来
	//在这里,该程序运行前,文件carinfo.txt并不存在。在这种情况下,方法open()将新建一个名为carinfo.txt的文件。
	//如果在运行该程序时,carinfo.txt已经存在,open()将首先截断该文件,即将其长度截短到零------丢弃原有的内容,然后将新的输出加入到该文件中。
	//打开文件用于接受输入时可能失败。例如,指定的文件可能已经存在,但禁止对其进行访问。因此细心的程序员将检查打开文件的操作是否成功。

	cout << "Enter the make and model of automobile: ";
	cin.getline(automobile, 50);
	cout << "Enter the model year: ";
	cin >> year;
	cout << "Enter the original asking price: ";
	cin >> a_price;
	d_price = 0.913 * a_price;

//display information on screen with cout
	cout << fixed;
	cout.precision(2);
	cout.setf(ios_base::showpoint);
	cout << "Make and model:  " << automobile << endl;
	cout << "Year: " << year << endl;
	cout << "Was asking $" << a_price << endl;
	cout << "Now asking $" << d_price << endl;

//now do exact same things using outFile instead of cout
	outFile << fixed;
	outFile.precision(2);
	outFile.setf(ios_base::showpoint);
	outFile << "Make and model:  " << automobile << endl;
	outFile << "Year: " << year << endl;
	outFile << "Was asking $" << a_price << endl;
	outFile << "Now asking $" << d_price << endl;

	outFile.close();
	//done with file,程序使用完该文件后,应该将其关闭,close()不需要使用文件名作为参数,这是因为outFile已经同特定的文件关联起来。
	//如果忘记关闭,程序正常终止时将自动关闭它

	system("pause");
	return 0;
}
#endif

屏幕输出的是使用cout的结果。

该程序的可执行文件所在的目录,将有一个名为carinfo.txt的新文件(根据编译器的配置,该文件也可能位于其他文件夹),其中包含使用outFile生成的输出。

3.读取文本文件

接下来介绍文本文件输入,它是基于控制台输入的。控制台输入涉及多个方面,下面首先总结这些方面。

·必须包含头文件iostream。

·头文件iostream定义了一个用于处理输入的istream类。

·头文件iostream声明了一个名为cin的istream变量(对象)。

·必须指明名称空间std;例如,为引用元素cin,必须使用编译指令using或前缀std::。

·可以结合使用cin和运算符>>来各种读取类型的数据。

·可以使用cin和get()方法来读取一个字符,使用cin和getline()来读取一行字符。

·可以结合使用cin和eof()、fail()方法来判断输入是否成功。

·对象cin本身被用作测试条件时,如果最后一个读取操作成功,它将被转移为布尔值true,否则被转换为false。

文件输入与此及其相似。

·必须包含头文件fstream。

·头文件fstream定义了一个用于处理输入的ifstream类。

·需要声明一个或多个ifstream变量(对象),并以自己喜欢的方式对其进行命名,条件是遵守常用的命名规则。

·必须指明名称空间std;例如,为引用元素ifstream,必须使用编译指令using或前缀std::。

·需要将ifstream对象与文件关联起来。为此,方法之一是使用open()方法。

·使用完文件后,应使用方法close()将其关闭。

·可结合使用ifstream对象和运算符>>来读取各种类型的数据。

·可以使用ifstream对象和get()方法来读取一个字符,使用ifstream对象和getline()来读取一行字符。

·可以结合使用ifstream和eof()、fail()方法来判断输入是否成功。

·ifstream对象本身被用作测试条件时,如果最后一个读取操作成功,它将被转移为布尔值true,否则被转换为false。

注意,虽然头文件iostream提供了一个预先定义好的名为cin的istream对象,但您必须声明自己的ifstream对象,为其命名,并将其同文件关联起来。下面演示了如何声明这种对象:

cpp 复制代码
ifstream inFile;   //inFile an ifstream object
ifstream fin;      //fin an ifstream object

下面演示了如何将这种对象与特定的文件关联起来:

cpp 复制代码
inFile.open("bowling.txt");   //inFile used to read bowling.txt file

char filename[50];
cin >> filename;   //user specifies a name
fin.open(filename);  //fin used to read specified file

注意,方法open()接受一个C-风格字符串作为参数,这可以是一个字面字符串,也可以是存储在数组中的字符串。

下面演示了如何使用这种对象:

cpp 复制代码
double wt;
inFile >> wt;  //read a number from bowling.txt

char line[81];
fin.getline(line,81);  //read a line of text

重要的是,声明一个ifstream对象并将其同文件关联起来后,便可以像使用cin那样使用它。所有可以用于cin的操作和方法都可用于ifstream对象(如前述示例中的inFile和fin)。

如果试图打开一个不存在的文件用于输入,将导致后面使用ifstream对象进行输入时失败。检查文件是否被成功打开的首先方法是使用方法is_open(),为此,可以使用类似于下面的代码:

cpp 复制代码
inFile.open("bowling.txt");

if(!inFile.is_open())
{
   exit(EXIT_FAILURE);
}

如果文件被成功打开,方法is_open()将返回true;因此,如果文件没有被打开,表达式!inFile.isopen()将为true。函数exit()的原型是在头文件cstdlib中定义的,在该头文件中,还定义了一个用于同操作系统通信的参数值EXIT_FAILURE。函数exit()终止程序。

程序清单6.16中的程序打开用户指定的文件,读取其中的数字,然后指出文件中包含多少个值以及它们的和与平均值。

cpp 复制代码
//6.16
#if 1
#include<iostream>
#include<fstream>
#include<cstdlib>   //support for exit()
using namespace std;
const int SIZE = 60;

int main()
{
	char filename[SIZE];
	ifstream inFile;   //object for hangding file input

	cout << "Enter name of data file: ";
	cin.getline(filename, SIZE);
	inFile.open(filename);   //associate inFile with a file
	//检查文件是否被成功打开
	if (!inFile.is_open())   //failed to open file
	{
		cout << "Could not open the file " << filename << endl;
		cout << "Program terminating.\n";
		exit(EXIT_FAILURE);
	}
	double value;
	double sum = 0.0;
	int count = 0;   //number of items read 

	inFile >> value;  //get first value
	while (inFile.good())   //while input good and not at EOF
	{
		++count;  //one more item read
		sum += value;  //calculate running total
		inFile >> value;  //get next value
	}
	if (inFile.eof())
		cout << "End of file reached.\n";
	else if (inFile.fail())
		cout << "Input terminnated by data missmatch.\n";
	else
		cout << "Input terminated for unknown reason.\n";
	if (count == 0)
		cout << "No data processed.\n";
	else
	{
		cout << "Item read: " << count << endl;
		cout << "Sum: " << sum << endl;
		cout << "Average: " << sum / count << endl;
	}
	inFile.close();

	system("pause");
	return 0;
}
#endif

要运行程序清单6.16中的程序,首先必须创建一个包含数字的文本文件。为此,可以使用文本编辑器(如用于编写代码的文本编辑器)。假设该文件名为scores.txt,包含的内容如下:

18 19 18.5 13.5 14

16 19.5 20 18 12 18.5

17.5

程序还必须能找到这个文件。通常,除非在输入的文件名中包含路径,否则程序将在可执行文件所属的文件夹中查找。

相关推荐
江梦寻几秒前
思科模拟器路由器配置实验
开发语言·网络·网络协议·学习·计算机网络
代码小鑫2 分钟前
A034-基于Spring Boot的供应商管理系统的设计与实现
java·开发语言·spring boot·后端·spring·毕业设计
奋飞安全15 分钟前
初试js反混淆
开发语言·javascript·ecmascript
guoruijun_2012_416 分钟前
fastadmin多个表crud连表操作步骤
android·java·开发语言
浪里个浪的102418 分钟前
【C语言】计算3x3矩阵每行的最大值并存入第四列
c语言·开发语言·矩阵
一只特立独行的程序猿23 分钟前
关于GCC内联汇编(也可以叫内嵌汇编)的简单学习
汇编·学习·gcc
@东辰25 分钟前
【golang-技巧】-自定义k8s-operator-by kubebuilder
开发语言·golang·kubernetes
虾球xz29 分钟前
游戏引擎学习第10天
学习·游戏引擎
Chef_Chen31 分钟前
从0开始学习机器学习--Day25--SVM作业
学习·机器学习·支持向量机
乐悠小码32 分钟前
数据结构------队列(Java语言描述)
java·开发语言·数据结构·链表·队列