成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

C++IO流詳解

trilever / 2735人閱讀

摘要:在使用時(shí)候必須要包含頭文件并引入標(biāo)準(zhǔn)命名空間。在該頭文件下,標(biāo)準(zhǔn)庫三個(gè)類進(jìn)行流的輸入進(jìn)行流的輸出進(jìn)行流的輸入輸出將結(jié)構(gòu)體的內(nèi)容轉(zhuǎn)換成字符串字符串的內(nèi)容輸出到結(jié)構(gòu)體當(dāng)中注意實(shí)際是在其底層維護(hù)了一個(gè)類型的對(duì)象用來保存結(jié)果。

一. C語言輸入輸出

C語言中我們用到的最頻繁的輸入輸出方式就是scanf ()與printf()。
scanf(): 從標(biāo)準(zhǔn)輸入設(shè)備(鍵盤)讀取數(shù)據(jù),并將值存放在變量中。
printf(): 將指定的文字/字符串輸出到標(biāo)準(zhǔn)輸出設(shè)備(屏幕,網(wǎng)卡,顯示器等)。注意寬度輸出和精度輸出控制。
C語言借助了相應(yīng)的緩沖區(qū)來進(jìn)行輸入與輸出。如下圖所示

對(duì)輸入輸出緩沖區(qū)的理解:
(1).可以屏蔽掉低級(jí)I/O的實(shí)現(xiàn),低級(jí)I/O的實(shí)現(xiàn)依賴操作系統(tǒng)本身內(nèi)核的實(shí)現(xiàn),所以如果能夠屏蔽這部分的差異,可以很容易寫出可移植的程序。
(2).可以使用這部分的內(nèi)容實(shí)現(xiàn)“行”讀取的行為,對(duì)于計(jì)算機(jī)而言是沒有“行”這個(gè)概念,有了這部分,就可以定義“行”的概念,然后解析緩沖區(qū)的內(nèi)容,返回一個(gè)“行”。

二.C++輸入輸出

C++標(biāo)準(zhǔn)庫提供了一組豐富的輸入/輸出功能,本文重點(diǎn)講解C++編程中最常見的 I/O 操作

C++的 I/O 發(fā)生在流中,流是字節(jié)序列,如果字節(jié)流是從設(shè)備(如鍵盤,磁盤驅(qū)動(dòng)器,網(wǎng)絡(luò)連接等)流向內(nèi)存,這叫做輸入操作,如果字節(jié)流是從內(nèi)存流向設(shè)備,這叫做輸出操作。

標(biāo)準(zhǔn)輸出流 :
預(yù)定義的對(duì)象 cout 是 ostream 類的一個(gè)實(shí)例,cout 對(duì)象"連接"到標(biāo)準(zhǔn)輸出設(shè)備,通常是顯示屏。

標(biāo)準(zhǔn)輸入流 :
預(yù)定義的對(duì)象 cin 是 istream 類的一個(gè)實(shí)例,cin 對(duì)象附屬到標(biāo)準(zhǔn)輸入設(shè)備,通常是鍵盤。

我們來研究下面這一段代碼

#include#includeusing namespace std;struct Student{	string _name;	int _age;};int main(){	Student s;	cin >> s._name >> s._age;	cout << s._name << " " << s._age << endl;	scanf("%s%d", s._name.c_str(), &s._age);	printf("%s %d", s._name.c_str(), s._age);}

這段代碼看上去沒有什么問題,但如果我們第二次輸入的字符串過長,會(huì)導(dǎo)致程序崩潰,原因如下 :

string內(nèi)部會(huì)有一個(gè)_Buf數(shù)組,當(dāng)存儲(chǔ)的字符串大小小于15字節(jié)時(shí),不會(huì)去堆上開辟空間存儲(chǔ)字符串,會(huì)將字符串存儲(chǔ)在_Buf數(shù)組中,但無論第一次輸入的字符串大小是大于15字節(jié)還是小于15字節(jié),第二次如果輸入過長,都會(huì)導(dǎo)致程序崩潰,原因在于第二次是用scanf進(jìn)行輸入,使用scanf輸入,不會(huì)影響string的size和capacity,所以輸入過長就會(huì)越界寫入

#include#includeusing namespace std;struct Student{	string _name;	int _age;};int main(){	Student s;	cin >> s._name >> s._age;	cout << s._name << " " << s._age << endl;	scanf("%s%d", s._name.c_str(), &s._age);	cout << s._name << " " << s._age << endl;}

這段代碼和上一段代碼相比只是最后的輸出使用了cout,跟上面一樣,如果輸入過長也會(huì)導(dǎo)致越界寫入,除此之外,就算輸入的長度在合法的范圍內(nèi),打印出來的結(jié)果也不是我們想要的,原因是cout在輸出時(shí)是根據(jù)string的size來輸出的,而scanf輸入時(shí)并沒有改變string的size,所以打印結(jié)果不是我們想要的,上面的printf如果輸入的長度在合法的范圍內(nèi),打印結(jié)果就是我們想要的,原因是printf打印字符串時(shí)是根據(jù)’/0’的位置來判斷的.

想要解決上面的兩個(gè)問題,我們提前把空間開好即可

#include#includeusing namespace std;struct Student{	string _name;	int _age;};int main(){	Student s;	cin >> s._name >> s._age;	cout << s._name << " " << s._age << endl;	s._name.resize(100); // 提前開好空間	scanf("%s%d", s._name.c_str(), &s._age);	printf("%s %d/n", s._name.c_str(), s._age);	cout << s._name << " " << s._age << endl;}

因此,建議大家在C++中盡量去用cin和cout,用cout和cin不方便的地方,再去用scanf和printf(格式控制輸出時(shí))

三.C++ IO流

C++系統(tǒng)實(shí)現(xiàn)了一個(gè)龐大的類庫,其中ios為基類,其他類都是直接或間接派生自ios類

(1).C++標(biāo)準(zhǔn)IO流

C++標(biāo)準(zhǔn)庫提供了4個(gè)全局流對(duì)象cin、cout、cerr、clog,使用cout進(jìn)行標(biāo)準(zhǔn)輸出,即數(shù)據(jù)從內(nèi)存流向控制臺(tái)(顯示器)。使用cin進(jìn)行標(biāo)準(zhǔn)輸入即數(shù)據(jù)通過鍵盤輸入到程序中,同時(shí)C++標(biāo)準(zhǔn)庫還提供了cerr用來進(jìn)行標(biāo)準(zhǔn)錯(cuò)誤的輸出,以及clog進(jìn)行日志的輸出,從上圖可以看出,cout、cerr、clog是ostream類的三個(gè)不同的對(duì)象,因此這三個(gè)對(duì)象現(xiàn)在基本沒有區(qū)別,只是應(yīng)用場景不同。

在使用時(shí)候必須要包含頭文件并引入std標(biāo)準(zhǔn)命名空間。

注意:
(1). cin為緩沖流。鍵盤輸入的數(shù)據(jù)保存在緩沖區(qū)中,當(dāng)要提取時(shí),是從緩沖區(qū)中拿。如果一次輸入過多,會(huì)留在那兒慢慢用,如果輸入錯(cuò)了,必須在回車之前修改,如果回車鍵按下就無法挽回了。只有把輸入緩沖區(qū)中的數(shù)據(jù)取完后,才要求輸入新的數(shù)據(jù)。

(2). 輸入的數(shù)據(jù)類型必須與要提取的數(shù)據(jù)類型一致,否則出錯(cuò)。出錯(cuò)只是在流的狀態(tài)字state中對(duì)應(yīng)位置,程序繼續(xù)。

(3). 空格和回車都可以作為數(shù)據(jù)之間的分格符,所以多個(gè)數(shù)據(jù)可以在一行輸入,也可以分行輸入。但如果是字符型和字符串,則空格(ASCII碼為32)無法用cin輸入,字符串中也不能有空格?;剀嚪矡o法讀入。

#includeusing namespace std;int main(){	// 輸入 hello world	string a;	cin >> a;	cout << a << endl; // hello	cin >> a;	cout << a << endl; // world	getline(cin,a);	cout << a << endl;}

(4). cin和cout可以直接輸入和輸出內(nèi)置類型數(shù)據(jù),原因:標(biāo)準(zhǔn)庫已經(jīng)將所有內(nèi)置類型的輸入和輸出全部重載了

(5). 對(duì)于自定義類型,如果要支持cin和cout的標(biāo)準(zhǔn)輸入輸出,需要對(duì)<<和>>進(jìn)行重載

(6). 循環(huán)輸入結(jié)構(gòu)

string str;while(cin>>str){	cout<<str<<endl;}char buff[100];while(scanf("%s",buff) != EOF){	printf("%s/n",buff);}

兩種方式都能達(dá)到循環(huán)輸入的目的,使用ctrl + c終止輸入
(1). cin>>str 等同于 istream& operator>>(cin,str),返回值為cin對(duì)象,通過operator bool()來判斷是否有讀取錯(cuò)誤
(2). scanf函數(shù)當(dāng)讀取發(fā)生錯(cuò)誤或讀到文件末尾,會(huì)返回EOF

(2).C++文件IO流

ofstream
輸出文件流,用于創(chuàng)建文件并向文件寫入信息
ifstream
輸入文件流,用于從文件讀取信息
fstream
文件流,且同時(shí)具有 ofstream 和 ifstream 兩種功能,這意味著它可以創(chuàng)建文件,向文件寫入信息,從文件讀取信息

文件常見的打開方式 :
(1). in 以讀的方式打開文件
(2). out 以寫的方式打開文件
(3). binary 以二進(jìn)制方式對(duì)文件進(jìn)行操作
(4). ate 輸出位置從文件的末尾開始
(5). app 以追加的方式對(duì)文件進(jìn)行寫入
(6). trunc 先將文件內(nèi)容清空再打開文件

常用成員函數(shù)
(1). put 插入一個(gè)字符到文件
(2). write 插入一段字符到文件
(3). get 從文件提取字符
(4). read 從文件提取多個(gè)字符
(5). tellg 獲取當(dāng)前字符在文件當(dāng)中的位置
(6). seekg 設(shè)置對(duì)文件進(jìn)行操作的位置
(7). >>運(yùn)算符重載 將數(shù)據(jù)形象地以“流”的形式進(jìn)行輸入(用于文本文件)
(8). <<運(yùn)算符重載 將數(shù)據(jù)形象地以“流”的形式進(jìn)行輸出(用于文本文件)

以文本的形式操作文件

對(duì)文本文件進(jìn)行寫入操作

//以文本的形式對(duì)文件進(jìn)行寫入void Write(){	ofstream outfile("test.txt"); // 以寫的方式打開文件	outfile.put("c"); // 向文件寫入一個(gè)字符"c"	outfile.write("hello world",5); // 向文件寫入長度為n的字符串	outfile << "hehe"; // 向文件寫入字符串	outfile.close(); // 關(guān)閉文件}

對(duì)文件文件進(jìn)行讀取操作

//以文本的形式對(duì)文件進(jìn)行讀取void ReadTxt(){	ifstream infile("test.txt");	// seekg(),tellg()	char c, c1, c2;	infile.seekg(2);	infile >> c;	infile.seekg(3, ios::beg);	infile >> c1;	infile.seekg(-1,ios::end);	infile >> c2;	cout << c << endl;	cout << c1 << endl;	cout << c2 << endl;	// get	char c;	while (infile.get(c))	{		cout << c;	}	cout << endl;	// read	infile.seekg(0, ios::end);	int length = infile.tellg();	infile.seekg(0, ios::beg);	char* buffer = new char[length];	infile.read(buffer, length);	if (infile)	{		cout << buffer << endl;	}	delete[]buffer;	// >>	infile.seekg(0, ios::end);	int length = infile.tellg();	infile.seekg(0, ios::beg);	char* buffer = new char[length];	infile >> buffer;	cout << buffer << endl;}

對(duì)二進(jìn)制文件進(jìn)行寫入操作

void write(){	ofstream outfile("test.bin",ios::out | ios::binary);	outfile.put("l");	outfile.write("lyp hello linux",10);	}

對(duì)二進(jìn)制文件進(jìn)行讀取操作

void read(){	ifstream infile("test.bin", ios::in | ios::binary);	// get	char c;	while (infile.get(c))	{		cout << c;	}	cout << endl;		// read	infile.seekg(0, ios::end);	int length = infile.tellg();	infile.seekg(0, ios::beg);	char* buffer = new char[length];	infile.read(buffer, length);	if (infile)	{		cout << buffer << endl;	}	delete[]buffer;}

四.stringstream介紹

在C語言中,如果想要將一個(gè)整形變量的數(shù)據(jù)轉(zhuǎn)化為字符串格式,我們一般有以下兩種方式
(1). itoa

int a = 20;char buffer[10];itoa(a,buffer,10); // 將數(shù)字轉(zhuǎn)換成10進(jìn)制字符

(2). sprintf

struct ServerInfo{	char _ip[20];	int _port;};int main(){	ServerInfo info = {"2020.110.400.83",250};	char buffer[128];	// 序列化,將結(jié)構(gòu)體中的內(nèi)容轉(zhuǎn)換成字符串	sprintf(buffer, "%s %d", info._ip, info._port); // 加空格,在buffer數(shù)組里就有空格	// 反序列化,將數(shù)組的內(nèi)容讀到結(jié)構(gòu)體中	ServerInfo rinfo;	sscanf(buffer, "%s %d", rinfo._ip, &rinfo._port);}

但是兩個(gè)函數(shù)在轉(zhuǎn)化時(shí),都得需要先給出保存結(jié)果的空間,那空間要給多大呢,就不太好界定,而且轉(zhuǎn)化格式不匹配時(shí),可能還會(huì)得到錯(cuò)誤的結(jié)果甚至程序崩潰。

在C++中,可以使用stringstream類對(duì)象來避開此問題。
在程序中如果想要使用stringstream類,必須要包含頭文件。在該頭文件下,標(biāo)準(zhǔn)庫三個(gè)類:
(1). istringstream 進(jìn)行流的輸入
(2). ostringstream 進(jìn)行流的輸出
(3). stringstream 進(jìn)行流的輸入輸出

#include#includeusing namespace std;struct ServerInfo{	char _ip[20];	int _port;};int main(){	ServerInfo info = {"2020.110.400.83",250};	// 將結(jié)構(gòu)體的內(nèi)容轉(zhuǎn)換成字符串	stringstream sm;	sm << info._ip << " " << info._port;	string buffer = sm.str();	cout << buffer << endl;		// 字符串的內(nèi)容輸出到結(jié)構(gòu)體當(dāng)中	stringstream sm;	sm.str("2020.110.400.83 250");	ServerInfo rinfo;	sm >> rinfo._ip >> rinfo._port;		stringstream sm("2020.110.400.83 250");	ServerInfo rinfo;	sm >> rinfo._ip >> rinfo._port;	}

注意:
(1). stringstream實(shí)際是在其底層維護(hù)了一個(gè)string類型的對(duì)象用來保存結(jié)果。
(2). 多次數(shù)據(jù)類型轉(zhuǎn)化時(shí),一定要用clear()來清空,才能正確轉(zhuǎn)化,但clear()不會(huì)將stringstream底層的string對(duì)象清空。
(3). 可以使用s. str("")方法將底層string對(duì)象設(shè)置為""空字符串。
(4). 可以使用s.str()將讓stringstream返回其底層的string對(duì)象。
(5). stringstream使用string類對(duì)象代替字符數(shù)組,可以避免緩沖區(qū)溢出的危險(xiǎn),而且其會(huì)對(duì)參數(shù)類型進(jìn)行推演,不需要格式化控制,也不會(huì)出現(xiàn)格式化失敗的風(fēng)險(xiǎn),因此使用更方便,更安全。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/121139.html

相關(guān)文章

  • Java IO詳解

    摘要:后綴名是父類名。將字符讀取流對(duì)象作為參數(shù)傳遞給緩沖對(duì)象的構(gòu)造函數(shù)。讀寫失敗讀取關(guān)閉失敗寫入關(guān)閉失敗字節(jié)流操作從文件系統(tǒng)中的某個(gè)文件中獲得輸入字節(jié)。和字節(jié)流需求,想要操作圖片數(shù)據(jù)。 概述 IO流用來處理設(shè)備之間的數(shù)據(jù)傳輸,Java對(duì)數(shù)據(jù)的操作是通過流的方式,Java用于操作流的對(duì)象都在IO包中。 流按操作數(shù)據(jù)分為兩種:字節(jié)流與字符流流按流向分為:輸入流、輸出流 IO流常用基類 字符流的抽...

    DC_er 評(píng)論0 收藏0
  • 少啰嗦!一分鐘帶你讀懂Java的NIO和經(jīng)典IO的區(qū)別

    摘要:的選擇器允許單個(gè)線程監(jiān)視多個(gè)輸入通道。一旦執(zhí)行的線程已經(jīng)超過讀取代碼中的某個(gè)數(shù)據(jù)片段,該線程就不會(huì)在數(shù)據(jù)中向后移動(dòng)通常不會(huì)。 1、引言 很多初涉網(wǎng)絡(luò)編程的程序員,在研究Java NIO(即異步IO)和經(jīng)典IO(也就是常說的阻塞式IO)的API時(shí),很快就會(huì)發(fā)現(xiàn)一個(gè)問題:我什么時(shí)候應(yīng)該使用經(jīng)典IO,什么時(shí)候應(yīng)該使用NIO? 在本文中,將嘗試用簡明扼要的文字,闡明Java NIO和經(jīng)典IO之...

    Meils 評(píng)論0 收藏0
  • 我的阿里之路+Java面經(jīng)考點(diǎn)

    摘要:我的是忙碌的一年,從年初備戰(zhàn)實(shí)習(xí)春招,年三十都在死磕源碼,三月份經(jīng)歷了阿里五次面試,四月順利收到實(shí)習(xí)。因?yàn)槲倚睦砗芮宄业哪繕?biāo)是阿里。所以在收到阿里之后的那晚,我重新規(guī)劃了接下來的學(xué)習(xí)計(jì)劃,將我的短期目標(biāo)更新成拿下阿里轉(zhuǎn)正。 我的2017是忙碌的一年,從年初備戰(zhàn)實(shí)習(xí)春招,年三十都在死磕JDK源碼,三月份經(jīng)歷了阿里五次面試,四月順利收到實(shí)習(xí)offer。然后五月懷著忐忑的心情開始了螞蟻金...

    姘擱『 評(píng)論0 收藏0
  • Node.js知識(shí)點(diǎn)詳解(一)基礎(chǔ)部分

    摘要:基礎(chǔ)的端到端的基準(zhǔn)測試顯示大約比快八倍。所謂單線程,就是指一次只能完成一件任務(wù)。在服務(wù)器端,異步模式甚至是唯一的模式,因?yàn)閳?zhí)行環(huán)境是單線程的,如果允許同步執(zhí)行所有請(qǐng)求,服務(wù)器性能會(huì)急劇下降,很快就會(huì)失去響應(yīng)。 模塊 Node.js 提供了exports 和 require 兩個(gè)對(duì)象,其中 exports 是模塊公開的接口,require 用于從外部獲取一個(gè)模塊的接口,即所獲取模塊的 e...

    whjin 評(píng)論0 收藏0
  • Java NIO詳解

    摘要:前言本篇主要講解中的機(jī)制和網(wǎng)絡(luò)通訊中處理高并發(fā)的分為兩塊第一塊講解多線程下的機(jī)制第二塊講解如何在機(jī)制下優(yōu)化資源的浪費(fèi)服務(wù)器單線程下的機(jī)制就不用我介紹了,不懂得可以去查閱下資料那么多線程下,如果進(jìn)行套接字的使用呢我們使用最簡單的服務(wù)器來幫助大 前言 本篇主要講解Java中的IO機(jī)制和網(wǎng)絡(luò)通訊中處理高并發(fā)的NIO 分為兩塊:第一塊講解多線程下的IO機(jī)制第二塊講解如何在IO機(jī)制下優(yōu)化CPU資...

    rickchen 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<