You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言符号表Insert函数触发段错误(core dumped)问题求助

C语言符号表段错误问题解决

问题背景

需修改给定的C语言符号表代码,要求:

  • 移除字符数组"label"
  • 将结构体中的symbol从char[]改为char*
  • 仅允许在main函数中接收输入

修改后调用Insert函数时持续出现segmentation fault (core dumped)错误,调整链表赋值方式后问题依旧,原代码如下:

#include<stdio.h>
/* #include<conio.h> */
#include<malloc.h>
#include<string.h>
#include<stdlib.h>
int size=0;
void Insert();
void Display();
void Delete(); // Prototypes declared since functions are declared after our main function.
int Search(char lab[]);
void Modify();

struct SymbTab { 
    char* symbol;
    int addr;
    struct SymbTab *next;};

struct SymbTab *first,*last; //defines two pointers that are automatically set to NULL.

void main() { // Main function: the only function that takes in input.
    int op,y; // Variable declarations.
    int addrs;
    char symbl[30];
    do { 
        printf("\n\tSYMBOL TABLE IMPLEMENTATION\n");
        printf("\n\t1.INSERT\n\t2.DISPLAY\n\t3.DELETE\n\t4.SEARCH\n\t5.END\n");
        printf("\n\tEnter your option : ");
        scanf("%d",&op); // Asks for input.
        switch(op) { // All possible responses to whatever the user inputs.
        case 1: // Calls the Insert case.
            printf("Insert symbol: ");
            fgets(symbl, sizeof(symbl), stdin);
            scanf("%s", symbl); // Takes user input and stores in symbol.
            printf("Insert address:");
            scanf("%d", addrs); // Takes user input and stores in addr.
            Insert(symbl, addrs); // Passes symbol and addr (which now contain the user's input) as parameters into the Insert function.
            break; // Exists the Insert case and reruns starting at the beginning of the "do".
        case 2: // Calls the Display case.
            Display(); // Calls the Display function.
            break; // Exists the Display case and reruns starting at the beginning of the "do".
        case 3: // Calls the Delete case.
            printf("\n\tEnter the symbol to be deleted: %s", symbl);
            y = Search(symbl);
            if(y == 0)
                printf("\n\tLabel not found\n");
                break;
            if (y == 1) 
                Delete(symbl);
                break; // Exists the Delete case and reruns starting at the beginning of the "do".
        case 4: // Calls the Search case.
            scanf("\n\tEnter the label to be searched: %s", symbl);
            y=Search(symbl);
            printf("\n\tSearch Result:");
            if(y==1)
                printf("\n\tThe label is present in the symbol table\n");
            else
                printf("\n\tThe label is not present in the symbol table\n");
            break; // Exists the Search case and reruns starting at the beginning of the "do".
        case 5: // If the user's input is invalid/doesn't match with any of the existing functions, the program exits/ends.
            exit(0);
            }
    }
    while(op<5);

}  /* and of main */

// Precondition: Two parameters: a key (string of characters) and an address (int).
void Insert(char * symbl, int address) {
    struct SymbTab *p;
    p=malloc(sizeof(struct SymbTab));
    strcpy(p->symbol,symbl);
    p->next=NULL;
    if (size==0) {
        first=p;
        last=p;
    }
    else
    {
        last->next=p;
        last=p;
    }
    size++;
printf("\n\tLabel inserted\n");
    }

// Postcondition: Variable (with it's corresponding address) are added into the symbol table, and print statement is displatyed on the screen.

错误原因分析

  1. 未初始化指针的非法访问:Insert函数中,p->symbol是未分配内存的空指针,直接用strcpy复制字符串会写入非法内存区域,这是段错误的核心原因。
  2. scanf参数错误:main中scanf("%d", addrs)缺少取地址符&,会把输入值写入随机内存地址,引发崩溃或未定义行为。
  3. 输入处理混乱:scanf("%d", &op)后会留下换行符,后续fgets会读取空行,导致symbl内容异常。
  4. 函数声明与定义不匹配:Insert的声明是void Insert();,但定义是带参数的void Insert(char * symbl, int address),调用时会出现参数不匹配的未定义行为。
  5. 分支逻辑错误:case 3中的if语句没有用大括号包裹,导致break会直接跳出switch,即使y==1也不会执行Delete操作。
  6. 错误的scanf用法:case 4中用scanf输出提示字符串是错误的,应该先用printf提示,再用scanf读取输入。

修正后的完整代码

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int size = 0;
void Insert(char *symbl, int address);
void Display();
void Delete(char *symbl);
int Search(char *lab);
void Modify();

struct SymbTab { 
    char* symbol;
    int addr;
    struct SymbTab *next;
};

struct SymbTab *first = NULL, *last = NULL;

int main() {
    int op, y;
    int addrs;
    char symbl[30];
    char dummy[2]; // 用于读取换行符

    do { 
        printf("\n\tSYMBOL TABLE IMPLEMENTATION\n");
        printf("\n\t1.INSERT\n\t2.DISPLAY\n\t3.DELETE\n\t4.SEARCH\n\t5.END\n");
        printf("\n\tEnter your option : ");
        scanf("%d", &op);
        // 读取scanf留下的换行符
        fgets(dummy, sizeof(dummy), stdin);

        switch(op) {
            case 1:
                printf("Insert symbol: ");
                fgets(symbl, sizeof(symbl), stdin);
                // 去掉fgets读取的换行符
                symbl[strcspn(symbl, "\n")] = '\0';
                printf("Insert address: ");
                scanf("%d", &addrs);
                // 读取scanf留下的换行符
                fgets(dummy, sizeof(dummy), stdin);
                Insert(symbl, addrs);
                break;
            case 2:
                Display();
                break;
            case 3:
                printf("\n\tEnter the symbol to be deleted: ");
                fgets(symbl, sizeof(symbl), stdin);
                symbl[strcspn(symbl, "\n")] = '\0';
                y = Search(symbl);
                if(y == 0) {
                    printf("\n\tLabel not found\n");
                } else if (y == 1) {
                    Delete(symbl);
                }
                break;
            case 4:
                printf("\n\tEnter the label to be searched: ");
                fgets(symbl, sizeof(symbl), stdin);
                symbl[strcspn(symbl, "\n")] = '\0';
                y = Search(symbl);
                printf("\n\tSearch Result:");
                if(y == 1) {
                    printf("\n\tThe label is present in the symbol table\n");
                } else {
                    printf("\n\tThe label is not present in the symbol table\n");
                }
                break;
            case 5:
                exit(0);
            default:
                printf("\n\tInvalid option, try again\n");
        }
    } while(op < 5);

    return 0;
}

void Insert(char *symbl, int address) {
    struct SymbTab *p = malloc(sizeof(struct SymbTab));
    if(p == NULL) {
        printf("\n\tMemory allocation failed\n");
        return;
    }
    // 为symbol分配内存并复制字符串
    p->symbol = malloc(strlen(symbl) + 1);
    if(p->symbol == NULL) {
        free(p);
        printf("\n\tMemory allocation failed for symbol\n");
        return;
    }
    strcpy(p->symbol, symbl);
    p->addr = address;
    p->next = NULL;

    if(size == 0) {
        first = p;
        last = p;
    } else {
        last->next = p;
        last = p;
    }
    size++;
    printf("\n\tLabel inserted\n");
}

void Display() {
    struct SymbTab *temp = first;
    if(size == 0) {
        printf("\n\tSymbol table is empty\n");
        return;
    }
    printf("\n\tSymbol\tAddress\n");
    printf("\t----------------\n");
    while(temp != NULL) {
        printf("\t%s\t%d\n", temp->symbol, temp->addr);
        temp = temp->next;
    }
}

int Search(char *lab) {
    struct SymbTab *temp = first;
    while(temp != NULL) {
        if(strcmp(temp->symbol, lab) == 0) {
            return 1;
        }
        temp = temp->next;
    }
    return 0;
}

void Delete(char *symbl) {
    struct SymbTab *temp = first, *prev = NULL;
    while(temp != NULL && strcmp(temp->symbol, symbl) != 0) {
        prev = temp;
        temp = temp->next;
    }
    if(temp == NULL) {
        printf("\n\tLabel not found\n");
        return;
    }
    // 删除表头节点
    if(prev == NULL) {
        first = first->next;
        if(first == NULL) {
            last = NULL;
        }
    } else {
        prev->next = temp->next;
        if(temp == last) {
            last = prev;
        }
    }
    free(temp->symbol);
    free(temp);
    size--;
    printf("\n\tLabel deleted\n");
}

关键修改说明

  • 为p->symbol分配内存:用malloc(strlen(symbl)+1)申请足够空间存储字符串(加1是为了存结束符\0),避免非法内存访问。
  • 修正scanf参数:给addrs加上取地址符&,确保输入写入正确内存。
  • 处理输入换行符:用fgets读取scanf留下的换行符,避免后续输入混乱;同时去掉fgets读取的换行符,保证字符串格式正确。
  • 修正函数声明:让Insert、Delete的声明与定义参数匹配,避免未定义行为。
  • 修复分支逻辑:给case3的if语句加上大括号,确保逻辑正确。
  • 补全缺失的Display、Search、Delete函数实现:原代码中这些函数只有声明没有实现,运行时会报错。

内容的提问来源于stack exchange,提问作者Zaynab B.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 23:30:45