指针与scanf引发访问违规问题排查求助
商品出入库程序访问违规问题排查
问题背景
我写的这段代码原本要实现:输入商品名称、出入库标识(单个字母,如i=入库、o=出库)和转移数量,输入"FINE"时程序结束。但现在保存商品数量时出现访问违规,找不到问题所在,求帮忙排查:
原代码
#define MAX 20 #define END "FINE" typedef struct type_struct { char name[MAX]; char move[2]; int quantity; struct type_struct* next; }type; void insert(type* p) { type* aux; aux = p; while (aux != NULL) aux = aux->next; aux = malloc(sizeof(type)); printf("name of good: "); scanf("%s", aux->name); getchar(); printf("in or out?: "); scanf("%c", aux->move); printf("quantity: "); scanf("%d", aux->quantity); printf("\n"); } int main(void) { type* phrase=NULL; char fine[5]; strcpy(fine, END); do { insert(phrase); } while ((strcmp(phrase, fine) == 0)); }
错误点分析与修复
核心访问违规原因:读取数量时
scanf("%d", aux->quantity);传参错误,scanf读整数需要传入变量地址,应该改成scanf("%d", &aux->quantity);。直接传aux->quantity会把输入的数值当成内存地址写入,必然触发访问违规。链表插入逻辑失效:
- insert函数的参数是
type* p,属于值传递,main里的phrase永远是NULL,新节点根本无法链接到链表上。需要把参数改成指针的指针type** p,才能修改外部的链表头指针。 - 找到链表尾后malloc的新节点,没有把它链接到原链表的尾部,导致链表永远无法正常构建。
- insert函数的参数是
循环结束条件完全错误:
strcmp(phrase, fine)是把链表指针和字符串数组比较,类型不匹配,逻辑完全不成立。应该在输入商品名称时判断是否为"FINE",如果是就终止程序。野指针问题:malloc新节点后没有初始化
next指针为NULL,可能导致后续链表遍历出现未知错误。
修复后的完整代码
#include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX 20 #define END "FINE" typedef struct type_struct { char name[MAX]; char move[2]; int quantity; struct type_struct* next; } type; void insert(type** p) { type* aux = *p; // 定位到链表最后一个节点 while (aux != NULL && aux->next != NULL) { aux = aux->next; } type* new_node = malloc(sizeof(type)); if (!new_node) { printf("内存分配失败\n"); return; } new_node->next = NULL; // 初始化next指针 printf("输入商品名称(输入FINE结束):"); scanf("%s", new_node->name); // 判断是否触发结束条件 if (strcmp(new_node->name, END) == 0) { free(new_node); *p = NULL; // 告诉main循环终止 return; } printf("出入库标识(i/o):"); scanf("%s", new_node->move); new_node->move[1] = '\0'; // 确保字符串合法 printf("转移数量:"); scanf("%d", &new_node->quantity); printf("\n"); // 将新节点加入链表 if (*p == NULL) { *p = new_node; } else { aux->next = new_node; } } int main(void) { type* phrase = NULL; do { insert(&phrase); } while (phrase != NULL); // 清理链表内存,避免泄漏 type* temp; while (phrase != NULL) { temp = phrase; phrase = phrase->next; free(temp); } return 0; }
内容的提问来源于stack exchange,提问作者Poinsaett
相关产品推荐
相关产品推荐

