1

我觉得这是一个相当基本的问题,但我已经在互联网上搜索了一个多小时,但我还没有找到答案。

我正在编写一个将输入作为字符串的文本界面。如果输入字符串是数字,我想将字符串转换为整数并将其推送到我创建的堆栈中。

文本界面代码如下:

#include <iostream>
#include "textInterface.h"
#include "Stack.h"
#include <string>
#include <regex>

using namespace std;

void Interface(){
    Stack stack = Stack();

    string input;

    cout << "Please enter a number or operation";
    cin >> input;


     if (input == "."){
         cout << stack.pop();
     } //this pops the stack

     if (input == "+"){
         int a = stack.pop();
         int b = stack.pop();
         int c = a + b;
         stack.push(c);
     } //pops the first two things off the stack, adds them, and pushes the result

     if (input == "-"){
        int a = stack.pop();
        int b = stack.pop();
        int c = a - b;
        stack.push(c);
     } //pops the first two things off the stack, subtracts them, and pushes the result

     if (input == "*"){
        int a = stack.pop();
        int b = stack.pop();
        int c = a * b;
        stack.push(c);
     } //pops the first two things off the stack, multiplies them, and pushes the result

     if (input == ".s"){
         cout << stack.count();
     } //returns the size of the stack

     if (regex_match(input, "[0-9]")){
         int num;
         stringstream convert(input);
         convert >> num;
         stack.push(num);
     } //This is the part with the error!!! 

}

就像我说的,我想检查输入是否是数字,如果是,则将字符串转换为 int 并将其压入堆栈。我以前使用过正则表达式,但已经有一段时间了,而且是在 Python 中(我是 C++ 新手)。我知道我的 regex_match 公式不正确,有没有人有任何关于如何使其正确的建议,或者对资源阅读的建议?

4

2 回答 2

2

不要检查它是否看起来像一个整数,然后将其转换为整数。相反,将其转换为整数并查看是否有效。使用std::stoi(或stolstoll,取决于您期望的数字有多大。)(在<string>):请参见此处

如果字符串无法转换为指定大小的整数,则会引发异常,因此您必须在try. (如果你是 Python 达人,这种风格应该很熟悉。)

此外,如果有一个数字但它没有占据整个字符串(即尾随垃圾),则size_t指向的第二个参数将设置为第一个未使用字符的索引,所以如果你想检查整个string 是一个数字,您还应该检查以确保返回的索引是输入字符串的大小。

如果您对异常感到不舒服,即使是标准库抛出的异常,也可以只使用底层的标准 c 函数strtol和朋友。它们具有类似的接口,但使用任意值返回结合设置errno来尝试传达失败。我个人认为异常界面不那么繁琐,但一如既往,口味各不相同。

于 2013-09-26T23:43:30.043 回答
0

我赞成您的问题,因为我遇到了同样的问题,但没有找到明显的解决方案。我开发了一个有点缺陷的解决方案,但对于常见情况来说已经足够了。从谷歌上看,这绝对是缺乏答案的东西。因此,为了人类知识,我将在这里发布我的解决方案。

bool StringCtr::IsNumeric(bool onlyIntegersYieldTrue /*= false*/, int intRadix /*= 0*/) const
{
    _ASSERT(intRadix == 0 || intRadix >= 2 && intRadix <= 36);

    bool const acceptsFloats = !onlyIntegersYieldTrue;
    bool ok = false;
    if (!Empty())
    {
        char* pEnd = 0;
        long li1;
        li1 = strtol(Cstr(), &pEnd, intRadix);
        ok = ! (li1 == 0L && pEnd == Cstr());
        if (!ok && acceptsFloats)
        {
            double d1;
            d1 = strtod(Cstr(), &pEnd);
            ok = ! (d1 == 0.0 && pEnd == Cstr());
        }
        if (ok && !acceptsFloats)
        {
            ok = ok && !Contains(".");
            ok = ok && !Contains("e");
        }
    }           
    return ok;
}

所以这是我的字符串类的一个方法,我相信从那里调用的其他方法是不言自明的。这是尝试使用能够接受许多格式的标准 C 标记器 (strtol)。这实际上是需要真正小心的事情,因为例如在使用 0(自动)基数时,以 0 开头的数字将被解释为八进制基数。否则它很方便,因为它会识别 0x.. 十六进制符号模式,并区分整数和浮点数。它甚至应该理解指数符号,例如“-1.05e12”。

无论如何,这取决于您真正需要的解析能力,您认为您的用户会期望程序识别什么样的符号约定?最后,不要听人们说“这很容易,只要检查一下,foreach (char c) { ok = c >= '0' && c <= '9'; }因为这是胡说八道,显然还不够。负数、浮点数以及我之前提到的所有内容呢?

干杯!

于 2013-09-27T00:27:44.680 回答