我正在使用以下函数将脚本拉入我的C应用程序:
char *anne_script_load(char fileName[]){
char path[6400] = "data/scripts/";
strncat(path, fileName, 6000);
strncat(path, ".lua", 5);
struct stat fileInfo;
char *contents = NULL;
FILE * pFile;
stat(path, &fileInfo);
contents = (char*)malloc(fileInfo.st_size);
pFile = fopen (path,"r");
fread (contents,1,fileInfo.st_size,pFile);
fclose(pFile);
printf("Script path: %s\n", path);
printf("Script loaded: %s\n", contents);
return contents;
}
在运行时,第二个printf
生成以下输出:
test script - if you see this load is working :) helicopters����
我的控制台上的乱码文本看起来不一样,但我不确定它是否重要:我的理论是文件流不以空字节结尾(它不作为ac string
存储在磁盘上,毕竟 - 所以我自己终止了如下:
contents[fileInfo.st_size] = 0;
这似乎有效,但我担心这个解决方案的稳健性。有没有更好的,普遍接受的做法?
答案 0 :(得分:3)
您需要在malloc中添加+1才能终止:
if(stat(path, &fileInfo) != 0) {
perror("stat");
...
}
contents = (char*)malloc(fileInfo.st_size + 1); // don't forget this
pFile = fopen (path,"r");
if(pFile == 0) {
perror("fopen");
...
}
int n = fread (contents,1,fileInfo.st_size,pFile);
if(n != fileInfo.st_size) {
perror("read");
...
}
contents[n] = 0; // terminate after what you read. Not what you think you read.
**检查fopen,stat和read的返回值。**
答案 1 :(得分:1)
这里有很多东西可以改进......但是为了回答你的问题,fread()将字节读入你没有初始化的数组中。在C中,你不能指望在通过fread读取的最后一个字节之后有一个\ 0字符 - 你必须先将它放在那里,或者使用memset()或calloc()。
此外,如果文件内容被视为文本字符串,请务必在大小上分配一个额外的字节来保存终止\ 0字符!
答案 2 :(得分:1)
你必须以字符串结尾,否则printf()
将无法确定何时停止从你刚刚传递的指针中读取。这同样适用于其他函数,例如strcmp()
,您可以使用两个具有相同内容的字符串,同时由于非空终止字符串而使strcmp()
大喊非零。
所以contents[fileInfo.st_size] = 0;
就好了。
您可以在Wikipedia
上阅读更多关于以空字符结尾的字符串的内容