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

如何让支持括号的C语言计算器处理含空格的表达式?

解决带空格表达式的计算器问题

你实现的计算器在处理带空格的表达式(如(2 + 3) * 2)时输出错误结果2,但无空格的表达式(如(2+3)*2)能得到正确结果10,问题出在输入读取不完整和未处理空格字符两个核心环节,以下是具体修复方案:

问题根源分析

  1. 输入截断:原代码使用scanf("%s", str)读取输入,%s会在遇到空格时停止读取,因此输入(2 + 3) * 2时,str实际只存储了(2,后续内容完全未被处理,导致计算错误。
  2. 空格干扰逻辑:即使能读取完整带空格的字符串,原代码没有跳过空格,空格会被当作非数字、非运算符的特殊字符进入栈操作逻辑,破坏计算流程。

修正后的完整代码

#include <stdio.h> 
#include <stdlib.h>
#include <string.h>
#define MAX_SIZE 1024 

int insert_operand(int *operand, int * top_num, int num) /* 数据入栈 */
{
     (*top_num) ++;
     operand[*top_num] = num; /* 存储数据 */
      
     return 0; /* 正常退出 */
}

int insert_oper (char * oper , int *top_oper , char ch) 
{
     (*top_oper)++;
     oper[*top_oper] = ch; /* 存储运算符 */

     return 0; /* 正常退出 */
}

int compare(char *oper , int *top_oper , char ch) /* 比较运算符优先级 */
{
     if((oper[*top_oper] == '-' || oper[*top_oper] == '+') 
             && (ch == '*' || ch == '/'))
     {
         return 0; // 当前运算符优先级更高,直接入栈
     }

     else if(*top_oper == -1 || ch == '('
             || (oper[*top_oper] == '(' && ch != ')'))
     {
         return 0; // 栈空、左括号或左括号后非右括号,直接入栈
     }

     else if (oper[*top_oper] =='(' && ch == ')')
     {
         (*top_oper)--; // 弹出左括号,不处理右括号
         return 1; 
     }

     else
     {
         return -1; // 当前运算符优先级更低,先计算栈顶运算
     }

}

int deal_date(int *operand ,char *oper ,int *top_num, int *top_oper) /* 执行运算 */
{
     int num_1 = operand[*top_num]; /* 取出栈顶两个数据 */
     int num_2 = operand[*top_num - 1];

     int value = 0;

     if(oper[*top_oper] == '+') 
     {
         value = num_1 + num_2;
     }

     else if(oper[*top_oper] == '-') 
     {
         value = num_2 - num_1;
     }

     else if(oper[*top_oper] == '*') 
     {
         value = num_2 * num_1;
     }

     else if(oper[*top_oper] == '/') 
     {
         value = num_2 / num_1;
     }

     (*top_num) --; /* 数据栈栈顶下移 */
     operand[*top_num] = value; /* 运算结果入栈 */
     (*top_oper) --; /* 运算符栈栈顶下移 */

     return 0; // 补充缺失的返回值
}

int main()
{
     int operand[MAX_SIZE] = {0}; /* 数据栈初始化 */
     int top_num = -1;

     char oper[MAX_SIZE] = {0}; /* 运算符栈初始化 */
     int top_oper = -1;

     // 修改1:用fgets读取整行输入,支持空格
     char *str = (char *) malloc (sizeof(char) * 100); 
     if (str == NULL) {
         perror("malloc failed");
         return 1;
     }
     fgets(str, 100, stdin);

     // 修改2:去除fgets读取到的换行符(如果存在)
     size_t len = strlen(str);
     if (len > 0 && str[len-1] == '\n') {
         str[len-1] = '\0';
     }

     char* temp;
     char dest[MAX_SIZE];
     int num = 0;

     int i = 0;
     while(*str != '\0')
     {
         // 修改3:跳过所有空格字符
         while (*str == ' ') {
             str++;
             if (*str == '\0') break;
         }
         if (*str == '\0') break;

         temp = dest;

         while(*str >= '0' && *str <= '9') /* 判断是否为数字 */
         {
             *temp = *str;
             str++;
             temp++;
         } /* 遇到非数字退出 */

         if(*str != '(' && temp != dest) /* 优化判断:只要读取到数字就处理 */
         {
             *temp = '\0';

             num = atoi(dest); /* 字符串转数字 */
             insert_operand(operand, &top_num,num); /* 数字入栈 */
         }

         while(1)
         {
             // 再次检查空格,防止处理完数字后遇到空格
             if (*str == ' ') {
                 str++;
                 continue;
             }
             if (*str == '\0') break;

             i = compare(oper,&top_oper,*str); /* 判断运算符优先级 */

             if(i == 0)
             {
                 insert_oper(oper,&top_oper,*str); /* 运算符入栈 */
                 break;
             }

             else if(i == 1) /* 括号内表达式结束 */
             {
                 str++;
                 break; // 处理完右括号后跳出循环
             }

             else if(i == -1) /* 执行运算 */
             {
                 deal_date(operand,oper,&top_num,&top_oper);
             }

         }

         if (*str != '\0') {
             str ++; /* 指向表达式的下一个字符 */
         }
     }

     printf("%d\n",operand[0]); /* 输出结果 */

     free(str); // 释放malloc分配的内存
     return 0; 
}

关键修改说明

  1. 输入读取优化:用fgets替代scanf("%s"),支持读取包含空格的整行输入,同时处理fgets可能读取到的换行符,避免干扰后续字符串处理。
  2. 空格跳过逻辑:在进入数字读取和运算符处理前,先跳过所有空格字符,确保只有有效字符(数字、运算符、括号)进入核心计算逻辑。
  3. 边界判断优化:将原*(temp - 1) != '\0'改为temp != dest,更准确判断是否读取到数字字符,避免边界错误。
  4. 健壮性修复:补充deal_date函数的返回值,释放malloc分配的内存,避免内存泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 04:55:45