fscanf和链表的char *

时间:2013-03-08 05:47:23

标签: c linux struct linked-list scanf

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

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

rutvik

阿比纳夫

但打印数据时......

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

1 rutvik 9876655433

2 nav1234567789


让我们暂停一下char指针。 代码适用于结构

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

};

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

输出:

1 Rutvik 9876655433

2 Abhinav 578692242758466

578692242758466 是出乎意料的。

2 个答案:

答案 0 :(得分:3)

您分配sizeof(char)个字节,这是一个字节,足够大于字符串末尾的空字节。您使用的%s读取的内容不受限制。

这是堆缓冲区溢出;它通常会导致不快乐。您需要确定要分配的数据量(32,64,4096,其他一些数字),然后使用格式字符串,例如%31s%63s或{{1}或者将数据读入其中的任何内容。

不要忘记检查分配是否成功!

有些人会谴责你施放%4095s。如果你使用一种不接受未声明的函数的模式进行编译,那么一般来说,演员阵容没什么大不了的。

答案 1 :(得分: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));