机械工程C程序中链表函数recherche_noe、creation_noeud引发段错误求助
排查并修复你的机械工程C程序段错误问题
让我们一步步拆解你代码里的核心问题——尤其是recherche_noe和creation_noeud函数的致命缺陷,这些正是触发段错误的主要原因:
1. recherche_noe函数的致命错误
这个函数存在两个严重问题:
- 类型不匹配:函数声明返回
noeuds(即struct noeud*),但你返回的是maillages类型的temp,指针类型混乱直接触发段错误。 - 破坏原链表:你用
temp = mail指向原maillage结构体,然后修改temp->lst_noe = temp->lst_noe->next,这会直接移动原链表的头指针,导致节点丢失,后续访问链表时必然触发空指针访问。
修复后的recherche_noe:
noeuds recherche_noe(maillages mail, int num){ noeuds temp = mail->lst_noe; // 用noeuds类型指针遍历,不修改原链表 while(temp != NULL){ if(temp->num == num) return temp; temp = temp->next; } printf("Le noeud recherche n'existe pas\n"); return NULL; // 找不到返回NULL,避免返回垃圾值 }
2. creation_noeud函数的核心问题
- 返回类型错误:函数功能是创建节点链表,却定义返回
matrices类型,且没有任何return语句,导致栈中垃圾值被返回,引发未定义行为。应改为void类型。 - 输入处理逻辑缺陷:
getchar()的使用会吃掉有效输入,且未初始化节点的u或f,导致后续使用时出现垃圾值。
修复后的creation_noeud:
void creation_noeud(maillages mail){ int i; for (i=0; i<mail->nb_noe; i++){ noeuds new = (noeuds)malloc(sizeof(struct noeud)); if(new == NULL){ // 检查malloc是否成功,避免空指针 perror("Erreur allocation noeud"); exit(EXIT_FAILURE); } new->num = i+1; new->u = 0.0; // 初始化避免垃圾值 new->f = 0.0; printf("Deplacement du noeud %d (laissez vide pour saisir l'effort): ", i+1); while(getchar() != '\n'); // 清除缓冲区残留的换行符 fgets(buffer, sizeof(buffer), stdin); buffer[strcspn(buffer, "\n")] = '\0'; // 去掉换行符 if(strlen(buffer) > 0){ // 用户输入了位移u new->u = atof(buffer); } else { // 用户直接回车,输入力f printf("Donner l'effort du noeud %d: ", i+1); scanf("%lf", &new->f); } new->next = mail->lst_noe; mail->lst_noe = new; } }
3. recherche_elt函数的类似修复
和recherche_noe一样,它破坏了原链表的lst_elt指针,且返回逻辑错误:
修复后的recherche_elt:
elements recherche_elt(maillages mail, int num){ elements temp = mail->lst_elt; while(temp != NULL){ if(temp->num == num) return temp; temp = temp->next; } printf("L'element recherche n'existe pas\n"); return NULL; }
4. assemblage函数的错误修复
- 移除了未初始化
i就调用recherche_elt的错误语句 - 遍历元素时先获取当前元素,避免多次调用
recherche_elt破坏链表 - 增加空指针检查,避免访问无效内存
修复后的assemblage:
void assemblage(maillages mail){ int a,b,i; elements current_elt; noeuds current_noe; mail->K = creation_mat(mail->nb_noe, mail->nb_noe,"K"); mail->U = creation_mat(mail->nb_noe, 1,"U"); mail->F = creation_mat(mail->nb_noe, 1,"F"); // 初始化F矩阵 // 组装K矩阵 for (i=0; i<mail->nb_elt; i++){ current_elt = recherche_elt(mail, i+1); if(current_elt == NULL) continue; // 找不到元素则跳过 a = current_elt->n1 - 1; b = current_elt->n2 - 1; mail->K->tab[a][a] += current_elt->k; mail->K->tab[a][b] -= current_elt->k; mail->K->tab[b][a] -= current_elt->k; mail->K->tab[b][b] += current_elt->k; } // 组装U矩阵 for (i=0; i<mail->nb_noe; i++){ current_noe = recherche_noe(mail, i+1); if(current_noe != NULL){ mail->U->tab[i][0] = current_noe->u; } else { mail->U->tab[i][0] = 0.0; // 找不到节点则设为0 } } }
5. produit函数的补全(避免后续问题)
当前函数未完成,补全矩阵乘法逻辑:
matrices produit(matrices mat1, matrices mat2, char *nom){ int i,j,k; matrices prod = NULL; if(mat1->m != mat2->n){ printf("Erreur, les matrices ne sont pas compatibles\n\n"); return NULL; }else{ prod = creation_mat(mat1->n, mat2->m, nom); if(prod == NULL) return NULL; // 执行矩阵乘法 for(i=0; i<mat1->n; i++){ for(j=0; j<mat2->m; j++){ prod->tab[i][j] = 0.0; for(k=0; k<mat1->m; k++){ prod->tab[i][j] += mat1->tab[i][k] * mat2->tab[k][j]; } } } } return prod; }
额外注意事项
- 初始化
maillage结构体:在main中创建实例后,要将lst_noe、lst_elt初始化为NULL,nb_noe、nb_elt初始化为0,避免访问未初始化指针。 - 内存释放:程序结束前记得释放所有
malloc分配的内存(节点、元素、矩阵),避免内存泄漏。 - 输入验证:对用户输入的节点编号、元素的
n1/n2等进行范围验证,避免数组越界。
内容的提问来源于stack exchange,提问作者Talal C.
相关产品推荐
相关产品推荐

