C++ 标准输入输出与文件操作
标准输入输出
基本输入输出
头文件 <iostream>
,命名空间 std
,定义了 cin
,cout
,cerr
,clog
#include <iostream>
using namespace std;
int main(){
char str[] = "Hello";
char data[100]
int a;
cout << "value of str is: " << str << endl;
cin >> a;
cin.getline(data, 100);
cerr << "Error" << endl; // 非缓冲标准错误流
clog << "Log" << endl; // 缓冲标准错误流
}
cin
常用成员方法:
成员方法名 | 功能 |
---|---|
getline(str,n,ch) | 从输入流中接收 n-1 个字符给 str 变量,当遇到指定 ch 字符时会停止读取,默认情况下 ch 为 '\0'。 |
get() | 从输入流中读取一个字符,同时该字符会从输入流中消失。 |
gcount() | 返回上次从输入流提取出的字符个数,该函数常和 get()、getline()、ignore()、peek()、read()、readsome()、putback() 和 unget() 联用。 |
peek() | 返回输入流中的第一个字符,但并不是提取该字符。 |
putback(c) | 将字符 c 置入输入流(缓冲区)。 |
ignore(n,ch) | 从输入流中逐个提取字符,但提取出的字符被忽略,不被使用,直至提取出 n 个字符,或者当前读取的字符为 ch。 |
operator>> | 重载 >> 运算符,用于读取指定类型的数据,并返回输入流对象本身。 |
cout
,cerr
,clog
常用成员方法:
成员方法名 | 功能 |
---|---|
put(ch) | 输出单个字符 |
write(str, n) | 输出指定的字符串。 |
tellp() | 用于获取当前输出流指针的位置。 |
seekp(pos) seek(off, way) |
设置输出流指针的位置。 |
flush() | 刷新输出流缓冲区。 |
operator<< | 重载 << 运算符,使其用于输出其后指定类型的数据。 |
cin
读取
cin
逐字节读取
int ch; // 注意 ch 是 int 类型的,因为 EOF 为 -1,如果读取到的字符 ASCII 码为 0xFF,如果类型为 char,其值就等于 -1,会被误判为文件结尾
while ((ch = cin.get()) != EOF){
// 处理ch
}
cin
读入一行字符串
getline(buf, n, ch)
如果输入流中\n
或者ch
之前的字符个数达到或者超过n
,程序出错,虽然会向buf
中读入n-1
个字符,但之后的读入操作都会失败,可用cin.clear()
清除错误标记,使之恢复正常。
const int MAX_LINE_LEN = 1000;
char szBuf[MAX_LINE_LEN + 10];
while(cin.getline(szBuf, MAX_LINE_LEN+5))
// 处理
cin
读入结束判断
Windows 中,键盘 Ctrl
+ Z
+ Enter
表示输入结束
UNIX / Linux / Mac OS 中,Ctrl
+D
表示输入结束
cin
读取到文件末尾,就会返回 false(这是因为 istream
类对 operator bool()
进行了重载,cin
没有读到输入结尾时为 true
,否则为 false
),如果 cin
在读取中发生了错误,同样返回 false
。
输入输出错误
c++ 将输入输出错误的所有可能情况归结为四类流状态(定义于 ios_base
,但 ios
派生于 ios_base
,故 ios_base::badbit
可写作 ios::badbit
):
badbit
:发生了(或许是物理上的)致命性错误,流将不能继续使用eofbit
:输入结束failbit
:I/O 操作失败,主要原因是非法数据goodbit
:一切止常,没有错误发生,也没有输入结束
可分别用 bad()
,eof()
,fail()
,bad()
成员函数来检测如上的流状态,而clear()
可用于清除流状态,clear(流状态)
可用于设置流状态。
cout
格式化输出
ostream
类中可实现格式化输出的常用成员方法:
成员函数 | 说明 |
---|---|
flags(fmtfl) | 当前格式状态全部替换为 fmtfl。注意,fmtfl 可以表示一种格式,也可以表示多种格式。 |
precision(n) | 设置输出浮点数的精度为 n。 |
width(w) | 指定输出宽度为 w 个字符。 |
fill(c) | 在指定输出宽度的情况下,输出的宽度不足时用字符 c 填充(默认情况是用空格填充)。 |
setf(fmtfl, mask) | 在当前格式的基础上,追加 fmtfl 格式,并删除 mask 格式。其中,mask 参数可以省略。 |
unsetf(mask) | 在当前格式的基础上,删除 mask 格式。 |
fmtfl
和 mask
参数的可选值:
标 志 | 作 用 |
---|---|
ios::boolalpha |
把 true 和 false 输出为字符串 |
ios::left |
输出数据在本域宽范围内向左对齐 |
ios::right |
输出数据在本域宽范围内向右对齐 |
ios::internal |
数值的符号位在域宽内左对齐,数值右对齐,中间由填充字符填充 |
ios::dec |
设置整数的基数为 10 |
ios::oct |
设置整数的基数为 8 |
ios::hex |
设置整数的基数为 16 |
ios::showbase |
强制输出整数的基数(八进制数以 0 开头,十六进制数以 0x 打头) |
ios::showpoint |
强制输出浮点数的小点和尾数 0 |
ios::uppercase |
在以科学记数法格式 E 和以十六进制输出字母时以大写表示 |
ios::showpos |
对正数显示“+”号 |
ios::scientific |
浮点数以科学记数法格式输出 |
ios::fixed |
浮点数以定点格式(小数形式)输出 |
ios::unitbuf |
每次输出之后刷新所有的流 |
<iomanip>
中定义格式控制符:
*dec
,hex
,oct
,fixed
,scientific
,left
,*right
,setbase(b)
,setw(w)
,setfill(c)
,setprecision(n)
,setiosflags(mask)
,resetiosflags(mask)
,boolapha
,*noboolalpha
,showpoint
,*noshowpoint
,showpos
,*noshowpos
,uppercase
,*nouppercase
,internal
(*
表示默认)
如
cout << hex << 16 << endl; // 输出 10
cout << resetiosflags(ios::basefield)<< scientific << 123 << endl; // 输出 1.230000e+02
输入输出重定向
cin
和 cout
都可以被重定向。
方法一:用 freopen()
-
该函数定义在
<stdio.h>
头文件
方法二:用 rdbuf()
-
该函数定义在
<ios>
头文件,由于ios
是istream
和ostream
的基类,所以,该函数也被继承,因此,cout
与cin
可直接调用该函
方法三:控制台重定向
- 命令行执行时
<in.txt
将cin
输入重定向到in.txt
,>out.txt
将cout
重定向到out.txt
管理输出缓存区
缓冲区刷新原因:
- 程序正常结束
- 缓存区满
- 用
endl
、flush
、ends
显式刷新flush
刷新缓冲区,但不输出任何额外的字符ends
向缓冲区插入一个空字符,然后刷新缓冲区
-
用
unitbuf
清空缓冲区(默认情况下,cerr
是设置unitbuf
的)- 设置
cout << unitbuf;
,每次输出后都立即刷新缓冲区
- 设置
-
被关联的流读写时,关联到的流缓冲区会刷新(默认情况下,
cin
和cerr
都关联到cout
,因此,读cin
或写cerr
都会导致cout
的缓冲区被刷新)
文件操作
文件流
头文件:<fstream>
ofstream
:该数据类型表示输出文件流,用于创建文件并向文件写入信息。ifstream
:该数据类型表示输入文件流,用于从文件读取信息。fstream
:该数据类型通常表示文件流,且同时具有ofstream
和ifstream
两种功能,这意味着它可以创建文件,向文件写入信息,从文件读取信息。
fstream
,ifstream
是从 istream
派生出来的,因此 cin
的成员方法,同样适用于 fstream
,ifstream
类的文件流对象,同样地,cout
的成员方法,同样适用于 fstream
,ofstream
类的文件流对象。
-
fstream
,ifstream
,ofstream
的常用成员方法open()
、is_open()
、close()
、swap()
、good()
、eof()
-
fstream
,ifstream
的常用成员方法operator>>
、gcount()
、get()
、getline(str,n,ch)
、ignore(n,ch)
、peek()
、putback(c)
-
fstream
,ofstream
的常用成员方法operator<<
、put()
、write()
、tellp()
、seekp()
、flush()
打开文件
用成员函数 open(fileName, mode)
,mode
为文件的打开模式标记
模式标记 | 适用对象 | 作用 |
---|---|---|
ios::in |
ifstream fstream | 打开文件用于读取数据。如果文件不存在,则打开出错。 |
ios::out |
ofstream fstream | 打开文件用于写入数据。如果文件不存在,则新建该文件;如果文件原来就存在,则打开时清除原来的内容。 |
ios::app |
ofstream fstream | 打开文件,用于在其尾部添加数据。如果文件不存在,则新建该文件。 |
ios::ate |
ifstream | 打开一个已有的文件,并将文件读指针指向文件末尾(读写指 的概念后面解释)。如果文件不存在,则打开出错。 |
ios:: trunc |
ofstream | 打开文件时会清空内部存储的所有数据,单独使用时与 ios::out 相同。 |
ios::binary |
ifstream ofstream fstream | 以二进制方式打开文件。若不指定此模式,则以文本模式打开。 |
ios::in | ios::out |
fstream | 打开已存在的文件,既可读取其内容,也可向其写入数据。文件刚打开时,原有内容保持不变。如果文件不存在,则打开出错。 |
ios::in | ios::out |
ofstream | 打开已存在的文件,可以向其写入数据。文件刚打开时,原有内容保持不变。如果文件不存在,则打开出错。 |
ios::in | ios::out | ios::trunc |
fstream | 打开文件,既可读取其内容,也可向其写入数据。如果文件本来就存在,则打开时清除原来的内容;如果文件不存在,则新建该文件。 |
判断文件是否打开成功,可以直接看“对象名”这个表达式的值是否为 true。
打开文件也可用 ifstream
、ofstream
、fstream
的构造函数。
文本方式和二进制方式打开文件并没有本质上的区别,除了换行符:UNIX/Linux 平台上,文本文件换行符为 \n
,Windows 平台上,文本文件换行符为 \r\n
。故在 Windows 平台上,若以文本方式打开文件,则读入 \r\n
会转换为一个字符 \n
,若写入 \n
则会自动写为 \r\n
。
文件关闭
close()
方法用于关闭已打开的文件。
即便不调用 close()
方法,当文件流对象生命周期结束时,会调用其析构函数,析构函数会先调用 close()
方法切断与任何文件的关联。
如果程序崩溃,很可能文件流对象的析构函数未能执行,所以一定要手动调用 close()
方法关闭文件,否则文件可能不完整。
文件读写
-
operator>>
,operator<<
-
逐个读取(写入)字符,用
get()
和put()
方法。(虽然是逐个字符读取(写入),但其实,操作系统会在文件输出缓冲区中缓冲字符(文件输入缓冲区中一次性读取很多数据)。 -
get
一次读取一个字符有两种形式int get()
和istream& get(char& c)
-
put(c)
输出字符 c。 -
getline()
用于一次读取一行字符串 -
getline(buf, bufSize)
:读取bufSize-1
个字符到buf
,或遇到\n
为止(\n
不读入),并在buf
读入数据的结尾添加\0
-
getline(buf, bufSize, delim)
:读取bufSize-1
个字符到buf
,或遇到delim
为止,并在buf
读入数据的结尾添加\0
-
若要以二进制形式读取文件(如直接将某一 class 的对象以二进制形式存入文件,然后再读取出来),需要用到
read()
和write()
成员方法 -
write(buffer, count)
:将 buffer 指向的 count 个字节写入文件,传入 buffer 的地址需要强制类型转换为char *
-
read(buffer, count)
:与write
方法类似
注:以二进制方式读写用
read()
和write()
,在 Linux 平台上用文本方式打开和用二进制方式打开文件都没有问题,但在 Windows 平台上,应该用二进制方式打开文件,否则可能出错。
文件读写指针
seekg(offset, mode)
(seekp(offset, mode)
)成员函数设置读(写)指针位置,mode
为文件读写指针的设置模式:
ios::beg
:使文件指针指向文件开始向后offset
字节处ios::cur
:使文件指针从当前位置移动,offset 正数向尾部移动,负数向起始方向移动ios::end
:使文件指针指向文件结尾向前|offset|
字节处
tellg()
(tellp()
)获取文件读(写)指针的位置。