Checking if input is integer with regex

Dec 24, 2018 at 3:58am
Hi everyone;

The folowing code is working but it works correctly with one chracter. So sees 1aa as an interger. so looking at the first character

Is it possible to see the whole entry with a regex?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
#include <string>
#include <regex>
using namespace std;

int main()
{
	int input;
	cout << "Enter an int:  ";
	cin >> input;
	if (cin.fail())
		cout << "Not an int\n";
	else
		cout <<"Yes an int\n";
	return 0;
}
Last edited on Dec 24, 2018 at 4:07am
Dec 24, 2018 at 5:10am
Reading the input as a string and parsing it with a regular expressions is one option;
asking std::stoi to parse the input string is another.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <iostream>
#include <regex>
#include <string>
#include <limits>
#include <cctype>
#include <iomanip>

bool is_int( const std::string& str ) { // check with regex (does not accept leading zeroes before first digit)

    static constexpr auto max_digits = std::numeric_limits<int>::digits10 ;
    static const std::string ub = std::to_string(max_digits-1) ;
    static const std::regex int_re( "^\\s*([+-]?[1-9]\\d{0," + ub + "}|0)\\s*$" ) ;

    return std::regex_match( str, int_re ) ;
}

bool is_int2( std::string str ) { // check with std::stoi (accepts any amount of leading zeroes)

    try {

        std::size_t pos = 0 ;
        std::stoi( str, std::addressof(pos) ) ;
        while( std::isspace( str.back() ) ) str.pop_back() ;
        return pos == str.size() ; // fully parsed except for white space at the end
    }

    catch( const std::exception& ) { return false ; }
}

int main() {

    std::cout << std::boolalpha ;

    for( std::string str : { "  1234567  ", "+123", "1.23", "0", "-23", "2+3", "+-23", "123456789987654", "123 456", "00123" } )
        std::cout << std::quoted(str) << " : " << is_int(str) << ' ' << is_int2(str) << '\n' ;
}

http://coliru.stacked-crooked.com/a/4502932506ad53ee
https://rextester.com/QAJMI17365
Dec 24, 2018 at 2:24pm
@JLBorges, isn’t std::numeric_limits<int>::digits10 a bit too ‘restrictive’?
I mean, if I change main() this way:
1
2
3
4
5
6
7
8
9
10
11
12
13
int main() {

    std::cout << std::boolalpha ;

    // for( std::string str : { "  1234567  ", "+123", "1.23", "0", "-23", "2+3", "+-23", "123456789987654", "123 456", "00123" } )
    std::cout << "std::numeric_limits<int>::max() == "
              << std::numeric_limits<int>::max() << " --> "
              << static_cast<int>(std::log10(std::numeric_limits<int>::max()) + 1)
              << " digits\nbut std::numeric_limits<int>::digits10 - 1 == "
              << std::numeric_limits<int>::digits10 - 1 << ", so:\n";
    std::string str { std::to_string(std::numeric_limits<int>::max()) };
        std::cout << std::quoted(str) << " : " << is_int(str) << ' ' << is_int2(str) << '\n' ;
}


The output becomes:
std::numeric_limits<int>::max() == 2147483647 --> 10 digits
but std::numeric_limits<int>::digits10 - 1 == 8, so:
"2147483647" : false true

Dec 24, 2018 at 2:47pm
> isn’t std::numeric_limits<int>::digits10 a bit too ‘restrictive’?

Yes, it is. In the above implementation, std::numeric_limits<int>::digits10 is only 9
because all 10-digit decimal numbers can't be represented.
https://en.cppreference.com/w/cpp/types/numeric_limits/digits10#Example
Dec 24, 2018 at 11:58pm
without be change
"  1234567  " : true true
"+123" : true true
"1.23" : false false
"0" : true true
"-23" : true true
"2+3" : false false
"+-23" : false false
"123456789987654" : false false
"123 456" : false false
"00123" : false true
"2147483647" : false true
after change to std::to_string(max_digits)
"  1234567  " : true true
"+123" : true true
"1.23" : false false
"0" : true true
"-23" : true true
"2+3" : false false
"+-23" : false false
"123456789987654" : false false
"123 456" : false false
"00123" : false true
"2147483647" : true true

I can't not see it changes but only except 2147483647
I only deleted "-1"
Last edited on Dec 25, 2018 at 12:15am
Dec 25, 2018 at 12:14am
I found another the code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
 //Example 1
 #include <iostream>
 #include <regex>
 #include <string>
 
 using namespace std;
 
 int main()
 {
 	string input;
 	regex integer("(\\+|-)?[[:digit:]]+");
 	//As long as the input is correct ask for another number
 	while(true)
 	{
 		cout<<"Give me an integer!"<<endl;
 		cin>>input;
 		if(!cin) break;
 		//Exit when the user inputs q
 		if(input=="q")
 			break;
 		if(regex_match(input,integer))
 			cout<<"integer"<<endl;
 		else
 		{
 			cout<<"Invalid input"<<endl;
 		}
 	}
 }


https://solarianprogrammer.com/2011/10/12/cpp-11-regex-tutorial/
Dec 25, 2018 at 12:31am
Another possibility:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
#include <sstream>
#include <string>

bool parse_int(const std::string& str, int& n) {
    std::istringstream sin(str);
    return sin >> n >> std::ws && sin.eof();
}

int main() {
    std::string line;
    while (std::getline(std::cin, line)) {
        int n = 0;
        if (!parse_int(line, n))
            std::cout << "bad int\n";
        else
            std::cout << "good int: " << n << '\n';
    }
}

Dec 25, 2018 at 1:30am
thanks everyone.
@dutch I tried it's working

2
good int: 2
2s
bad int
a1
bad int
2.a
bad int
2.0
bad int
2000
good int: 2000
+2000
good int: 2000
-2000
good int: -2000
Last edited on Dec 25, 2018 at 1:31am
Topic archived. No new replies allowed.