C++ Numerical Input Validation - c++

I'm used to Python and I'm now learning C++ which is a bit more complicated to me. How can I modify the input so that it fits the description in the comment at the top of my code? I tried to include if (input[0]!='.' &&...) but it just returns 0. I want it to be included as part of the number. Same with the characters after the first character of the input.
I also don't know how I can separate numbers with more than three digits (starting from the end of the number obviously) with a comma (so 1000000 should be returned as 1,000,000).
/*
* The first character can be a number, +, -, or a decimal point
* All other characters can be numeric, a comma or a decimal point
* Any commas must be in their proper location (ie, separating hundreds from thousands, from millions, etc)
* No commas after the decimal point
* Only one decimal point in the number
*
*/
#include <iostream>
#include <cmath>
#include <climits>
#include <string>
int ReadInt(std::string prompt);
int ReadInt(std::string prompt)
{
std::string input;
std::string convert;
bool isValid=true;
do {
isValid=true;
std::cout << prompt;
std::cin >> input;
if (input[0]!='.' && input[0]!='+' && input[0]!='-' && isdigit(input[0]) == 0) {
std::cout << "Error! Input was not an integer.\n";
isValid=false;
}
else {
convert=input.substr(0,1);
}
long len=input.length();
for (long index=1; index < len && isValid==true; index++) {
if (input[index]==',') {
;
}
else if (isdigit(input[index]) == 0){
std::cout << "Error! Input was not an integer.\n";
isValid=false;
}
else if (input[index] == '.') {
;
}
else {
convert += input.substr(index,1);
}
}
} while (isValid==false);
int returnValue=atoi(convert.c_str());
return returnValue;
}
int main()
{
int x=ReadInt("Enter a value: ");
std::cout << "Value entered was " << x << std::endl;
return 0;
}

Writing parsing code is tricky. When parsing, it is easy to make a mess of the control flow. I suggest dividing up the I/O from the validation code: make a separate function bool IsVaildInt(const std::string& s) that returns whether s is a valid input, and do the prompts outside in a calling function.
It helps to think through systematically for every character what constitutes a valid input. If you are familiar with regexes, like cigien suggested, that may be a good way of organizing your approach even if you end up writing the parsing code by hand instead of using a regex library.
Here are the requirements that you posted:
* The first character can be a number, +, -, or a decimal point
* All other characters can be numeric, a comma or a decimal point
* Any commas must be in their proper location (ie, separating hundreds
from thousands, from millions, etc)
* No commas after the decimal point
* Only one decimal point in the number
That's a lot of logic, but it's doable. It sounds like you are working on this as an exercise to master C++ basics, so I won't post any code. Instead, here's an outline for how I would approach this:
Test that the first character is either 0-9, +, -, or decimal point. If it's not, return invalid.
Search the string for whether it has a decimal point. If it does, remember its position.
Loop over the remaining characters, in reverse starting from the last character.
Separate from the loop index, make a counter that says what the current digit place is (... -1 for tenths, 0 for ones, 1 for tens, 2 for hundreds, ...). If the string has a decimal point, use that vs. the string length to determine the digit place of the last character.
If a character is a comma, check that it is in a valid location compared to the current digit place. If not, return invalid.
Otherwise, if the character is a decimal point, it must be the one identified earlier. If not, that means there are multiple decimal points, so return invalid.
Otherwise, the character must be a digit 0-9, and the digit place counter should be incremented. If the character is not a digit, return invalid.
Finally, if the loop makes it all the way through without hitting an error, return that the string is valid.

Related

User defined functions used in competitive programming to take input

I'm new to competitive programming and I've seen people not using conventional I/O stream such cin or scanf() rather they define their own function to take inputs. There is one such function that I've come across many times and I do not get the code. Here it is
int get(){
char ch;
while(ch=getchar(),(ch<'0'||ch>'9')&&ch!='-');
if (ch=='-'){
int s=0;
while(ch=getchar(),ch>='0'&&ch<='9')s=s*10+ch-'0';
return -s;
}
int s=ch-'0';
while(ch=getchar(),ch>='0'&&ch<='9')s=s*10+ch-'0';
return s;
}
what does this getchar() function really does and what is the whole point of this entire function. I guess this must be to optimize the code for taking large inputs but how is it done.
this must be a silly question for the experienced people but since I'm a newbie any help would be appreciated.
while(ch=getchar(),(ch<'0'||ch>'9')&&ch!='-');
skips all input until 0,1,2,3,4,5,6,7,8,9 or - is read
if (ch=='-'){
If a negative sign is read, continue reading digits:
int s=0;
Start with a sum of zero
while(ch=getchar(),ch>='0'&&ch<='9')s=s*10+ch-'0';
While reading digits, keep accumulating the sum by moving the previous 1 decimal to the left (multiply by 10) and adding the next digit (subtracting ascii value of 0 leaves '0' -> 0, '1' -> 1 etc).
return -s;
Returns the sum, but negative.
If the negation sign wasn't there, we do EXACTLY the same, but return positive.
NOTES
There is no parsing delimiters, embedded space, positive signs (+123), neither is there any range/overflow checking. Notable quirk: "aaaaa -" will be parsed as 0
Conclusion:
Do not do this. Use scanf or int i; if (std::cin >> i) { /*something*/ }

Input validation for integer

I am having trouble with some basic input validation. I have done a lot of searching but cant seem to find the answer that works with my code. I am trying to validate integer input. I am able to test whether a char was entered or not but I need another parameter to test if the number is actually an int and not a double or float.
do
{
cout << "\nHow many numbers would you like to enter?" << endl;
cin >> size;
if (size < 1 || cin.fail())
{
cout << "\nInvalid input" << endl;
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
}while(size < 1 || cin.fail());
Too late. By the time operator>> does its job, the horse has left the barn already. You have to figure it out before you actually parse the value.
If you tell operator>> to extract a value into an integer, operator>> will, first, skip any spaces, parse an optional negative sign, then as many digits as it sees. And that's what you will get.
If the last digit is followed by a ".", operator>> doesn't care. It stops, because you told it to parse an integer, and calls it a day.
Similarly, if you tell operator>> to extract a value into one of the floating point types (float, double, long double), operator>> will parse anything that looks like a floating point number, and put it into the floating point type instance. Since an integer looks like a perfectly valid floating point number, either an integer or a floating point number will parse equally, and stored.
You have no indication of what was actually parsed, except the value itself.
So, there are two ways of doing this. One way is to always parse the value into a floating point number, then check if the parsed number is a whole number, or contains any fractional part, then proceed accordingly.
Or, you could parse this yourself. Use get() to parse one character at a time. Ignore any leading whitespace, then collect everything that follows: an optional minus sign, zero or more digits, an optional period followed by zero or more digits, and an optional "e" followed by an exponent.
If you collected a period or an "e", as part of this process, you know that you just parsed a floating point number, otherwise it's going to be an integer. Then, take everything that's been collected, and then parse it, with std::istringstream's assistance, into your selected value.
(Technically, "e" does not necessarily indicate a floating point value; for example 1e3 will happily live inside an int, it's up to you to decide how you wish to handle this case).
I think you could read the input first then do the validation afterward.
If you can use a c11 compiler and the application only wants positive number and do not care symbols e.g "+", "-", you could try something like the following code:
#include <regex>
...
std::regex integers(R"(\d+)");
enum{INPUT_SIZE=256};
char input[INPUT_SIZE];
do
{
memset(input, 0, INPUT_SIZE);
cin >> input;
if(std::regex_match(input, input+strlen(input), integers))
{
cout << input << " is an integer\n";
}
else
{
cout << "input is not an integer";
}
}while(1);

Distinguishing between numbers and other symbols [c++]

I'm reading a text file and extracting pieces of information of it by means of parsing (line by line).
Here is an example of the text file:
0 1.1 9 -4
a #!b .c. f/
a4 5.2s sa4.4 -2lp
So far, I'm able to split each line using empty spaces ' ' as separators. So I can save, for example, the value of "1.1" into a string variable.
What I want to do (and here is where I'm stuck) is to determine if the piece of information that I'm reading represents a number. Using the previous example, these strings do not represent numbers: a #!b .c. f/ a4 5.2s sa4.4 -2lp
Alternatively, these strings do represent numbers: 0 1.1 9 -4
Then I would like store the strings that represent numbers into a double type variable (I know how to do the conversion to double part).
So, How can I distinguishing between numbers and other symbols? I'm using c++.
You can do this:
// check for integer
std::string s = "42";
int i;
if(!s.empty() && (std::istringstream(s) >> i).eof())
{
// number is an integer
std::cout << "i = " << i << '\n';
}
// check for real
s = "4.2";
double d;
if(!s.empty() && (std::istringstream(s) >> d).eof())
{
// number is real (floating point)
std::cout << "d = " << d << '\n';
}
The eof() check makes sure that the number is not followed by non numeric characters.
Assuming a current (C++11) compiler, the easiest way to handle this is probably to do the conversion using std::stod. You can pass this the address of a size_t that indicates the location of the first character that could not be used in the conversion to double. If the entire input converted to double, it will be the end of the string. If it's any other value, at least part of the input didn't convert.
size_t pos;
double value = std::stod(input, &pos);
if (pos == input.length())
// the input was numeric
else
// at least part of the input couldn't be converted.

How do I convert a single char in string to an int

Keep in mind, if you choose to answer the question, I am a beginner in the field of programming and may need a bit more explanation than others as to how the solutions work.
Thank you for your help.
My problem is that I am trying to do computations with parts of a string (consisting only of numbers), but I do not know how to convert an individual char to an int. The string is named "message".
for (int place = 0; place < message.size(); place++)
{
if (secondPlace == 0)
{
cout << (message[place]) * 100 << endl;
}
}
Thank you.
If you mean that you want to convert the character '0' to the integer 0, and '1' to 1, et cetera, than the simplest way to do this is probably the following:
int number = message[place] - '0';
Since the characters for digits are encoded in ascii in ascending numerical order, you can subtract the ascii value of '0' from the ascii value of the character in question and get a number equal to the digit.

C++: Big Integers

I am a writing a lexer as part of a compiler project and I need to detect if an integer is larger than what can fit in a int so I can print an error. Is there a C++ standard library for big integers that could fit this purpose?
The Standard C library functions for converting number strings to integers are supposed to detect numbers which are out of range, and set errno to ERANGE to indicate the problem. See here
You could probably use libgmp. However, I think for your purpose, it's just unnecessary.
If you, for example, parse your numbers to 32-bit unsigned int, you
parse the first at most 9 decimal numbers (that's floor(32*log(2)/log(10)). If you haven't more, the number is OK.
take the next digit. If the number you got / 10 is not equal to the number from the previous step, the number is bad.
if you have more digits (eg. more than 9+1), the number is bad.
else the number is good.
Be sure to skip any leading zeros etc.
libgmp is a general solution, though maybe a bit heavyweight.
For a lighter-weight lexical analyzer, you could treat it as a string; trim leading zeros, then if it's longer than 10 digits, it's too long; if shorter then it's OK, if exactly 10 digits, string compare to the max values 2^31=2147483648 or 2^32=4294967296. Keep in mind that -2^31 is a legal value but 2^31 isn't. Also keep in mind the syntax for octal and hexadecimal constants.
To everyone suggesting atoi:
My atoi() implementation does not set errno.
My atoi() implementation does not return INT_MIN or INT_MAX on overflow.
We cannot rely on sign reversal. Consider 0x4000...0.
*2 and the negative bit is set.
*4 and the value is zero.
With base-10 numbers our next digit would multiply this by 10.
This is all nuts. Unless your lexer is parsing gigs of numerical data, stop the premature optimization already. It only leads to grief.
This approach may be inefficient, but it's adequate for your needs:
const char * p = "1234567890123";
int i = atoi( p );
ostringstream o;
o << i;
return o.str() == p;
Or, leveraging the stack:
const char * p = "1234567890123";
int i = atoi( p );
char buffer [ 12 ];
snprintf( buffer, 12, "%d", i );
return strcmp(buffer,p) == 0;
How about this. Use atol, and check for overflow and underflow.
#include <iostream>
#include <string>
using namespace std;
main()
{
string str;
cin >> str;
int i = atol(str.c_str());
if (i == INT_MIN && str != "-2147483648") {
cout << "Underflow" << endl;
} else if (i == INT_MAX && str != "2147483647") {
cout << "Overflow" << endl;
} else {
cout << "In range" << endl;
}
}
You might want to check out GMP if you want to be able to deal with such numbers.
In your lexer as you parse the integer string you must multiply by 10 before you add each new digit (assuming you're parsing from left to right). If that running total suddenly becomes negative, you've exceeded the precision of the integer.
If your language (like C) supports compile-time evaluation of expressions, then you might need to think about that, too.
Stuff like this:
#define N 2147483643 // This is 2^31-5, i.e. close to the limit.
int toobig = N + N;
GCC will catch this, saying "warning: integer overflow in expression", but of course no individual literal is overflowing. This might be more than you require, just thought I'd point it out as stuff that real compilers to in this department.
You can check to see if the number is higher or lower than INT_MAX or INT_MIN respectively. You would need to #include <limits.h>