How to perform range checking using regular expressions?
Take a 4-bit number (i.e. "dddd") as an example, how can I check whether it is within given range, say [1256-4350] or not?
To check whether the input is a 4 digit number use regex_match, and then convert the string to an integer using std::stoi to check the range.
std::regex expr(R"(\d{4})");
if(std::regex_match(input, expr)) {
int num = std::stoi(input);
if(num >= 1256 && num <= 4350) {
// input is within range
}
}
As Jarod42 mentions in the comments, since you've already validated the input is a 4 digit number, it's not necessary to convert it to an integer. Assuming input is an std::string, this would work too
if(input >= "1256" && input <= "4350") {
// input is within range
}
Using this website, the regex you are after should look like this: ^(125[6-9]|12[6-9][0-9]|1[3-9][0-9]{2}|[23][0-9]{3}|4[0-2][0-9]{2}|43[0-4][0-9]|4350)$.
That being said, I think it is far more readable and maintainable do break it into two steps, first validate the data type and then the range. (What happens when the range shifts? Your entire regex will most likely be made useless).
Here is a great site that will give you the answer.
For your example:
(\b(125[6-9]|12[6-9][0-9]|1[3-9][0-9]{2}|[23][0-9]{3}|4[0-2][0-9]{2}|43[0-4][0-9]|4350)\b
Yeah, I know this will work. I just want to check if we can verify it's indeed a number and at the same time check its range using
Okay... But don't use regex for this task. It's a terrible choice.
#include <iostream>
#include <sstream>
using namespace std;
bool is_number_in_range(string s) {
istringstream str(s);
int i; char c;
str >> i;
if( str.fail() ) return false;
return i>=1256 && i<=4350 && str.eof();
}
int main() {
cout<< is_number_in_range("0") << '\n'<<
is_number_in_range("1234") << '\n'<<
is_number_in_range("1256") << '\n'<<
is_number_in_range("2000") << '\n'<<
is_number_in_range("4350") << '\n'<<
is_number_in_range("5000") << '\n'<<
is_number_in_range("abcd") << '\n'<<
is_number_in_range("1234.0") << '\n';
return 0;
}
see it live
Related
In this code the value needed in the code is given by the user via command line. But I need the code to reject any numerical value <0 and every alphanumeric code or string (-23 is not accepted, h42b is not accepted,hello is not accepted, 10 is accepted)
int main(int argc, char* argv[])
{
int S = argc > 1 ? std::atoi(argv[1]) : 100;
if (S < 0) {
S = 100;
std::cout << "S value must be >0, value set to 100" << '\n';
}
If the user puts any value that's not a number>0 I want the code to print "S value must be >0, value set to 100".
I tried using a for loop, but I don't know how to reject alphanumerical codes or strings.
Can you tell me what can I use? It shouldn't be an advanced tool, just something that gets the job done nicely
I need the code to reject any numerical value <0 and every alphanumeric code or string
means you cannot assume numerical input, which means you cannot use atoi().
If the user puts any value that's not a number
... then you need to detect that. You can only detect if you can access the input.
Which means you need to read it in as input without assumptions on syntax or formatting. I.e. you need to store in a string.
We are however not looking at normal input, you are working on commandline. Which means you need to parse enough to decide when to give up. As far as I understand, that is when even the first parameter is not a number. For that a loop is not needed - if the program fails there is nothing which you can process in additional loop iterations (assuming that you do not want to ignore the first, non-numerical, parameter and process the second, i.e. whatever is after the first blank).
So all in all
verfiy that there is at least one paratemer (your code already does this)
get the first parameter
as a string, not as a number
try whether it is a number, with something NOT expecting it to be a number; i.e. not atoi()
if you select sscanf() make sure to interpret the return value (not only the scanned value)
if you detect a number use it
if you do not detect a number output the useage message
You can convert char array to std::string for convenience and then iterate over it, using std::isdigit to check whether it is a digit in range (0-9). If not, assign 100 to S, print error message and break the loop.
Quick solution looks might look like this:
#include <cctype>
#include <iostream>
#include <string>
int main(int argc, char *argv[]) {
int S{0};
bool correct_input{true};
std::string argument(argv[1]);
for (auto character : argument) {
if (!std::isdigit(character)) {
S = 100;
std::cout << "S value must be >0, value set to 100" << '\n';
correct_input = false;
break;
}
}
if (correct_input) {
S = std::stoi(argument);
}
}
If it is not too advanced you can use a regex to get the job done:
#include <iostream>
#include <regex>
#include <sstream>
int main(int argc, char* argv[]) {
std::regex regex("^(\\+)?([1-9][0-9]*)$");
for (int i = 0; i < argc; i++) {
std::string argument(argv[i]);
std::uint32_t value = 100;
// has argument the desired pattern, i.e. is it a positive number above 0?
if (std::regex_match(argument, regex)) {
std::stringstream strValue;
strValue << argument;
strValue >> value;
std::cout << "value: " << value << "\n";
} else
std::cout << "Input should be a number > 0 (value setted to 100)! provided: " << argument << "\n";
}
return 0;
}
Input:
1 +2 100 0 -1 h23b h3ll0 test
Output:
value: 1
value: 2
value: 100
Input should be a number > 0 (value setted to 100)! provided: 0
Input should be a number > 0 (value setted to 100)! provided: -1
Input should be a number > 0 (value setted to 100)! provided: h23b
Input should be a number > 0 (value setted to 100)! provided: h3ll0
Input should be a number > 0 (value setted to 100)! provided: test
Using regex has the benefit that this approach is highly customizable and you will only encounter numbers in your for-loop that are positive. You don't have to check if the current argument is a number or is above 0. The regex takes care of that. All you have to do is to check if the current argument matches with the regex. However, I don't know how "advanced" this feature is for someone starting with c++ or someone starting with programming. To convert your string you can use any method. I used a stringsteam. Simply write your value into the stream and then read it back into your desired variable. Hope it helped!
If you want to take a closer look at the regex: https://regexr.com/61bjl
I will try to implement this in the different ways as suggested. In the meantime I wrote this:
bool string_is_numeric(char* string) {
size_t length = strlen(string);
for(size_t i = 0; i < length; i++) {
if(!isdigit(string[i]) && static_cast<int> (string[i]) != 46 ) {
return false; }
}
return true;
}
int main(int argc, char* argv[])
{
int S = argc > 1 ? std::atoi(argv[1]) : 99;
if (argc > 1 && (S < 0 || !string_is_numeric (argv[1]))) {
S = 99;
std::cout << "S value not valid. Only numerical values > 0
are
allowed. Value set to 99" << '\n';
}
}
This code as far as I tried works. And let the user write the '.' for decimal numbers.
I am getting few problems when reading code. This is the text file.
2X^6+3X^3+4X^0=0
5X^6+X^2+X^1-4X^0=0
I am getting a proper input for the first line but in second line first I need to ignore. I searched here and found how to use it and it's work to get to next line ignoring all the left over characters of first line.
You can see in second line with X there is no integer, now problem is the second while loop is running continuously. If I add 1 in text file with the X the file reads perfectly. Also how can I put a condition to satisfy this that when there is directly X or -X, it should store 1 or -1 and goes to next character? Also you can see ^ I have to store this in a variable whereas I should ignore it but didn't how to ignore it?
Thanks in advance
int main()
{
int in;
int power;
char x;
char f;
fstream fin;
fin.open("input1.txt");
list l1,l2;
while(fin.peek() != 61)
{
fin>>in;
fin>>x;
fin>>f;
fin>>power;
cout<<in<<endl<<x<<endl<<f<<endl<<power<<endl;
l1.addtoend(in,power,x);
cout<<endl;
}
fin.ignore(2,'\n');
while(fin.peek() != 61)
{
fin>>in;
fin>>x;
fin>>f;
fin>>power;
cout<<in<<endl<<x<<endl<<f<<endl<<power<<endl;
l2.addtoend(in,power,x);
cout<<endl;
}
l1.display();
l2.display();
}
Unfortunately, this is not so simple as expected.
We need to split up the task into smaller parts.
What you want to do, is splitting your equation in terms and extract from this the coefficients and exponents.
Splitting up something in similar parts is also called tokenizing.
So, your equation consists of terms, which all follow the same pattern. First an optional sign, followed by the coefficients, then a “X^”, and, at the end the exponent (which may or may not have a sign).
And since all terms have the same pattern, we can find them with a so-called regex. C++ supports this functionality. Also for splitting up a text in smaller tokens/terms/pattern-matches, we have a special iterator std::sregex_token_iterator. Like any other iterator in C++, it iterates over the source string and extracts (and copies) all matched patterns.
OK, then we found already a solution for the first sub task. Extract all terms and put them into a std::vector. We will use the std::vectors range constructor, to do this, while defining the variable.
The next step is to get the coefficient. Here we need some special handling, because the coefficient can be omitted with an assumed 1. Using this assumption, we will read the term and convert the coefficient to an integer. And because we want to do that in one statement, we use std::transform from the STL’s algorithm library.
Getting the exponents is easier. We simply convert anything in a term following the ‘^’-sign to an integer. We again use std::transform to work on all terms in one statement.
Last but not least, we will get the right-hand-side of the equation and convert it also to an integer.
Please note:
All this can be done also with float type values
We could also allow spaces in the equation
For that, we would simple modify the std::regex-string.
Please see the complete example below:
#include <iostream>
#include <string>
#include <vector>
#include <iterator>
#include <regex>
#include <algorithm>
#include <iomanip>
int main() {
std::string equation{ "5X^6+X^2+X^1-4X^0=0" };
const std::regex re(R"(([+-]?\d?X\^[+-]?\d+))");
std::vector<std::string> terms{ std::sregex_token_iterator(equation.begin(), equation.end(), re,1),std::sregex_token_iterator() };
std::vector<int> coefficients(terms.size());
std::vector<int> exponents(terms.size());
int rightHandSite{ 0 };
// Everything in front of X is the coefficient. Handle special case, when no digit is given
std::transform(terms.begin(), terms.end(), coefficients.begin(), [](const std::string& s) {
std::string temp = s.substr(0U, s.find('X'));
if (1 == temp.size() && !std::isdigit(temp[0])) temp += '1';
return std::stoi(temp); });
// Get all exponents
std::transform(terms.begin(), terms.end(), exponents.begin(), [](const std::string & s) {
return std::stoi(s.substr(s.find('^') + 1)); });
// Get right Hand site of equation
rightHandSite = std::stoi(equation.substr(equation.find('=') + 1));
// Show result
std::cout << "\nEquation: " << equation << "\n\nFound '" << terms.size() << "' terms.\n\nCoeffient Exponent\n";
for (size_t i = 0U; i < terms.size(); ++i)
std::cout << std::right << std::setw(9) << coefficients[i] << std::setw(10) << exponents[i] << "\n";
std::cout << "\n --> " << rightHandSite << "\n";
return 0;
}
There are many other possible solutions. But maybe it will give you some idea on what you could do.
Is there a equivalent of TryParse in C++(gcc) ?
I would like to parse a string which may contain (+31321) and store it as long. I know phone numbers are stored as strings and string matched but for my needs , I would like to store them as long and sometimes they might contain pluses (+). What would parse it in C++?
The trouble with strtoul() and family there is no real way to test for failure.
If it fails to parse then it returns 0 without setting errno (which is only set on overflow).
boost lexical cast
#include <boost/lexical_cast.hpp>
int main()
{
try
{
long x = boost::lexical_cast<long>("+1234");
std::cout << "X is " << x << "\n";
}
catch(...)
{
std::cout << "Failed\n";
}
}
Doing it using streams
int main()
{
try
{
std::stringstream stream("+1234");
long x;
char test;
if ((!(stream >> x)) || (stream >> test))
{
// You should test that the stream into x worked.
// You should also test that there is nothing left in the stream
// Above: if (stream >> test) is good then there was content left after the long
// This is an indication that the value you were parsing is not a number.
throw std::runtime_error("Failed");
}
std::cout << "X is " << x << "\n";
}
catch(...)
{
std::cout << "Failed\n";
}
}
Using scanf:
int main()
{
try
{
char integer[] = "+1234";
long x;
int len;
if (sscanf(integer, "%ld%n", &x, &len) != 1 || (len != strlen(integer)))
{
// Check the scanf worked.
// Also check the scanf() read everything from the string.
// If there was anything left it indicates a failure.
throw std::runtime_error("Failed");
}
std::cout << "X is " << x << "\n";
}
catch(...)
{
std::cout << "Failed\n";
}
}
+31321 can be parsed as a long with the usual stream extraction operators.
#include <iostream>
#include <sstream>
int main()
{
std::istringstream s("+31321");
long n;
s >> n;
std::cout << n << '\n';
}
demo: http://ideone.com/4rmlp
Although parsing an actual phone number (with parentheses, dashes, extensions, etc) may not be as simple.
In fact, before convert the string into a number, the numbers should be "normalized" to a common format. This requires removing all symbols, and replace them with proper representation.
But you must be very care about representing telephone numbers (that are NOT numbers: they are not subjected to regular arithmetic) as string: Number beginning with one or more zeroes are not the same as the ones with the zeroes removed:
00 is the typical replacement for +, but a number without the 00 (or +) in front should be prefixed by 00c where c is the country code.
You need to do some pre-processing to come to a uniform string representation, before converting, otherwise you risk to "alias" different things.
the input extraction operator >> (i hope it's an acceptable name) applies and returns a stream&, that has a bool operator, meaning the extraction has been succesfully attempted. For instance, from the Cubbi answer:
...
std::istringstream s("+31321");
long n;
if (s >> n)
std::cout << n << '\n';
....
This will succed, of course, given the appropriate content of s.
Somewhat different (easier but not type safe) also the scanf family has practical tools available in c++ as well c. You could of course write the example this way:
...
long n;
if (sscanf("+31321", "%d", &n) == 1)
std::cout << n << '\n';
...
A subset of regular expressions make this rather powerful: for instance to match a comma separed multi fields with left space trimming:
if (sscanf("a,b,c", " [^,], [^,], [^,]", a,b,c) == 3) ...
I am currently learning C++ and I have been asked to make a program which will calculate the interest that would be paid on a deposit of a given size. One of the requirements is that we display an error message when non-integer data is entered.
I however cannot work out how to detect if non-integer data has been entered. If anyone could provide an example of how this problem is solved it would be much appreciated!
You don't have to check yourself. The expression (std::cin >> YourInteger) evaluates to a bool, whcih is true if and only if YourInteger was succesfully read. This leads to the idiom
int YourInteger;
if (std::cin >> YourInteger) {
std::cout << YourInteger << std::endl;
} else {
std::cout << "Not an integer\n";
}
this should be a clear enough starting point.
char* GetInt(char* str, int& n)
{
n = 0;
// skip over all non-digit characters
while(*str && !isdigit(*str) )
++str;
// convert all digits to an integer
while( *str && isdigit(*str) )
{
n = (n * 10) + *str - '0';
++str;
}
return str;
}
You need to find out if the input value contains non numeric characters. That is, anything other than 0-9.
You have to first take input as string and then verify if every digit is indeed numeric.
You can iterate the string and test if each character is a valid digit using the built in function isdigit() defined in <cctype>. You might also want to allow for a single comma if you're working with decimal numbers.
So I am currently learning C++ and decided to make a program that tests my skills I have learned so far. Now in my code I want to check if the value that the user enters is a double, if it is not a double I will put a if loop and ask them to reenter it. The problem I have is how do I go about checking what type of variable the user enters, ex- if a user enters a char or string, I can output an error message. Here is my code:
//cubes a user entered number
#include <iostream>
using namespace std;
double cube(double n); //function prototype
int main()
{
cout << "Enter the number you want to cube: "; //ask user to input number
double user;
cin >> user; //user entering the number
cout << "The cube of " << user << " is " << cube(user) << "." << endl; //displaying the cubed number
return 0;
}
double cube (double n) //function that cubes the number
{
return n*n*n; // cubing the number and returning it
}
Edit: I would have to say I just started and don't have the slightest of clue about your code, but I will check out your link. By the way, I haven't learned how to work with templates yet,I am learning about dealing with data, only Chapter 3 in my C++ Primer Plus 5th edition.
Safe C++ Way
You can define a function for this using std::istringstream:
#include <sstream>
bool is_double(std::string const& str) {
std::istringstream ss(str);
// always keep the scope of variables as close as possible. we see
// 'd' only within the following block.
{
double d;
ss >> d;
}
/* eat up trailing whitespace if there was a double read, and ensure
* there is no character left. the eof bit is set in the case that
* `std::ws` tried to read beyond the stream. */
return (ss && (ss >> std::ws).eof());
}
To assist you in figuring out what it does (some points are simplified):
Creation of a input-stringstream initialized with the string given
Reading a double value out of it using operator>>. This means skipping whitespace and trying to read a double.
If no double could be read, as in abc the stream sets the fail-bit. Note that cases like 3abc will succeed and will not set the fail-bit.
If the fail-bit is set, ss evaluates to a zero value, which means false.
If an double was read, we skip trailing whitespace. If we then are at the end of the stream (note that eof() will return true if we tried to read past the end. std::ws does exactly that), eof will return true. Note this check makes sure that 3abc will not pass our check.
If both cases, right and left of the && evaluate to true, we return true to the caller, signaling the given string is a double.
Similar, you check for int and other types. If you know how to work with templates, you know how to generalize this for other types as well. Incidentally, this is exactly what boost::lexical_cast provides to you. Check it out: http://www.boost.org/doc/libs/1_37_0/libs/conversion/lexical_cast.htm.
C Way One
This way has advantages (being fast) but also major disadvantages (can't generalized using a template, need to work with raw pointers):
#include <cstdlib>
#include <cctype>
bool is_double(std::string const& s) {
char * endptr;
std::strtod(s.c_str(), &endptr);
if(endptr != s.c_str()) // skip trailing whitespace
while(std::isspace(*endptr)) endptr++;
return (endptr != s.c_str() && *endptr == '\0');
}
strtod will set endptr to the last character processed. Which is in our case the terminating null character. If no conversion was performed, endptr is set to the value of the string given to strtod.
C Way Two
One might thing that std::sscanf does the trick. But it's easy to oversee something. Here is the correct way to do it:
#include <cstdio>
bool is_double(std::string const& s) {
int n;
double d;
return (std::sscanf(s.c_str(), "%lf %n", &d, &n) >= 1 &&
n == static_cast<int>(s.size()));
}
std::sscanf will return the items converted. Although the Standard specifies that %n is not included in that count, several sources contradict each other. It's the best to compare >= to get it right (see the manpage of sscanf). n will be set to the amount of the processed characters. It is compared to the size of the string. The space between the two format specifiers accounts for optional trailing whitespace.
Conclusion
If you are a beginner, read into std::stringstream and do it the C++ way. Best not mess with pointers until you feel good with the general concept of C++.
There is no suitable way to check if a string really contains a double within the standard library. You probably want to use Boost. The following solution is inspired by recipe 3.3 in C++ Cookbook:
#include <iostream>
#include <boost/lexical_cast.hpp>
using namespace std;
using namespace boost;
double cube(double n);
int main()
{
while(true)
{
cout << "Enter the number you want to cube: ";
string user;
cin >> user;
try
{
// The following instruction tries to parse a double from the 'user' string.
// If the parsing fails, it raises an exception of type bad_lexical_cast.
// If an exception is raised within a try{ } block, the execution proceeds
// with one of the following catch() blocks
double d = lexical_cast <double> (user);
cout << "The cube of " << d << " is " << cube(d) << "." << endl;
break;
}
catch(bad_lexical_cast &e)
{
// This code is executed if the lexical_cast raised an exception; We
// put an error message and continue with the loop
cout << "The inserted string was not a valid double!" << endl;
}
}
return 0;
}
double cube (double n)
{
return n*n*n;
}
sscanf can do what you want; it returns the number of arguments properly processed. This should get you started:
//cubes a user entered number
#include <iostream>
#include <cstdio>
using namespace std;
double cube(double n); //function prototype
int main()
{
cout << "Enter the number you want to cube: "; //ask user to input number
string user;
cin >> user; //user entering the number
// Convert the number to a double.
double value;
if(sscanf(user.c_str(), "%lf", &value) != 1)
{
cout << "Bad! " << user << " isn't a number!" << endl;
return 1;
}
cout << "The cube of " << user << " is " << cube(user) << "." << endl; //displaying the cubed number
return 0;
}
double cube (double n) //function that cubes the number
{
return n*n*n; // cubing the number and returning it
}
Other methods posted in other answers have their advantages and disadvantages. This one has issues with trailing characters and isn't "C++"-y.
I would have to say I just started and don't have the slightest of clue about your code, but I will check out your link. By the way, I haven't learned how to work with templates yet,I am learning about dealing with data, only Chapter 3 in my C++ Primer Plus 5th edition.
You can fall back on C and use strtod
You program reads in a string and then passes it to a function that attempts to convert the string into double.
bool is_double(const char* strIn, double& dblOut) {
char* lastConvert = NULL;
double d = strtod(strIn, &lastConvert);
if(lastConvert == strIn){
return false;
} else {
dblOut = d;
return true;
}
}