Checking if input is integer with regex

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
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
@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

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

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
Topic archived. No new replies allowed.