C语言字符串解析问题:表达式拆分整数与运算符失败求助
C语言字符串解析函数问题
我刚学C语言,现在碰到字符串解析的问题。需要解析像50 + 50或50+50这样的输入字符串,把它拆成包含50、+、50的数组,但当前代码有问题:输入带空格时会丢失第二个整数,输入无空格时程序直接崩溃。
以下是我的辅助函数、parseString函数及测试用main函数:
int testnumber = 0; void test() { testnumber++; printf("Test %d", testnumber); printf("\n"); } bool isNumber(char *token) { int i; for (i = 0; token[i] != '\0'; i++) { if (!isdigit(token[i])) return false; } return true; } bool isOperator(char *token) { if (strlen(token) > 1) return false; switch (token[0]) { case '+': case '-': case '*': case '/': case '%': return true; default: return false; } } char **parseString(char *input) { test(); int n_spaces = 0, i, start = 0, end; for (i = 0; i < strlen(input); i++) { if (input[i] == ' ') { n_spaces++; } } char **tokens = malloc(sizeof(char *) * (n_spaces + 1)); for (i = 0; i < strlen(input); i++) { if (input[i] == ' ') { end = i; tokens = realloc(tokens, sizeof(char*) * (n_spaces + 1)); tokens[n_spaces] = malloc(end - start + 1); strncpy(tokens[n_spaces], input + start, end - start); tokens[n_spaces][end - start] = '\0'; start = i + 1; n_spaces++; } } end = strlen(input); tokens[n_spaces] = malloc(end - start + 1); strncpy(tokens[n_spaces], input + start, end - start); tokens[n_spaces][end - start] = '\0'; n_spaces++; int j = 0; for (i = 0; i < n_spaces; i++) { char *temp = tokens[i]; if (isNumber(temp)) { tokens[j++] = temp; } else if (isOperator(temp)) { tokens[j++] = temp; } } test(); tokens[j] = NULL; return tokens; }
测试用main函数:
int main() { // Declare variable 'size' and initialize it with 100 size_t size = 100; // Allocate memory for a character array and assign it to pointer 'input' char *input = malloc(size); // Read input from standard input and store it in the character array 'input' fgets(input, (int) size, stdin); char **tokens = parseString(input); printf("%s\n", tokens[0]); printf("%s\n", tokens[1]); printf("%s\n", tokens[2]); test(); int i; /*for (i = 0; *(tokens + i); i++) { printf("%s\n", *(tokens + i)); }*/ test(); // Free up memory. free(input); free(tokens); return 0; }
测试情况
输入50 + 50时输出:
Test 1 Test 2 50 + (null) Test 3 Test 4 Process finished with exit code 0
输入50+50时输出:
Test 1 Test 2 (null) Process finished with exit code -1073741819 (0xC0000005)
问题根源
- 带空格输入丢失第二个整数:初始统计的
n_spaces是空格数量,但后续循环中每遇到空格就让n_spaces++,导致数组索引越界,覆盖了正常存储的token数据。 - 无空格输入崩溃:输入
50+50时没有空格,整个字符串被作为一个token存入,但这个token既不是纯数字也不是单个运算符,筛选后tokens[0]被设为NULL,main函数访问tokens[1]和tokens[2]时触发内存越界错误。
修复后的代码
核心逻辑改成逐字符识别数字和运算符,不再依赖空格分割:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include <stdbool.h> int testnumber = 0; void test() { testnumber++; printf("Test %d\n", testnumber); } // 判断单个字符是否为数字 bool isNumberChar(char c) { return isdigit(c); } // 判断单个字符是否为运算符 bool isOperatorChar(char c) { switch(c) { case '+': case '-': case '*': case '/': case '%': return true; default: return false; } } char **parseString(char *input) { test(); // 去掉fgets读入的换行符 input[strcspn(input, "\n")] = '\0'; int tokenCount = 0; // 初始分配足够空间(最多3个有效token+NULL) char **tokens = malloc(sizeof(char*) * 4); int len = strlen(input); int i = 0; while(i < len) { // 跳过空格 while(i < len && isspace(input[i])) { i++; } if(i >= len) break; // 截取连续数字 if(isNumberChar(input[i])) { int start = i; while(i < len && isNumberChar(input[i])) { i++; } int tokenLen = i - start; tokens[tokenCount] = malloc(tokenLen + 1); strncpy(tokens[tokenCount], input + start, tokenLen); tokens[tokenCount][tokenLen] = '\0'; tokenCount++; } // 截取单个运算符 else if(isOperatorChar(input[i])) { tokens[tokenCount] = malloc(2); tokens[tokenCount][0] = input[i]; tokens[tokenCount][1] = '\0'; tokenCount++; i++; } // 跳过无效字符(可选,假设输入仅包含数字、运算符和空格) else { i++; } } // 添加结束标记并调整内存大小 tokens[tokenCount] = NULL; tokens = realloc(tokens, sizeof(char*) * (tokenCount + 1)); test(); return tokens; } int main() { size_t size = 100; char *input = malloc(size); fgets(input, (int)size, stdin); char **tokens = parseString(input); // 遍历输出所有有效token for(int i = 0; tokens[i] != NULL; i++) { printf("%s\n", tokens[i]); } test(); test(); // 正确释放内存:先释放每个token,再释放数组本身 for(int i = 0; tokens[i] != NULL; i++) { free(tokens[i]); } free(tokens); free(input); return 0; }
修复说明
- 处理换行符:用
strcspn移除fgets读入的换行符,避免干扰解析逻辑。 - 逐字符解析:直接识别连续数字和单个运算符,无论输入是否带空格都能正确拆分。
- 内存优化:初始分配足够空间,最后用
realloc调整到实际所需大小,避免索引越界。 - 内存释放:原代码未释放单个token的内存,修复后先逐个释放token,再释放数组。
内容的提问来源于stack exchange,提问作者Gurka
相关产品推荐
相关产品推荐

