【问题标题】:fscanf and linked list's char *fscanf 和链表的 char *
【发布时间】:2013-03-08 05:47:22
【问题描述】:
struct node {
        ...
        char *name;
        ...
        struct node *next;
};

在递归函数中:

head->name = (char *) malloc(sizeof(char));
if (fscanf(fp, "id\t%d\nname\t%s\nmobile\t%lld\n", &head->id, head->name, &head->mobile) > 0) {
    printf("%s\n", head->name);

它存储正确的数据...假设...

鲁特维克

阿比纳夫

但是当打印数据时...

printf("%d\t%s\t%lld\n", head->id, head->name, head->mobile);

1 路特维克 9876655433

2 ��导航 1234567789


让我们暂时搁置 char 指针。 代码与结构配合得很好

struct node {
...
char name[10];
...
struct node *next;

};

但不是当我取名字 [20] 时,它会影响 long long mobile 的价值... 为什么??

输出:

1 鲁特维克 9876655433

2 阿比纳夫 578692242758466

578692242758466 出乎意料。

【问题讨论】:

  • “它存储正确的数据” 从您的输出来看,我怀疑从分配 single char 而不是适当大小的缓冲区开始为您的name 字段。

标签: c linux struct linked-list scanf


【解决方案1】:

您分配sizeof(char) 字节,这是一个字节,足够大,可以在字符串末尾放置一个空字节。您使用不受长度限制的%s 阅读。

这是堆缓冲区溢出;它通常会导致不快乐。您需要决定要分配多少数据(32、64、4096 或其他数量)字节,然后使用格式字符串,例如 %31s%63s%4095s 或其他读取数据。

别忘了检查分配是否成功!

有些人会谴责你投malloc()。如果您使用不接受未声明函数的模式进行编译,那么一般来说转换没有什么问题。

【讨论】:

  • 谢谢伙计,但我没有明白你关于强制转换 malloc() 的最后一点。我尝试使用 malloc() 分配 10 个字节,但没有成功,并且确实需要格式化字符串,例如 %10s!
  • 演员表问题可以忽略。请注意,如果为字符串分配 N 个字节,则应将 %s 中的大小限制为 N-1 个字节(32 与 %31s 等)。这是scanf() 等人的怪癖;他们使用 N-1 而不是 N(遗留行为;现在无法更改 - 由于现有技术,1989 年也无法更改)。
【解决方案2】:

这一行:

head->name = (char *) malloc(sizeof(char));

仅分配 1 字节内存。您需要确定最大大小并分配那么多字符:

head->name = (char *) malloc(sizeof(char) * MAXNAME);

那你不妨把结构改成:

struct node {
        ...
        char name[MAXNAME];
        ...
        struct node *next;
};

更好的选择是保持结构不变,设置一个 MAXNAME 大小 buffer 以使用 scanf 从文件中读取,然后为名称分配足够的空间:

// + 1 for the null character at the end
head->name = (char *) malloc(sizeof(char) * (strlen(buffer) + 1)); 

【讨论】:

  • 您好,感谢您的回复,char name[10] 有效。但是当我使用 char name[20] 时,它会影响 long long mobile 的价值...帮助我理解它。
猜你喜欢
  • 2015-06-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多