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

如何将数学表达式字符串分割为指定子串并存入数组?附C代码求助

如何将表达式字符串分割为自定义子串?

你需要将数学表达式字符串分割为包含标识符、运算符、函数名、括号等的数组,要求忽略空格影响,例如y = sin(log(tan(x)))和y=sin(log(tan(x)))、y = sin ( log ( tan ( x ) ) )都要分割成{"y", "=", "sin", "(", "log", "(", "tan", "(", "x", ")", ")", ")"}这样的结果。

你现有代码的核心问题

你的当前代码存在几个致命问题:

  • strtok用法错误:strtok的第二个参数是分隔符字符集合,不是子串。比如你传入"sin"作为分隔符,strtok会把s、i、n这三个字符单独当成分隔符,而不是把"sin"作为整体识别,完全达不到你的需求。
  • 无控制调用strtok:多次循环调用strtok却未处理返回值为NULL的情况,会导致指针越界或读取无效内存。
  • 数组与循环逻辑混乱:st数组定义了7个元素,但循环仅执行4次,剩余未初始化的元素打印时会输出垃圾值;firstDone的逻辑也无法正确遍历所有需要分割的子串。

正确实现思路与代码

这种场景本质是简单的词法分析,需要逐个字符扫描字符串,识别预定义的关键字、符号和标识符,同时跳过空格。以下是可行的C实现:

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

// 预定义需要识别的关键字(函数名)
const char *keywords[] = {"sin", "cos", "log", "tan", NULL};
// 单个字符的符号
const char symbols[] = "=()";

// 检查当前位置是否匹配关键字,匹配成功返回关键字长度,否则返回0
int match_keyword(const char *str) {
    for (int i = 0; keywords[i] != NULL; i++) {
        int len = strlen(keywords[i]);
        if (strncmp(str, keywords[i], len) == 0) {
            // 避免类似"sina"被误识别为"sin"
            if (!isalpha(str[len])) {
                return len;
            }
        }
    }
    return 0;
}

// 分割表达式,结果存入tokens数组,返回token数量
int split_expression(const char *expr, char tokens[][20], int max_tokens) {
    int token_count = 0;
    int len = strlen(expr);
    int i = 0;

    while (i < len && token_count < max_tokens) {
        // 跳过所有空白字符
        while (isspace(expr[i])) {
            i++;
        }
        if (i >= len) break;

        // 尝试匹配关键字
        int kw_len = match_keyword(&expr[i]);
        if (kw_len > 0) {
            strncpy(tokens[token_count], &expr[i], kw_len);
            tokens[token_count][kw_len] = '\0';
            token_count++;
            i += kw_len;
            continue;
        }

        // 识别单个字符符号
        char c = expr[i];
        if (strchr(symbols, c) != NULL) {
            tokens[token_count][0] = c;
            tokens[token_count][1] = '\0';
            token_count++;
            i++;
            continue;
        }

        // 处理标识符(连续字母组成的变量名,比如y、x)
        if (isalpha(c)) {
            int start = i;
            while (i < len && isalpha(expr[i])) {
                i++;
            }
            int id_len = i - start;
            strncpy(tokens[token_count], &expr[start], id_len);
            tokens[token_count][id_len] = '\0';
            token_count++;
            continue;
        }

        // 遇到未知字符时跳过(也可根据需求添加报错逻辑)
        i++;
    }

    return token_count;
}

int main() {
    char expr[] = "y = sin(log(tan(x)))";
    char tokens[20][20]; // 预设最多存储20个token
    int count = split_expression(expr, tokens, 20);

    printf("分割结果:\n");
    for (int i = 0; i < count; i++) {
        printf("\"%s\"%s", tokens[i], (i == count-1) ? "" : ", ");
    }
    printf("\n");

    // 测试带空格的表达式
    char expr2[] = "sin ( cos ( x ) )";
    int count2 = split_expression(expr2, tokens, 20);
    printf("\n带空格的表达式分割结果:\n");
    for (int i = 0; i < count2; i++) {
        printf("\"%s\"%s", tokens[i], (i == count2-1) ? "" : ", ");
    }
    printf("\n");

    return 0;
}

代码关键说明

  • 关键字匹配:match_keyword函数确保只有完整的关键字被识别,避免长字符串被误拆分。
  • 空格处理:通过isspace跳过所有空白字符,保证空格不影响分割结果。
  • 多类型识别:依次处理关键字、单字符符号、标识符,覆盖表达式的常见组成部分。
  • 边界控制:限制token数量避免数组越界,同时处理字符串末尾的边界情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 09:05:57