什么是輸入輸出流
????????C++ 的輸入輸出操作是通過 流(stream) 機制實現的。
? ? ? ? 使用cin和cout
#include <iostream>
using namespace std;
int main()
{string name;int age;cout << "請輸入你的名字:";cin >> name;cout << "請輸入你的年齡:";cin >> age;cout << "你好," << name << ",你今年 " << age << " 歲。" << endl;return 0;
}
? ? ? ? 需要解釋的建議轉專業;
? ? ? ? 注意:
????????cin >> 是以空格為分隔符,遇空格就停止。
????????文件的輸入和輸出:ifstream/ofstream
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
// 寫入文件ofstream fout("data.txt");fout << "Hello, file!" << endl;fout << "C++ 文件操作示例" << endl;fout.close();
// 讀取文件ifstream fin("data.txt");string line;while (getline(fin, line)){cout << "讀到: " << line << endl;}fin.close();return 0;
}
? ? ? ? 文件寫入操作
// 寫入文件
ofstream fout("data.txt");
fout << "Hello, file!" << endl;
fout << "C++ 文件操作示例" << endl;
fout.close();
????????ofstream fout("data.txt");
:創建一個?ofstream
?對象?fout
,并且將其與文件?data.txt
?關聯起來。ofstream
?用于向文件寫入數據。若文件不存在,會創建該文件;若文件已存在,會清空原有內容。
??fout << "Hello, file!" << endl;
?和?fout << "C++ 文件操作示例" << endl;
:向文件?data.txt
?寫入兩行內容,endl
?用于換行。
??fout.close();
:關閉文件,釋放與文件關聯的資源。
? ? ? ? 文件讀取操作
// 讀取文件
ifstream fin("data.txt");
string line;
while (getline(fin, line))
{cout << "讀到: " << line << endl;
}
fin.close();
????????ifstream fin("data.txt");
:創建一個?ifstream
?對象?fin
,并將其與文件?data.txt
?關聯起來。ifstream
?用于從文件讀取數據。
??string line;
:定義一個?string
?類型的變量?line
,用于存儲從文件中讀取的每一行內容。
??while (getline(fin, line))
:使用?getline
?函數從文件中逐行讀取內容,每次讀取一行并存儲到?line
?變量中。getline
?函數在讀取到文件末尾時會返回?false
,循環結束。
??cout << "讀到: " << line << endl;
:將讀取到的每一行內容輸出到控制臺。
??fin.close();
:關閉文件,釋放與文件關聯的資源。
? ? ? ? 注:在 C++ 里,使用?ofstream
?或 ifstream 創建對象時不指定文件打開方式是可行的。
????????ofstream
?默認的打開方式
????????使用?ofstream
?類創建對象并關聯文件,卻不明確指定打開方式時,ofstream
?會采用默認的打開方式。默認情況下,ofstream
?以?ios::out | ios::trunc
?模式打開文件。
????????ios::out
:表明以輸出模式打開文件,也就是用于向文件寫入數據。
??ios::trunc
:意味著如果文件已經存在,會先把文件內容清空,再進行寫入操作;若文件不存在,則會創建該文件。
????????手動指定打開方式
????????若有特殊需求,也能手動指定文件的打開方式。ofstream
?類的構造函數可以接收第二個參數,用于指定打開方式。
????????字符串流:stringstream
#include <iostream>
#include <sstream>
using namespace std;
int main()
{string input = "42 3.14 hello";stringstream ss(input);int i;double d;string s;ss >> i >> d >> s;cout << "Integer: " << i << ", Float: " << d << ", String: " << s << endl;return 0;
}
? ? ? ? 頭文件
#include <iostream>
#include <sstream>
????????#include <sstream>
:該頭文件引入了?stringstream
?類,stringstream
?類能夠將字符串當作流來處理,可進行字符串的輸入和輸出操作。
????????定義輸入字符串并創建?stringstream
?對象
string input = "42 3.14 hello";
stringstream ss(input);
????????string input = "42 3.14 hello";?
:定義了一個字符串?input
,其中包含一個整數、一個浮點數和一個字符串,它們之間用空格分隔。
??stringstream ss(input);?
:創建了一個?stringstream
?對象?ss
,并將字符串?input
?作為初始內容。這樣?ss
?就可以像處理輸入流一樣處理這個字符串。
????????定義變量并從?stringstream
?中提取數據
int i;
double d;
string s;
ss >> i >> d >> s;
????????int i;
、double d;
?和?string s;
:分別定義了一個整數變量?i
、一個雙精度浮點數變量?d
?和一個字符串變量?s
,用于存儲從?stringstream
?中提取的數據。
??ss >> i >> d >> s;
:使用?>>
?運算符從?stringstream
?對象?ss
?中依次提取數據,并將其存儲到對應的變量中。>>
?運算符會根據變量的類型自動進行類型轉換。在這個例子中,它會先將字符串中的第一個整數?"42"
?轉換為整數類型并存儲到?i
?中,接著將第二個浮點數?"3.14"
?轉換為雙精度浮點數類型并存儲到?d
?中,最后將剩余的字符串?"hello"
?存儲到?s
?中。
????????i
、d
、s
?的順序不是絕對不能換,交換順序后,代碼的執行結果會依賴于?stringstream
?對象?ss
?中存儲的字符串內容。如果字符串內容的順序與變量類型的提取順序不匹配,就可能導致提取失敗或者得到不符合預期的結果。
? ? ? ? 注:
????????stringstream
?類的介紹
????????stringstream
?是 C++ 標準庫?<sstream>
?頭文件中定義的類,它繼承自?iostream
?類,結合了?istream
(輸入流)和?ostream
(輸出流)的功能,允許你像操作文件流或標準輸入輸出流一樣操作字符串。stringstream
?主要有以下三個子類:
????????istringstream
:用于從字符串中讀取數據,相當于輸入流。
??ostringstream
:用于向字符串中寫入數據,相當于輸出流。
??stringstream
:既可以讀取也可以寫入字符串,兼具前兩者的功能。
????????stringstream
?對象的初始化
????????stringstream
?對象不一定要接受一個?string
?類對象來初始化。
????????使用?string
?對象初始化
#include <iostream>
#include <sstream>
#include <string>int main() {std::string input = "42 3.14 hello";std::stringstream ss(input);return 0;
}
????????stringstream
?對象?ss
?被初始化為包含字符串?"42 3.14 hello"
。
????????默認初始化
#include <iostream>
#include <sstream>int main() {std::stringstream ss;ss << "This is a test";return 0;
}
????????這里先默認初始化了?stringstream
?對象?ss
,之后可以使用?<<
?運算符向其寫入數據。
????????>>
?運算符能從?stringstream
?對象中提取對應類型數據的原理
????????>>
?運算符是 C++ 中用于輸入流操作的提取運算符。當它用于?stringstream
?對象時,其工作原理基于 C++ 的流操作和類型轉換機制。
????????流操作
????????stringstream
?是一個流對象,>>
?運算符會從流中讀取數據。它會按照空格、制表符或換行符等空白字符來分割流中的內容,每次提取一個 “詞”(token)。
? ? ? ? 類型轉換
????????當?>>
?運算符遇到不同類型的變量時,會嘗試將讀取到的字符串數據轉換為該變量的類型。這是通過 C++ 的流庫中預定義的類型轉換函數實現的。
????????整數類型:當目標變量是整數類型(如?int
)時,>>
?運算符會嘗試將讀取到的字符串轉換為整數。如果字符串包含有效的整數字符序列,就會成功轉換;否則會導致流狀態錯誤。
#include <iostream>
#include <sstream>int main() {std::string input = "42";std::stringstream ss(input);int num;ss >> num;std::cout << "Integer: " << num << std::endl;return 0;
}
????????>>
?運算符將字符串?"42"
?轉換為整數?42
?并存儲到?num
?中。
? ? ? ? 浮點數和它一樣操作;
????????
- 字符串類型:當目標變量是?
std::string
?類型時,>>
?運算符會讀取直到遇到下一個空白字符為止的字符串。#include <iostream> #include <sstream> #include <string>int main() {std::string input = "hello world";std::stringstream ss(input);std::string word;ss >> word;std::cout << "String: " << word << std::endl;return 0;//僅僅輸出“hello” }
????????
>>
?運算符讀取到?"hello"
?就停止了,因為遇到了空格,所以?word
?被賦值為?"hello"
。
? ? ? ? I/O常見技巧:
? ? ? ? 讀取整行:? ? ? ? ? ? ? getline(cin,str)
? ? ? ? 清除輸入緩沖:? ? ? ?cin.ignore()或 cin.clear()
? ? ? ? 判斷文件是否打開:fin.is_open()
? ? ? ? 檢查流狀態:? ? ? ? ? ?cin.fail()、fin.eof()
? ? ? ? 小結
? ? ? ? 標準流(cin,cout,cerr):控制臺輸入輸出
? ? ? ? 文件流(ifstream/ofstream/fstream):文件讀寫
? ? ? ? 字符串流(stringstream):字符串格式轉換
????????流格式控制:設置小數位、對齊等
????????C++ 使用 <iomanip> 頭文件提供了一系列 格式控制操作符。
? ? ? ? 常見格式控制符:(省略std::)
? ? ? ? fixed:使用固定小數位表示法
? ? ? ? scientific:科學計數法
? ? ? ? setprecision(n):設置小數位保留精度
? ? ? ? setw(n):設置輸出字符串寬度
? ? ? ? left/right/internal:設置對齊方式
? ? ? ? setfill(c):設置填充字符
? ? ? ? showpos:顯示正號(+)
? ? ? ? 格式化數字輸出
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{double pi = 3.141592653;cout << "Default Output: " << pi << endl;cout << fixed << setprecision(3);cout << "Round to 3 decimal places: " << pi << endl;cout << setw(10) << right << setfill('*') << 42 << endl;// 右對齊,寬度 10,用 * 填充return 0;
}
? ? ? ? 輸出保留三位小數的pi值
cout << fixed << setprecision(3);
cout << "Round to 3 decimal places: " << pi << endl;
????????cout << fixed << setprecision(3);
????????fixed
?是一個操縱符,它會讓浮點數以固定點表示法輸出,也就是小數點后的位數固定。
??setprecision(3)
?同樣是一個操縱符,它指定了輸出浮點數時小數點后的位數為 3。這兩個操縱符結合使用,就能讓后續輸出的浮點數保留三位小數。
????????右對齊輸出整數并填充字符
cout << setw(10) << right << setfill('*') << 42 << endl;
????????setw(10)
:這是一個操縱符,它設置了下一個輸出項的寬度為 10 個字符。如果輸出項的實際寬度小于 10 個字符,就會按照指定的填充字符進行填充。
??right
:這是一個操縱符,它指定輸出項右對齊。
??setfill('*')
:這是一個操縱符,它指定了填充字符為?*
。
??42
?是要輸出的整數。綜合起來,這段代碼會以右對齊的方式輸出整數?42
,寬度為 10 個字符,不足的部分用?*
?填充,輸出結果為?********42
。
????????中文字符流(UTF-8 / 寬字符)
????????中文字符通常需要用 寬字符(wchar_t)+ 寬流(wcout/wcin) 或確保控制臺支持 UTF-
8 編碼。
????????寬字符流輸出中文(Windows 下推薦)
#include <iostream>
#include <locale>
using namespace std;
int main()
{
// 設置全局 locale,使 wcout 能輸出中文
//(Windows 使用 "chs" 或 "zh_CN.UTF-8")locale::global(locale(""));wcout << L"Hello, World" << endl;return 0;
}
? ? ? ? 頭文件
#include <iostream>
#include <locale>
????????#include <iostream>
:這是標準輸入輸出流的頭文件,借助它可以使用?cout
、wcout
、cin
?等標準輸入輸出對象。
? ?#include <locale>
:該頭文件提供了處理區域設置的功能,能讓程序適配不同地區的語言、貨幣、日期格式等。
? ? ? ? 設置全局區域設置
locale::global(locale(""));
????????locale::global
?函數用于設置全局的區域設置。
??locale("")
?代表使用系統默認的區域設置。在 Windows 系統中,這可能會使用 "chs" 或者 "zh_CN.UTF - 8",從而確保程序能正確處理中文等寬字符。
? ? ? ? 輸出寬字符字符串
wcout << L"Hello, World" << endl;
????????wcout
?是用于輸出寬字符的標準輸出流對象。
? ?L"Hello, World"
?是寬字符字符串,以?L
?作為前綴,表明其中的每個字符是寬字符類型(通常是?wchar_t
)。
????????封裝文件讀寫成類
????????將文件 I/O 封裝成類能提升代碼復用性與清晰度,特別適合數據處理類。????????
????????封裝為 FileManager 類
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
class FileManager
{
public:FileManager(const string& fname) : filename(fname) {}void writeLine(const string& text){ofstream fout(filename, ios::app); // 追加寫入if (fout.is_open()){fout << text << endl;fout.close();}else{cerr << "無法打開文件用于寫入!" << endl;}}void readAll() const{ifstream fin(filename);if (fin.is_open()){string line;while (getline(fin, line)){cout << "讀到: " << line << endl;}fin.close();}else{cerr << "無法打開文件用于讀取!" << endl;}}
private:string filename;
};
int main()
{FileManager file("data.txt");file.writeLine("你好,文件!");file.writeLine("C++ 文件封裝測試。");file.readAll();return 0;
}
????????writeLine
?方法
void writeLine(const string& text)
{ofstream fout(filename, ios::app); // 追加寫入if (fout.is_open()){fout << text << endl;fout.close();}else{cerr << "無法打開文件用于寫入!" << endl;}
}
- 功能:該方法用于向文件中追加一行文本。
- 實現步驟:
- 創建一個?
ofstream
?對象?fout
,并以追加模式(ios::app
)打開指定的文件。 - 檢查文件是否成功打開,如果成功,則將傳入的文本?
text
?寫入文件,并在末尾添加換行符?endl
。 - 關閉文件流。
- 如果文件無法打開,則使用?
cerr
?輸出錯誤信息(這里也可以換成cout,但cerr本身就是專門用來輸出錯誤信息的。
- 創建一個?
? ? ? ? readall方法
void readAll() const
{ifstream fin(filename);//上面那一步就等同于://ifstream fin;//fin.open(filename);//省略掉了使用open()函數if (fin.is_open()){string line;while (getline(fin, line)){cout << "讀到: " << line << endl;}fin.close();}else{cerr << "無法打開文件用于讀取!" << endl;}
}
- 功能:該方法用于讀取文件中的所有行,并將每行內容輸出到控制臺。
- 實現步驟:
- 創建一個?
ifstream
?對象?fin
,并打開指定的文件。 - 檢查文件是否成功打開,如果成功,則使用?
getline
?函數逐行讀取文件內容,直到文件結束。 - 對于每一行,將其輸出到控制臺,并在前面加上提示信息 “讀到:”。
- 關閉文件流。
- 如果文件無法打開,則使用?
cerr
?輸出錯誤信息。
- 創建一個?
注:
? ? ? ? cerr和cout的區別
? ? ? ? 緩沖機制
cout
:cout
?是帶有緩沖的輸出流。這意味著當你向?cout
?輸出數據時,數據會先被存儲在緩沖區里,等緩沖區滿了或者遇到特定的刷新條件(像遇到?endl
、調用?flush()
?函數或程序結束return 0 的時候直接刷新等),才會將數據輸出到對應的設備(一般是控制臺)。cerr
:cerr
?是無緩沖的輸出流。一旦你向?cerr
?輸出數據,數據會立刻被輸出到對應的設備,不會進行緩沖。這種特性使得?cerr
?適合用于輸出錯誤信息,因為在程序出錯時,你希望錯誤信息能馬上顯示出來,而不是等到緩沖區滿了才顯示。
? ? ? ? 用途
cout
:通常用于輸出程序的正常運行結果。比如在計算并輸出一些數據、顯示提示信息等場景下使用。cerr
:專門用于輸出程序運行過程中出現的錯誤信息。使用?cerr
?可以讓錯誤信息和正常輸出區分開來,方便調試和監控程序。
? ? ? ? 輸出目標
cout
:默認情況下,cout
?的輸出目標是標準輸出設備,一般是控制臺。不過,你可以通過重定向操作將其輸出到文件或者其他設備。cerr
:默認情況下,cerr
?的輸出目標是標準錯誤輸出設備,同樣通常是控制臺。和?cout
?不同的是,cerr
?的輸出不會被重定向操作影響,它始終會輸出到標準錯誤輸出設備,這樣能確保錯誤信息不會被誤重定向到其他地方。
? ? ? ? 小結
? ? ? ? 技術點:核心語法/類? ? ? ?場景
? ? ? ? 格式流控制:<iomanip>? ? 小數精度、對齊、美觀輸出
? ? ? ? 中文字符流:wcout,L"",locale? 終端/日志中正確輸出中文
? ? ? ? 文件操作封裝:自定義類+ifstream/ofstream? 實現面向對象的數據存取方式
????????stringstream 實現類型轉換、如何讀寫二進制文件 (ios::binary)
????????使用 stringstream 實現類型轉換
????????stringstream 是一個靈活的字符串流工具,能像輸入輸出流一樣操作字符串。
????????當你創建一個?stringstream
?對象后,就可以使用?<<
?運算符向這個對象里插入數據,也能使用?>>
?運算符從這個對象中提取數據。
stringstream
?類,它能讓你像操作標準輸入輸出流(如? cin
?和? cout
)一樣對字符串進行操作,從而 實現字符串和其他數據類型之間的轉換 。?
????????字符串 ? 數字轉換
#include <iostream>
#include <sstream>
using namespace std;
int main()
{string str = "42.5";double num;stringstream ss(str);ss >> num;cout << "字符串轉數字: " << num << endl;int i = 100;stringstream ss2;ss2 << i;string s = ss2.str();cout << "數字轉字符串: " << s << endl;return 0;
}
????????字符串轉數字
string str = "42.5";
double num;
stringstream ss(str);
ss >> num;
cout << "字符串轉數字: " << num << endl;
stringstream
?對象創建與初始化:stringstream ss(str);
:創建一個?stringstream
?對象?ss
,并使用字符串?str
?對其進行初始化。這意味著?ss
?中包含了字符串?"42.5"
(這種類似構造函數的初始化只能是字符串類型,不能是int、double等類型,沒有對應的構造函數)。
- 字符串轉換為數字:
ss >> num;
:使用輸入運算符?>>
?從?stringstream
?對象?ss
?中讀取數據,并嘗試將其轉換為?double
?類型,然后存儲到變量?num
?中。這里?"42.5"
?被成功轉換為?42.5(注意必須用stringstream類型的對象來轉化為其他類型的對象,不能直接轉化,必須用stringstream當跳板)
。
????????數字轉字符串
int i = 100;
stringstream ss2;
ss2 << i;
string s = ss2.str();
cout << "數字轉字符串: " << s << endl;
stringstream
?對象創建:stringstream ss2;
:創建一個空的?stringstream
?對象?ss2
。(這是因為stringstream類型的對象不能直接被int類型初始化,沒有這個構造函數,必須分成兩步)
- 數字寫入?
stringstream
?對象:ss2 << i;
:使用輸出運算符?<<
?將整數?i
?的值寫入?stringstream
?對象?ss2
?中。此時?ss2
?中存儲了表示?100
?的字符串。
?- 使用?
<<
?運算符將一個?int
?類型的變量?i
(這里?i
?的值為 100)插入到?stringstream
?對象?ss2
?中時,100
?會以字符串的形式存儲在?ss2
?里。
- 獲取?
stringstream
?中的字符串:string s = ss2.str();
:調用?str()
?方法從?stringstream
?對象?ss2
?中獲取存儲的字符串,并將其賦值給字符串變量?s
。
? ? ? ? 注:
????????str()
?方法的功能
????????stringstream
?類提供了一個名為?str()
?的成員函數,其作用是獲取?stringstream
?對象當前存儲的字符串內容。這個方法返回一個?std::string
?類型的對象,該對象包含了?stringstream
?中存儲的所有字符。
????????string s = ss2.str();
?的執行過程
- 調用?
ss2.str()
:ss2
?是?stringstream
?對象,調用它的?str()
?方法,會返回一個?std::string
?對象,這個對象包含了?ss2
?中當前存儲的字符串?"100"
(100以字符串的形式被存儲)。 - 賦值操作:把?
ss2.str()
?返回的?std::string
?對象賦值給字符串變量?s
。經過這一步,變量?s
?就存儲了?"100"
?這個字符串。
????????讀寫二進制文件 (ios::binary)
#include <iostream>
#include <fstream>
using namespace std;
struct Person
{char name[20];int age;
};
int main()
{
// 寫入ofstream fout("people.dat", ios::binary);Person p1 = {"Alice", 25};Person p2 = {"Bob", 30};fout.write(reinterpret_cast<char*>(&p1), sizeof(p1));fout.write(reinterpret_cast<char*>(&p2), sizeof(p2));fout.close();
// 讀取ifstream fin("people.dat", ios::binary);Person p;while (fin.read(reinterpret_cast<char*>(&p), sizeof(p))){cout << "Name: " << p.name << ", Age: " << p.age << endl;}fin.close();return 0;
}
????????寫入部分
ofstream fout("people.dat", ios::binary);
Person p1 = {"Alice", 25};
Person p2 = {"Bob", 30};
fout.write(reinterpret_cast<char*>(&p1), sizeof(p1));
fout.write(reinterpret_cast<char*>(&p2), sizeof(p2));
fout.close();
? ? ? ? ios::binary:是一個文件打開模式標志,表示以二進制模式打開文件。在二進制模式下,數據會以字節形式直接寫入文件,不進行額外的字符轉換(如換行符轉換),這對于存儲結構體等二進制數據非常重要。
fout.write(reinterpret_cast<char*>(&p1), sizeof(p1));
fout.write(reinterpret_cast<char*>(&p2), sizeof(p2));
fout.write()
?是?ofstream
?類的成員函數,用于將指定數量的字節寫入文件。reinterpret_cast<char*>(&p1)
?和?reinterpret_cast<char*>(&p2)
:&p1
?和?&p2
?分別是?p1
?和?p2
?結構體對象的地址。reinterpret_cast<char*>
?是 C++ 中的強制類型轉換操作符,它將結構體對象的地址轉換為?char*
?類型。這是因為?write
?函數要求第一個參數是?char*
?類型的指針,指向要寫入的數據的起始地址。
sizeof(p1)
?和?sizeof(p2)
:sizeof
?是 C++ 的一個操作符,用于獲取對象或類型所占用的字節數(這里是對象,不是地址)。這里?sizeof(p1)
?和?sizeof(p2)
?分別表示?p1
?和?p2
?結構體對象的大小,即要寫入文件的字節數。
????????讀取部分
ifstream fin("people.dat", ios::binary);
Person p;
while (fin.read(reinterpret_cast<char*>(&p), sizeof(p)))
{cout << "Name: " << p.name << ", Age: " << p.age << endl;
}
fin.close();
????????定義一個?Person
?結構體的對象?p
,用于存儲從文件中讀取的數據。
while (fin.read(reinterpret_cast<char*>(&p), sizeof(p)))
{cout << "Name: " << p.name << ", Age: " << p.age << endl;
}
fin.read()
?是?ifstream
?類的成員函數,用于從文件中讀取指定數量的字節到指定的內存地址。reinterpret_cast<char*>(&p)
:將?p
?結構體對象的地址轉換為?char*
?類型,作為?read
?函數的第一個參數,表示讀取的數據要存儲的起始地址。sizeof(p)
:表示要從文件中讀取的字節數,即一個?Person
?結構體對象的大小。while (fin.read(...))
:read
?函數在成功讀取指定數量的字節時返回?fin
?對象本身,在布爾上下文中,fin
?對象會被轉換為?bool
?類型,如果讀取成功則為?true
,如果遇到文件結束符(EOF)或讀取錯誤則為?false
。因此,這個?while
?循環會不斷讀取文件,直到文件結束。- 在循環體中,使用?
cout
?輸出從文件中讀取的?p
?結構體對象的?name
?和?age
?成員。
注:
????????結構體的內存布局
????????Person
?結構體的定義如下:
struct Person
{char name[20];int age;
};
????????在內存中,結構體的成員是連續存儲的。name
?數組占據前 20 個字節,age
?這個?int
?類型的成員接著存儲在?name
?之后,一般?int
?類型在常見的系統上占 4 個字節。所以,Person
?結構體的總大小(sizeof(Person)
)通常是 24 個字節(20 字節的?name
?數組加上 4 字節的?age
)。
????????數據讀取過程
Person p;
while (fin.read(reinterpret_cast<char*>(&p), sizeof(p)))
{cout << "Name: " << p.name << ", Age: " << p.age << endl;
}
- 定義一個?
Person
?結構體的對象?p
,用于存儲從文件中讀取的數據,讀出來的數據就存儲在了這個定義的p中。 reinterpret_cast<char*>(&p)
:把?p
?這個?Person
?結構體對象的地址強制轉換為?char*
?類型。這是因為?read
?函數要求第一個參數是?char*
?類型的指針,指向數據要存儲的起始地址。sizeof(p)
:確定要從文件中讀取的字節數,這里是?Person
?結構體的大小。read
?函數會從文件中讀取?sizeof(p)
?字節的數據,然后把這些數據依次存放到?p
?結構體對象的內存空間里。- 由于結構體成員在內存中是連續存儲的,文件中的前 20 個字節會被存到?
p.name
?數組中,接下來的 4 個字節會被存到?p.age
?中。這樣,文件中的二進制數據就和?p
?結構體的成員一一對應起來了。
小貼士
寫二進制:write(reinterpret_cast<char*>(&obj),sizeof(obj) )
讀二進制:read(reinterpret_cast<char*>(&obj),sizeof(obj))
必須用reinterpret_cast因為write/read操作的是char*指針
結構體對齊注意 :添加 #pragma pack(1) 或 alignas(1) 以避免字節填充問題
小結
std::stoi(str)、std::stod(str):字符串轉 int/double
#include <iostream>
#include <string>using namespace std;int main() {string intStr = "123";string doubleStr = "3.14";int num = stoi(intStr);double dNum = stod(doubleStr);cout << "字符串 \"" << intStr << "\" 轉 int 結果: " << num << endl;cout << "字符串 \"" << doubleStr << "\" 轉 double 結果: " << dNum << endl;return 0;
}
用法示例;