fscanf在一个有字符串的结构中

时间:2014-12-02 20:34:31

标签: c string malloc structure scanf

我的代码出了问题 我想fscanf result.txt到结构,但它不起作用;

result.txt格式:

point name (for examples)
623   john
457   peter
312   chuck
etc.

首先我算出行{I} malloc。对于结构的字符串,我必须再次malloc,但我不知道字符串的长度。所以我在for循环中计算它。

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

typedef struct ranklist {
   int point;
   char* name;
} ranklist;

int how_many_lines (FILE *fp){

   rewind(fp);

   int ch;
   int line=0;

   while (EOF != (ch = fgetc(fp)))
       if (ch=='\n')
          ++line;

   rewind(fp);

   return line+1;
}

int how_many_letter(FILE *fp){

   int ch;
   int letter = 0;
   int space=0;

   while ('\n' != (ch = fgetc(fp)))
       if (ch==' ')
           space=1;
       if (space == 1)
           letter++;

   return letter;
}

int main()
{
    FILE *fp;
    int y;
    int name_length;

    ranklist** r;

    fp = fopen("result.txt","r");

    int lines;
    lines = how_many_lines(fp);


    r = (ranklist**) malloc(lines * sizeof(ranklist*));
    for (y = 0; y < lines; ++y){
       name_length = how_many_letter(fp);
       r[y] = (ranklist*) malloc(name_length * sizeof(ranklist));
    }

    for(y = 0; y < lines; y++){
       fscanf(fp,"%d %s", &(r[y]->point), r[y]->name);
    }

    for( y = 0; y < lines; y++){
        printf("%d %s", (r[y]->point), r[y]->name);
    }


    for (y = 0; y < lines; ++y)
       free(r[y]);
    free(r);

    fclose(fp);

   return 0;
}

2 个答案:

答案 0 :(得分:0)

我对您的代码进行了一些更改,并添加了一些注释来解释。只要对任何疑问发表评论。

int how_many_lines (FILE *fp){

   rewind(fp);

   int ch;
   int line=0;

   while (EOF != (ch = fgetc(fp)))
       if (ch=='\n')
          ++line;

   rewind(fp);

   return line+1;
}

int how_many_letter(FILE *fp){

   int ch;
   int letter = 0;

   // find first space since we
   // know the input format <number> <name>
   while ((ch = fgetc(fp)) != ' ');
   // count the number of characters until end of file
   // or '\n'
   while ((ch = fgetc(fp)) != '\n' && ch != EOF )
    letter++;

   return (letter);
}

int main()
{
    FILE *fp;
    int y;
    int name_length;

    ranklist** r;

    fp = fopen("file.txt","r");

    int lines;
    lines = how_many_lines(fp);
    printf("[%d]\n", lines);

    r = (ranklist**) malloc(lines * sizeof(ranklist*));
    for (y = 0; y < lines; ++y){
       name_length = how_many_letter(fp);
       // you must allocate memory for ranklist element and string name
       r[y] = (ranklist *) malloc(sizeof(ranklist));
       r[y]->name = (char *) malloc(name_length * sizeof(char));
    }

    // rewind pointer again
    rewind(fp);
    for(y = 0; y < lines; y++){
       fscanf(fp,"%d %s", &(r[y]->point), r[y]->name);
    }

    for( y = 0; y < lines; y++){
        printf("%d %s\n", (r[y]->point), r[y]->name);
    }


    for (y = 0; y < lines; ++y)
       free(r[y]);
    free(r);

    fclose(fp);

   return 0;
}

答案 1 :(得分:0)

要修复的示例

int how_many_records(FILE *fp){
    char ch;
    int line=0;
    int status;

    rewind(fp);
    while((status=fscanf(fp, "%*d %*[^\n]%c", &ch))==1)
        ++line;
    if(status != EOF){
        ++line;
    }
    rewind(fp);

    return line;
}

int how_many_letter(FILE *fp){
    int letter = 0;
    long pos = ftell(fp);

    //fscanf(fp, " %*[^\n]%n", &letter);
    fscanf(fp, " %*s%n", &letter);
    fseek(fp, pos, SEEK_SET);

    return letter;
}

int main(void){
    FILE *fp = fopen("result.txt","r");
    int y;
    int name_length;
    int lines = how_many_records(fp);
    ranklist *r = malloc(lines * sizeof(*r));//just pointer, Do not need double pointer

    for (y = 0; y < lines; ++y){
        fscanf(fp, "%d", &r[y].point);
        name_length = how_many_letter(fp);
        r[y].name = malloc(name_length + 1);
        fscanf(fp,"%s", r[y].name);
    }
    fclose(fp);

    for( y = 0; y < lines; y++){
        printf("%d %s\n", r[y].point, r[y].name);
        free(r[y].name);
    }
    free(r);

    return 0;
}