【问题标题】:fgets and sscanf records from file with delimitators带有分隔符的文件中的 fgets 和 sscanf 记录
【发布时间】:2017-06-01 15:23:16
【问题描述】:

我必须从一个文件中读取多条记录(记录的每个组成部分用逗号分隔),我无法理解问题所在,所以这是我的文件:

Rossi,Mario,M,mariorossi@gmail.com,3923333332,Portiere Bianchi,Giuseppe,M,giuseppebianchi@gmail.com,3470000021,Attaccante Ferrari,Anna,F,annaferrari@gmail.com,3466482645,Attaccante Romano, Antonio,M,antonioromano@gmail.com,3450394672,Centrocampista

这是我的代码:

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

struct dati_giocatori {
    char cognome[20];
    char nome[20];
    char genere[20];
    char email[50];
    char telefono[16];
    char ruolo[20];
};

typedef struct dati_giocatori GIOCATORE;

void stampa_file(FILE *pfile, GIOCATORE *vettore, int dim, char *stringa);

int main (){

    FILE *pfile;
    GIOCATORE *vettore;
    int dim=0;
    char stringa[200];


        printf("Quanti giocatori vuoi visualizzare?");
        scanf("%d",&dim);
        vettore=(GIOCATORE*)malloc(dim*sizeof(GIOCATORE));

        pfile=fopen("Giocatori.txt","r");  

        stampa_file(pfile,vettore,dim,stringa);
        system("pause");
        fclose(pfile);

        pfile=fopen("Giocatoriv.txt","r");
        system("pause");

        free(vettore);
        fclose(pfile);
        system("pause");

    return 0;
    system("pause");
}

void stampa_file(FILE *pfile, GIOCATORE *vettore, int dim, char *stringa){
    int i=0;
    int j=0;

    if(pfile!=NULL){
     if(!feof(pfile)){
        while(i<dim){
            if(!feof(pfile)){
                fgets(stringa,200,pfile);
                    sscanf(stringa,"%[^,],%[^,],%[^,],%[^,],%[^,],%s",vettore[i].cognome,vettore[i].nome,
                            vettore[i].genere,vettore[i].email,vettore[i].telefono,vettore[i].ruolo);
                i++;
                }
                else{
                    printf("\n----- Giocatori finiti -----\n");
                    printf("\n");
                    i=dim;
                }
            }
        }
     else{
         printf("\nFile finito.\n");
     }

    }
    else{
        printf("Errore nell'apertura del file.\n");
        printf("\n");
    }

     while(j<dim){
            printf("%s,%s,%s,%s,%s,%s\n",vettore[j].cognome,vettore[j].nome,
                  vettore[j].genere,vettore[j].email,vettore[j].telefono,vettore[j].ruolo);
            j++;
                    }   
    system("pause");
}

我知道问题出在sscanf(),因为它只在屏幕上打印每条记录的第一个组件和五个逗号,但我不知道如何解决这个问题......它没有分配记录中正确位置的正确数据,sscanf() 格式是否正确?我对分隔符不是很熟悉,我应该如何解决这个问题?

感谢大家的帮助。很抱歉您等了这么久才回复,但我昨天无法编辑。我也很抱歉发布错误,我是堆栈溢出的新手,我也是 C 的新手(这是我的第一语言)......(只是为了让我很难,我也不是您可以通过我的语法错误注意到的母语人士)。 是的,电子邮件地址是假的。 顺便说一句,老实说,我不知道检查文件是否在每条记录的末尾都有换行符......在编写文件时,我认为按“回车”会给我换行符,但读你的 cmets 我不确定了。我想在每条记录的末尾使用换行符,但我该怎么做呢?而且,这会让我的代码工作吗? (我第二次打开该文件,因为我只是在尝试其他操作,所以请不要介意,系统暂停也是如此)。

【问题讨论】:

  • 你对if (!feof(...))的使用并不比while (!feof(...))which is wrong好。
  • 我希望您在示例文件中发布了虚假的电子邮件地址...
  • 每条记录的末尾是否有换行符? (您发布的内容中没有)。
  • 文件是否包含换行符?
  • 发布使用的确切输入和看到的确切输出。

标签: c record fgets scanf


【解决方案1】:

好的,首先下次让你的问题,特别是你的代码更具可读性(你必须正确使用缩进)。我不明白你为什么使用这么多system("pause"); 也是错误的方式。您还可以转换vettore=(GIOCATORE*)malloc(dim*sizeof(GIOCATORE));you should not do it 的结果。您打开文件,然后使用它,关闭它并打开一个新文件,对它什么都不做,所以我删除了它。注意使用while (!feof(file)) is always wrong。然后在你的stampa_file 函数中我做了很多改变。

这里是代码。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
 * NOTE: I'M NOT CHECKING **ANY** RETURNING ERROR
 * SUCH AS FROM FOPEN OR MALLOC.
 */
struct dati_giocatori {
    char cognome[20];
    char nome[20];
    char genere[20];
    char email[50];
    char telefono[16];
    char ruolo[20];
};

typedef struct dati_giocatori GIOCATORE;

void stampa_file(FILE *pfile, GIOCATORE *vettore, int dim, char *stringa);

int main (){
    FILE *pfile;
    GIOCATORE *vettore;
    int dim=0;
    char stringa[200];
    printf("Quanti giocatori vuoi visualizzare?");
    scanf("%d",&dim);
    vettore= malloc(dim*sizeof*vettore);
    pfile=fopen("Giocatori.txt","r");  
    stampa_file(pfile,vettore,dim,stringa);
    fclose(pfile);
    return 0;
}

void stampa_file(FILE *pfile, GIOCATORE *vettore, int dim, char *stringa){
    int i=0;
    int j=0;
    size_t size = 200;
    if(pfile!=NULL){
            while((getline(&stringa, &size, pfile)) != -1 && i<dim) {
                sscanf(stringa,"%[^,],%[^,],%[^,],%[^,],%[^,],%s",vettore[i].cognome,vettore[i].nome,
                            vettore[i].genere,vettore[i].email,vettore[i].telefono,vettore[i].ruolo);
                i++;
            }
    }
    printf("No more records to read\n");
    while(j<i){
        printf("%s,%s,%s,%s,%s,%s\n",vettore[j].cognome,vettore[j].nome,
                  vettore[j].genere,vettore[j].email,vettore[j].telefono,vettore[j].ruolo);
        j++;
      }
    if(dim > i){
        printf("Not enough players\n");
    }   
}

这是我用于测试的文件:

罗西,马里奥,M,mariorossi@gmail.com,3923333332,Portiere Bianchi,Giuseppe,M,giuseppebianchi@gmail.com,3470000021,Attaccante 法拉利,Anna,F,annaferrari@gmail.com,3466482645,Attaccante Romano,Antonio,M,antonioromano@gmail.com,3450394672,Centrocampista

【讨论】:

  • 如果您阅读过my comment under the OP,您会看到如果文本文件包含换行符,则 OP 代码似乎可以工作,但如果不包含换行符则不会。您的代码也适用于换行符,但并非没有。在 OP 回答 cmets 中提出的问题之前,我们无法真正有效地回答这个问题。
  • @DavidBowling 告诉我我是否错了。 getline 至少读取 size 元素或直到找到 \nEOF。在问题代码中,他假设一行是200 characters,因此getline 没有任何问题。
  • 我没说使用getline()有问题。问题是OP没有规定记录是否以\n字符终止,这影响解析操作。发布的示例不包含换行符,但看起来确实如此。事情的真相是什么?我只是通过针对复制粘贴到文件中的示例运行您的代码来仔细检查 - 它崩溃了。 OP 代码似乎对我有用,带有合理的换行符,这就引出了一个问题,OP 的 real 问题是什么?还在等他们回复……
  • 请注意,我并不是说 OP 代码是正确的,或者您的建议是错误的;只是我们还不够了解回答
  • 非常感谢你们,我试着编辑我的第一篇文章,有什么想知道的可以问我
猜你喜欢
  • 1970-01-01
  • 2019-02-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-05
  • 2021-11-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多