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

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)

问题根源

  1. 带空格输入丢失第二个整数:初始统计的n_spaces是空格数量,但后续循环中每遇到空格就让n_spaces++,导致数组索引越界,覆盖了正常存储的token数据。
  2. 无空格输入崩溃:输入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;
}

修复说明

  1. 处理换行符:用strcspn移除fgets读入的换行符,避免干扰解析逻辑。
  2. 逐字符解析:直接识别连续数字和单个运算符,无论输入是否带空格都能正确拆分。
  3. 内存优化:初始分配足够空间,最后用realloc调整到实际所需大小,避免索引越界。
  4. 内存释放:原代码未释放单个token的内存,修复后先逐个释放token,再释放数组。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 01:55:16