Using cin.get to get an integer - c++

I want to get a string of numbers one by one, so I'm using a while loop
with cin.get() as the function that gets my digits one by one.
But cin.get() gets the digits as chars and even though I'm trying to use
casting I can't get my variables to contain the numrical value and not the ascii value
of the numbers I get as an input.

cin.get can’t parse numbers. You could do it manually – but why bother re-implementing this function, since it already exists?*
int number;
std::cin >> number;
In general, the stream operators (<< and >>) take care of formatted output and input, istream::get on the other hand extracts raw characters only.
* Of course, if you have to re-implement this functionality, there’s nothing for it.
To get the numeric value from a digit character, you can exploit that the character codes of the decimal digits 0–9 are consecutive. So the following function can covert them:
int parse_digit(char digit) {
return digit - '0';
}

Related

C++ Atoi can't handle special characters

Im using this atoi to remove all letters from the string. But my string uses special characters as seen below, because of this my atoi exits with an error. What should I do to solve this?
#include <iostream>
#include <string>
using namespace std;
int main() {
std::string playerPickS = "Klöver 12"; // string with special characters
size_t i = 0;
for (; i < playerPickS.length(); i++) { if (isdigit(playerPickS[i])) break; }
playerPickS = playerPickS.substr(i, playerPickS.length() - i); // convert the remaining text to an integer
cout << atoi(playerPickS.c_str());
}
This is what I believe is the error. I only get this when using those special characters, thats why I think thats my problem.
char can be signed or unsigned, but isidigt without a locale overload expects a positive number (or EOF==-1). In your encoding 'ö' has a negative value. You can cast it to unsigned char first: is_digit(static_cast<unsigned char>(playerPickS[i])) or use the locale-aware variant.
atoi stops scanning when it finds something that's not a digit (roughly speaking). So, to get it to do what you want, you have to feed it something that at least starts with the string you want to convert.
From the documentation:
[atoi] Discards any whitespace characters until the first non-whitespace character is found, then takes as many characters as possible to form a valid integer number representation and converts them to an integer value. The valid integer value consists of the following parts:
(optional) plus or minus sign
numeric digits
So, now you know how atoi works, you can pre-process your string appropriately before passing it in. Good luck!
Edit: If your call to isdigit is failing to yield the desired result, the clue lies here:
The behavior is undefined if the value of ch is not representable as unsigned char and is not equal to EOF.
So you need to check for that yourself before you call it. Casting playerPickS[i] to an unsigned int will probably work.

How to deal with garbage characters in a string?

Suppose I have a string that contains a necessary numeric character but it is not terminated by '/0', it has garbage characters instead. Actually, the string has garbage characters after the number. So how to deal with the garbage character while storing that numerical character in another string or variable?
So how to deal with the garbage character while storing that numerical character in another string or variable?
Only copy a substring. Example:
std::string example "garbage1garbage";
char numerical = example[7];
We got the numerical character excluding the garbage entirely.
If the text be converted is in a std::string, then you can extract a number from the front as follows:
#include <sstream>
...
std::string input = "128734garbage";
std::istringstream iss{input};
int num;
if (iss >> num)
...use_num...
else
std::cerr << "wasn't able to parse an int from input\n";
Just change int to double, uint64_t, ... - whatever suits your data.
If you have only a pointer to the text and know it's not null-terminated, just getting the text into a std::string is problematic. You could instead use a function that converts text to a number, but stops at the first invalid character. std::stol et al, and the other unsigned and floating point variants linked from the same reference page, are good candidates for that.
From your "another string or variable" - the above addresses storing into a numeric variable. You can then create a new std::string from the number using std::to_string, or a std::ostringstream, if that's what you want to do. This will standardise the output format though, so input like say "1E4" might end up looking like say 1000.0. Alternatively, with the stol-type functions you can use the pointer-to-the-end-of-the-number to work out the length of the numeric part, and use std::string::substr() to extract the leading number as a new std::string object.
You should also be aware that the distinction between number and garbage is not always what you might expect. For example "0XBEFHJQ" might be split by some of the above functions as 0xBEF hex and HJQ garbage.

Put a non-numeric input into an integer variable

I’m having a bit of a problem in C++. When I wrote this:
int a = ‘:‘;
cout << a;
This printed out 58. It checks out with the ASCII table.
But if I write this:
int a;
cin >> a;
//i type in “:”
cout << a;
This will print out 0. It seems like if I put in any non-numeric input, a will be 0. I expected it to print out the equivalent ASCII number.
Can someone explain this for me? Thank you!
There are two things at work here.
First, ':' is a char, and although a char looks like a piece of text in your source code, it's really just a number (typically, an index into ASCII). This number can be assigned to other numeric types, such as int.
However, to deal with this oddity in a useful way, the IOStreams library treats char specially, for a numeric type. When you insert an int into a stream using formatted insertion (e.g. cout << 42), it automatically generates a string that looks like that number; but, when you insert a char into a stream using formatted extraction (e.g. cout << ';'), it does not do that.
Similarly, when you do formatted extraction, extracting into an int will interpret the user's input string as a number. Forgetting the char oddity, : in a more general sense is not a number, so your cin >> a does not succeed, as there is no string that looks like a number to interpret. (If a were a char, this "decoding" would again be disabled, and the task would succeed by simply copying the character from the user input.)
It can be confusing, but you're working in two separate data domains: user input as interpreted by IOStreams, and C++ data types. What is true for one, is not necessarily true for the other.
You're declaring a as an int, then the operator>> expects digits, but you give a punctuation, which makes extraction fails. As the result, since C++11, a is set to 0; before C++11 a won't be modified.
If extraction fails (e.g. if a letter was entered where a digit is expected), value is left unmodified and failbit is set. (until C++11)
If extraction fails, zero is written to value and failbit is set. (since C++11)
And
I expected it to print out the equivalent ASCII number.
No, even for valid digits, e.g. if you input 1, a will be set with value 1, but not its ASCII number, i.e. 49.
This will print out 0. It seems like if I put in any non-numeric input, a will be 0. I expected it to print out the equivalent ASCII number.
Since C++11 when extraction fails 0 will be automatically assigned.
However, there is a way where you can take a char input from std::cin and then print its ASCII value. It is called type-casting.
Here is an example:
#include <iostream>
int main()
{
char c;
std::cin >> c;
std::cout << int(c);
return 0;
}
Output:
:
58

isdigit() not recognising "1" as a numeric value

I am parsing a string, validating whether a number inside the string is an int.
std::string segmentS
if(!isdigit(std::stoi(segmentS))){
std::cout<<"Not a location +"<<segmentS<<std::endl;
//does something
break;
}
segmentS is the substring that is suppose to be the integer
Even when I ensure that segmentS is a number, !isdigit(std::stoi(segmentS)) still holds true. Even when segmentS is printed out after the not a location message, it is 1 which is a number, however it isn't being seen as a number, when it runs into this if statement.
std::stoi(segmentS) will convert segmentS to an int value, which is then passed into isdigit, except isdigit assumes the input is a character.
Remove the call to stoi.
isdigit takes a single char as an input, not an integer.

using peek() in overloading an input stream

I'm working on overloading >> for a fraction class and there are a few different types of input that need to be handled. Examples: 1/2 (regular fraction), 2+3/4 (mixed number), 2 (whole number). The professor provided a hint below saying that we need to use the peek() function in order to figure out what the second character is after the integer. So what that means is that temp needs to be declared as an int right? My question is that if temp is an int, how do you get the rest of the fraction (when it's not a whole number)?
Based on my experience, I would declare temp as a string instead and not use peek. But the int and peek approach must have some merit since the prof suggested it.
in >> temp;
if (in.peek() == '+'){
doSomething...
} else if (in.peek() == '/'){
doSomethingElse...
} else {
doThirdOption
}
Here, when you use in>>temp , it will get all the numbers till some non numeric character is encountered. At this time, using peek() you can check if the next character is a '+' or a '/'. In either case, you will have to read another number from the input stream and repeat this procedure.
Once the user hits enter, then you have all your numbers, and you can perform the required operations.
Also, if you have to calculate the value of fractions, you might be better off using float or double datatypes instead of int.