如何从终端输入提取数值与运算符以实现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
相关产品推荐
相关产品推荐

