C++流的输入输出

一.概述

       C++流是读写(输入和输出)逻辑的通用实现,让您能够用统一的模式读写数据。不管是磁盘或键盘读取数据,还是将输入写入显示器或磁盘,这些模式都相同。您只需使用合适的流类,类的实现将负责处理与设备和操作系统相关的细节。

       如std:cout 是 ostream 类的一个对象,用于输出到控制台。要使用 std::cout,需要包含提供它的头文件,这个头文件还提供了 std::cin,让您能够从流中读取数据。

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

       流能够以一致的方式访问不同的设备,比如要将 Hello World 写入文本文件,可将同样的语法用于文件流对象 fsHello:

fsHello << "Hello World!" << endl; 

用于写入流时,运算符<<被称为流插入运算符,可将其用于写入屏幕、文件等。

用于将流中的数据写入变量时,运算符>>被称为流提取运算符,可将其用于从键盘、文件等读取输入。

二. 重要的C++流类和流对象

C++提供了一组标准类和头文件,可帮助您执行重要而常见的输入/输出操作。

std 命名空间中常用的 C++流类
类/对象用途
cout标准输出流,通常被重定向到控制台
cin标准输入流,通常用于将数据读入变量
cerr用于显示错误信息的标准输出流
fstream用于操作文件的输入和输出流,继承了 ofstream 和 ifstream
ofstream用于操作文件的输出流类,即用于创建文件
ifstream用于操作文件的输入流类,即用于读取文
stringstream用于操作字符串的输入和输出流类,继承了 istringstream 和 ostringstream,通常用于在字符串和其 他类型之间进行转换

        cout、cin 和 cerr 分别是流类 ostream、istream 和 ostream 的全局对象。由于是全局对象, 它们在 main( )开始之前就已初始化。

        使用流类时,可指定为您执行特定操作的控制符(manipulator)。std::endl 就是一个这样的控制符, 您一直在使用它来插入换行符:

std::cout << "This lines ends here" << std::endl; 

下表列出了其他几个控制符和标志。

std 命名空间中常用于流的控制符
类/对象 用途
输出控制符
endl插入一个换行符
ends插入一个空字符
基数控制符
dec让流以十进制方式解释输入或显示输出
hex让流以十六进制方式解释输入或显示输出
oct让流以八进制方式解释输入或显示输出
浮点数表示控制符
fixed让流以定点表示法显示数据
scientific让流以科学表示法显示数据
<iomanip>控制符
setprecision设置小数精度
setw设置字段宽度
setfill设置填充字符
setbase设置基数,与使用 dec、hex 或 oct 等效
setiosflag通过类型为 std::ios_base::fmtflags 的掩码输入参数设置标志
resetiosflag将 std::ios_base::fmtflags 参数指定的标志重置为默认值

三. 使用 std::cout 将指定格式的数据写入控制台

1.使用 std::cout 修改数字的显示格式

可以让 cout 以十六进制或八进制方式显示整数。

#include <iostream> 
#include <iomanip>
using namespace std;

int main()
{
	cout << "Enter an integer: ";
	int input = 0;
	cin >> input;

	cout << "Integer in octal: " << oct << input << endl;
	cout << "Integer in hexadecimal: " << hex << input << endl;

	cout << "Integer in hex using base notation: ";
	cout << setiosflags(ios_base::hex | ios_base::showbase | ios_base::uppercase);
	cout << input << endl;

	cout << "Integer after resetting I/O flags: ";
	cout << resetiosflags(ios_base::hex | ios_base::showbase | ios_base::uppercase);
	cout << input << endl;

	return 0;
}

       上述代码示例以修改 cout 显示用户输入的整数 input 的方式。使用了控制符 oct 和 hex。使用了 setiosflags( )让 cout 以十六进制方式(并使用大写字母)显示该数字,其结果是 cout 将 253 显示为 OXFD。使用了 resetiosflags( ),其效果是再次使用 cout 显示该整数时,将显示为十进制。要将显示整数时使用的基数改为十进制,也可使用下面这种方式:

cout << dec << input << endl;

       对于诸如 Pi 等数字,可指定 cout 显示它们时使用的精度(小数点后面的位数), 还可指定以定点表示法或科学表示法显示它们。

#include <iostream> 
#include <iomanip>
using namespace std;

int main()
{
	const double Pi = (double)22.0 / 7;
	cout << "Pi = " << Pi << endl;

	cout << endl << "Setting precision to 7: " << endl;
	cout << setprecision(7);
	cout << "Pi = " << Pi << endl;
	cout << fixed << "Fixed Pi = " << Pi << endl;
	cout << scientific << "Scientific Pi = " << Pi << endl;

	cout << endl << "Setting precision to 10: " << endl;
	cout << setprecision(10);
	cout << "Pi = " << Pi << endl;
	cout << fixed << "Fixed Pi = " << Pi << endl;
	cout << scientific << "Scientific Pi = " << Pi << endl;

	cout << endl << "Enter a radius: ";
	double radius = 0.0;
	cin >> radius;
	cout << "Area of circle: " << 2 * Pi*radius*radius << endl;

	return 0;
}

2.使用 std::cout 对齐文本和设置字段宽度

       可使用 setw( )控制符来设置字段宽度,插入到流中的内容将在指定宽度内右对齐。在这种情况下,还可使用 setfill( )指定使用什么字符来填充空白区域。

#include <iostream>
#include <iomanip>
using namespace std;

int main()
{
	cout << "Hey - default!" << endl;

	cout << setw(35); 
	cout << "Hey - right aligned!" << endl;

	cout << setw(35) << setfill('*');
	cout << "Hey - right aligned!" << endl;

	cout << "Hey - back to default!" << endl;

	return 0;
}

四. 使用 std::cin 进行输入

       std::cin 用途广泛,能够将输入读取到基本类型(如 int、double 和 char*)变量中。还可使用 getline( )从键盘读取一行输入。

1.使用 std::cin 将输入读取到基本类型变量中

使用 cin 可将标准输入读取到 int、double 和 char 变量中。

#include<iostream> 
using namespace std; 

int main() 
{
	cout << "Enter an integer: ";
	int inputNum = 0;
	cin >> inputNum;

	cout << "Enter the value of Pi: ";
	double Pi = 0.0;
	cin >> Pi;

	cout << "Enter three characters separated by space: " << endl;
	char char1 = '\0', char2 = '\0', char3 = '\0';
	cin >> char1 >> char2 >> char3;

	cout << "The recorded variable values are: " << endl;
	cout << "inputNum: " << inputNum << endl;
	cout << "Pi: " << Pi << endl;
	cout << "The three characters: " << char1 << char2 << char3 << endl;

	return 0;
}

2.使用 std::cin:get 将输入读取到 char*缓冲区中

cin 能够将输入直接写入 int 变量,也可将输入直接写入 char 数组(C 风格字符串):

cout << "Enter a line: " << endl; 
char charBuf [10] = {0}; 
cin >> charBuf;

写入 C 风格字符串缓冲区时,务必不要超越缓冲区的边界,以免导致程序崩溃或带来安全隐患, 这至关重要。因此,将输入读取到 char 数组(C 风格字符串)时,下面是一种更好的方法:

cout << "Enter a line: " << endl; 
char charBuf[10] = {0}; 
cin.get(charBuf, 9);

3.使用 std::cin 将输入读取到 std::string 中

#include<iostream> 
#include<string> 
using namespace std; 

int main() 
{
	cout << "Enter your name: ";
	string name;
	cin >> name;
	cout << "Hi " << name << endl;

	return 0;
}

输入字符串中如果有空格,空格后的内容就会读取不到,要读取整行输入(包括空白),需要使用 getline( ):

#include<iostream> 
#include<string> 
using namespace std; 

int main()
{
	cout << "Enter your name: ";
	string name;
	getline(cin, name);
	cout << "Hi " << name << endl;

	return 0;
}

五. 使用 std::fstream 处理文件

       C++提供了 std::fstream,旨在以独立于平台的方式访问文件。std::fstream 从 std::ofstream 那里继承了写入文件的功能,并从 std::ifstream 那里继承了读取文件的功能。

       要使用 std::fstream 类或其基类,需要包含头文件<fstream>。

1.使用 open( )和 close( )打开和关闭文件

要使用 fstream、ofstream 或 ifstream 类,需要使用方法 open( )打开文件:

fstream myFile; 
myFile.open("HelloFile.txt",ios_base::in|ios_base::out|ios_base::trunc); 
if (myFile.is_open()) 
{ 

 myFile.close(); 
} 

       open( )接受两个参数: 第一个是要打开的文件的路径和名称(如果没有提供路径,将假定为应用程序的当前目录设置); 第二个是文件的打开模式。在上述代码中,指定了模式 ios_base::trunc( 即便指定的文件存在,也重新创建它)、ios_base::in(可读取文件)和 ios_base::out(可写入文件)。

      在上述代码中使用了 is_open( ),它检测 open( )是否成功。

      保存到文件时,必须使用 close()关闭文件流。

还有另一种打开文件流的方式,那就是使用构造函数:

fstream myFile("HelloFile.txt",ios_base::in|ios_base::out|ios_base::trunc);

如果只想打开文件进行写入,可使用如下代码:

ofstream myFile("HelloFile.txt", ios_base::out); 

如果只想打开文件进行读取,可使用如下代码:

ifstream myFile("HelloFile.txt", ios_base::in);

       无论是使用构造函数还是成员方法open( )来打开文件流,都建议在使用文件流对象前,使用 open( )检查文件打开操作是否成功。

可在下述各种模式下打开文件流。

  • ios_base::app:附加到现有文件末尾,而不是覆盖它。
  • ios_base::ate:切换到文件末尾,但可在文件的任何地方写入数据。
  • ios_base::trunc:导致现有文件被覆盖,这是默认设置。
  • ios_base::binary:创建二进制文件(默认为文本文件)。
  • ios_base::in:以只读方式打开文件。
  • ios_base::out:以只写方式打开文件。

2.使用 open( )创建文本文件并使用运算符<<写入文本

#include<fstream> 
#include<iostream> 
using namespace std;

int main()
{
	ofstream myFile;
	myFile.open("HelloFile.txt", ios_base::out);

	if (myFile.is_open())
	{
		cout << "File open successful" << endl;

		myFile << "My first text file!" << endl;
		myFile << "Hello file!";

		cout << "Finished writing to file, will close now" << endl;
		myFile.close();
	}

	return 0;
}

       以 ios_base::out 模式(即只写模式)打开文件。检查 open( )是否成功,然后使用插入运算符<<写入该文件流。最后, 关闭文件流。

3.使用 open( )和运算符>>读取文本文件

#include<fstream> 
#include<iostream> 
#include<string> 
using namespace std;

int main()
{
	ifstream myFile;
	myFile.open("HelloFile.txt", ios_base::in);

	if (myFile.is_open())
	{
		cout << "File open successful. It contains: " << endl;
		string fileContents;

		while (myFile.good())
		{
			getline(myFile, fileContents);
			cout << fileContents << endl;
		}

		cout << "Finished reading file, will close now" << endl;
		myFile.close();
	}
	else
		cout << "open() failed: check if file is in right folder" << endl;

	return 0;
}

4.读写二进制文件

       写入二进制文件的流程与前面介绍的流程差别不大,重要的是在打开文件时使用 ios_base::binary 标志。通常使用 ofstream::write 和 ifstream::read 来读写二进制文件。

#include<fstream> 
#include<iomanip> 
#include<string> 
#include<iostream> 
using namespace std;

struct Human
{
	Human() {};
	Human(const char* inName, int inAge, const char* inDOB) : age(inAge)
	{
		strcpy(name, inName);
		strcpy(DOB, inDOB);
	}

	char name[30];
	int age;
	char DOB[20];
};

int main()
{
	Human Input("Siddhartha Rao", 101, "May 1916");

	ofstream fsOut("MyBinary.bin", ios_base::out | ios_base::binary);

	if (fsOut.is_open())
	{
		cout << "Writing one object of Human to a binary file" << endl;
		fsOut.write(reinterpret_cast<const char*>(&Input), sizeof(Input));
		fsOut.close();
	}

	ifstream fsIn("MyBinary.bin", ios_base::in | ios_base::binary);

	if (fsIn.is_open())
	{
		Human somePerson;
		fsIn.read((char*)&somePerson, sizeof(somePerson));

		cout << "Reading information from binary file: " << endl;
		cout << "Name = " << somePerson.name << endl;
		cout << "Age = " << somePerson.age << endl;
		cout << "Date of Birth = " << somePerson.DOB << endl;
	}

	return 0;
}

       首先创建了结构 Human 的一个实例(该结构包含属性 name、age 和 BOD), 并使用 ofstream 将其持久化到磁盘中的二进制文件 MyBinary.bin 中。接下来,使用另一个类型为 ifstream 的流对象读取这些信息。输出的 name 等属性是从二进制文件中读取的。该示例还演示了如何使用 ifstream::read 和 ofstream::write 来读写文件。使用了 reinterpret_cast,它让编译器将结构解释为 char*。read后使用 C 风格类型转换方式,这与write后的类型转换方式等价。

六. 使用 std::stringstream 对字符串进行转换

要使用 std::stringstream 类,需要包含头文件<sstream>。

#include<fstream> 
#include<sstream> 
#include<iostream> 
using namespace std;

int main()
{
	cout << "Enter an integer: ";
	int input = 0;
	cin >> input;

	stringstream converterStream;
	converterStream << input;
	string inputAsStr;
	converterStream >> inputAsStr;

	cout << "Integer Input = " << input << endl;
	cout << "String gained from integer = " << inputAsStr << endl;

	stringstream anotherStream;
	anotherStream << inputAsStr;
	int Copy = 0;
	anotherStream >> Copy;

	cout << "Integer gained from string, Copy = " << Copy << endl;

	return 0;
}

      上方程序让用户输入一个整型值,并使用运算符<<将其插入到一个 stringstream 对象中; 然后, 使用提取运算符将这个整数转换为 string。接下来,将存储在 inputAsStr 中的字符串转换为整数,并将其存储到 Copy 中。

注意

  • 只想读取文件时,务必使用 ifstream。
  • 只想写入文件时,务必使用 ofstream。
  • 插入文件流或从文件流中提取之前,务必使用 is_open( )核实是否成功地打开了它。
  • 使用完文件流后,别忘了使用方法 close( )将其关闭。
  • 使用代码 cin>>strData;从 cin 提取内容 到 string 中时,通常导致 strData 只包含空白前的文本,而不是整行。
  • 函数 getline(cin, strData);从输入流中获取整行,其中包括空白。
  • 23
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值