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

基于二叉搜索树的代码行计数器开发问题求助

二叉搜索树提取文本标识符问题修复

问题1:编译错误解决

代码里的n -> lineList = {};会触发编译错误,因为C语言不允许直接给数组赋值空大括号(数组属于不可赋值的左值)。替换成memset(n -> lineList, 0, sizeof(n -> lineList));来初始化数组,记得引入<string.h>头文件。

问题2:行号存储逻辑修复

  1. newTree函数原本没接收行号参数,创建新节点时没法存入第一次出现的行号,得加个int lineNumber参数,把行号放到lineList[0]里。
  2. 全局变量head没初始化,会导致野指针,直接初始化为NULL。
  3. 主循环里lineNumber没自增,所有行都被标成了行号1,每次读完一行后要让lineNumber++。
  4. 结构体里的struct Word * word;根本没定义,属于冗余代码,直接删掉。
  5. 提取标识符的内部循环可能越界,要加个i < len的判断。
  6. 输出行号时调整格式,加上方括号和逗号分隔,和期望输出一致。

修复后的完整代码

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

struct Node {
    char * data;
    int lineList[100];
    int counter;
    struct Node * ltree;
    struct Node * rtree;
};

struct Node * head = NULL; // 初始化避免野指针

struct Node * newTree(char * identifier, int lineNumber) {
    struct Node * n = malloc(sizeof(struct Node));
    n -> data = malloc(strlen(identifier) + 1);
    memset(n -> lineList, 0, sizeof(n -> lineList)); // 初始化行号数组
    n -> counter = 1;
    strcpy(n -> data, identifier);
    n -> lineList[0] = lineNumber; // 存入首次出现的行号
    n -> ltree = n -> rtree = NULL;
    return n;
}

struct Node * insert(struct Node * tree, char * identifier, int lineNumber) {
    if (tree == NULL)
        return newTree(identifier, lineNumber); // 传递行号给新节点
    int cmp = strcmp(identifier, tree -> data);
    if (cmp == 0) {
        // 防数组越界
        if (tree->counter >= 100) {
            printf("Warning: 行号数组已满,无法存储更多行号\n");
            return tree;
        }
        tree -> lineList[tree -> counter] = lineNumber;
        tree -> counter++;
        return tree;
    }

    if (cmp < 0)
        tree -> ltree = insert(tree -> ltree, identifier, lineNumber);
    else
        tree -> rtree = insert(tree -> rtree, identifier, lineNumber);
    return tree;
}

void inorder(struct Node * tree) {
    if (tree == NULL)
        return;
    inorder(tree -> ltree);

    printf("Identifier: %s\nCounter: %d\nLines Appeared: [", tree -> data, tree -> counter);
    for (int i = 0; i < tree -> counter; i++) {
        printf("%d", tree -> lineList[i]);
        if (i != tree->counter - 1) {
            printf(", "); // 行号间加逗号分隔
        }
    }
    printf("]\n\n");

    inorder(tree -> rtree);
}

int main() {
    FILE * fp = fopen("test.txt", "r");
    if (!fp) { // 检查文件是否打开成功
        perror("无法打开文件");
        return 1;
    }

    char buf[200];
    char id[100];
    int lineNumber = 1;
    int j;
    while (fgets(buf, sizeof(buf), fp)) {
        int i = 0;
        int len = strlen(buf);
        for (j = 0, i = 0; i < len; i++) {
            if (isalpha(buf[i]) || buf[i] == '_') {
                // 避免越界访问buf
                while (i < len && (isalnum(buf[i]) || buf[i] == '_'))
                    id[j++] = buf[i++];

                id[j] = '\0'; // 标识符字符串结尾

                head = insert(head, id, lineNumber);

                j = 0;
            }
        }
        lineNumber++; // 每行处理完行号加1
    }
    inorder(head);
    fclose(fp); // 关闭文件

    // 可选:添加递归释放内存的函数,防止内存泄漏
    return 0;
}

运行输出(针对你的test.txt)

Identifier: Hello
Counter: 2
Lines Appeared: [4, 6]

Identifier: Lochlann
Counter: 1
Lines Appeared: [5]

Identifier: main
Counter: 1
Lines Appeared: [3]

Identifier: printf
Counter: 3
Lines Appeared: [4, 5, 6]

Identifier: include
Counter: 1
Lines Appeared: [1]

Identifier: stdio
Counter: 1
Lines Appeared: [1]

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 06:20:27