underdog
underdog

Reputation: 49

Why can't part of a string be passed onto atoi or stoi?

I tried doing this to some substrings which were all natural numbers

fi = stoi(f[i]) - stoi(s[i]);
se = stoi(s[i]) - stoi(f[i]);

where f and s are 2 strings. This was solved when I assigned the part of the string to a new variable. I experienced similar stuff with atoi(str.c_str()). Why does stoi and atoi behave like this?

Upvotes: 0

Views: 1986

Answers (2)

Remy Lebeau
Remy Lebeau

Reputation: 597051

If f and s are strings, then f[i] and s[i] are single chars. atoi() and std::stoi() do not take single chars as input. They are simply not designed to work that way.

atoi() takes a const char* as input, and expects it to be a pointer to a null-terminated C-style string. So, to pass it a single char, you will have to construct a char[2] array first, eg:

char arr[] = { f[i], '\0' };
int i = atoi(arr);

std::stoi() takes a std::string as input. To pass it a single char, you have to construct a 1-char std::string first. However, std::string does not have a constructor that accepts only a single char as input, but there are many different ways that you can produce a 1-char std::string, eg:

std::string s(1, f[i]);
int i = std::stoi(s);
std::string s(f, i, 1);
int i = std::stoi(s);
std::string s(&f[i], 1);
int i = std::stoi(s);
std::string s(f+i, f+(i+1)); // if f is a char[]/char*
int i = std::stoi(s);
std::string s(f.begin()+i, f.begin()+(i+1)); // if f is a std::string
int i = std::stoi(s);
std::string s = f.substr(i, 1); // if f is a std::string
int i = std::stoi(s);
std::string s = { f[i] };
int i = std::stoi(s);
std::string s;
s = f[i]; // std::string has an operator=(char) overload
int i = std::stoi(s);
std::string s;
s.resize(1);;
s[0] = f[i];
int i = std::stoi(s);
std::string s = std::string_view(&f[i], 1);
int i = std::stoi(s);

That being said, if all of the chars are between '0'..'9' inclusive, then you don't need to use atoi()/std::stoi() to convert them to integers. Just subtract '0' from them instead, eg:

fi = (f[i] - '0') - (s[i] - '0');
se = (s[i] - '0') - (f[i] - '0');

This works because in ASCII, characters '0'..'9' are defined as sequential values 48..57, thus the above is really just doing this:

'0' - '0' = 0 -> 48 - 48 = 0
'1' - '0' = 1 -> 49 - 48 = 1
'2' - '0' = 2 -> 50 - 48 = 2
and so on...

Upvotes: 1

Slava
Slava

Reputation: 44268

Why can't part of a string be passed onto atoi or stoi?

It can, to get a substring from std::string you need to call std::string::substr() method. Something like:

std::stoi( f.substr( i, 1 ) ); 

assuming you want 1 symbol substring long starting from position i. std::string::operator[] does not give you a substring, but a single character from that position, ie std::string can act as a container of chars.

Upvotes: 4

Related Questions