我目前正在为我的 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/