公共服務標準化指南廊坊seo關(guān)鍵詞排名
C語言的輸入與輸出
在C語言當中,我們使用最頻繁的輸入輸出方式就是scanf與printf:
- scanf: 從標準輸入設備(鍵盤)讀取數(shù)據(jù),并將讀取到的值存放到某一指定變量當中。
- printf: 將指定的數(shù)據(jù)輸出到標準輸出設備(屏幕),使用時需要注意寬度輸出和精度輸出的控制。
C語言借助了相應的緩沖區(qū)來進行輸入與輸出。如下圖所示:
對輸入輸出緩沖區(qū)的理解:
- 可以屏蔽掉低級I/O的實現(xiàn)。 低級I/O的實現(xiàn)依賴操作系統(tǒng)本身內(nèi)核的實現(xiàn),所以如果能夠屏蔽這部分的差異,可以很容易寫出可移植的程序。
- 可以使用這部分的內(nèi)容實現(xiàn)“行”讀取的行為。 對于計算機而言是沒有“行”這個概念的,有了這部分,就可以定義“行”的概念,然后解析緩沖區(qū)的內(nèi)容,返回一個“行”。
流是什么
“流”即是流動的意思,是物質(zhì)從一處向另一處流動的過程,是對一種有序連續(xù)且有方向性的數(shù)據(jù)的抽象描述。
C++流是指信息從外部輸入設備(如鍵盤)向計算機內(nèi)部(如內(nèi)存)輸入和從計算機內(nèi)部向外部輸出設備(如顯示器)輸出的過程。這種輸入輸出的過程被形象的比喻為“流”。
它的特性是:有序連續(xù)、具有方向性
為了實現(xiàn)這種流動,C++定義了I/O標準類庫,這些每個類都稱為流/流類,用以完成某方面的功能
C++IO流
C++系統(tǒng)實現(xiàn)了一個龐大的類庫,其中ios為基類,其他類都是直接或間接派生自ios類
C++標準IO流
C++標準庫提供了4個全局流對象(cin、cout、cerr、clog):
- 使用cout進行標準輸出,即數(shù)據(jù)從內(nèi)存流向控制臺(顯示器)。
- 使用cin進行標準輸入,即數(shù)據(jù)通過鍵盤輸入到程序中。
- 使用cerr進行標準錯誤的輸出。
- 使用clog進行日志的輸出。
從上圖可以看出,cout、cerr、clog都是由ostream類實例化出的三個不同的對象,因此這三個對象基本沒什么區(qū)別,只是應用場景不同。
在使用時候必須要包含#include文件并引入std標準命名空間。
注意:
1、cin為緩沖流。 鍵盤輸入的數(shù)據(jù)保存在緩沖區(qū)中,當要提取時,是從緩沖區(qū)中拿。 如果一次輸入過多,會留在那兒慢慢用,如果輸入錯了,必須在回車之前修改,如果回車鍵按下就無法挽回了。只有把輸入緩沖區(qū)中的數(shù)據(jù)取完后,才要求輸入新的數(shù)據(jù)。
2、輸入的數(shù)據(jù)類型必須與要提取的數(shù)據(jù)類型一致,否則出錯。出錯只是在流的狀態(tài)字state中對應位置位(置1),程序繼續(xù)。
3、空格和回車都可以作為數(shù)據(jù)之間的分格符,所以多個數(shù)據(jù)可以在一行輸入,也可以分行輸 入。但如果是字符型和字符串,則空格(ASCII碼為32)無法用cin輸入,字符串中也不能有空格?;剀嚪矡o法讀入。
#include <iostream>
#include <string>
using namespace std;
int main(){string s;cin >> s; //輸入:"hello world"cout << s << endl; //輸出:"hello"return 0;
}
對于含有空格的字符串,我們需要使用getline函數(shù)進行讀取,因為getline函數(shù)只有遇到’\n’才會停止讀取。
#include <iostream>
#include <string>
using namespace std;
int main(){string s;getline(cin, s); //輸入:"hello world"cout << s << endl; //輸出:"hello world"return 0;
}
4、cin和cout可以直接輸入和輸出內(nèi)置類型數(shù)據(jù),原因:標準庫已經(jīng)將所有內(nèi)置類型的輸入和輸出全部重載了
5、對于自定義類型,如果要支持cin和cout的標準輸入輸出,需要對<<和>>進行重載。
6、循環(huán)輸入和輸出
// 單個元素循環(huán)輸入
while (cin >> a) {// ...
}
// 多個元素循環(huán)輸入
while (c >> a >> b >> c) {// ...
}
// 整行接收
while (cin >> str) {// ...
}
7、istream類型對象轉(zhuǎn)換為邏輯條件判斷值
istream& operator>> (int& val);
explicit operator bool() const;
實際上我們看到使用while(cin>>i)去流中提取對象數(shù)據(jù)時,調(diào)用的operator>>,返回值是 istream類型的對象,那么這里可以做邏輯條件值,源自于istream的對象又調(diào)用了operator bool,operator bool調(diào)用時如果接收流失敗,或者有結(jié)束標志,則返回false。
C++文件IO流
C++標準庫中的<fstream>
頭文件提供了用于文件輸入和輸出的類和接口。這些類通常與文件流對象一起使用,允許你打開、讀取、寫入和關(guān)閉文件。以下是一些常用的<fstream>
接口和類的介紹:
ifstream
(輸入文件流):ifstream
類用于從文件中讀取數(shù)據(jù)。
- 常用成員函數(shù):
open(const char* filename, ios_base::openmode mode = ios_base::in)
:打開指定文件以供讀取。mode
參數(shù)指定了文件的打開模式,例如ios::in
表示只讀模式。close()
:關(guān)閉打開的文件。is_open()
:檢查文件是否已經(jīng)成功打開。get()
:從文件中讀取一個字符。getline(char* buffer, streamsize count, char delim)
:從文件中讀取一行文本,直到遇到指定的分隔符或達到指定的字符數(shù)。operator>>
:用于從文件中讀取各種數(shù)據(jù)類型,例如int
、double
等。
ofstream
(輸出文件流):
ofstream
類用于向文件中寫入數(shù)據(jù)。- 常用成員函數(shù):
open(const char* filename, ios_base::openmode mode = ios_base::out)
:打開指定文件以供寫入。mode
參數(shù)指定了文件的打開模式,例如ios::out
表示只寫模式。close()
:關(guān)閉打開的文件。is_open()
:檢查文件是否已經(jīng)成功打開。put(char c)
:將字符寫入文件。write(const char* buffer, streamsize count)
:將指定數(shù)量的字節(jié)寫入文件。operator<<
:用于將各種數(shù)據(jù)類型寫入文件,例如int
、double
等。
fstream
(文件流):
fstream
類可用于既可以讀取又可以寫入文件的情況。- 它繼承了
ifstream
和ofstream
的所有成員函數(shù),因此可以用于打開、讀取和寫入文件。
以下是一些常見的文件打開模式:
- ios::in:
- 打開文件以供讀取。可以使用
ifstream
類或fstream
類來讀取文件內(nèi)容。
- 打開文件以供讀取。可以使用
- ios::out:
- 打開文件以供寫入??梢允褂?code>ofstream類或
fstream
類來寫入文件內(nèi)容。如果文件不存在,則會創(chuàng)建一個新文件;如果文件已存在,則會截斷(清空)文件內(nèi)容。
- 打開文件以供寫入??梢允褂?code>ofstream類或
- ios::app:
- 打開文件以供追加寫入。新數(shù)據(jù)將被添加到文件的末尾,而不會截斷文件內(nèi)容。如果文件不存在,則會創(chuàng)建一個新文件。
- ios::binary:
- 以二進制模式打開文件。這個模式用于處理二進制文件,如圖像、音頻或其他非文本文件。在二進制模式下,不會執(zhí)行文本的自動換行和轉(zhuǎn)換。
- ios::ate:
- 打開文件后,將文件指針移到文件的末尾。這可以讓你立即開始讀取或?qū)懭胛募哪┪膊糠帧?/li>
- ios::trunc:
- 如果文件已存在,在打開文件時會截斷(清空)文件內(nèi)容。通常與
ios::out
一起使用,以確保文件被清空后寫入新數(shù)據(jù)。
- 如果文件已存在,在打開文件時會截斷(清空)文件內(nèi)容。通常與
這些打開模式可以組合使用,通過按位或運算符|
來實現(xiàn)。例如,要以二進制追加寫入的方式打開文件,可以使用ios::binary | ios::app
。
代碼示例:
#include <iostream>
#include <fstream>
using namespace std;int main() {// 打開一個文本文件以供讀取ifstream inputFile("input.txt", ios::in);// 打開一個二進制文件以供寫入,如果不存在則創(chuàng)建ofstream binaryFile("output.bin", ios::out | ios::binary);// 打開一個文本文件以供追加寫入ofstream appendFile("log.txt", ios::out | ios::app);if (inputFile.is_open() && binaryFile.is_open() && appendFile.is_open()) {// 文件已成功打開,可以進行讀取和寫入操作// ...// 關(guān)閉文件inputFile.close();binaryFile.close();appendFile.close();} else {cout << "無法打開文件" << endl;}return 0;
}
控制文件指針位置
tellg
和seekg
是C++中用于在文件流對象中控制文件指針位置的函數(shù),通常與ifstream
和fstream
一起使用,用于讀取文件的特定位置或獲取當前文件指針的位置。
-
tellg
函數(shù):tellg
函數(shù)用于獲取當前文件指針的位置(讀取位置)。它返回一個類型為streampos
的值,表示當前文件指針的位置。streampos
通常是一個整數(shù)類型,用于表示文件的字節(jié)偏移量。用法示例:
ifstream inputFile("example.txt", ios::in);if (inputFile.is_open()) {// 獲取當前文件指針的位置streampos currentPosition = inputFile.tellg();cout << "當前文件指針位置:" << currentPosition << endl;// 讀取文件內(nèi)容// ...// 獲取新的文件指針位置currentPosition = inputFile.tellg();cout << "新的文件指針位置:" << currentPosition << endl; }
-
seekg
函數(shù):seekg
函數(shù)用于設置文件指針的位置,以便在文件中進行定位。它允許你將文件指針移動到文件的特定位置,以便讀取或?qū)懭霐?shù)據(jù)。seekg
接受兩個參數(shù),第一個參數(shù)是偏移量,第二個參數(shù)是基準位置,用于確定偏移量是相對于文件的開頭、當前位置還是文件的末尾。基準位置可以是以下之一:
ios::beg
:基于文件的開頭。ios::cur
:基于當前文件指針位置。ios::end
:基于文件的末尾。
用法示例:
ifstream inputFile("example.txt", ios::in);if (inputFile.is_open()) {// 將文件指針移動到文件的第10個字節(jié)(相對于文件開頭)inputFile.seekg(10, ios::beg);// 讀取從第10個字節(jié)開始的內(nèi)容string data;inputFile >> data;cout << "從第10個字節(jié)開始的內(nèi)容:" << data << endl;// 將文件指針移動到文件末尾inputFile.seekg(0, ios::end);// 獲取文件末尾的位置streampos endPosition = inputFile.tellg();cout << "文件末尾位置:" << endPosition << endl; }
文件操作示例
以二進制的形式操作文件
以二進制的形式對文件進行寫入操作:
//以二進制的形式對文件進行寫入
void WriteBinary(){ofstream ofile; //定義文件流對象ofile.open("test.bin", ofstream::out | ofstream::binary); //以二進制寫入的方式打開test.bin文件char data[] = "Hello World";ofile.write(data, strlen(data)); //將data字符串寫入文件ofile.put('!'); //將字符'!'寫入文件ofile.close(); //關(guān)閉文件
}
以二進制的形式對文件進行讀取操作:
//以二進制的形式對文件進行讀取
void ReadBinary(){ifstream ifile; //定義文件流對象ifile.open("test.bin", ofstream::in | ofstream::binary); //以二進制讀取的方式打開test.bin文件ifile.seekg(0, ifile.end); //跳轉(zhuǎn)到文件末尾int length = ifile.tellg(); //獲取當前字符在文件當中的位置,即文件的字符總數(shù)ifile.seekg(0, ifile.beg); //重新回到文件開頭char data[100];ifile.read(data, length); //將文件當中的數(shù)據(jù)全部讀取到字符串data當中ifile.close(); //關(guān)閉文件
}
以文本的形式操作文件
以文本的形式對文件進行寫入操作:
//以文本的形式對文件進行寫入
void WriteTxt(){ofstream ofile; //定義文件流對象ofile.open("test.txt"); //以寫入的方式打開test.txt文件char data[] = "Hello World";ofile.write(data, strlen(data)); //將data字符串寫入文件ofile.put('!'); //將字符'!'寫入文件ofile.close(); //關(guān)閉文件
}
以文本的形式對文件進行讀取操作:
//以文本的形式對文件進行讀取
void ReadTxt(){ifstream ifile; //定義文件流對象ifile.open("test.txt"); //以讀取的方式打開test.txt文件ifile.seekg(0, ifile.end); //跳轉(zhuǎn)到文件末尾int length = ifile.tellg(); //獲取當前字符在文件當中的位置,即文件的字符總數(shù)ifile.seekg(0, ifile.beg); //重新回到文件開頭char data[100];ifile.read(data, length); //將文件當中的數(shù)據(jù)全部讀取到字符串data當中cout << length << endl;cout << data << endl;ifile.close(); //關(guān)閉文件
}
注意: 使用ofstream類對象的open函數(shù)時,若不指定打開方式,則默認以寫的方式打開文件;使用ifstream類對象的open函數(shù)時,若不指定打開方式,則默認以讀的方式打開文件;使用fstream類對象的open函數(shù)時,若不指定打開方式,則默認以寫+讀的方式打開文件。
使用>>和<<對文件進行操作
使用>>和<<運算符對文件進行讀寫操作,會變得很簡單,也很形象。
對文件進行寫入操作:
//對文件進行寫入操作
void WriteFile(){ofstream ofs("data.txt"); //定義文件流對象,并打開文件ofs << "Hello World"; //字符串“流入”文件ofs.close(); //關(guān)閉文件
}
對文件進行讀取操作:
//對文件進行讀取操作
void ReadFile(){ifstream ifs("data.txt"); //定義文件流對象,并打開文件char data[100];ifs >> data; //文件數(shù)據(jù)“流入”字符串dataifs.close(); //關(guān)閉文件
}
stringstream流
在C語言中,我們?nèi)羰窍胍獙⒁粋€整型變量的數(shù)據(jù)轉(zhuǎn)化為字符串格式,有以下兩種方法:
1、使用itoa函數(shù)進行轉(zhuǎn)化。
int a = 10;
char arr[10];
itoa(a, arr, 10); //將整型的a轉(zhuǎn)化為十進制字符數(shù)字存儲在字符串a(chǎn)rr當中
2、使用sprintf函數(shù)進行轉(zhuǎn)化。
int a = 10;
char arr[10];
sprintf(arr, "%d", a); //將整型的a轉(zhuǎn)化為字符串格式存儲在字符串a(chǎn)rr當中
雖然itoa函數(shù)和sprintf函數(shù)都能完成轉(zhuǎn)化,但是在兩個函數(shù)在轉(zhuǎn)化時,都需要先給出保存結(jié)果的空間,而空間的大小是不太好界定的,除此之外,轉(zhuǎn)化格式不匹配時,可能還會得到錯誤的結(jié)果甚至程序崩潰。
在C++中,我們可以使用stringstream類對象來避開此問題。在程序當中如果想要使用stringstream,必須要包含頭文件sstream。在該頭文件下,有三個類:
類 | 對應操作場景 |
---|---|
ostringstream | 輸出操作 |
istringstream | 輸入操作 |
stringstream | 輸入操作+輸出操作 |
以下是stringstream
的一些常用接口:
1、stringstream
的構(gòu)造函數(shù):
stringstream()
:創(chuàng)建一個空的字符串流。
stringstream(std::string str)
:使用給定的字符串 str
初始化字符串流。
2、插入數(shù)據(jù)到字符串流:
<<
操作符:插入數(shù)據(jù)到字符串流中。你可以使用它來插入各種數(shù)據(jù)類型,如整數(shù)、浮點數(shù)、字符串等。
std::stringstream ss;
int num = 42;
ss << "The answer is: " << num;
3、從字符串流中提取數(shù)據(jù):
>>
操作符:從字符串流中提取數(shù)據(jù)。你可以使用它來提取數(shù)據(jù)到不同的數(shù)據(jù)類型。
int extractedNum;
ss >> extractedNum;
4、獲取字符串流中的字符串:
str()
函數(shù):獲取字符串流中的全部內(nèi)容作為一個字符串。
std::string content = ss.str();
5、清空字符串流:
clear()
函數(shù):清空字符串流的狀態(tài)和內(nèi)容。
ss.clear();
6、指定基數(shù)(進制):
std::hex
、std::oct
、std::dec
:可以使用這些流控制器來指定插入或提取整數(shù)時的進制,如十六進制、八進制或十進制。
int num = 255;
ss << std::hex << num; // 將 num 以十六進制插入
7、獲取當前位置:
tellg()
函數(shù):獲取當前的讀取位置。
std::streampos pos = ss.tellg();
8、設置讀取位置:
seekg(std::streampos pos)
:將讀取位置設置為指定的位置。
ss.seekg(0); // 設置讀取位置為開頭
stringstream流操作示例
1、將數(shù)值類型數(shù)據(jù)格式化為字符串。
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
int main(){int a = 10;string sa;stringstream s;s << a; //將int類型的a放入輸入流s >> sa; //從s中抽取前面插入的int類型的值,賦值給string類型(方式一)cout << sa << endl;s.str(""); //將stringstream底層管理的string對象設置為""。s.clear(); //將上次轉(zhuǎn)換狀態(tài)清空掉//進行下一次轉(zhuǎn)換double b = 3.14;s << b;sa = s.str(); //獲取stringstream中管理的string類型(方式二)cout << sa << endl;return 0;
}
2、字符串拼接。
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
int main(){string rets;stringstream s;s << "Hello" << "World"; //將多個字符串放入stringstream中s >> rets; //方式一獲取cout << rets << endl;s.str(""); //將stringstream底層管理的string對象設置為空字符串s.clear(); //將上次轉(zhuǎn)換狀態(tài)清空掉s << "Thanks" << " " << "for" << " " << "reading"; //將多個字符串放入stringstream中rets = s.str(); //方式二獲取cout << rets << endl;return 0;
}
注意事項:
- stringstream實際是在底層維護了一個string類型的對象用來保存結(jié)果。
- stringstream在轉(zhuǎn)換結(jié)尾時(即最后一個轉(zhuǎn)換后),會將其內(nèi)部狀態(tài)設置為badbit,因此在下一次轉(zhuǎn)換前必須調(diào)用clear將狀態(tài)重置為goodbit才可以轉(zhuǎn)換,但clear不會將stringstream底層的string對象清空。
- 可以使用s.str(“”)的方式將stringstream底層的string對象設置為空字符串,否則多次轉(zhuǎn)換時,會將結(jié)果全部累積在底層string對象中。
- 獲取stringstream轉(zhuǎn)換后的結(jié)果有兩個方法,一是使用>>運算符之間從流當中提取,二是使用s.str( )獲取stringstream底層的string對象。
- stringstream使用string類對象代替字符數(shù)組,可以避免緩沖區(qū)溢出的危險,而且其會對參數(shù)類型進行推演,不需要格式化控制,也不會存在格式化失敗的風險,因此使用更方便,更安全。