推 Arim:喔喔~看來我誤解fread的行為了~謝謝大大的解釋 07/14 14:47
你可以先試試看下面的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