C++<第三十六篇>:輸入輸出流

數(shù)據(jù)的輸入和輸出像水流一樣將數(shù)據(jù)從一個地方流到另一個地方,這個過程稱為“流”帕翻。

(1)C 和 C++ 的 輸入輸出策略

輸入流的數(shù)據(jù)來源可能是鍵盤鸠补,也有可能是文件。

在 C 中的IO策略如下:

使用 scanf()嘀掸、gets() 等函數(shù)從鍵盤讀取數(shù)據(jù)紫岩,使用 printf()、puts() 等函數(shù)向屏幕上輸出數(shù)據(jù)睬塌;
使用 fscanf()泉蝌、fgets() 等函數(shù)讀取文件中的數(shù)據(jù)歇万,使用 fprintf()、fputs() 等函數(shù)向文件中寫入數(shù)據(jù)勋陪;

在 C++ 中的IO策略如下:

C的IO解決方案在C++中也可以使用贪磺;
使用 cin 等函數(shù)從鍵盤讀取數(shù)據(jù),使用 cout 等函數(shù)向屏幕上輸出數(shù)據(jù)诅愚;
C++ 的文件操作寒锚,需要使用流類,使用 ifstream 類讀取文件中的數(shù)據(jù)违孝,使用 ofstream 類向文件中寫入數(shù)據(jù)刹前;
fstream 類既可以讀取文件中的數(shù)據(jù),也可以將數(shù)據(jù)寫入文件雌桑。

輸入輸出流的派生體系如下:

image.png

這些流類各自的功能分別為:

istream:常用于接收從鍵盤輸入的數(shù)據(jù)腮郊;
ostream:常用于將數(shù)據(jù)輸出到屏幕上;
ifstream:用于讀取文件中的數(shù)據(jù)筹燕;
ofstream:用于向文件中寫入數(shù)據(jù)轧飞;
iostream:繼承自 istream 和 ostream 類,因為該類的功能兼兩者于一身撒踪,既能用于輸入过咬,也能用于輸出;
fstream:兼 ifstream 和 ofstream 類功能于一身制妄,既能讀取文件中的數(shù)據(jù)掸绞,又能向文件中寫入數(shù)據(jù)。

C++ 常用的兩個對象 cincout耕捞,它們定義在<iostream>庫中哭廉,屬于 C++ 的內(nèi)置對象。
它們常用的用法是:

int n;
cout << "請輸入數(shù)字:";
cin >> n;
cout << "輸入數(shù)字為:" << n << endl;

由于 cincout 不是關(guān)鍵字幻锁,而是對象沸伏,所以可以調(diào)用對象的成員函數(shù)。

cin 的成員函數(shù)有:

成員方法名 功能
getline(str,n,ch) 從輸入流中接收 n-1 個字符給 str 變量磷斧,當(dāng)遇到指定 ch 字符時會停止讀取振愿,默認(rèn)情況下 ch 為 '\0'。
get() 從輸入流中讀取一個字符弛饭,同時該字符會從輸入流中消失冕末。
gcount() 返回上次從輸入流提取出的字符個數(shù),該函數(shù)常和 get()侣颂、getline()档桃、ignore()、peek()憔晒、read()藻肄、readsome()销凑、putback() 和 unget() 聯(lián)用。
peek() 返回輸入流中的第一個字符仅炊,但并不是提取該字符斗幼。
putback(c) 將字符 c 置入輸入流(緩沖區(qū))。
ignore(n,ch) 從輸入流中逐個提取字符抚垄,但提取出的字符被忽略蜕窿,不被使用,直至提取出 n 個字符呆馁,或者當(dāng)前讀取的字符為 ch桐经。
operator>> 重載 >> 運(yùn)算符,用于讀取指定類型的數(shù)據(jù)浙滤,并返回輸入流對象本身阴挣。

cout 的成員函數(shù)有:

成員方法名 功能
put() 輸出單個字符。
write() 輸出指定的字符串纺腊。
tellp() 用于獲取當(dāng)前輸出流指針的位置畔咧。
seekp() 設(shè)置輸出流指針的位置。
flush() 刷新輸出流緩沖區(qū)揖膜。
operator<< 重載 << 運(yùn)算符誓沸,使其用于輸出其后指定類型的數(shù)據(jù)。

另外壹粟,cerrclog拜隧,這兩個對象也是 C++ 的內(nèi)置對象,且也是輸出對象趁仙,和 cout 的用法一致洪添,包括成員函數(shù)也一致。
它們和 cout 的區(qū)別是:

(1)cout 除了可以將數(shù)據(jù)輸出到屏幕上雀费,通過重定向干奢,還可以實現(xiàn)將數(shù)據(jù)輸出到指定文件中;
     而 cerr 和 clog 都不支持重定向坐儿,它們只能將數(shù)據(jù)輸出到屏幕上律胀;
(2)cout 和 clog 都有緩沖區(qū)宋光,即它們在輸出數(shù)據(jù)時貌矿,會先將要數(shù)據(jù)放到緩沖區(qū),等緩沖區(qū)滿或者手動換行(使用換行符 '\n' 或者 endl)時罪佳,才會將數(shù)據(jù)全部顯示到屏幕上逛漫;
     而 cerr 則沒有緩沖區(qū),它會直接將數(shù)據(jù)輸出到屏幕上赘艳。
(2)輸出字符串

使用 cout 對象可以輸出字符串酌毡, cout 是 ostream 對象克握,調(diào)用 put 函數(shù)可以輸出單個字符,代碼如下:

cout.put('A');

put 函數(shù)的返回值是 ostream枷踏,所以如果想要輸出多個字母菩暗,可以這樣寫:

cout.put('A').put('B').put('C');

那么,如何輸出一個字符串呢旭蠕?

調(diào)用 write 函數(shù)即可實現(xiàn)停团,代碼如下:

cout.write(str, 1);

write 有兩個參數(shù),第一個參數(shù)是將要輸出的字符串掏熬,第二個參數(shù)是輸出字符串前多少個字符佑稠。

write 函數(shù)的返回值是 ostream,所以可以連續(xù)調(diào)用:

cout.write(str, 1).write(str, 2);
(3)輸出當(dāng)前輸出流指針位置

調(diào)用輸出流 tellp 方法可以獲取當(dāng)前輸出流的指針位置旗芬,一般用于文件操作:

//文件輸出流對象
ofstream outfile;
outfile.open("test.txt"); // 打開文件舌胶,如果文件不存在,則新建
const char* str = "zhangsan";
for (int i = 0; i < strlen(str); i++) {
    outfile.put(str[i]); // 輸出一個字符到文件中
    long pos = outfile.tellp(); // 獲取當(dāng)前輸出流指針位置
    cout << pos << " ";
}
cout << endl;
outfile.close(); // 關(guān)閉流

輸出結(jié)果是:

1 2 3 4 5 6 7 8
(4)輸出流指針位置的跳躍

一般情況下疮丛,輸出1的字符幔嫂,輸出流指針位置自動+1,輸出n個字符誊薄,輸出流指針位置自動+n婉烟。

使用輸出流的 seekp 函數(shù)可以實現(xiàn)輸出流指針的跳躍。

seekp 函數(shù)用于指定下一個進(jìn)入輸出緩沖區(qū)的字符所在的位置暇屋,演示代碼如下:

//文件輸出流對象
ofstream outfile;
outfile.open("test.txt"); // 打開文件似袁,如果文件不存在,則新建
const char* str = "zhangsan";
for (int i = 0; i < strlen(str); i++) {
    outfile.put(str[i]); // 輸出一個字符到文件中
    if (i == 2) 
    {
        outfile.seekp(10);
    }
}

test.txt文件中的內(nèi)容是:

image.png

可以配合 tellp 函數(shù)打印當(dāng)前指針位置咐刨,代碼如下:

//文件輸出流對象
ofstream outfile;
outfile.open("test.txt"); // 打開文件昙衅,如果文件不存在,則新建
const char* str = "zhangsan";
for (int i = 0; i < strlen(str); i++) {
    outfile.put(str[i]); // 輸出一個字符到文件中
}
cout << "當(dāng)前輸出流指針位置:" << outfile.tellp() << endl;

outfile.seekp(4); // 將輸出流指針位置改成4定鸟,下次輸出從4開始

cout << "當(dāng)前輸出流指針位置:" << outfile.tellp() << endl;

outfile.seekp(40); // 將輸出流指針位置改成4

cout << "當(dāng)前輸出流指針位置:" << outfile.tellp() << endl;

outfile.close(); // 關(guān)閉流

輸出結(jié)果是:

當(dāng)前輸出流指針位置:8
當(dāng)前輸出流指針位置:4
當(dāng)前輸出流指針位置:40

seekp 還有一個帶有兩個形參的函數(shù)而涉,用法如下:

//文件輸出流對象
ofstream outfile;
outfile.open("test.txt"); // 打開文件,如果文件不存在联予,則新建
const char* str = "zhangsanlisi";

for (int i = 0; i < strlen(str); i++) {
    outfile.put(str[i]); // 輸出一個字符到文件中
}

cout << "當(dāng)前輸出流指針位置:" << outfile.tellp() << endl;

outfile.seekp(4, ios::cur); // 從當(dāng)前位置向正方向偏移4個單位

cout << "當(dāng)前輸出流指針位置:" << outfile.tellp() << endl;

outfile.seekp(-4, ios::end); // 從結(jié)尾位置向負(fù)方向偏移4個單位

cout << "當(dāng)前輸出流指針位置:" << outfile.tellp() << endl;

outfile.seekp(4, ios::beg); // 從起始位置向正方向偏移4個單位

cout << "當(dāng)前輸出流指針位置:" << outfile.tellp() << endl;

outfile.close(); // 關(guān)閉流

seekp 的第一個參數(shù)是偏移量啼县,可以是正整數(shù),也可以是負(fù)整數(shù)沸久,正負(fù)表示偏移的方向季眷。
第二個參數(shù)是從什么位置偏移,可以接受的值有三個:

ios::beg   從起始位置偏移
ios::cur   從當(dāng)前位置偏移
ios::end   從結(jié)尾開始偏移

以上代碼最終輸出結(jié)果是:

當(dāng)前輸出流指針位置:12
當(dāng)前輸出流指針位置:16
當(dāng)前輸出流指針位置:8
當(dāng)前輸出流指針位置:4
(5)cout格式化輸出

ostream 類可實現(xiàn)格式化輸出卷胯,ostream 格式化相關(guān)的成員函數(shù)有:

成員函數(shù) 說明
flags(fmtfl) 當(dāng)前格式狀態(tài)全部替換為 fmtfl子刮。注意,fmtfl 可以表示一種格式窑睁,也可以表示多種格式挺峡。
precision(n) 設(shè)置輸出浮點(diǎn)數(shù)的精度為 n葵孤。
width(w) 指定輸出寬度為 w 個字符。
fill(c) 在指定輸出寬度的情況下橱赠,輸出的寬度不足時用字符 c 填充(默認(rèn)情況是用空格填充)尤仍。
setf(fmtfl, mask) 在當(dāng)前格式的基礎(chǔ)上,追加 fmtfl 格式狭姨,并刪除 mask 格式吓著。其中,mask 參數(shù)可以省略送挑。
unsetf(mask) 在當(dāng)前格式的基礎(chǔ)上绑莺,刪除 mask 格式。

其中 fmtfl 和 mask 的可選值有:

標(biāo) 志 作 用
ios::boolapha 把 true 和 false 輸出為字符串
ios::left 輸出數(shù)據(jù)在本域?qū)挿秶鷥?nèi)向左對齊
ios::right 輸出數(shù)據(jù)在本域?qū)挿秶鷥?nèi)向右對齊
ios::internal 數(shù)值的符號位在域?qū)拑?nèi)左對齊惕耕,數(shù)值右對齊纺裁,中間由填充字符填充
ios::dec 設(shè)置整數(shù)的基數(shù)為 10
ios::oct 設(shè)置整數(shù)的基數(shù)為 8
ios::hex 設(shè)置整數(shù)的基數(shù)為 16
ios::showbase 強(qiáng)制輸出整數(shù)的基數(shù)(八進(jìn)制數(shù)以 0 開頭,十六進(jìn)制數(shù)以 0x 打頭)
ios::showpoint 強(qiáng)制輸出浮點(diǎn)數(shù)的小點(diǎn)和尾數(shù) 0
ios::uppercase 在以科學(xué)記數(shù)法格式 E 和以十六進(jìn)制輸出字母時以大寫表示
ios::showpos 對正數(shù)顯示“+”號
ios::scientific 浮點(diǎn)數(shù)以科學(xué)記數(shù)法格式輸出
ios::fixed 浮點(diǎn)數(shù)以定點(diǎn)格式(小數(shù)形式)輸出
ios::unitbuf 每次輸出之后刷新所有的流

下面是一些舉例說明:

【flags(fmtfl)】 當(dāng)前格式狀態(tài)全部替換為 fmtfl

bool a = true;
cout << a << endl;

bool類型本質(zhì)上是一個整數(shù)司澎,當(dāng)a=true時欺缘,打印顯示為1,當(dāng)a=false時挤安,打印顯示為0谚殊。

如果想要打印顯示為:true 或者 false,那么就需要輸出格式化蛤铜。

bool a = true;
cout.flags(ios::boolalpha);
cout << a << endl;

cout 對象的 flags 函數(shù)傳入的輸出格式為:ios::boolalpha(把 true 和 false 輸出為字符串)嫩絮。

【precision(n)】 設(shè)置輸出浮點(diǎn)數(shù)的精度為 n

float a = 1.1f;
double b = a / 3;
cout << b << endl;

以上代碼的打印結(jié)果是:

0.366667

如果要求只保留兩位小數(shù),那么需要將輸出結(jié)果格式化:

float a = 1.1f;
double b = a / 3;
cout.precision(2);
cout << b << endl;

輸出結(jié)果是:

0.37

【width(w)】 指定輸出寬度為 w 個字符

cout.width(20);
cout << "zhangsan" << endl;

以上代碼的輸出結(jié)果是:

        zhangsan

輸出寬度為20围肥,默認(rèn)右對齊剿干。

對齊方式分為:左對齊和右對齊,可以設(shè)置flag保證其對其方式:

左對齊:

cout.flags(ios::left);

右對齊:

cout.flags(ios::right);

【正數(shù)符號的輸出】

有關(guān)負(fù)數(shù)和正數(shù)的輸出穆刻,負(fù)數(shù)的輸出都是帶有 - 號的置尔,正數(shù)的輸出默認(rèn)不帶 + 號,如果想要輸出正數(shù)的符號氢伟,就需要對正數(shù)的輸出進(jìn)行格式化:

cout.flags(ios::showpos);
cout << 100 << endl;

輸出結(jié)果是:

+100

結(jié)合 ios::internal 使用榜轿,將數(shù)值的符號位在域?qū)拑?nèi)左對齊,數(shù)值右對齊朵锣,中間由填充字符填充:

cout.width(20);
cout.flags(ios::showpos | ios::internal);
cout << 100 << endl;

輸出結(jié)果是:

+                100

【fill(c)】 在指定輸出寬度的情況下谬盐,輸出的寬度不足時用字符 c 填充(默認(rèn)情況是用空格填充)

cout.width(20);
cout << "zhangsan" << endl;

以上代碼的輸出結(jié)果是:

        zhangsan

輸出結(jié)果前面默認(rèn)用空格填充,相當(dāng)于:

cout.width(20);
cout.fill();
cout << "zhangsan" << endl;

但是猪勇,如果想要將左邊的空格用其它字符填充设褐,需要調(diào)用 fill 函數(shù)填充字符:

cout.width(20);
cout.fill('#');
cout << "zhangsan" << endl;

輸出結(jié)果是:

############zhangsan

【進(jìn)制輸出】

cout 有關(guān)進(jìn)制的輸出格式有:

ios::dec:設(shè)置整數(shù)的基數(shù)為 10
ios::oct:設(shè)置整數(shù)的基數(shù)為 8
ios::hex:設(shè)置整數(shù)的基數(shù)為 16

代碼如下:

int a = 177;

cout.flags(ios::dec); // 10進(jìn)制輸出
cout << a << endl;

cout.flags(ios::oct); // 8進(jìn)制輸出
cout << a << endl;

cout.flags(ios::hex); // 16進(jìn)制輸出
cout << a << endl;

以上代碼的輸出結(jié)果為:

177
261
b1

其中,8進(jìn)制和16進(jìn)制的輸出結(jié)果很奇怪泣刹,它們并不是很標(biāo)準(zhǔn)化(8進(jìn)制應(yīng)該以0開頭助析,16進(jìn)制應(yīng)該以0x開頭),使用輸出格式:ios::showbase 可以讓進(jìn)制數(shù)顯示的更加標(biāo)準(zhǔn)椅您,代碼如下:

int a = 177;

cout.flags(ios::dec); // 10進(jìn)制輸出
cout << a << endl;

cout.flags(ios::oct | ios::showbase); // 8進(jìn)制輸出
cout << a << endl;

cout.flags(ios::hex | ios::showbase); // 16進(jìn)制輸出
cout << a << endl;

輸出結(jié)果是:

177
0261
0xb1

【unsetf(mask)】 在當(dāng)前格式的基礎(chǔ)上外冀,刪除 mask 格式

cout.width(20);
cout.flags(ios::showpos | ios::internal);
cout << 100 << endl;

以上代碼的輸出結(jié)果是:

+                100

ios::showpos:表示正數(shù)的符號輸出
ios::internal:表示符號左對齊,數(shù)值右對齊

如果想要去掉 ios::internal掀泳,就需要調(diào)用 unsetf 函數(shù):

cout.width(20);
cout.flags(ios::showpos | ios::internal);
cout.unsetf(ios::internal);
cout << 100 << endl;

此時的輸出結(jié)果是:

                +100

【setf(fmtfl, mask)】 在當(dāng)前格式的基礎(chǔ)上雪隧,追加 fmtfl 格式,并刪除 mask 格式员舵。其中脑沿,mask 參數(shù)可以省略

如果想要添加某輸出格式,可以使用 setf 函數(shù):

cout.width(20);
cout.flags(ios::showpos);
cout.setf(ios::internal);
cout << 100 << endl;

以上代碼 setf 只有一個參數(shù)马僻,它可以帶有兩個參數(shù)庄拇,但是目前的測試結(jié)果是有問題的。

【強(qiáng)制輸出浮點(diǎn)數(shù)的小點(diǎn)和尾數(shù) 0】

使用輸出格式 ios::showpoint 可以強(qiáng)制輸出浮點(diǎn)數(shù)的小點(diǎn)和尾數(shù) 0:

float a = 1;
cout.flags(ios::showpoint);
cout << a << endl;

輸出結(jié)果是:

1.00000

【科學(xué)計數(shù)法格式輸出】

使用輸出格式:ios::scientific 可以將浮點(diǎn)數(shù)以科學(xué)記數(shù)法格式輸出韭邓,代碼如下:

float a = 1.11f;
cout.flags(ios::scientific);
cout << a << endl;

輸出結(jié)果是:

1.110000e+00

如果想恢復(fù)成小數(shù)輸出措近,可以重新執(zhí)行小數(shù)輸出格式:ios::fixed,代碼如下:

float a = 1.11f;
cout.flags(ios::scientific);
cout << a << endl;
cout.flags(ios::fixed);
cout << a << endl;

輸出格式為:

1.110000e+00
1.110000

【大寫格式輸出】

使用輸出格式:ios::uppercase 可以實現(xiàn)大寫格式輸出女淑,但是只適用于科學(xué)計數(shù)法和16進(jìn)制瞭郑,演示代碼如下:

float a = 1.11f;
cout.flags(ios::scientific | ios::uppercase); // 科學(xué)計數(shù)法小寫字母轉(zhuǎn)大寫字母
cout << a << endl;

int b = 177;
cout.flags(ios::hex | ios::showbase | ios::uppercase); // 16進(jìn)制的小寫字母轉(zhuǎn)大寫字母
cout << b << endl;

輸出結(jié)果是:

1.110000E+00
0XB1
(6)使用流操縱算子格式化輸出

<iomanip> 頭文件中定義的一些常用的格式控制符,它們都可用于格式化輸出:

流操縱算子 作 用 是否常用
dec(默認(rèn)) 以十進(jìn)制形式輸出整數(shù) 常用
hex 以十六進(jìn)制形式輸出整數(shù) 常用
oct 以八進(jìn)制形式輸出整數(shù) 常用
fixed 以普通小數(shù)形式輸出浮點(diǎn)數(shù) 常用
scientific 以科學(xué)計數(shù)法形式輸出浮點(diǎn)數(shù) 常用
left 左對齊鸭你,即在寬度不足時將填充字符添加到右邊 常用
right(默認(rèn)) 右對齊屈张,即在寬度不足時將填充字符添加到左邊 常用
setbase(b) 設(shè)置輸出整數(shù)時的進(jìn)制,b=8袱巨、10 或 16 常用
setw(w) 指定輸出寬度為 w 個字符袜茧,或輸入字符串時讀入 w 個字符。注意瓣窄,該函數(shù)所起的作用是一次性的笛厦,即只影響下一次 cout 輸出。 常用
setfill(c) 在指定輸出寬度的情況下俺夕,輸出的寬度不足時用字符 c 填充(默認(rèn)情況是用空格填充) 常用
setprecision(n) 設(shè)置輸出浮點(diǎn)數(shù)的精度為 n裳凸。
在使用非 fixed 且非 scientific 方式輸出的情況下,n 即為有效數(shù)字最多的位數(shù)劝贸,如果有效數(shù)字位數(shù)超過 n姨谷,則小數(shù)部分四舍五人,或自動變?yōu)榭茖W(xué)計 數(shù)法輸出并保留一共 n 位有效數(shù)字映九。
在使用 fixed 方式和 scientific 方式輸出的情況下梦湘,n 是小數(shù)點(diǎn)后面應(yīng)保留的位數(shù)。
常用
setiosflags(mask) 在當(dāng)前格式狀態(tài)下,追加 mask 格式捌议,mask 參數(shù)可選擇表 2 中的所有值哼拔。 常用
resetiosflags(mask) 在當(dāng)前格式狀態(tài)下,刪除 mask 格式瓣颅,mask 參數(shù)可選擇表 2 中的所有值倦逐。 常用
boolapha 把 true 和 false 輸出為字符串 不常用
noboolalpha(默認(rèn)) 把 true 和 false 輸出為 0、1 不常用
showbase 輸出表示數(shù)值的進(jìn)制的前綴 不常用
noshowbase (默認(rèn)) 不輸出表示數(shù)值的進(jìn)制.的前綴 不常用
showpoint 總是輸出小數(shù)點(diǎn) 不常用
noshowpoint(默認(rèn)) 只有當(dāng)小數(shù)部分存在時才顯示小數(shù)點(diǎn) 不常用
showpos 在非負(fù)數(shù)值中顯示 + 不常用
noshowpos(默認(rèn)) 在非負(fù)數(shù)值中不顯示 + 不常用
uppercase 十六進(jìn)制數(shù)中使用 A~E宫补。若輸出前綴檬姥,則前綴輸出 0X,科學(xué)計數(shù)法中輸出 E 不常用
nouppercase (默認(rèn)) 十六進(jìn)制數(shù)中使用 a~e粉怕。若輸出前綴健民,則前綴輸出 0x,科學(xué)計數(shù)法中輸出 e贫贝。 不常用
internal 數(shù)值的符號(正負(fù)號)在指定寬度內(nèi)左對齊秉犹,數(shù)值右對 齊,中間由填充字符填充平酿。 不常用

其用法可以舉例說明:

int a = 177;
cout << hex << a << endl; // 16進(jìn)制格式輸出
cout << setbase(8) << a << endl; // 8進(jìn)制格式輸出

float b = 1.11f;
cout << scientific << b << endl; // 科學(xué)計數(shù)法格式輸出

float c = 1.110000e+00;
cout << fixed << c << endl; // 小數(shù)格式輸出

string e = "zhangsan";
cout << setw(20) << left << setfill('C') << e << endl; // 寬度為20凤优,左對齊,用字符C填充

cout << setprecision(2) << 1.1111 << endl; // 設(shè)置浮點(diǎn)數(shù)的精度蜈彼,保留2位小數(shù)

float f = 1.11f;
cout << setiosflags(ios::scientific) << f << endl; // 在當(dāng)前格式狀態(tài)下筑辨,追加 mask 格式
cout << resetiosflags(ios::scientific) << f << endl; // 在當(dāng)前格式狀態(tài)下,刪除 mask 格式

輸出結(jié)果是:

b1
261
1.110000e+00
1.110000
zhangsanCCCCCCCCCCCC
1.11
0x1.1c28f60000000p+0
1.11
(7)輸入輸出重定向

在默認(rèn)情況下幸逆,cin 只能接收從鍵盤輸入的數(shù)據(jù)棍辕,cout 也只能將數(shù)據(jù)輸出到屏幕上。但通過重定向还绘,cin 可以將指定文件作為輸入源楚昭,即接收文件中早已準(zhǔn)備好的數(shù)據(jù),同樣 cout 可以將原本要輸出到屏幕上的數(shù)據(jù)轉(zhuǎn)而寫到指定文件中拍顷。

C++ 中抚太,實現(xiàn)重定向的常用方式有 3 種,分別是:

(1)freopen()函數(shù)實現(xiàn)重定向

    FILE* file = new FILE();
    string lineStr;

    freopen_s(&file, "in.txt", "r", stdin); // 將標(biāo)準(zhǔn)輸入流重定向到 in.txt 文件
    freopen_s(&file, "out.txt", "w", stdout); // 將標(biāo)準(zhǔn)輸出重定向到 out.txt文件
    while (cin >> lineStr) 
    {
        cout << lineStr << endl;
    }
    fclose(stdout);
    fclose(stdin);

此時昔案,cin 和 cout 被重定向為文件的輸入輸出尿贫,那么怎么恢復(fù)到控制臺輸出呢?

恢復(fù)到控制臺輸出:
    freopen_s(&file, "CON", "w", stdout); 
恢復(fù)到控制臺輸入(目測無效):
    freopen_s(&file, "CON", "r", stdin);

(2)rdbuf()函數(shù)實現(xiàn)重定向

    ifstream fin("in.txt"); //打開 in.txt 文件踏揣,等待讀取
    ofstream fout("out.txt"); // 打開 out.txt 文件庆亡,等待寫入
    streambuf* oldcin;
    streambuf* oldcout;
    string linStr;
    oldcin = cin.rdbuf(fin.rdbuf()); // 用 rdbuf() 重新定向
    oldcout = cout.rdbuf(fout.rdbuf()); //用 rdbuf() 重新定向
    while (cin >> linStr) // // 從input.txt文件讀入,并寫入 out.txt
    {
        cout << linStr << endl;
    }
    cin.rdbuf(oldcin); // 恢復(fù)鍵盤輸入
    cout.rdbuf(oldcout); //恢復(fù)屏幕輸出

    fin.close();
    fout.close();

(3)通過控制臺實現(xiàn)重定向

cmd打開控制臺捞稿,輸入:xxx.exe又谋,執(zhí)行應(yīng)用的可執(zhí)行文件"xxx.exe"可以直接運(yùn)行代碼拼缝,但是這樣無法做到 cin 和 cout 的重定向;
如果輸入:xxx.exe <in.txt >out.txt 的話彰亥,可以做到重定向咧七;

<in.txt:將 cin 從控制臺輸入重定向到文件(in.txt)輸入,當(dāng)前目錄要確保存在文件 in.txt剩愧;
>out.txt:將 cout 從控制臺輸出重定向到文件(out.txt)輸出猪叙。

編輯代碼:

string lineStr;
while(cin >> lineStr)
    cout << lineStr << endl;

在控制臺輸入:xxx.exe <in.txt >out.txt 

此時發(fā)現(xiàn)娇斩,in.txt 中的文本已經(jīng)寫到out.txt文件中仁卷。
(8)如何忽視輸入的指定字符
int n;
cin.ignore();
cin >> n;
cout << n;

cin 的 ignore 函數(shù)可以實現(xiàn)忽視輸入的字符,以上代碼中 ignore() 忽視一個字符犬第,假如輸入:

12345

那么輸出結(jié)果是:

2345

ignore 函數(shù)還可以含有一個形式參數(shù)

istream & ignore(int n =1);

表示跳過幾個字符锦积。

ignore 函數(shù)還可以含有兩個形式參數(shù):

istream & ignore(int n =1, int delim = EOF);

此函數(shù)的作用是跳過輸入流中的 n 個字符,或跳過 delim 及其之前的所有字符歉嗓,哪個條件先滿足就按哪個執(zhí)行丰介。
兩個參數(shù)都有默認(rèn)值,因此 cin.ignore() 就等效于 cin.ignore(1, EOF)鉴分, 即跳過一個字符哮幢。

兩個參數(shù)的舉例代碼:

int n;
cin.ignore(5, '1');
cin >> n;
cout << n;

輸入和輸出結(jié)果是:

ABC123
23
(9)查看輸入流下一個字符

cin 的 peek() 函數(shù)可以查看輸入流下一個字符。

[本章完...]

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末志珍,一起剝皮案震驚了整個濱河市橙垢,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌伦糯,老刑警劉巖柜某,帶你破解...
    沈念sama閱讀 222,590評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異敛纲,居然都是意外死亡喂击,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,157評論 3 399
  • 文/潘曉璐 我一進(jìn)店門淤翔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來翰绊,“玉大人,你說我怎么就攤上這事旁壮〖嗍龋” “怎么了?”我有些...
    開封第一講書人閱讀 169,301評論 0 362
  • 文/不壞的土叔 我叫張陵寡具,是天一觀的道長秤茅。 經(jīng)常有香客問我,道長童叠,這世上最難降的妖魔是什么框喳? 我笑而不...
    開封第一講書人閱讀 60,078評論 1 300
  • 正文 為了忘掉前任课幕,我火速辦了婚禮,結(jié)果婚禮上五垮,老公的妹妹穿的比我還像新娘乍惊。我一直安慰自己,他們只是感情好放仗,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,082評論 6 398
  • 文/花漫 我一把揭開白布润绎。 她就那樣靜靜地躺著,像睡著了一般诞挨。 火紅的嫁衣襯著肌膚如雪莉撇。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,682評論 1 312
  • 那天惶傻,我揣著相機(jī)與錄音棍郎,去河邊找鬼。 笑死银室,一個胖子當(dāng)著我的面吹牛涂佃,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蜈敢,決...
    沈念sama閱讀 41,155評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼辜荠,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了抓狭?” 一聲冷哼從身側(cè)響起伯病,我...
    開封第一講書人閱讀 40,098評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎辐宾,沒想到半個月后狱从,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,638評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡叠纹,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,701評論 3 342
  • 正文 我和宋清朗相戀三年季研,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片誉察。...
    茶點(diǎn)故事閱讀 40,852評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡与涡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出持偏,到底是詐尸還是另有隱情驼卖,我是刑警寧澤,帶...
    沈念sama閱讀 36,520評論 5 351
  • 正文 年R本政府宣布鸿秆,位于F島的核電站酌畜,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏卿叽。R本人自食惡果不足惜桥胞,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,181評論 3 335
  • 文/蒙蒙 一恳守、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧贩虾,春花似錦催烘、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,674評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至策精,卻和暖如春舰始,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蛮寂。 一陣腳步聲響...
    開封第一講書人閱讀 33,788評論 1 274
  • 我被黑心中介騙來泰國打工蔽午, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留易茬,地道東北人酬蹋。 一個月前我還...
    沈念sama閱讀 49,279評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像抽莱,于是被迫代替她去往敵國和親范抓。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,851評論 2 361

推薦閱讀更多精彩內(nèi)容