如何将数学表达式字符串分割为指定子串并存入数组?附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
相关产品推荐
相关产品推荐

