Some times we need to turn a number into a string or a string with digits into a number. Luckily, the standard libraries have functions to cover both scenarios.
#include <iostream>
#include <string>
int main()
{
int value = 42;
std::string text = std::to_string(value);
std::cout << text << '\n';
return 0;
}
The integer 42 is stored in value. std::to_string takes that integer and returns a std::string containing two chars, '4' and '2'. That string is then assigned to text.
The print statement then shows those two chars, and we see the original integer has not changed value. This compiles fine without warning.
This all still applies to floating point numbers.
#include <iostream>
#include <string>
int main()
{
double temperature = 36.6;
std::string text = std::to_string(temperature);
std::cout << text << '\n';
return 0;
}
The float temperature with value 36.6 is stored in temperature. std::to_string translates that to string, and that result is assigned to text. What appears after the decimal point and when that appears is dependent on implementation, though it's never an issue for finite doubles, and the print statement shows the string representation of the number. No special formatting is applied.
We perform the opposite operation by using functions starting with sto.
#include <iostream>
#include <string>
int main()
{
std::string text{"123"};
// Convert this string to an integer
int number = std::stoi(text);
std::cout << number << '\n';
return 0;
}
text contains three chars '1', '2', and '3'. Calling std::stoi converts that string to an integer 123, assigned to number. The number printed is 123. If the string contained anything other than digits and whitespace, that call would have thrown an exception, but that is avoided in this example by giving it valid input.
A string might contain digits as well as other characters beyond that part of the number. std::stoi reads until the first char that doesn't parse as part of a decimal integer.
#include <iostream>
#include <string>
int main()
{
std::string text{"456defgh"};
int number = std::stoi(text);
std::cout << number << '\n';
return 0;
}
Calling std::stoi on "456defgh" returns 456 and leaves the remainder of the string unread. The rest of the print statement shows that this worked and gave a correct numeric result, with the additional characters being discarded.
If you want to be sure that the entire string passed consisted only of valid digits, then pass it a second argument where std::stoi can write the number of characters it read.
#include <iostream>
#include <string>
int main()
{
std::string text{"789"};
std::size_t chars_processed = 0;
// Pass an address so stoi can report how many characters it processed
int number = std::stoi(text, &chars_processed);
std::cout << number << '\n';
std::cout << chars_processed << '\n';
return 0;
}
If std::stoi is given the pointer to a string, it will return the number of characters that it parsed as an integer from the second argument. Following the call, number has 789 and chars_processed has 3. If chars_processed was not equal to the length of the string, 3 in this case, then there were leftover characters in the string that the integer conversion part could not parse.
Floating point has a very similar implementation using std::stod.
#include <iostream>
#include <string>
int main()
{
std::string text{"3.14159"};
// Convert this string to a double
double pi = std::stod(text);
std::cout << pi << '\n';
return 0;
}
Passing a string to std::stod returns a double, which is then printed. The function recognizes numbers that contain both an integer part and a floating point part. Again, all characters which cannot parse the decimal representation of the number, before and after the digits themselves, will be ignored, as will any leading whitespace in the string you pass it.
If you pass std::stoi or std::stod an invalid value, as in an empty string or one which solely consisted of characters non compliant to a decimal int or float, then you will throw an exception of type std::invalid_argument.
#include <iostream>
#include <string>
int main()
{
std::string text{""};
// int number = std::stoi(text); // throws std::invalid_argument
std::cout << "conversion skipped\n";
return 0;
}
This particular code has that function call commented out, so when this code is run, instead of failing the whole program, there will simply be a warning of an issue of this sort and the print statement will never be reached. We should consider this when programming.
If you give std::stoi a value which will not fit in a 32 bit integer, then it will throw an exception of type std::out_of_range.
#include <iostream>
#include <string>
int main()
{
std::string text{"99999999999999999999"};
// int number = std::stoi(text); // throws std::out_of_range
std::cout << "value too large\n";
return 0;
}
And here again, we just have the line that would throw the exception commented out so the program does not stop unexpectedly. In a more complex program, we would use std::stoll if we know that it will go into a long long, or would write our own logic to catch this out of range exception and return some default value.
Exercise: Converting Between Strings and NumbersStarter code, hints and solutionOpenClose
Practice: Converting Between Strings and Numbers
Work through the mission, reveal hints only when needed, and compare your result with the model solution.
Your challenge
Change text to 42cats. Predict both the integer returned by stoi and chars_processed, and explain what the remaining letters mean for this conversion.
Mission checklist
- Run the starter as a baseline, then predict the change requested in Your challenge.
- Make that change in your editor; use the lesson-specific hints if you need help.
- Compile and run your answer, then compare with the worked solution and explain the result.
Starter program
This is the working baseline, not the completed answer. Compile as C++20, then make the change described above.
#include <iostream>
#include <string>
int main()
{
std::string text{"789"};
std::size_t chars_processed = 0;
// Pass an address so stoi can report how many characters it processed
int number = std::stoi(text, &chars_processed);
std::cout << number << '\n';
std::cout << chars_processed << '\n';
return 0;
}Hints
stoi returns the parsed integer and stores a separate count through &chars_processed. That & takes an address; it is not bitwise AND.
Try a small numeric prefix followed by letters, such as "42cats", and predict both outputs. Text with no valid numeric prefix can throw, so it needs error handling rather than an assumed zero result.
Worked solution
text is now 42cats. stoi parses the numeric prefix, returning 42, and reports two consumed characters through chars_processed. The letters remain outside that parsed prefix.
#include <iostream>
#include <string>
int main()
{
std::string text{"42cats"};
std::size_t chars_processed = 0;
// Pass an address so stoi can report how many characters it processed
int number = std::stoi(text, &chars_processed);
std::cout << number << '\n';
std::cout << chars_processed << '\n';
return 0;
}
Example output
42
2
0 comments
No comments yet. Be the first.