【问题标题】:strcmp in Linked List insertion crashing program链表插入崩溃程序中的strcmp
【发布时间】:2018-02-09 05:13:20
【问题描述】:

作为作业的一部分,我应该在 c 中实现一个单链表。 我以前用几种不同的语言做过很多次,但是在经历了几个小时的痛苦之后,我在使用 strcmp 时遇到了问题。 这是我正在使用的结构:

typedef struct node {
    char *name;
    float score;
    struct node *next;
} node;

问题是插入函数特有的,它应该类似于插入排序,因为我需要让列表中的节点按字母顺序排序。(我的教授指定插入函数进行排序,尽管没有将其称为插入排序)。

void insert(node **start, char *name, float score) { //  to insert a record into the linked list sorted by name in dictionary order.

//create new node
    node *n_node = new_node(name, score);

    node *current;
    current = *start;

    if (current != NULL) { //-----------if list is not empty
        node *prev = NULL;

        if (current->next != NULL) { //--if list has more than 1 element
            while (current != NULL && strcmp(name, current->name) > 0) { //cycle through list to sorted insertion point
             //                      ^^^^^^^Problem Here^^^^^^^^
            //while name is greater than current name, means lower on alphabet (z>a)
                prev = current;
                current = current->next;
            }
            if (current != NULL) { //-----not at end of list
            //once current is not < new node, connect between prev and current
                prev->next = n_node;
                n_node->next = current;
            } else { // ------------------at end of list
                prev->next = n_node;
            }

        } else { //-----------------------list has only one element
            current->next = n_node;
        }
    } else { //--------------------------List is empty - assign new node as first element
        *start = n_node;
    }

}

问题是我的程序在没有任何错误或警告的情况下崩溃和烧毁(我正在使用带有 CDT 的 eclipse)。 该程序运行良好时 while (current != NULL &amp;&amp; strcmp(name, current-&gt;name) &gt; 0) 被修改为 while (current != NULL /*&amp;&amp; strcmp(name, current-&gt;name) &gt; 0*/).

对我来说,namecurrent-&gt;name 导致strcmp 的操作出现问题似乎很明显,但我似乎无法解决这个问题。

编辑: 我要补充一点,这个函数是从另一个函数调用的,该函数从包含名称和标记对的文件中检索和标记字符串,但我的测试并未表明它通过调用传递了错误的字符串或字符。

更多细节,这里是我的 new_node 函数:

node *new_node(char *name, float score) {
    node *new = (struct node*) malloc(sizeof(struct node));
    new->name = malloc(strlen(name) + 1);
    strcpy(new->name, name);
    new->score = score;
    new->next = NULL;
    return new;
}

(我意识到使用new 作为节点的名称并不聪明,我会改变它) 以及调用插入的函数:

int data_import(node **startp, char *infilename) { // to import data from the file and insert .
    int max_line = 100;
    char line[max_line];
    char delimiters[] = ",";

    char name[500] = "";
    char *namep;
    namep = &name[0];

    float score = 0.0f;
    int i = 0;

    FILE *fi;
    char *token;
    // open file to read
    fi = fopen(infilename, "r");
    if (fi == NULL) {  // Cannot open the file.
        perror("error");
        return 0;
    }

    // read each line, increase counter, retrieve data
    while (fgets(line, max_line, fi) != NULL) {
        //fputs(line, stdout);  //console output confirmation

        token = strtok(line, delimiters);
        strcpy(namep, token);
        token = strtok(NULL, delimiters); //increment token to mark variable
        score = atof(token);
        insert(startp, namep, score);

        i++;
    }
    //close file
    fclose(fi);
    return i;
}

【问题讨论】:

  • 显示你的函数 new_node 和要插入的调用者。可疑的问题可能在那些。
  • 请注意,如果您的前两件商品乱序,您的清单将无法正确排序。
  • 您可以在gdb 下运行,当它崩溃时检查变量,这至少可以让您了解它崩溃的原因。当它到达strcmp 时,current 不能为 NULL,因此name 是无效指针或存在越界问题。可能不是问题,但您应该始终检查 malloc 是否返回有效指针。
  • 注意:使用指针指向指针可以将插入函数减少到大约十行代码,只包含一个循环和一个条件。

标签: c linked-list eclipse-cdt strcmp


【解决方案1】:

如果您将名为 apple 的元素作为您的第一个元素并尝试添加名为 about 的元素,会发生什么?

您将立即被抛出下面的 while 循环,并且您的 prev 将被取消分配:

while (current != NULL && strcmp(name, current->name) > 0) { //cycle through list to sorted insertion point
             //                      ^^^^^^^Problem Here^^^^^^^^
            //while name is greater than current name, means lower on alphabet (z>a)
                prev = current;
                current = current->next;
            }

我觉得这个特殊的部分很可疑:

之后您将进入以下程序:

 if (current != NULL) { //-----not at end of list
            //once current is not < new node, connect between prev and current
                prev->next = n_node;
                n_node->next = current;
            }

因为您的 *prev 未分配并且您尝试访问它(prev->next = n_node;)。您将在这里崩溃。

【讨论】:

  • 我不敢相信我错过了!似乎将这两个语句都包含在一个额外的 if(strcmp(name, current-&gt;name) &gt; 0) 中,并在链表顶部添加一个 else 就可以了。
猜你喜欢
  • 1970-01-01
  • 2018-11-03
  • 1970-01-01
  • 2021-11-08
  • 1970-01-01
  • 1970-01-01
  • 2015-07-22
  • 1970-01-01
  • 2017-11-21
相关资源
最近更新 更多