【问题标题】:C - fscanf error with char *C - 字符的 fscanf 错误 *
【发布时间】:2017-11-09 07:29:49
【问题描述】:

我正在尝试读取这种格式的 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

这些列是:hp、Universe 颜色、Universe 编号和名称。我所做的是读取该行并将参数保存在一个名为 Warriors 的结构数组中,格式如下:

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;
}

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;
}

但由于某种原因我无法理解,最终的战士名单都具有相同的名称,例如:

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 

inName 指针有问题吗?

当我调试时,第一次迭代打印:

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

第二次迭代打印:

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

等等。

【问题讨论】:

  • 请注意,要读取的姓氏会被保留。因为您没有单独保存名称;您只需将指向 inName 的指针复制到结构中,而不是分配空间并复制名称。由于inName 是 read 函数的局部变量,您还会发现名称早晚会损坏。您也应该显示结构定义,但很明显您在结构中的名称有 char *

标签: c arrays pointers structure scanf


【解决方案1】:

问题是您读取了名字,然后为文件中的每个战士设置了一个指向该名字的指针。对于文件中的每个元素,您必须为其名称分配新内存(使用 malloc)并将新名称复制到其中(使用 strcpy)。因为你声明了名字 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;

}

还有另一种很酷的方法是使用 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;

}

别忘了:

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

【讨论】:

    【解决方案2】:

    来自 scanf 的所有输入都写入为 inName[50] 指定的相同内存位置。在每次迭代中,您都将覆盖内容,但将相同的地址分配给 guerrero.name。当您打印出来时,您会打印最后一个条目。

    你可以试试这个:

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

    【讨论】:

      猜你喜欢
      • 2017-03-29
      • 2015-02-09
      • 2011-08-13
      • 1970-01-01
      • 1970-01-01
      • 2011-05-25
      • 1970-01-01
      • 2020-03-20
      • 1970-01-01
      相关资源
      最近更新 更多