news 2026/5/2 0:29:22

C++字符串处理实战:用map和substr搞定PAT乙级里的中英文混合计算器

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C++字符串处理实战:用map和substr搞定PAT乙级里的中英文混合计算器

C++字符串处理实战:用map和substr搞定中英文混合计算器

在编程竞赛和实际开发中,处理混合了不同语言和格式的输入字符串是常见挑战。今天我们要探讨一个有趣的问题:如何用C++优雅地解析并计算同时包含中文数字拼音(如"yi"、"er")和数学表达式(如"3+5")的混合输入字符串。

1. 问题分析与设计思路

当我们面对"yi+er"或"3+wu"这样的混合表达式时,传统的字符串处理方法会显得力不从心。我们需要设计一个既能识别中文数字又能处理标准数学运算的系统。

核心挑战在于:

  • 如何高效识别和转换中文数字拼音
  • 如何准确解析数学表达式中的运算符和操作数
  • 如何处理可能存在的边界条件(如开方运算)

解决方案的核心是结合C++的map容器和字符串处理函数substrstoi等。map提供了中文数字到整数的快速映射,而substr则能帮助我们精确提取字符串中的关键部分。

2. 基础数据结构准备

首先,我们需要建立中文数字与阿拉伯数字的映射关系。这是整个系统的基石:

#include <iostream> #include <map> #include <string> #include <cmath> // 用于数学运算如sqrt, pow std::map<std::string, int> createChineseNumberMap() { std::map<std::string, int> numMap; std::string chineseNumbers[] = {"ling", "yi", "er", "san", "si", "wu", "liu", "qi", "ba", "jiu"}; for (int i = 0; i < 10; ++i) { numMap[chineseNumbers[i]] = i; } return numMap; }

这个映射表将"yi"对应到1,"er"对应到2,依此类推。使用map的优势在于其O(log n)的查找效率,这对于频繁的数字转换操作至关重要。

3. 混合表达式的解析策略

面对混合表达式,我们需要设计一个灵活的解析流程:

  1. 输入分类:判断输入是纯数字、中文数字还是数学表达式
  2. 运算符定位:在表达式中找到运算符的位置
  3. 操作数提取:分离左右操作数
  4. 类型转换:将中文数字转换为阿拉伯数字(如需要)
  5. 运算执行:根据运算符执行相应计算

关键代码实现

int evaluateExpression(const std::string& expr, const std::map<std::string, int>& numMap) { // 检查是否为开方运算 if (expr.substr(0, 4) == "sqrt") { int num = std::stoi(expr.substr(4)); return static_cast<int>(std::sqrt(num)); } // 查找运算符位置 size_t opPos = expr.find_first_of("+-*/%^"); if (opPos == std::string::npos) { // 无运算符,可能是纯数字或中文数字 if (isdigit(expr[0])) { return std::stoi(expr); } else { return numMap.at(expr); } } // 提取左右操作数 std::string left = expr.substr(0, opPos); std::string right = expr.substr(opPos + 1); // 转换操作数为数字 int leftNum = isdigit(left[0]) ? std::stoi(left) : numMap.at(left); int rightNum = isdigit(right[0]) ? std::stoi(right) : numMap.at(right); // 执行运算 switch (expr[opPos]) { case '+': return leftNum + rightNum; case '-': return leftNum - rightNum; case '*': return leftNum * rightNum; case '/': return leftNum / rightNum; case '%': return leftNum % rightNum; case '^': return static_cast<int>(std::pow(leftNum, rightNum)); default: return 0; } }

4. 边界条件与异常处理

在实际应用中,我们需要考虑各种边界情况:

  • 无效输入:如何处理不存在的中文数字或非法表达式
  • 除零错误:除法运算中的零除数问题
  • 负数开方:实数范围内无解的情况
  • 大数运算:结果超出整数范围的处理

增强版的错误处理

try { int result = evaluateExpression(inputStr, chineseNumMap); std::cout << result << std::endl; } catch (const std::out_of_range&) { std::cerr << "错误:无效的中文数字输入" << std::endl; } catch (const std::invalid_argument&) { std::cerr << "错误:无效的数字格式" << std::endl; } catch (...) { std::cerr << "未知错误发生" << std::endl; }

5. 性能优化与扩展思考

对于需要处理大量表达式的场景,我们可以考虑以下优化:

  1. 预编译正则表达式:使用正则表达式加速模式匹配
  2. 缓存计算结果:对重复表达式进行缓存
  3. 并行处理:利用多线程处理独立表达式

扩展功能可能包括:

  • 支持更多中文数字单位(如"shi"、"bai"、"qian")
  • 添加变量支持(如"x=5; x+3")
  • 实现更复杂的数学函数(三角函数、对数等)

6. 实际应用案例

让我们看一个完整的示例,处理以下输入序列:

yi+er 3*wu sqrt16 10%3

处理代码

int main() { auto chineseNumMap = createChineseNumberMap(); std::vector<std::string> inputs = {"yi+er", "3*wu", "sqrt16", "10%3"}; for (const auto& expr : inputs) { try { int result = evaluateExpression(expr, chineseNumMap); std::cout << expr << " = " << result << std::endl; } catch (...) { std::cout << expr << " → 计算错误" << std::endl; } } return 0; }

预期输出

yi+er = 3 3*wu = 15 sqrt16 = 4 10%3 = 1

7. 测试与调试技巧

开发这类字符串处理程序时,系统的测试策略至关重要:

  • 单元测试:为每个功能模块编写测试用例
  • 边界测试:特别测试空字符串、单个字符等边界情况
  • 性能测试:评估处理大量输入时的响应时间

推荐测试用例

输入表达式预期输出测试目的
"ling"0基本中文数字
"9"9纯数字
"san+si"7中文数字加法
"10/2"5数字除法
"sqrt9"3开方运算
"er^3"8幂运算
"abc+def"错误无效输入处理

8. 代码重构与模块化设计

随着功能增加,我们需要保持代码的整洁和可维护性:

  1. 分离关注点:将数字映射、表达式解析、运算执行分离到不同类/函数
  2. 使用面向对象设计:创建ExpressionEvaluator类封装相关功能
  3. 配置化:将中文数字映射等可配置项外置

重构后的类结构

class ChineseNumberConverter { private: std::map<std::string, int> numberMap; public: ChineseNumberConverter(); int toNumber(const std::string& str) const; }; class MathExpressionParser { public: struct Operands { int left; int right; char op; }; static Operands parse(const std::string& expr, const ChineseNumberConverter& converter); }; class ExpressionEvaluator { public: int evaluate(const std::string& expr); };

这种设计使得每个类只负责单一职责,更易于测试和维护。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/2 0:27:01

League Akari:英雄联盟客户端终极效率工具完整指南

League Akari&#xff1a;英雄联盟客户端终极效率工具完整指南 【免费下载链接】League-Toolkit An all-in-one toolkit for LeagueClient. Gathering power &#x1f680;. 项目地址: https://gitcode.com/gh_mirrors/le/League-Toolkit 你是否曾在英雄联盟BP阶段因手速…

作者头像 李华
网站建设 2026/5/2 0:26:26

FACTS Leaderboard:大模型真实性评估的多维度基准测试

1. 项目概述&#xff1a;FACTS Leaderboard的诞生背景在2023年大语言模型爆发式发展后&#xff0c;行业面临一个关键挑战&#xff1a;如何客观评估模型生成内容的真实性&#xff1f;传统基准测试如TruthfulQA和Natural Questions已无法满足需求——当GPT-4在这些测试中达到90%准…

作者头像 李华