简体   繁体   English

检查输入字符串是否为数字,是否使用C ++,如果是,则将其转换为int(正则表达式?)

[英]Checking if an input string is a number and in C++ and, if so, converting it to an int (regex?)

I feel like this is a fairly basic question, but I've searched the internet for over an hour and I haven't found the answer. 我觉得这是一个非常基本的问题,但是我已经在互联网上搜索了一个多小时,但没有找到答案。

I'm writing a text interface that takes an input as a string. 我正在编写一个将输入作为字符串的文本接口。 If the input string is a number, I want to convert the string to an integer and push it onto a stack that I created. 如果输入字符串是数字,我想将字符串转换为整数并将其压入我创建的堆栈中。

The code of the text interface is as follows: 文本界面的代码如下:

#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!!! 

}

Like I said, I'd like to check if input is a number, and if so, convert the string to an int and push it onto the stack. 就像我说的,我想检查输入是否为数字,如果是,则将字符串转换为int并将其压入堆栈。 I've worked with regular expressions before, but it's been a while and it was in Python (I'm new to C++). 我以前使用过正则表达式,但是已经有一段时间了,并且它是在Python中使用的(我对C ++还是陌生的)。 I know my regex_match is not formulated correctly, does anyone have any advice on how to make it correct, or suggestions for resources to read? 我知道我的regex_match格式不正确,是否有人对如何使其正确无任何建议,或者有阅读资源的建议?

Don't check if it looks like an integer and then convert it to an integer. 不要检查它是否看起来像整数,然后将其转换为整数。 Rather, convert it to an integer and see if that worked. 而是将其转换为整数,看看是否可行。 Use std::stoi (or stol or stoll , depending on how big you expect the number to be.) (in <string> ): See here . 使用std::stoi (或stolstoll ,具体取决于您期望的数字大小。)(在<string> ):请参见此处

If the string cannot be converted to an integer of the indicated size, an exception will be thrown, so you have to execute that function inside of a try . 如果无法将字符串转换为指定大小的整数,则将引发异常,因此您必须在try内执行该函数。 (That style should be familiar if you're a pythonista.) (如果您是pythonista,则应熟悉该样式。)

Also, if there was a number but it didn't occupy the entire string (ie trailing garbage), the size_t pointed to be the second argument will be set to the index of the first unused character, so if you want to check that the entire string is a number, you should also check to make sure that the returned index is the size of the input string. 另外,如果有一个数字但它没有占用整个字符串(即结尾的垃圾),则将指向第二个参数的size_t设置为第一个未使用字符的索引,因此,如果要检查整个字符串是一个数字,还应该检查以确保返回的索引是输入字符串的大小。

If you're uncomfortable with exceptions, even those thrown by the standard library, it's possible to just use underlying standard c functions, strtol and friends. 如果您对异常(即使是标准库抛出的异常)不满意,则可以只使用基础标准c函数, strtol和friends。 Those have a similar interface, but use an arbitrary value return combined with setting errno to try to communicate failure. 它们具有相似的接口,但是使用结合设置errno的任意值返回来尝试通信失败。 Personally I think the exception interface is less fiddly, but, as always, tastes vary. 就我个人而言,我认为异常接口不太友好,但与往常一样,口味也有所不同。

I upvoted your question because I had the same problem and found no obvious solution. 我赞成您的问题,因为我有同样的问题,但没有找到明显的解决方案。 I developped a, somewhat flawed, solution but good enough for common cases. 我开发了一个有缺陷的解决方案,但对于常见情况来说已经足够了。 Still it is definitely something that lacks answers when looking from google. 从Google进行搜索时,肯定仍然缺少答案。 So for the sake of humanity knowledge I'm going to post my solution here. 因此,出于对人类的了解,我将在此处发布我的解决方案。

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;
}

so this is a method of my string class, the other methods called from there are self explanatory enough I believe. 所以这是我的字符串类的一个方法,我相信其他从那里调用的方法都具有足够的自我解释。 This is trying to use standard C tokenizer (strtol) which is able to accept a lot of formats. 这试图使用能够接受许多格式的标准C标记器(strtol)。 That is actually something to be real careful about, because for example number starting with 0 will be interpreted as octal base, when using 0 (auto) radix. 实际上,这是要特别小心的事情,因为例如使用0(自动)基数时,以0开头的数字将被解释为八进制基数。 otherwize it is convenient because it will recognize 0x.. hexa notation pattern, and distinguish between integers and floating points. 否则它很方便,因为它将识别0x ..十六进制表示法模式,并区分整数和浮点数。 it should even understand exponent notation eg "-1.05e12" for example. 它甚至应该理解指数符号,例如“ -1.05e12”。

Anyways, it depends on the parsing power you really need, what kind of notation convention you think your users will excpect the program to recognize ? 无论如何,这取决于您真正需要的解析能力,您认为用户希望程序识别哪种符号约定? And in the end, do not listen to people saying "it is easy, just check foreach (char c) { ok = c >= '0' && c <= '9'; } because this is bullshit and obviously not sufficient. What about negative numbers, floating points, and all that I mentioned before ? 最后,不要听别人说“很简单,只需检查foreach (char c) { ok = c >= '0' && c <= '9'; }因为这是胡扯,显然还不够。负数,浮点数以及我之前提到的所有内容如何?

cheers ! 欢呼!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM