看板 C_and_CPP 關於我們 聯絡資訊
你可以先試試看下面的code會產生怎樣的output: #include <cstdio> struct foo { char str[8]; int val; }; int main() { std::FILE* in = std::fopen("/path/to/filename", "r"); foo f; std::fread(&f, sizeof(f), 1, in); std::printf("%c%c%c%c%c%c%c%c\n%d", f.str[0], f.str[1], f.str[2], f.str[3], f.str[4], f.str[5], f.str[6], f.str[7], f.val); std::fclose(in); return 0; } 其中讀取的檔案內容為"foobar 12345",在我的電腦上印出的結果是: foobar 1 892613426 在我的電腦上sizeof(foo)剛好是12,所以fread直接抓了12個bytes往foo塞, 其中前八個bytes剛好是"foobar 1",而"2345"的ascii值分別是0x32 0x33 0x34 0x35, 因為我的電腦是little endian,所以若將其解釋為int是0x35343332 = 892613426, 這其中牽涉到太多的細節,例如endianness和struct的alignment, 無論結果如何,結論就是這樣寫是不對的,更不用說還寫到一個std::string物件上... 正確的寫法應該是一個一個field去讀,你想要寫的東西應該是類似這樣的: #include <cstddef> #include <fstream> #include <string> struct foo { std::string str; double val; }; int main() { std::ifstream in("/path/to/filename"); foo f[20]; for (std::size_t i = 0; i < 20; ++i) { in >> f[i].str >> f[i].val; } return 0; } 關於std::ifstream的用法,相信你去翻任何C++的書上都會有教, in >> f[i].str; 實際上是overload operator>>, 左邊是一個std::istream,右邊是一個std::string, 會把檔案目前的位置到下一個delimiter(如空白或tab或換行)之間的內容存到右邊, 這部份standard library會自動幫你處理字串長度的問題,所以不用擔心, 若右邊是接double則為設法將讀到的內容解釋為數字存進該double, 不過要注意如果輸入的一行是類似這樣:"foo bar 42", 那就會出錯,因為f[i].str會讀到"foo",接著f[i].val讀到"bar"就炸裂了 希望這樣解釋對你有幫助 -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 114.25.210.26
Arim:喔喔~看來我誤解fread的行為了~謝謝大大的解釋 07/14 14:47