简体   繁体   English

C-带字符的fscanf错误*

[英]C - fscanf error with char *

I'm trying to read a txt file with this format: 我正在尝试读取以下格式的txt文件:

8590 2 07 Goku
8591 2 07 Vegeta
6973 2 07 Picolo
5432 3 02 Jerez
6773 3 02 Sour
4689 4 03 Mosco
6981 5 06 Cabba
7891 5 06 Frost

The columns are: hp, universe color, universe number and name. 这些列是:hp,Universe颜色,Universe号和名称。 What I do is this read the line and save the parameters in an array of structures called warrior with this format: 我要做的是读取此行并将参数保存在具有以下格式的称为warrior的结构数组中:

typedef struct Warrior{
    int hp;
    int color;
    int universe;
    char * name;
    int posX;
    int posY;
    int ki;
} warrior;

warrior createWarrior(int inHp, int inColor, int inUniverse, char * inName){
    warrior guerrero; 
    guerrero.hp = inHp;
    guerrero.color = inColor;
    guerrero.universe = inUniverse;
    guerrero.name = inName;
    guerrero.posX= 0;
    guerrero.posY= 0;
    guerrero.ki=0;
    return guerrero;
}

The readFile code is: readFile代码为:

warrior * readFile(char * nameFile, warrior * listGuerrero){
    FILE * filePointer;
    int sizeFile = 0, ch = 0;
    int inHp, inColor, inUniverse;
    char inName[50];

    filePointer = fopen(nameFile, "r");

    while(fscanf(filePointer, "%d %d %d %s\n", &inHp, &inColor, &inUniverse, inName) != EOF){
        sizeFile ++;
    }

    rewind(filePointer);

    listGuerrero = (warrior *)malloc(sizeFile*sizeof(warrior));
    for(int k = 0; k < sizeFile; k++){
        fscanf(filePointer, "%d %d %d %s\n", &inHp, &inColor, &inUniverse, &inName[0]);
        listGuerrero[k] = createWarrior(inHp,inColor,inUniverse,inName);
        printf("k: %d - HP: %d - Color: %d - Universo: %d - Nombre: %s \n", k, listGuerrero[k].hp, listGuerrero[k].color, listGuerrero[k].universe, listGuerrero[k].name);
    }

    fclose(filePointer);
    return listGuerrero;
}

But for some reason I can't understand, the final list of warriors all have the same name like: 但是由于某种原因,我无法理解,最终的战士名单都具有相同的名称,例如:

j: 0 - HP: 8590 - Color: 2 - Universo: 7 - Nombre: Frost 
j: 1 - HP: 8591 - Color: 2 - Universo: 7 - Nombre: Frost 
j: 2 - HP: 6973 - Color: 2 - Universo: 7 - Nombre: Frost 
j: 3 - HP: 5432 - Color: 3 - Universo: 2 - Nombre: Frost 
j: 4 - HP: 6773 - Color: 3 - Universo: 2 - Nombre: Frost 
j: 5 - HP: 4689 - Color: 4 - Universo: 3 - Nombre: Frost 
j: 6 - HP: 6981 - Color: 5 - Universo: 6 - Nombre: Frost 
j: 7 - HP: 7891 - Color: 5 - Universo: 6 - Nombre: Frost 

Is something wrong with the inName pointer? inName指针有问题吗?

When I debug, the first iteration prints: 当我调试时,第一次迭代打印:

j: 0 - HP: 8590 - Color: 2 - Universo: 7 - Nombre: Goku

And the second iteration prints: 第二遍打印:

j: 0 - HP: 8590 - Color: 2 - Universo: 7 - Nombre: Vegeta 
j: 1 - HP: 8591 - Color: 2 - Universo: 7 - Nombre: Vegeta

and so on. 等等。

the problem is that you read the first name and after that for every warrior in the file you just set a pointer to that first name. 问题是您读取了名字,然后对文件中的每个战士都设置了指向该名字的指针。 For every element from your file you must allocate new memory for it's name (using malloc) and copy the new name into it( using strcpy). 对于文件中的每个元素,您都必须为其名称分配新内存(使用malloc),并将新名称复制到其中(使用strcpy)。 Because you declared the name char* 因为您声明了名称char *

warrior createWarrior(int inHp, int inColor, int inUniverse, char * inName){

    warrior guerrero; 
    guerrero.hp = inHp;
    guerrero.color = inColor;
    guerrero.universe = inUniverse;

    guerrero.name = malloc(sizeof(char) * 30); // 30 is the length of the name

    strcpy(guerrero.name,inName); // copy new name 
    guerrero.posX= 0;
    guerrero.posY= 0;
    guerrero.ki=0;

    return guerrero;

}

There is another cool way to do it using strdup() which basically alocates new memory and copy the parameter string there ( but i've not tested this): 还有一种使用strdup()的很酷的方法,它基本上是分配新的内存并将参数字符串复制到那里(但是我还没有测试过):

warrior createWarrior(int inHp, int inColor, int inUniverse, char * inName){

    warrior guerrero; 
    guerrero.hp = inHp;
    guerrero.color = inColor;
    guerrero.universe = inUniverse;

    guerrero.name = strdup(inName);
    guerrero.posX= 0;
    guerrero.posY= 0;
    guerrero.ki=0;

    return guerrero;

}

Don't forget: 不要忘记:

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

All of your input from scanf is written to the same memory location given for inName[50]. 您所有来自scanf的输入都被写入为inName [50]指定的相同存储位置。 In each iterration you are overwritting the content, but assigning the same address to the guerrero.name. 在每次迭代中,您都覆盖了内容,但为guerrero.name分配了相同的地址。 And when you print out, you get last entry printed. 当您打印出来时,您将得到最后一个打印条目。

You may try this: 您可以尝试以下方法:

warrior createWarrior(int inHp, int inColor, int inUniverse, char * inName){
...
guerrero.name = strdup(inName);
....
return guerrero;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM