c - 我需要有关在 C 文本文件中显示前 5 名分数的功能的帮助

标签 c sorting return-value

我目前正在为我的 C 编程初学者类(class)创建一个非常简单的程序,但我陷入了困境。我希望能够打印保存在文本文件中的 5 个最佳分数,但现在它只显示前 5 行而不是最佳得分行。历史记录部分工作正常,正在打印所有内容,但我无法理解如何打印 5 个最佳分数,也许它与整理外部文本文件中的信息有关?抱歉,如果这篇文章很愚蠢,但我需要去某个地方询问(我对此很基础)。

这是我认为无法正常工作的代码的一部分,它用于代码块:

#include <stdio.h>
#include <time.h>
#include <stdlib.h>

char name [40];     // Here every integer and character etc. is introduced as global.
int menu(char *name);
int startPractice(int choice);
int startTest(int choice, char *name);
char randomOperator();
int getRandomNumber(int min, int max);
int calc(int a, int b, char c);
int rand(void);
int showHistory();
int saveHistory(char *name, float average);
int showTop5();

struct gamer{
char *username;
float average;
};

int main()
{
printf("Hello and welcome to the program!\n"); // This is the introduction
printf("\nWhat is your name? ");
scanf("%s", &name);


printf("\nWelcome %s! \n\nWhat would you like to do? \n" , name);
menu(&name); // This line calls the main menu.

return 0;
}

int compare(const void *s1, const void *s2)
{
struct gamer *g1 = (struct gamer *)s1;
struct gamer *g2 = (struct gamer *)s2;/* same gender so sort by id */

return g1->average - g2->average;
}

int menu(char *name) {        // This is the main menu and whenever this function is called the program starts from here.
int qanswer;        // This variable is set so it can be used in this body, it is not a global integer.

printf("\n1. Do practices \n2. Do a test \n3. Quit \n4. Test history \n5. Top 5 \n");
scanf("%d", &qanswer);

switch (qanswer) {      // Switch cases for a more compressed code, here only one case will be activated and that is decided by the value of "qanswer".
    case 1:
        printf("\nNow, you can choose to do practices on: \n\n1. Additions\n2. Subtractions\n3. Addition and Subtractions: ");
        printf("\n\nEnter your choice: ");
        scanf("%d" , &qanswer);
        startPractice(qanswer);
        break;      //This breaks the code at any chosen case.
    case 2:
        printf("\nYou will be given 15 questions to solve as the test!\n\n");
        printf("\nYou can choose to do the test on: \n\n1. Additions\n2. Subtractions\n3. Addition and Subtractions: ");
        printf("\n\nEnter your choice: ");
        scanf("%d", &qanswer);
        startTest(qanswer, name);
        break;
    case 3:
        printf("\nExiting program... \n");
        exit(0); // Shuts down the program.
        break;
    case 4:
        printf("Test history\n");
        showHistory();
        break;
    case 5:
        printf("Top 5 test results:\n");
        showTop5();
        break;
    default:        // if the user enter anything except 1,2,3 this line of code will be returned.
        printf("Your input wasn't valid. Please try again...\n\n");
        menu(name);     // This calls the main menu again
}

return 0;
}

int startPractice(int choice) {     // If practice is chosen then this function will be called.

int a, b, answer1;
char c;

int i;
for (i = 1; i <= 10; i++) {     // The for loop runs this code until i=10 and increases by 1 each time. Therefore this code will run 10 times fully.
    a = getRandomNumber(1, 30);     // This calls the function for a random number.
    b = getRandomNumber(1, 30);
    if (choice == 1) {      // If choice is set to "1" c will be t to + otherwise -.
        c = '+';
    } else if (choice == 2) {
        c = '-';
    } else {
        c = randomOperator();
    }

    printf("%d. %d %c %d = ", i, a, c, b);
    scanf("%d", &answer1);

    while (answer1 != calc(a, b, c)){
        printf("Try again! ");
        scanf("%d", &answer1);
    }

    printf("Very good!\n\n");
}
printf("Practice is complete\n");
printf("\nNow what would you like to do?\n");
menu(name);

return 0;
}

int startTest(int choice, char *name) {
int a, b, answer1;
char c;
int counter = 0;
float average;
int i;
for (i = 1; i <= 15; i++) {
    a = getRandomNumber(1, 30);
    b = getRandomNumber(1, 30);
    if (choice == 1) {
        c = '+';
    } else if (choice == 2) {
        c = '-';
    } else {
        c = randomOperator();
    }

    printf("%d. %d %c %d = ", i, a, c, b);
    scanf("%d", &answer1);
    if (answer1 == calc(a, b, c)){
        counter++;
    }

    printf("\n\n");
}
printf("The test is complete\n");
average = (float) counter/(float)15;        // This calculates the average score as a float with the counter / 15.
printf("You scored %d out of 15 which is and average of %d %%\n", counter, (int)average*100);       // This line takes the value of average and multiply it by 100 to show the percentage.
saveHistory("Test", average);
printf("\nNow what would you like to do?\n");
menu(name); // This function calls the main menu again.

return 0;

}

int calc(int a, int b, char c) {        // This function is used to define the equation as (a + b) or (a - b).
switch(c) {
    case '+':
        return a+b;
    case '-':
        return a-b;
}
}

char randomOperator() {         //This code is used to decide if + or - is going to be used.
switch(getRandomNumber(0,1)) {      //Switch statement when you need two or more ways to return a value.
    case 0:
        return '+';     //If the random number is 0 return is + otherwise it is -.
    case 1:
        return '-';
}

return '+';
}

int getRandomNumber(int min, int max) {     // This simply decides a random value of min 0 and max 1.
return rand() % (max + 1 - min) + min;
}

int showHistory(){
FILE *f;
char c;
f=fopen("test.txt","rt");

if (f) {
    while((c=fgetc(f))!=EOF){
        printf("%c",c);
    }

    fclose(f);
    printf("\nWhat would you like to do now?\n");
} else {
    printf("There is no history file at the moment.");
}

menu(name);

return 0;
}

int saveHistory(char *name, float average){
FILE *f;
char c;
f=fopen("test.txt","a");

fprintf(f, "%s_%.2f\n", name, average);

fclose(f);
return 0;
}
int showTop5(){
//printf("\n");
FILE *f;
char c;
char line[256];
int count = 0;
f=fopen("test.txt","rt");

if (f) {
    while (fgets(line, sizeof(line), f)) {
        if (strlen(line) > 0) {
            count++;
        }
    }

    char delimiter[] = "_";
    char *ptr;

    fclose(f);

    f=fopen("test.txt","rt");

    struct gamer gamers[count];
    int i = 0;
    printf("\n");
    while (fgets(line, sizeof(line), f)) {
        ptr = strtok(line, delimiter);
        char n[40];
        strcpy(n, ptr);
        //printf("n: %s, ", n);
        ptr = strtok(NULL, delimiter);
        float avg = *(float *) ptr;
        //printf("points: %f\n", avg);
        gamers[i].average = avg;
        gamers[i].username = n;

        i++;
    }

    qsort(gamers, count, sizeof(struct gamer), compare);

    int j;
    for(j = 0; j < count; j++){
        if (j==5){
        break;
    }
        printf("Rank %d: %s with %.2f %% as average.\n", j+1, gamers[j].username, gamers[j]. average);
    }

    fclose(f);
} else {
    printf("There is no history file at the moment.");
}

menu(name);

return 0;
}

最佳答案

这行不通

 ptr = strtok(NULL, delimiter);
    float avg = *(float *) ptr;

您将文件中的分数视为 float 的二进制表示形式。不是,是文字。你需要做

   ptr = strtok(NULL, delimiter);
    float avg = atof(ptr);

关于c - 我需要有关在 C 文本文件中显示前 5 名分数的功能的帮助,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41515387/

相关文章:

javascript - 为什么 Array.sort 有时会比较某些值对两次?

c++ - std::map 是一个好的解决方案吗?

c++ - 这段 C++ 代码是如何工作的?

c - 获取线程函数c的参数

c - Arduino 电脑鼠标/输入设备

sorting - 对批处理文件结果进行排序

python - 如何优雅地忽略 Python 函数的某些返回值?

c++ - 一个函数可以返回多个值吗?

涉及 {} 的 C 代码

c - 为什么 C 中 sizeof() 运算符的输出不同