User defined functions used in competitive programming to take input - c++

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*/ }

Related

C++ Numerical Input Validation

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.

How to convert binary to decimal? (In a very simple way)

I need to write a program that converts binary numbers to decimal.
I'm very new to C++ so I've tried looking at other people's examples but they are way too advanced for me.. I thought I had a clever idea on how to do it but I'm not sure if my idea was way off or if I'm just missing something.
int main(void)
{
//variables
string binary;
int pow2 = binary.length() - 1;
int length = binary.length();
int index = 0;
int decimal = 0;
cout << "Enter a binary number ";
cin >> binary; cout << endl;
while(index < length)
{
if (binary.substr(index, 1) == "1")
{
decimal = decimal + pow(2, pow2);
}
index++;
pow2--;
}
cout << binary << " converted to decimal is " << decimal;
}
Your computer is a logical beast. Your computer executes your program, one line at a time. From start to finish. So, let's take a trip, together, with your computer, and see what it ends up doing, starting at the very beginning of your main:
string binary;
Your computer begins by creating a new std::string object. Which is, of course, empty. There's nothing in it.
int pow2 = binary.length() - 1;
This is the very second thing that your computer does.
And because we've just discovered that binary is empty, binary.length() is obviously 0, so this sets pow2 to -1. When you take 0, and subtract 1 from it, that's what you get.
int length = binary.length();
Since binary is still empty, its length() is still 0, and this simply creates a new variable called length, whose value is 0.
int index = 0;
int decimal = 0;
This creates a bunch more variables, and sets them to 0. That's the next thing your computer does.
cout << "Enter a binary number ";
cin >> binary; cout << endl;
Here you print some stuff, and read some stuff.
while(index < length)
Now, we get into the thick of things. So, let's see what your computer did, before you got to this point. It set index to 0, and length to 0 also. So, both of these variables are 0, and, therefore, this condition is false, 0 is not less than 0. So nothing inside the while loop ever executes. We can skip to the end of your program, after the while loop.
cout << binary << " converted to decimal is " << decimal;
And that's how you your computer always gives you the wrong result. Your actual question was:
sure if my idea was way off or if I'm just missing something.
Well, there also other problems with your idea, too. It was slightly off. For starters, nothing here really requires the use of the pow function. Using pow is like try to kill a fly with a hammer. What pow does is: it converts integer values to floating point, computes the natural logarithm of the first number, multiplies it by the second number, and then raises e to this power, and then your code (which never runs) finally converts the result from floating point to integer, rounding things off. Nothing of this sort is ever needed in order to simply convert binary to decimal. This never requires employing the services of natural logarithms. This is not what pow is for.
This task can be easily accomplished with just multiplication and addition. For example, if you already have the number 3, and your next digit is 7, you end up with 37 by multiplying 3 by 10 and then adding 7. You do the same exact thing with binary, base 2, with the only difference being that you multiply your number by 2, instead of 10.
But what you're really missing the most, is the Golden Rule Of Computer Programming:
A computer always does exactly what you tell it to do, instead of what you want it to do.
You need to tell your computer exactly what your computer needs to do. One step at a time. And in the right order. Telling your computer to compute the length of the string before it's even read from std::cin does not accomplish anything useful. It does not automatically recompute its length, after it's actually read. Therefore, if you need to compute the length of an entered string, you computer it after it's been read in, not before. And so on.

C++: Doubling digits using recursion

This is for my "Intro to C++" course. I need to
Write a program that uses a recursive function double_all_digit that doubles all digit from an integer. For example, double_all_digits(101) will return 110011
My code below works for only one digit; I have no idea how to proceed:
int double_all_digit(int x)
{
if(x < 10)
return (x*10) + x;
}
You have the base case; now for the recursion.
split the number into the 1's digit (use modulus) and the rest.
recur on the rest; your result is that number with all the digits doubled.
multiply that result by 100; add 11 times the 1's digit.
return this value up one level.
Here's a strategy:
convert a digit to a string. (use std::to_string)
iterate over characters in the string and append 2 characters in a new string for each character in the original. (See std::string::append)
convert the resulting string to an integer.
Since it's homework, you'll have to do the coding bit. :)

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

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>