所以我想保存游戏中最好的3个分数并将它们放在一个文件中。但出于某种原因,当我阅读文件时,最好的分数是53,32,32。目前不使用名称,只有3个分数。而且我也不熟悉文件。
typedef struct score{
unsigned char score[3];
//char name[20];
} SCORES;
这就是我节省的方式。
void guardar_highscore (SCORES top){
FILE *f;
f = fopen ("/var/www/html/highscore3.txt","wb");
if (f ==NULL)
perror ("nope2"),exit (1);
fprintf(f,"%d \n %d \n %d \n",top.score[0],top.score[1],top.score[2]);
fclose(f);
}
这就是我在结构中读它的方式。
SCORES ler_highscore (){
SCORES top={0};
int i=0;
char line[20];
FILE *f;
f = fopen ("/var/www/html/highscore3.txt","rb");
if (f ==NULL)
perror ("nope"), exit (1);
while(fgets(line,20, f) != NULL){
sscanf (line, "%c", &top.score[i]);
i++;
}
fclose(f);
return top;
}
答案 0 :(得分:2)
typedef struct score{
unsigned char score[3];
//char name[20];
} SCORES;
分数通常是数字,因此将它们存储为单个字符并没有多大意义。当你注意到你把它们写成整数(并且有一个额外的空格)时,问题就变得清晰了......
fprintf(f,"%d \n %d \n %d \n",top.score[0],top.score[1],top.score[2]);
但是你要把它们当成字符......
sscanf (line, "%c", &top.score[i]);
53,32,32看起来很像5
和两个空格的ASCII数字。如果您将字符5
写为数字,那么您将获得53.因为字符5
是数字53.请查看the ASCII table了解原因。
解决方案是始终如一地使用整数。
typedef struct {
int score[3];
} Scores;
请注意,ALL_CAPS
通常保留给常量,而不是类型。
guardar_highscore
基本保持不变,但我已将其清理干净了一些。
// The filename is now a variable so its used consistently
// and can be used in error messages.
const char Score_File[] = "highscore3.txt";
void guardar_highscore(const Scores *top) {
FILE *fd = fopen (Score_File,"wb");
if (fd == NULL) {
// A more informative error message than "nope".
fprintf( stderr, "Could not open '%s' for writing: %s\n", Score_File, strerror(errno) );
exit(1);
}
// Loop instead of repeating the formatting. This makes adding more
// scores easier.
// Note the stray whitespace is gone.
for( int i = 0; i < 3; i++ ) {
fprintf(fd, "%d\n", top->score[i]);
}
fclose(fd);
}
ler_highscore()
更改为整数读取。如果文件意外地大,它也只读取三行以防止溢出3元素列表。 从不信任您的输入 是一种很好的做法。
Scores ler_highscore() {
// This is the proper way to initialize a struct,
// each field must be initialized separately.
// A bare {0} happens to work because the struct is
// currently just a list, and if it doesn't you're
// going to overwrite all the elements anyway.
Scores top = { .score = {0} };
// No reason to skimp on the size of the line buffer.
char line[1024];
FILE *fd = fopen(Score_File, "rb");
if (fd == NULL) {
// Again, more informative error message.
fprintf( stderr, "Could not open '%s' for reading: %s", Score_File, strerror(errno) );
exit (1);
}
// Read 3 lines, no more. Otherwise we'll overflow memory.
for( int i = 0; i < 3; i++ ) {
// Use `sizeof(line)` rather than repeating the number.
// It avoids mistakenly letting them go out of sync.
if( fgets(line, sizeof(line), fd) == NULL ) {
fprintf( stderr, "Not enough scores in %s\n", Score_File );
break;
}
// Read one integer per line.
sscanf(line, "%d", &top.score[i]);
}
fclose(fd);
return top;
}