将最高分保存在文件中

时间:2017-05-15 23:44:16

标签: c

所以我想保存游戏中最好的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;
}

1 个答案:

答案 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;
}