Various results using atoi

Can someone explain why these calls do not return the same expected result?

unsigned int GetDigit(const string& s, unsigned int pos) { // Works as intended char c = s[pos]; return atoi(&c); // doesn't give expected results return atoi(&s[pos]); return atoi(&static_cast<char>(s[pos])); return atoi(&char(s[pos])); } 

Note : I'm not looking for a better way to convert char to int .

+6
source share
6 answers

None of your attempts are correct, including "working as intended" (it just happened by chance). To start atoi() , a null-terminated string is required that you do not provide.

How about the following:

 unsigned int GetDigit(const string& s, unsigned int pos) { return s[pos] - '0'; } 

This assumes that you know that s[pos] is a valid decimal digit. If you do not, some error checking is in order.

+10
source

What you do is use std::string , get one character from its internal representation and pass a pointer to it in atoi , which expects const char* point to a string with NULL termination. A std::string not guaranteed to preserve characters, so there is a zero end, just the luck is that your C ++ implementation seems to be doing this.

The correct way would be to query std::string for the null version of its contents using s.c_str() , and then call atoi with a pointer to it.

The code contains another problem , you return the result of atoi to unsigned int , and atoi returns the signed int . What if your line is "-123" ?

+3
source

Since int atoi(const char* s) takes a pointer to a character field, your last three uses return a number corresponding to consecutive digits starting with & s [pos], for example. it can give 123 for a string of type "123" , starting at position 0. Since the data inside a std::string not required to complete with a zero value, the answer may be something else in some implementation, that is, undefined.

Your β€œworking” approach also uses undefined behavior. It differs from other attempts because it copies the value of s[pos] to another location. It seems to work only until the next byte in memory next to the character c accidentally turns out to be a null or non-digital character, which is not guaranteed. Therefore, follow the recommendations of @aix.

To make it work, you can do the following:

 char c[2] = { s[pos], '\0' }; return atoi(c); 
+1
source

if you want to access the data as a string C - use s.c_str() , and then pass it to atoi .

atoi expects a C-style std::string , std::string is a C ++ class with various behaviors and characteristics. For starters - this should not be NULL terminated.

0
source

atoi takes a char pointer for this argument. In the first attempt, when you use char c , it takes a pointer to only one character, so you get the answer you want. However, in other attempts, you get a pointer to char , which, as it turned out, is the beginning of the string char s, so I assume that you get after atoi in subsequent attempts - this is the number converted from the characters at pos , pos+1 , pos+2 and to the end of line s .

0
source

If you really want to convert only one char to a string at a position (as opposed to a substring starting at that position and ending at the end of the line), you can do this in the following ways:

 int GetDigit(const string& s, const size_t& pos) { return atoi(string(1, s[pos]).c_str()); } int GetDigit2(const string& s, const size_t& pos) { const char n[2] = {s[pos], '\0'}; return atoi(n); } 

eg.

0
source

Source: https://habr.com/ru/post/899948/


All Articles