C++零碎知识-输入、输出和文件

1、相关类、对象

(1)输入输出流相关的类

streambuf类:管理输入/输出缓冲区的内存;

ios类:基于ios_base类,描述一般的流属性,包括一个指向streambuf的指针(如字段宽度,显示基数等);

ostream类:由ios类派生而来,提供输出方法;

istream类:由ios类派生而来,提供输入方法;

iostream类:继承输入、输出方法。

(2)iostream会使用宏定义定义8种,流对象分别面向窄、宽字符流。

cin是输入流,cout对应输出流,cerr对应标准错误流,无缓存显示错误信息,clog对应标准错误流,有缓存显示错误信息

默认情况下,以上对象关联到标准的输入输出设备,也就是键盘和屏幕

(3)重定向

在命令行运行模式下可以进行标准输入、输出连接设备的重定向,输入重定向(<)、输出重定向(>)。有些操作系统也允许对错误流的输出重定向。

在编译器中,我们执行重定向操作使用ios::rdbuf()方法。对于这个方法,如果不传参数,那么直接返回流对象的buffer指针。如果传递了某个流对象的buffer指针,那么将当前的流对象绑定到那个传递过来的流对象的buffer上。

// cout 重定向到文件
#include <fstream>
#include <iostream>
#include <string>
  
using namespace std;
  
int main()
{
    fstream file; // 定义fstream对象
    file.open("D:\cout.txt", ios::out); // 打开文件,并绑定到ios::out对象
    string line;
  
    // 先获取cout、cin的buffer指针
    streambuf *stream_buffer_cout = cout.rdbuf();
    streambuf *stream_buffer_cin = cin.rdbuf();
  
    // 获取文件的buffer指针
    streambuf *stream_buffer_file = file.rdbuf();
  
    // cout重定向到文件
    cout.rdbuf(stream_buffer_file);
  
    cout << "This line written to file" << endl;
  
    // cout重定向到cout,即输出到屏幕
    cout.rdbuf(stream_buffer_cout);
    cout << "This line is written to screen" << endl;
  
    file.close(); // 关闭文件
    return 0;
}

这是由于程序并不是直接对文件或收入输出设备操作的,而是从缓存中读取、存入,只要改变了流对应的缓存的指向,就可以实现重定向。

2使用cout进行输出

cout可以将字符字符串整形浮点型都转化为字符字节输出以文本的形式表示,并通过控制符或ios_base::setf();方法修改输出的属性。(不面向string类型,string使用的是cin的友元函数)

2.1重载<<运算符

cout重载了<<运算符,可以实现以上基本类型的输入输出,同时还可以实现对字符串指针所指空间内容的输出,并返回cout对象。

(1)指向字符串存储位置的指针,显示字符串,要输出地址需要转换为(void*)

(2)其他类型的指针会被转化为(void*)输出地址;

(3)字符串以结束的空字符为标志结束输出。

2.2其他类方法

某些老版本的C++会用int值来表示字符常量,为了能够显示是字符常量,输出类提供类方法put();

cout.put('a');
cout.put(14);//输出该ASCII码对应的字符

还有某些时候希望输出字符串的一部分,可以用write()类方法

cout.write(char* sptr,int len);

write()类方法不通过检测空字符结束输出,而是逐个字节显示对应的ASCII码。

这两个类方法,都会返回类对象也就是cout所以可拼接使用。

2.3刷新缓冲区

意思就是想缓冲区的内容送达设备或者文件中,有三种方法可以刷新

1、缓冲区填满,512个字节为单位一次性写入磁盘

2、利用控制字符flush或endl强制刷新,后者还有换行的作用(对屏幕意外的设备,或者文件是否起作用)

cout<<flush<<endl;

3、屏幕输出时,不必等待缓冲区满,输入即将发生会自动刷新

2.4输出格式化

这个前面复习过,可以用width()方法函数设置字段宽度

pricision()方法函数设置浮点数进度,fill()方法函数设置填充内容

对应的控制字符

setpricision(),setw(),setfill()

控制字符:

showpoint,showbase,boolalpha,showpose,uppercase

dec,hex,oct(basefield),left,right,internal(adjustfield),fixed,scitific(floatfield);

 

3使用cin进行输入

cin将标准输入翻译为字节流,解释输入的字符序列的方式,取决于用于存储输入的内存单元的格式。

cin>>value_holder;

value_holder的类型可以为基础类型,还可以是引用、解引用的指针、结构体或类对象。

函数原型为:

istream& operator>>(T&);

格式输入函数,将输入数据转化为目标类型。

3.1cin格式化

和cout对应的格式化控制符

dec、hex、oct(只对存储空间对应为整数时有效)

认为输入流中的输入的是整数的相应进制数,然后转化为对应的十进制数存储

和cout相似,要特别考虑字符串的输入的情况,

cin针对以下字符指针重载了>>抽取指针,读入从非空白字符开始,到第一个与目标类型不匹配的内容

signed char* 
char*
unsigned char*

在字符尾会自动填充'\0'。

关于cin如何检查输入

抽取字符会跳过空白(换行符、制表符、空格),从第一个非空开始读取,到第一个不匹配的内容结束。

如果第一个非空字符不是目标类型,cin将返回false,也不会修改目标内存的内容。

3.2流状态(iostate类型)

流状态由3个ios_base元素构成:eofbit、failbit、badbit。当读取带文件尾时,设置为eofbit为1;当没有读取到目标格式的字节,或者I/O输入输出有错时,状态位设为failbit;当出现其他无法检测的流时,状态位设为badbit。

如果一切正常,就是goodbit所有位都为0。

相关的常用方法函数有:clear(iostate s),exception(iostate s),fail(),eof();bad();

istream对象可以根据流状态,装换为bool类型,如果流状态位非0将转换为false类型。

3.3其他类方法

由于cin会跳过空字符(空格、制表、回车),所以有get()方法用于字符读取;

另外,由于cin遇到空字符会停止,不能读取整行,所以有get()、getline()方法用于字符行的读取。

1、单字符的输入

有两种形式

istream& get(char& ch);
int get(void);

这两个成员函数,一个返回调用对象的引用,一个返回字符ASCII码对应的值。注意第二个返回的是整数。

所以在遇到文件尾时,第一个会将cin的流状态设为eofbit=1使得cin检测为false;

而第二个函数会返回,符号常量EOF。

这两个成员函数有三方面的不同:1字符读取:一个参数复制,一个返回;2返回:一个返回流对象引用,一个返回int;3遇到文件尾:一个设置流状态标志位,一个返回EOF符号常量。

两个有个相同的特点,就是相对于<<抽取运算符,两个成员方法都不会进行格式转换。

2、字符串的行输入
 

istream& get(char* ch,int len,char ch);//不读取换行符

istream& getline(char* ch,int len,char ch);//读取并丢弃换行符

istream& ignore(int len,char ch);

三个参数的含义:用于存放存储字符串的内存的起始地址,第二个参数说明从流中读取的最多的字节数(大一,最后要不一个空字符),第三个是分界符标志位(默认为换行符'\n')。

前两个用于读取字符并存入到相应的位置,最后一个方法是读取和丢弃。

istream& ignore(int = 1,int EOF);//前一个默认丢弃下一个字符,后一个默认到文件为结束,满足其中一个就可以。

处理string时,可以用string类的友元函数,getline(istream& cin,string& str);

template<class _Elem,
	class _Traits,
	class _Alloc> inline
	basic_istream<_Elem, _Traits>& getline(
		basic_istream<_Elem, _Traits>& _Istr,
		basic_string<_Elem, _Traits, _Alloc>& _Str,
		const _Elem _Delim)
	{	// get characters into string, discard delimiter
	return (getline(_STD move(_Istr), _Str, _Delim));
	}

另外上面两个类方法如果读取了空行,会将流状态中failbit置为1。

getline类方法如果没有读取到最后一个字符,行中还有其他字符,也会将failbit置为1

其他成员方法:

read(char* str,int len);和write(char* str,int len);对应读取对应长度的字符,最后不添加空值字符。

char peek();返回下一个输入字符,不抽取;

int gcount();返回上一个非格式化抽取的字符数;

istream& putback(char);在输入流中插入字符,下一次读取。

4 文件的输入输出(重点)

对应的头文件fstream

计算机对文件的操作分为三个部分:将程序和文件关联的途径,让程序读取文件内容的途径以及让程序创建和写入文件的途径。

按照代码可以分为:建立ifstream,ofstream流对象;关联到文件,确定打开文件模式;使用继承的iostream类方法进行文件写入和读取。

ifstream fin;
fin.open("text.txt",ios_base::in);
fin>>ch;

ifstream fin("text.txt",ios_base::in);
fin>>ch;

ofstream fout("text.txt",ios_base::out);//等价为ios_base::out|ios_base::trunc
fout<<ch;

第二个参数为文件模式,可以省略,默认参数为后面的值,out等价于写入并截短为零。

此外和iostream一样,在文件和程序之间的流运用缓冲区,实现速率匹配。

4.1是否成功打开

从ios_base中继承流状态成员,failbit/eofbit/badbit。

如果打开不存在的文件读取的话会造成failbit,相应的fin为false。

不过这样检测不完全,如果文件模式不正确,不能检测出

常用以下模式

#include<cstdlib>
fin.open();
if(!fin.is_open()){
//如果没有成功打开
cerr<<"Could not open"<<char*<<endl;
exit(EXIT_FAILURE);
}

4.2打开的模式

文件模式对应的是openmode类型、

ios_base::openmode mode = ios_base::in;

常见的c++文件打开模式

例如在文件尾追加数据fout.open("text.txt",ios_base::out|ios_base::app);

4.3存入的方式:二进制存储

将数据存储在文件中可以存储为文本格式或二进制格式。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值