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

C语言程序执行correcttext函数后意外终止问题求助

程序执行correcttext后意外终止问题排查

问题场景

  • 操作流程:输入1加载coffee.txt文件,输入2调用correcttext函数加载englishWords.txt字典文件并进行文本比对
  • 问题表现:correcttext函数完成预期功能后,程序未返回主菜单,短暂停顿后意外终止

相关代码

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

int getchoice();
int print(char **x, int num);
int entertext(char ***x);
int correcttext(char ***x);// 仅输出文本中存在于字典里的单词
int countwords(char **x);
int countletters(char **x);

int main() {
    char **text = NULL;
    int choice=0;
    int num=0;
    while ((choice = getchoice()) != -1) {
        switch (choice) {
            case 1:
                num = entertext(&text);
                print(text, num);
                break;
            case 2:
                correcttext(&text);              
                break;
            case 3:
                countwords(text);
                break;
            case 4:
                countletters(text);
                break;
            default:
                break;
        }
    }

    for (int i = 0; i < num; i++) {
        free(text[i]);
    }
    free(text);

    return 0;
}

int getchoice(void) {
    int choice;
    printf("\n1: 输入文本\n2: 校正文本\n3: 单词数量\n4: 字母数量\n-1: 退出\n>");
    while (scanf("%d", &choice) != 1) {
        printf("无效选项... 请输入1-4之间的数字,或输入-1退出: ");
        while (getchar() != '\n');
    }
    if (choice < -1 || choice > 4) {
        printf("无效选项... 请输入1-4之间的数字,或输入-1退出: ");
        exit(1);
    }
    return choice;
}

int print(char **x, int num) {
    for (int i = 0; i < num; i++) {
        printf(" %s\n", x[i]);
    }
    return 0;
}

int entertext(char ***x) {
    int size = 0;
    *x = NULL;
    char *word = NULL;
    FILE *file;
    file = fopen("coffee.txt", "r");
    if (file == NULL) {
        printf("\n打开文件错误\n");
        return 0;
    }
    while (fscanf(file, "%49s", word = malloc(50 * sizeof(char))) != EOF) {
        size++;
        *x = realloc(*x, size * sizeof(char *));
        (*x)[size - 1] = malloc((strlen(word) + 1) * sizeof(char));
        strcpy((*x)[size - 1], word);
        free(word);  // 将word内容复制到(*x)后释放内存
    }
    fclose(file);

    return size;
}

int correcttext(char ***x) {
    int dictSize = 0;
    char **dict = NULL;
    char *dictWord = NULL;  // 重命名变量避免冲突
    FILE *file;
    file = fopen("englishWords.txt", "r");
    if (file == NULL) {
        printf("\n打开文件错误\n");
        return 0;
    }

    while (fscanf(file, "%49s", dictWord = malloc(50 * sizeof(char))) != EOF) {
        dictSize++;
        dict = realloc(dict, dictSize * sizeof(char *));
        dict[dictSize - 1] = malloc((strlen(dictWord) + 1) * sizeof(char));
        strcpy(dict[dictSize - 1], dictWord);
        free(dictWord);  // 将dictWord内容复制到dict后释放内存
    }

    fclose(file);

    // 这里的问题:用字典的长度dictSize遍历text,而不是text的实际长度
    // 同时,entertext加载的text每个元素是单个单词,不需要拆分
    for (int i = 0; i < dictSize; i++) {
        for (int j = 0; (*x)[i][j] != '\0'; j++) {
            char word[30] = "";
            int k = 0;
            while ((*x)[i][j] != ' ' && (*x)[i][j] != '\t' && (*x)[i][j] != '\n' && (*x)[i][j] != '\0') {
                word[k++] = (*x)[i][j++];
            }
            word[k] = '\0';

            for (int m = 0; m < dictSize; m++) {
                if (strcmp(word, dict[m]) == 0) {
                    printf("%s\n", (*x)[i]);
                    break;
                }
            }

            if ((*x)[i][j] == '\0') {
                break;
            }
        }
    }

    for (int i = 0; i < dictSize; i++) {
        free(dict[i]);
    }
    free(dict);
    return 0;
}

int countwords(char **x) {
    printf("单词数量, %s", x[0]);
    return 0;
}

int countletters(char **x) {
    printf("字母数量, %s", x[0]);
    return 0;
}  

问题原因及修复方案

核心问题1:correcttext遍历越界

correcttext用字典的单词数dictSize遍历text数组,但text的实际长度是main函数里的num,两者没有关联。如果字典单词数多于text的元素数,循环会访问text的越界内存,直接触发程序崩溃。

修复:修改correcttext参数,传入text的实际长度:

// 函数声明修改
int correcttext(char ***x, int textSize);

// main函数调用修改
case 2:
    correcttext(&text, num);              
    break;

// correcttext实现修改
int correcttext(char ***x, int textSize) {
    // 字典加载部分不变

    // 外层循环改为遍历text的实际长度
    for (int i = 0; i < textSize; i++) {
        char *currentWord = (*x)[i];
        for (int m = 0; m < dictSize; m++) {
            if (strcmp(currentWord, dict[m]) == 0) {
                printf("%s\n", currentWord);
                break;
            }
        }
    }

    // 字典释放部分不变
}

核心问题2:correcttext单词拆分逻辑冗余

entertext用fscanf("%49s")加载文件,会自动按空格分割单词,text的每个元素都是独立单词,不存在分隔符。原代码的拆分逻辑完全多余,还会引发额外内存访问错误。

修复:删除原函数中拆分单词的内层循环,直接用text[i]与字典比对。

次要问题:getchoice粗暴退出

输入无效选项时,原代码直接调用exit(1)终止程序,不符合返回主菜单重新输入的预期。

修复:替换exit(1)为循环重新获取输入:

int getchoice(void) {
    int choice;
    while (1) {
        printf("\n1: 输入文本\n2: 校正文本\n3: 单词数量\n4: 字母数量\n-1: 退出\n>");
        while (scanf("%d", &choice) != 1) {
            printf("无效选项... 请输入1-4之间的数字,或输入-1退出: ");
            while (getchar() != '\n');
        }
        if (choice >= -1 && choice <=4) {
            break;
        }
        printf("无效选项... 请输入1-4之间的数字,或输入-1退出: ");
        while (getchar() != '\n');
    }
    return choice;
}

内容的提问来源于stack exchange,提问作者BraVeHurt

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 11:22:29