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

如何从终端输入提取数值与运算符以实现C语言计算器功能?

问题描述

我正尝试从终端输入中提取多段内容以让计算器正常工作,需要提取空格分隔的每一部分:例如输入“160 + 23”时,要为第一个变量获取160、第二个变量获取“+”、最后一个变量获取23。

原代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFFER 25

void calculatrice(double,char,double);

int main(){
    char *str;
    printf("************************************************\n");
    printf("ecrire sous la forme x + y avec les espaces pour avoir un resultat\n");
    printf("quit pour quitter\n");
    printf("************************************************\n");
    char *text = calloc(1,1), buffer[BUFFER];
    while( fgets(buffer, BUFFER , stdin)){
        if (!strncmp(buffer, "quit",strlen("quit"))){
            break;
        }
        if (!strncmp(buffer, "flush",strlen("flush"))){
            system("clear");
        }
        text = realloc( text, strlen(text)+1+strlen(buffer) );
        if( !text ){
            strcat( text, buffer);
            printf("%s\n", buffer);
        }   
        double nb1 = strtol(&buffer[0], &str, 10);
        double nb2 = strtol(&buffer[3], &str, 10);
        calculatrice(nb1, buffer[2], nb2);
    }
    return 0;
}

void calculatrice(double value_1, char operator, double value_2){
    double result = 0;
    switch (operator)
    {
    case '+':
        result = value_1 + value_2;
        printf("resultat : %f\n",result);
        break;

    case '-':
        result = value_1 - value_2;
        printf("resultat : %f\n",result);
        break;

    case '*':
        result = value_1 * value_2;
        printf("resultat : %f\n",result);
        break;
    
    case '/':
        result = value_1 / value_2;
        printf("resultat : %f\n",result);
        break;

    case '%':
        result = (int)value_1 % (int)value_2;
        printf("resultat : %f\n",result);
        break;
    default:
        break;
    }
}

我曾尝试通过循环和判断空格的方式提取计算器所需的各部分内容,但得到的结果完全错误,希望得到正确的实现方法。


问题分析与解决方案

原代码的核心问题是硬编码位置提取内容(比如buffer[2]、buffer[3]),这种方式完全不灵活,一旦输入格式有细微变化(比如数字位数不同、空格数量变化)就会出错。以下是两种可靠的实现方法:

方法一:使用sscanf直接解析输入

sscanf可以按照指定格式从字符串中读取数据,非常适配这种固定格式的输入场景,代码简洁且容错性强。

修改后的完整代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFFER 25

void calculatrice(double, char, double);

int main() {
    printf("************************************************\n");
    printf("ecrire sous la forme x + y avec les espaces pour avoir un resultat\n");
    printf("quit pour quitter\n");
    printf("flush pour effacer l'ecran\n");
    printf("************************************************\n");

    char buffer[BUFFER];
    while (fgets(buffer, BUFFER, stdin)) {
        // 移除fgets读取的换行符,避免干扰命令判断
        buffer[strcspn(buffer, "\n")] = '\0';

        if (strcmp(buffer, "quit") == 0) {
            break;
        }
        if (strcmp(buffer, "flush") == 0) {
            system("clear");
            continue; // 跳过后续计算逻辑
        }

        double nb1, nb2;
        char op;
        // 按格式提取两个数字和运算符,成功读取3个参数则执行计算
        if (sscanf(buffer, "%lf %c %lf", &nb1, &op, &nb2) == 3) {
            calculatrice(nb1, op, nb2);
        } else {
            printf("格式错误!请输入如 x + y 这样的格式。\n");
        }
    }
    return 0;
}

void calculatrice(double value_1, char operator, double value_2) {
    double result = 0;
    switch (operator) {
        case '+':
            result = value_1 + value_2;
            printf("resultat : %.2f\n", result);
            break;
        case '-':
            result = value_1 - value_2;
            printf("resultat : %.2f\n", result);
            break;
        case '*':
            result = value_1 * value_2;
            printf("resultat : %.2f\n", result);
            break;
        case '/':
            if (value_2 == 0) {
                printf("错误:除数不能为0!\n");
                return;
            }
            result = value_1 / value_2;
            printf("resultat : %.2f\n", result);
            break;
        case '%':
            if ((int)value_2 == 0) {
                printf("错误:模运算除数不能为0!\n");
                return;
            }
            result = (int)value_1 % (int)value_2;
            printf("resultat : %.0f\n", result);
            break;
        default:
            printf("未知运算符!请使用 +、-、*、/、%\n");
            break;
    }
}

关键改进点:

  • 用sscanf按格式提取内容,无需依赖固定字符位置;
  • 处理了fgets读取的换行符,避免命令判断出错;
  • 增加输入格式错误提示,提升用户体验;
  • 补充除数为0的错误判断,避免程序崩溃;
  • 优化输出格式,让结果更美观。

方法二:使用strtok按空格分割字符串

如果需要更灵活的分割逻辑(比如支持多空格分隔),可以用strtok函数按空格分割输入字符串,再将分割后的部分转换为对应类型。

示例解析代码片段(替换main函数内的解析部分):

// 先移除换行符
buffer[strcspn(buffer, "\n")] = '\0';

// 第一次分割,获取第一个数字
char *token = strtok(buffer, " ");
if (token == NULL) {
    printf("格式错误!\n");
    continue;
}
double nb1 = atof(token);

// 第二次分割,获取运算符
token = strtok(NULL, " ");
if (token == NULL || strlen(token) != 1) {
    printf("运算符格式错误!\n");
    continue;
}
char op = token[0];

// 第三次分割,获取第二个数字
token = strtok(NULL, " ");
if (token == NULL) {
    printf("格式错误!\n");
    continue;
}
double nb2 = atof(token);

calculatrice(nb1, op, nb2);

注意事项:

  • strtok会修改原字符串,使用时需注意原数据的保留;
  • 需逐个检查分割后的token是否有效,避免空指针或格式错误。

内容的提问来源于stack exchange,提问作者Jean-Baptiste Lelandais

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 23:01:10