c - 列表插入中 strcmp 的分段错误
问题描述
我正在尝试按字母顺序创建一个列表(首先按作者,然后按名称)。我试图通过比较两个字符串来做到这一点,strcmp()
但我遇到了分段错误。
我将把 GDB 运行结果和函数留在这里,它是我使用列表制作的第一个程序之一,因此代码可能还有其他错误。
GDB 运行:
Program received signal SIGSEGV, Segmentation fault.
0x0000000000400c65 in insert (lPtr=0x7fffffffeb38, isbn_i=978044,
name_i=0x7fffffffeb40 "Suzanne Collins",
author_i=0x7fffffffeb80 "The Hunger Games") at main.c:178
178 while(strcmp(author_i, currPtr->author) < 0){
typedef struct library{ //struct insertion from stdin
int isbn;
char *author;
char *name;
int act; //actual books in memory
int tot; //total books
struct library *nextPtr; //node
}Lib;
typedef Lib *NodePtr;
//called by a while, receives input from integers and two arrays of char
void insert(NodePtr *lPtr, int isbn_i, char *name_i, char *author_i){
NodePtr newPtr = malloc(sizeof(Lib));
newPtr->isbn = isbn_i; //scanf insertion in node
newPtr->author = author_i;
newPtr->name = name_i;
newPtr->nextPtr = NULL;
NodePtr prevPtr = NULL;
newPtr->act = 1;
newPtr->tot = 1;
if(lPtr == NULL){ //empty list
*lPtr = newPtr;
return;
}
NodePtr currPtr = *lPtr;
while(strcmp(author_i, currPtr->author) < 0){ //author is different, list slides
prevPtr = currPtr;
currPtr = currPtr->nextPtr;
}
if(strcmp(author_i, currPtr->author)== 0){ //same author
while(strcmp(name_i, currPtr->name) < 0){ //list sliding
prevPtr = currPtr;
currPtr = currPtr->nextPtr;
}
if(strcmp(name_i, currPtr->name) == 0){
currPtr->act += 1; //updates current counter and returns (to avoid duplicates)
currPtr->tot += 1;
free(newPtr);
return;
}
}
prevPtr->nextPtr = newPtr; //insertion between two nodes
newPtr->nextPtr = currPtr;
}
解决方案
在以下代码中:
while(strcmp(author_i, currPtr->author) < 0){ //author is different, list slides
prevPtr = currPtr;
currPtr = currPtr->nextPtr;
}
如果您的列表作者仅包含应在您到达末尾而没有找到插入位置的位置后排序的作者,则您不检查是否currPtr->nextPtr
是NULL
(在列表的末尾) 。
author_i
示例(为简单起见,省略了无关字段):
currPtr = {author:"Cressida Cowell", nextPtr=NULL};
insert(lPtr = &currPtr, ...,author_i = "Suzanne Collins", ...);
/// insertion location loop
// while loop unrolled
if("Suzanne Collins" > "Cressida Cowell") {
prevPtr = currPtr ; // prevPtr = {author:"Cressida Cowell", nextPtr=NULL};
currPtr = currPtr->nextPtr; // currPtr = NULL
}
// next iteration
if("Suzanne Collins"> NULL->author ) // de-referencing a NULL pointer, causing a Segmentation fault
您可以通过以下修复部分修复代码:
while(strcmp(author_i, currPtr->author) < 0){ //author is different, list slides
prevPtr = currPtr;
currPtr = currPtr->nextPtr;
if(currPtr == NULL) {break;} // exit loop if at end of the list
}
您仍然需要处理currPtr == NULL
以避免在currPtr
检查标题时取消引用 NULL 指针,我的建议是结合插入位置搜索循环中的条件。
// implement a node comparison function
int compareLib(NodePtr lib1, NodePtr lib2) {
if((lib1 == NULL)||(lib2 == NULL)) return 0;
int author_compare = strcmp(lib1->author, lib2->author);
if (author_compare != 0) return author_compare;
return strcmp(lib1->name, lib2->name);
}
...
while(compareLib(newPtr, currPtr)){
prevPtr = currPtr;
currPtr = currPtr->nextPtr;
if(currPtr == NULL) {break;} // exit loop if at end of the list
}
currPtr == NULL
添加新列表节点时仍然需要处理
推荐阅读
- javascript - JavaScript 将字符串的首字母大写
- sql - 在 Oracle 中创建一个触发器,用于插入或更新表,同时保持旧记录不变
- jenkins - pod init 状态,同时在 k8s 中使用 helm 安装 jenkins
- python - RGB 到 HSD 转换
- jestjs - 开玩笑测试错误:无法解析 /myProj/public/libs/angularjs-datetime-picker/package.json
- wordpress - 从 Live WordPress 迁移到 Localhost 后,得到“不允许访问页面”
- c# - 在 Xamarin 中的 UI 和代码模块之间传递值的最佳方式
- python - Atom 中的“脚本”在哪里?
- angular - 是否可以以角度突出显示文本?
- android - 使用 Retrofit2 时总是调用 OnFailure 方法