前几天写类linux文件系统的时候,被这个搞死了,今天终于弄懂了
这是cpp文件
#include <iostream>
#include <fstream>
#include <stdio.h>
#include <iomanip>
using namespace std;
char ch[250];
struct s{
short a, b;
};
int main(){
FILE *file = fopen("test.txt", "wt+");
s st;
st.a = 1, st.b = 2;
fseek(file, 0, 0);
fwrite(&st, sizeof(short), sizeof(st) / sizeof(short), file);
//fseek(file, 0, 0);
//fread(&st, sizeof(short), sizeof(st) / sizeof(short), file);
char temp[256] = "flaf";
int c = 0x11110011;
fseek(file, sizeof(st), 0); //加上这一句结果就不一样了
fprintf(file, "%s", temp);
//fputs(temp, file);
fwrite(&c, sizeof(int), 1, file);
fseek(file, sizeof(st), 0);
//fgets(temp, sizeof(temp), file);
fscanf(file, "%s", temp);
fread(&c, sizeof(int), 1, file);
cout << temp <<" "<< c << endl;
fclose(file);
system("pause");
return 0;
}
先在文件里面写了个结构体,然后写入一个字符串“flat",再写入一个ini型整数c
结果在读取字符串的时候,后面总是跟有乱码,而且整数c也总是有时读得对有时错,就像这样
这里有一个点很关键,可我一直都没意识到,字符串结束符\0其实在fprintf的时候是不会printf出来的,就像你在屏幕上看不到那个\0一样,fprintf只是把屏幕上的效果反映到文件里而已
而另一个点就是机器存储是大端序还是小端序的问题,我的CPU是Intel系列的,所以是小端序,即存储的时候低位在前,运行上面的那个程序,然后用HexEdit查看txt文件,将会是这样子
可以看到c = 0x11110011存储成了11 00 11 11,反过来了
所以这就是乱码的真相了:fscanf读取字符串的时候会一直读到 00 为止,所以上面输出的时候是flaf加一个乱码,后面的那个整数自然就成了无意义的数字了
要注意的是,如果换成fputs和fgets结果还是一样会乱码的,fputs、fgets和gets、puts的区别如下:
gets读取并丢弃换行符,puts会在最后添加换行符
fgets存储输入中的换行符,但相对应的,fputs并不会在最后添加换行符
最后还要注意的是:
如果在文件流中先读以后立即写,或者先写以后立即读,即不加上如fflush,fseek之类的操作,那么读(写)后面所有写(读)的操作都会失败
Over~