【问题标题】:Problems on computing statistics and parsing a text file计算统计和解析文本文件的问题
【发布时间】:2020-11-29 20:16:48
【问题描述】:

一个必须是简单的问题,但我无法做到。

我必须在结构上扫描一个包含以下格式条目的文本文件: {"data1","data2",number1,number2}

然后计算首先填充一个结构。

练习文本: 考虑以下结构的定义

typedef struct {
char teamHome [30];
char teamHost [30];
int goalSquadraHome;
int goalSquadraOspite;
} match;

用于表示足球比赛的结果。 编写一个函数,将游戏数组及其大小 e 作为参数 返回包含以下信息的结果结构: 主队赢得的比赛场数, 客队获胜的场次, 关系的数量, 在一场比赛中进球最多的球队的名字。 然后编写一个程序,给定包含所有 380 场 2019/2020 赛季意甲比赛的数组, 打印结果中包含的信息。

代码如下:

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

typedef struct{
        char squadraCasa[30];
        char squadraOspite[30];
        int golSquadraCasa;
        int golSquadraOspite;
} partita;

typedef struct {
        int partite_casa;
        int partite_ospite;
        int pareggi;
        char squad_magg_num_goal[30];
} risultato;

int main(){

FILE *fp;
risultato risultati;
int maxgoal = 0;
risultati.partite_casa = 0;
risultati.partite_ospite = 0;
risultati.pareggi = 0;
partita partite[380];
int i=0;
if((fp = fopen("partiteSerieA1920.txt","rt"))==NULL){
    printf("Errore nell'apertura del file\n");
    exit(1);
}
while(!feof(fp)){
      fscanf(fp,"{\"%s\",\"%s\",%d,%d",partite[i].squadraCasa,partite[i].squadraOspite,partite[i].golSquadraCasa,partite[i].golSquadraOspite);
      i++;
}
for(i=0;i<380;i++){
    if(partite[i].golSquadraCasa>partite[i].golSquadraOspite){
       risultati.partite_casa++;
    }else if(partite[i].golSquadraCasa<partite[i].golSquadraOspite){
       risultati.partite_ospite++;
    }else
       risultati.pareggi++;
    if(partite[i].golSquadraCasa>maxgoal){
       strncpy(partite[i].squadraCasa,risultati.squad_magg_num_goal,30);
       maxgoal = partite[i].golSquadraCasa;
    }
    if(partite[i].golSquadraOspite>maxgoal){
       strncpy(partite[i].squadraOspite, risultati.squad_magg_num_goal,30);
       maxgoal = partite[i].golSquadraOspite;  
    }
}
fclose(fp);
printf("%d %d %d %s\n",risultati.partite_casa,risultati.partite_ospite,&risultati.pareggi,&risultati.squad_magg_num_goal);
return 0;
}

请告诉我如何正确安排。

【问题讨论】:

  • 请描述您面临的具体问题或错误。代码的预期行为与实际行为是什么?一个问题:在fscanf 中,您需要将&amp; 用于int 字段:&amp;partite[i].golSquadraCasa, &amp;partite[i].golSquadraOspite
  • 您的帖子中没有问题。问一个具体的问题。
  • 你能告诉我一些正确的而不是这个吗:{\"%s\",\"%s\",%d,%d?谢谢
  • 请注意,typedef struct {} foo 实际上并没有定义结构。它为匿名结构定义了一个 typedef。 IMO,您应该通过删除所有 typedef 来简化代码。
  • 您错误地使用了feofstackoverflow.com/questions/5431941/…

标签: c


【解决方案1】:

可能还有其他问题,但您的流量控制肯定是错误的。而不是不正确的while/feof循环(Why is “while ( !feof (file) )” always wrong?),尝试类似:

partita *p = partite;
while( 4 == fscanf(fp, "{\"%29s\",\"%29s\",%d,%d",
        p->squadraCasa,
        p->squadraOspite,
        &p->golSquadraCasa,
        &p->golSquadraOspite
    ) ){ 
    p++;
}

【讨论】:

  • 它给出了错误的结果。这就是我修改代码的方式: while( 4 == fscanf(fp, "{\"%30[^,]\",\"%30[^,]\",%d,%d}", p ->squadraCasa, p->squadraOspite, &p->golSquadraCasa, &p->golSquadraOspite ) ){ p++; }
  • @natale 使用%30[^,] 读取大小为 30 的数组是错误的。 scanf 可以将 31 个字节写入数组。如果您希望字符串在 lentgh 中为 30 个字节,则必须将缓冲区的大小(至少)声明为 31,以便有空间容纳空终止符。
【解决方案2】:

试试这个,它有点不同的方法:

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

typedef struct
{
    char squadraCasa[30];
    char squadraOspite[30];
    int golSquadraCasa;
    int golSquadraOspite;
} partita;

typedef struct
{
    int partite_casa;
    int partite_ospite;
    int pareggi;
    char squad_magg_num_goal[30];
} risultato;

// solves given problem and stores results in risultato struct
risultato *getResult(partita **playedGames, int size)
{
    risultato *result = malloc(sizeof(risultato));
    result->partite_casa = 0;
    result->partite_ospite = 0;
    result->pareggi = 0;

    int currentHighest = 0;

    for (int i = 0; i < size; i++)
    {
        if (playedGames[i]->golSquadraCasa > playedGames[i]->golSquadraOspite){
            result->partite_casa++;
            if(playedGames[i]->golSquadraCasa > currentHighest ){
                currentHighest = playedGames[i]->golSquadraCasa;
                strcpy(result->squad_magg_num_goal, playedGames[i]->squadraCasa);
            }
        }
        else if (playedGames[i]->golSquadraCasa < playedGames[i]->golSquadraOspite){
            result->partite_ospite++;
            if (playedGames[i]->golSquadraOspite > currentHighest){
                currentHighest = playedGames[i]->golSquadraOspite;
                strcpy(result->squad_magg_num_goal, playedGames[i]->squadraOspite);
            }
        }
        else{
            result->pareggi++;
        }
    }

    return result;
}

// This is a custom parser of a line from the file
// data = {"data1","data2",number1,number2}
// return -> partita struct
partita *newGame(char *data){

    partita *partite = malloc(sizeof(partita));
    char* temp;

    // Get Home Team
    temp = strchr(data, ',') -1;
    temp[0] = '\0';
    strcpy(partite->squadraCasa, data + 2);
    data = temp+1;


    // Get Away Team
    temp = strchr(data+1, ',') -1;
    temp[0] = '\0';
    strcpy(partite->squadraOspite, data + 2);
    data = temp + 1;

    // Get Home Score
    temp = strchr(data + 1, ',');
    temp[0] = '\0';
    partite->golSquadraCasa = atoi(data + 1);
    data = temp + 1;

    // Get Away Score
    temp = strchr(data, '}');
    temp[0] = '\0';
    partite->golSquadraOspite = atoi(data);

        // Return game
    return partite;
}

int main()
{

    FILE *fp;
    partita **partite = malloc(sizeof(partita *)); // list of size one, currently...
    risultato *risultati;
    char linea[50];
    int indice = 0;

    if ((fp = fopen("./partiteSerieA1920.txt", "rt")) == NULL)
    {
        printf("Errore nell'apertura del file\n");
        exit(1);
    }

    // For each linea in the file, load a game into an array.
    while (fgets(linea, 50,fp))
    {
        //chomp the \n
        linea[strlen(linea)-1]='\0';

        // increase size of list
        partite = realloc(partite, sizeof(partita *) * (indice + 1));

        // insert game into array of games
        partite[indice] = newGame(linea);

        indice++;
    }

    risultati = getResult(partite, indice);

    // Print risultato
    printf("\n----RESULT----\nHome Wins: %d\nAway Wins: %d\nTies: %d\nTeam With Most Goals: %s\n\n", risultati->partite_casa, risultati->partite_ospite, risultati->pareggi, risultati->squad_magg_num_goal);

    // free all allocated memory then return
    for (int i = 0; i < indice;i++){
        free(partite[i]);
    }
    free(partite);
    free(risultati);
    fclose(fp);
    return 0;
}

我试图运行您的代码,但无法正确解析文件中的数据,因此我为您制作了一个快速解析器(这已经在上面的代码中):

partita *newGame(char *data){

    partita *partite = malloc(sizeof(partita));
    char* temp;

    // Get Home Team
    temp = strchr(data, ',') -1;
    temp[0] = '\0';
    strcpy(partite->squadraCasa, data + 2);
    data = temp+1;


    // Get Away Team
    temp = strchr(data+1, ',') -1;
    temp[0] = '\0';
    strcpy(partite->squadraOspite, data + 2);
    data = temp + 1;

    // Get Home Score
    temp = strchr(data + 1, ',');
    temp[0] = '\0';
    partite->golSquadraCasa = atoi(data + 1);
    data = temp + 1;

    // Get Away Score
    temp = strchr(data, '}');
    temp[0] = '\0';
    partite->golSquadraOspite = atoi(data);

        // Return game
    return partite;
}

您始终可以尝试使用与此类似的东西来解析您引入的字符串或行,因为我发现只编写您知道符合您想要的规范的代码会更有效。

如果代码有问题或想了解更多有关此功能的信息,请告诉我。我试着用意大利语保留尽可能多的内容。

干杯

【讨论】:

  • 你在跑什么?复制第一个代码块中的所有内容
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-03-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-21
相关资源
最近更新 更多