C++如何从含+-/*符号的字符串中提取数字?
问题原因分析
你的代码逻辑存在两个核心问题:
getline每次只能指定单个分隔符,且||的短路求值特性会导致:只要第一个getline(test, segment, '-')执行成功,后面针对+/*的getline不会被触发。- 栈的「后进先出」特性,会让你最终输出的顺序和读取顺序相反。
以你的输入字符串 13-2+14-15*12 为例:
- 第一次循环:
getline以-为分隔符,读取到13并推入栈。 - 第二次循环:
getline继续以-为分隔符,从第一个-后开始读取,直到下一个-,中间的2+14因不含-被完整读取并推入栈。 - 第三次循环:
getline读取到剩余的15*12并推入栈。
最终栈内元素顺序为13、2+14、15*12,弹出时自然会得到15*12 2+14 13。
解决方案
以下是三种可行的解决方法,根据你的需求选择即可:
方法一:利用输入流自动处理数字读取
C++ 的输入流 >> 读取整数时,会自动跳过非数字字符,我们只需要在读取数字后跳过后续的运算符即可:
#include <iostream> #include <sstream> #include <stack> #include <string> using namespace std; int main() { stringstream test("13-2+14-15*12"); stack<int> numbers; int num; // 循环读取流中的整数 while (test >> num) { numbers.push(num); // 跳过数字后的运算符 char op; test >> op; } // 输出栈中数字 while (!numbers.empty()) { cout << numbers.top() << endl; numbers.pop(); } return 0; }
方法二:手动遍历字符串提取数字
如果需要处理浮点数或更灵活的格式控制,可以逐个字符遍历字符串,积累连续的数字:
#include <iostream> #include <stack> #include <string> #include <cctype> using namespace std; int main() { string s = "13-2+14-15*12"; stack<string> numbers; string currentNum; for (char c : s) { if (isdigit(c)) { currentNum += c; } else { if (!currentNum.empty()) { numbers.push(currentNum); currentNum.clear(); } } } // 处理字符串末尾的最后一组数字 if (!currentNum.empty()) { numbers.push(currentNum); } while (!numbers.empty()) { cout << numbers.top() << endl; numbers.pop(); } return 0; }
如果要支持浮点数,只需把判断条件改为 isdigit(c) || c == '.' 即可。
方法三:使用正则表达式匹配数字(C++11+)
用正则表达式可以简洁地匹配所有数字序列,适合复杂格式的字符串:
#include <iostream> #include <stack> #include <string> #include <regex> #include <iterator> using namespace std; int main() { string s = "13-2+14-15*12"; stack<string> numbers; regex numRegex(R"(\d+)"); // 匹配一个或多个数字 // 遍历所有匹配结果 for (sregex_iterator it(s.begin(), s.end(), numRegex); it != sregex_iterator(); ++it) { numbers.push(it->str()); } while (!numbers.empty()) { cout << numbers.top() << endl; numbers.pop(); } return 0; }
内容的提问来源于stack exchange,提问作者mmdmxi
相关产品推荐
相关产品推荐

