在字符串操作/指针中找不到错误

时间:2010-12-03 02:28:04

标签: c pointers string

首先,这是一个家庭作业,所以请不要为我编写任何代码,只需指出我的代码错误。

代码的基础是它是一本'地址/余额'书。我有一个带有变量的结构,但由于某种原因,我的双重链表正在搞乱,我无法弄清楚如何。有点花哨(不是真的)调试,我发现我认为fgets(字符串,200,文件); line会以某种方式覆盖我的head-> name指针,这似乎会抛弃其余的代码。相关代码片段在这里:

填充列表:

void populate_list(char* filename){
    FILE *file = NULL;
    char* name = NULL;
    char* streetaddress = NULL;
    char* city = NULL;
    char* state = NULL;
    char line[200];
    int zip;
    float balance;

    file = fopen(filename,"r");

    if(file==NULL){
        printf("Invalid input file\n");
        exit(1);
    }
    if(file == 0){
        printf("Invalid file.\n");
        exit(1);
    }

    while(!feof(file)){

        fgets(line, 200, file);

        name = strtok(line, ",");
        streetaddress = strtok(NULL, ",");
        city = strtok(NULL,",");
        state = strtok(NULL,",");
        zip = atoi(strtok(NULL,","));
        balance = atof(strtok(NULL,","));

        strip_spaces(name);
        strip_spaces(streetaddress);
        strip_spaces(city);
        strip_spaces(state);

        add_node(name, streetaddress, city, state, zip, balance);

    }

    fclose(file);
    return;
}

然后是add_node代码:

void add_node(char* name, char* streetaddress, char* city, char* state, int zip, float, balance){
    struct customer* addnode = NULL;

    if(find_duplicate(name)){
        print_filler(1);
        printf("DUPLICATE RECORD: %s\n", name);
        return;
    } else {
        addnode = (struct customer *) malloc(sizeof(struct customer));
        addnode->name = name;
        addnode->streetaddress = streetaddress;
        addnode->city = city;
        addnode->state = state;
        addnode->zip = zip;
        addnode->balance = balance;

        if(head == NULL) {
            head = addnode;
            addnode->prev = NULL;
        } else {
            tail->next = addnode;
            addnode->prev = tail;
        }

        tail = addnode;
        addnode->next = NULL;
    }

    print_list();
    return;
}

这个错误似乎是在第一次调用add_node之后发生的,并且在fgets()第二次关闭时发生。由于某种原因,它覆盖了整个fgets()行的head-> name。

还有其他随机的烦人的错误,我还没有确定,但我认为这可能是其他人的来源。

完整代码在这里,如果它有帮助:http://pastebin.com/k0pqyvT0

我的猜测是这与head->名称指针被fgets()覆盖有关,但我不能为我的生活弄清楚到底是做什么的,任何帮助/建议都会受到赞赏

编辑:解决方案是实现strdup()并在将字符串传递给add_node()时复制它们。谢谢你的所有答案。

4 个答案:

答案 0 :(得分:2)

  1. 变量“string”是指向任何内容的指针。您需要实际分配一个缓冲区,您可以在其中读取数据。
  2. strtok返回指向原始字符串的指针,然后更改。如果您希望在客户结构中保留它,则需要分配一个新缓冲区并将字符串复制到其中。

答案 1 :(得分:1)

我不知道它是否相关,但你的指针struct customer* addnode = NULL;是一个本地的add_node(),它不会被保存(即每次函数退出时,它都会被破坏)。当使用指向char的指针时也要小心,它似乎直观地是一个字符串,但是有一个问题,

所以,如果你做的事情如下:

while(!feof(file)) {

   name = strtoke(string, ",");
   // etc

   add_node(name, ... //etc);
}

因为您只复制引用即addnode->name = name,所以下一行读取将替换用作前一条记录的相同指针的内容,因此您将拥有具有相同属性的列表。< / p>

答案 2 :(得分:1)

主要问题是您分配的节点成员指向line缓冲区,每次调用fgets()填充缓冲区时都会覆盖该缓冲区。所以每个节点中的指针总是指向同一个缓冲区(它存在于堆栈中)。

解决方案(如其他答案中所述)是使用strdup()为每个节点成员分配的每个字符串的单独副本。所以这样的事情会起作用:

....
} else {
    addnode = (struct customer *) malloc(sizeof(struct customer));
    addnode->name = strdup(name);
    addnode->streetaddress = strdup(streetaddress);
    addnode->city = strdup(city);
    addnode->state = strdup(state);
    addnode->zip = strdup(zip);
    addnode->balance = strdup(balance);
    ...
}

在分配节点之后立即清零节点的内容也是一个好主意,这样你就不会有垃圾:

   addnode = (struct customer *) malloc(sizeof(struct customer));
   memset(addnode, '\0', sizeof(struct customer));

答案 3 :(得分:0)

Dark Falcon 指出时,你* add_node *代码不正确。你需要做这样的事情:

  void add_node(char* name, char* streetaddress, char* city, char* state, int zip, float balance){
    struct customer* addnode = NULL;

    strip_spaces(name);
    strip_spaces(streetaddress);
    strip_spaces(city);
    strip_spaces(state);

    if(find_duplicate(name)){
        print_filler(1);
        printf("DUPLICATE RECORD: %s\n", name);
        return;
    } else {
        addnode = (struct customer *) malloc(sizeof(struct customer));
        addnode->name = name;
        addnode->streetaddress = streetaddress;
        addnode->city = city;
        addnode->state = state;
        addnode->zip = zip;
        addnode->balance = balance;

        if(head == NULL) {
            head = addnode;
            addnode->prev = NULL;
        } else {
            tail->next = addnode;
            addnode->prev = tail;
        }

        tail = addnode;
        addnode->next = NULL;
    }

    print_list();
    return;
  }

然后像这样调用它:

    add_node(strdup(name), strdup(streetaddress), strdup(city), strdup(state), zip, balance);