isdigit() not recognising "1" as a numeric value - c++

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.

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.

Is this expression valid?

I've met this code:
std::string str;
std::getline(std::cin, str);
std::string sub = str.substr(str.find('.') + 1);
first reaction was - this is invalid code. But after some thoughts it seems to be not so simple. So is it valid C++ expression (has predictable behavior)?
PS if it is not so clear question is mostly related to what will happen when '.' would not be found in str, but not limited to that, as there could be other issues.
str.find('.') returns the index of the first occurrence of the character in your string. substr with one argument returns the suffix of the string starting at the given index. So what the line does is it returns the tail of the string starting right after the first dot. So if str is "hello.good.bye", sub will be good.bye.
However, there is potentially a problem with the code if the string does not in fact contain any dots. It will return the whole string. This may or may not be intended. This happens because if there is no dot, find will return npos, which is the largest number std::string::size_type can hold. Add 1 to it, and you will get 0 (that's how unsigned types behave, modulo 2n).
So the code always has predictable behavior.
From http://en.cppreference.com/w/cpp/string/basic_string/npos it seems that std::string::npos = -1;. That value is returned when the find is unsuccessful. In that case, the str.substr(0) will return the entire string.
It would seem it is valid and predictable code.
If you're asking about what happens if . is not found, you don't have to worry. std::string::find then returns std::string::npos, which is defined to be -1 by the standard, which, after adding 1 overflows and makes the argument 0:
std::string sub = str.substr(0);
which gives you the whole string. I don't know if that's the desired behavior, but it's certainly not undefined behavior.
Actually, in this specific case--because the string that contains "...does not matter..." actually does--the find() call is not going to find what it is looking for and so will return std::string::npos. You then add 1 to this.
npos is of type std::string::size_type, which is generally size_t, which is usually an unsigned integer of some sort.
npos is defined as the greatest possible value for size_type.
With size_type being unsigned adding 1 to the greatest possible value creates 0.
So you're calling std::string::substr(0). What does this do? It creates a copy of the whole string you called it on because substr takes a starting position and length (defaulting to npos, or "all the way to the end").
As far as I can see it is valid though it isn't particularly readable.
If str is empty then the find() method will return std::string::npos. This is equivalent to the largest unsigned int representable by std::size_type. By adding 1 to this you're causing an integer overflow and it will wrap around to 0. This means the substr() method is attempting to create a string using chars from position 0 till the end of the string. If str is empty then sub is also empty.

Does strcmp in C++ check every value in a string if the second parameter is "0"?

If my string input is 1234567890, and I do the following:
(strcmp(input,"0"))
Will that return 1 if there is a 0 in my character array of 1234567890 and 0 if there isn't?
I know I can test this, and I did, and the answer is yes, but I'm not sure why and I can't find absolute specifics on strcmp.
No. strcmp returns 0 if the two strings are the same, non 0 otherwise.
Looks like you didn't even bother to google!
No, it compares two strings.
strcmp() returns 0 only if both strings are the same. Otherwise, the return value says something about the first non-matching character.
In your case, this has to do with the comparison between '1' and your '0'. It makes no difference that the other string has a '0' at the end.
strcmp() will typically check all characters from the first one until the last one or until there's a mismatch in the two strings.
The exact internal implementation of strcmp(), if you're asking about that, is not specified in the language standard. In theory, it could find lengths of the two strings and if they are equal, compare the strings using units bigger than char and even do that backwards.
strcmp() compares strings, not searches for one in the other. It returns 0 if the strings are identical. Otherwise it returns either a positive or a negative value, representing the sign of the difference between the first mismatching characters (the characters' values being treated as unsigned).
Does strcmp in C++ check every value in a string if the second
parameter is “0”
No it does not, strcmp() is a string compare function which checks if one string equals another. If it does, it returns 0 if one string is ordinally greater than the other, it returns 1 and returns -1 otherwise.
To check if it does exist, I suggest you write your own function for this.
//return 1 if if the character exists, 0 otherwise
int DoesCharExist(const char *pData, char character)
{
char *data = pData;
while(*data++){
if(*data == character) return 1;
}
return 0;
}

Using cin.get to get an integer

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