In this lesson, we’ll take a look at how to construct objects of std::string, as well as how to create strings from numbers and vice-versa.
String construction
The string classes have a number of constructors that can be used to create strings. We’ll take a look at each of them here.
Note: string::size_type resolves to size_t, which is the same unsigned integral type that is returned by the sizeof operator. Its actual size varies depending on environment. For purposes of this tutorial, envision it as an unsigned int.
string::string()
Sample code:
Output: |
string::string(const string& strString)
Sample code:
Output: my string |
string::string(const string& strString, size_type unIndex) string::string(const string& strString, size_type unIndex, size_type unLength)
Sample code:
Output: string stri |
string::string(const char *szCString)
Sample code:
Output: my string |
string::string(const char *szCString, size_type unLength)
Sample code:
Output: my s |
string::string(size_type nNum, char chChar)
Sample code:
Output: QQQQ |
template<class InputIterator> string::string(InputIterator itBeg, InputIterator itEnd)
No sample code for this one. It’s obscure enough you’ll probably never use it. |
string::~string()
String destruction
No sample code here either since the destructor isn’t called explicitly. |
Constructing strings from numbers
One notable omission in the std::string class is the lack of ability to create strings from numbers. For example:
1 |
std::string sFour{ 4 }; |
Produces the following error:
c:vcprojectstest2test2test.cpp(10) : error C2664: 'std::basic_string<_Elem,_Traits,_Ax>::basic_string(std::basic_string<_Elem,_Traits,_Ax>::_Has_debug_it)' : cannot convert parameter 1 from 'int' to 'std::basic_string<_Elem,_Traits,_Ax>::_Has_debug_it'
Remember what I said about the string classes producing horrible looking errors? The relevant bit of information here is:
cannot convert parameter 1 from 'int' to 'std::basic_string
In other words, it tried to convert your int into a string but failed.
The easiest way to convert numbers into strings is to involve the std::ostringstream class. std::ostringstream is already set up to accept input from a variety of sources, including characters, numbers, strings, etc… It is also capable of outputting strings (either via the extraction operator>>, or via the str() function). For more information on std::ostringstream, see 23.4 -- Stream classes for strings.
Here’s a simple solution for creating std::string from various types of inputs:
1 2 3 4 5 6 7 8 9 10 11 |
#include <iostream> #include <sstream> #include <string> template <typename T> inline std::string ToString(T tX) { std::ostringstream oStream; oStream << tX; return oStream.str(); } |
Here’s some sample code to test it:
1 2 3 4 5 6 7 8 9 |
int main() { std::string sFour{ ToString(4) }; std::string sSixPointSeven{ ToString(6.7) }; std::string sA{ ToString('A') }; std::cout << sFour << '\n'; std::cout << sSixPointSeven << '\n'; std::cout << sA << '\n'; } |
And the output:
4 6.7 A
Note that this solution omits any error checking. It is possible that inserting tX into oStream could fail. An appropriate response would be to throw an exception if the conversion fails.
Converting strings to numbers
Similar to the solution above:
1 2 3 4 5 6 7 8 9 10 |
#include <iostream> #include <sstream> #include <string> template <typename T> inline bool FromString(const std::string& sString, T &tX) { std::istringstream iStream(sString); return !(iStream >> tX).fail(); // extract value into tX, return success or not } |
Here’s some sample code to test it:
1 2 3 4 5 6 7 8 |
int main() { double dX; if (FromString("3.4", dX)) cout << dX << '\n'; if (FromString("ABC", dX)) cout << dX << '\n'; } |
And the output:
3.4
Note that the second conversion failed and returned false.
![]() |
![]() |
![]() |
1. Feedback
The block sample is very neat and easy to read.
When I used to_string to convert 'A', I got 65 which is the ascii equivalent of A. When I used the ToString template, I get the letter A. Why the difference?
`std::to_string` converts numbers to string. When you call `std::to_string` with a `char`, you're calling `std::to_string(int)` (There is no overload for `char`s).
`ToString` uses `std::ostream`, which which treats `char` as characters, not as numbers.
Instead of
in the last example I somewhat prefer
The latter block of that example also seems to be missing the `std::` prefixes (or `using namespace std`) and uses `std::endl` instead of `'\n'`, which you now recommend in earlier lectures.
Changed to
"std::" added and "endl" removed, thanks for pointing that out!
Why does this happen?
a and b are different. why does one take the first 15 charactres, and the other takes the last few characters.
* Line 1, 2, 3, 4: Initialize your variables with brace initializers.
@std::string::string(const char *s, size_type count) constructs a string containing the first @count characters of @s.
@std::string::string(const std::string &other, size_type count) constructs a string containing all characters of @other, starting at @count.
See
https://en.cppreference.com/w/cpp/string/basic_string/basic_string
for more information.
Should I avoid doing something like this or the std::wstring will be constructed correctly. It work on what I'm doing but I'm not sure if I'm lucky that it work or it's perfectly fine.
The most obvious solution to convert an Int (or something simlar) into a string to me seems to be something like this:
Is there a strong reason against doing this (performance wise or style wise)?
I don't know what you did there or what you attempted to do.
If you want to convert a standard data type to a string you should use @std::to_string.
If you want to convert a custom type with overloaded io operator, you should use @std::stringstream.
In the last example, does
return bool? I thought it would return a stream reference to allow chaining. Or maybe it returns something that is implicitly converted to bool? But reference can't be empty or null, so how would it convert to bool?
Hi John!
std::istream::operator>> returns a reference to the stream. std::istream overloads the bool operator, returning whether or not the fail-bit is set.
References
* std::istream::operator>> - http://www.cplusplus.com/reference/istream/istream/operator%3E%3E/
* std::istream::operator bool - http://www.cplusplus.com/reference/ios/ios/operator_bool/
* Lesson 9.10 - Overloading typecasts
Thank you!
hey alex thanks for the tutorials but would using std::string to_string not be better than ussing the templated function you provided?
http://en.cppreference.com/w/cpp/string/basic_string/to_string
Hi Levi!
@std::to_string performs a simple @std::vsnprintf call whereas @std::istream::operator<< does all kinds of stuff. Without benchmarking I'd say @std::to_string is the better choice. This lesson was originally written in 2009, @std::to_string was introduced in 2011, I guess this is why @std::to_string isn't yet covered.
Same for all the @std::sto* functions linked at the bottom of cppreference.
Alex, in the last example i think you should put a comment like this in the code:
At Least for me, it kinda confused me for some time trying to understand why the second call failed, until I read the lesson 18.4 linked in the article.
I've added a comment. Thanks for the suggestion.
Ooooh, you moved Stream classes for strings to the next chapter (18.4). That's why I was clueless!
Oh, yes. Link updated.
In the last example in your table of String constructors, which is actually the destructor, you wrote:
"string::~string()
String construction ..."
Did you mean to write String "destruction"?
Yup, typo. Thanks for pointing that out.
Hey Alex,
I am confused as to when to use istringstream and ostringstream. In the lesson 13.4 — Stream classes for strings, we simply using stringstream for both purposes. So when do we use istringstream and when do we use ostringstream?
stringstream is more versatile, but if you only need to use an input stream or an output stream, then using istringstream or ostringstream express your intent more effectively and may prevent you from making mistakes (e.g. using << instead of >>).
"Warning: For this function only, NULLs are not treated as end-of-string characters in szCString! This means it is possible to read off the end of your string if unLength is too big. Be careful not to overflow your string buffer!"
-> what does this mean ? what is a null ? and how can it be inside a C-style string ?
-> is it bad that I got to this point in your lessons and still don't understand what is a null ? I know that is used instead of '0' for pointers
and thaaaaaaaaaaaaaaaaaaaaaannnnnnnnnnnnnnnkkkkkkkkkk's
In this context, I'm really talking about char '\0', which is the null terminator.
Which constructor is called in this case? Is "my string" a std::string constant or a C-style string constant?
It's a C-style constant, but if there's no constructor that handles const char* and there is one that handles std::string, the compiler should implicitly convert it to a std::string.
Thanks!
Typo ("it's" should be "its"): "It’s actual size varies depending on environment."
Also, you use the word "conversation" a couple times where I think you intended to use "conversion":
* "An appropriate response would be to throw an exception if the conversation fails."
* "Note that the second conversation failed and returned false."
Fixed. Thanks!
In the section "Constructing strings from numbers", the first testing sample code (the main() function) has:
.
This should be:
.
Thanks, fixed.
I think I missed where ever you first used "inline". What does that word do?
Sorry, that's section 7.5. It's right in the title.
I have found one more good reference for C++ Strings at https://www.tutorialcup.com/cplusplus/strings.htm
Hi,
The last two sample programs contain some minor errors.
Here's the source code for the first one:
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
template <typename T>
inline string ToString(T tX)
{
ostringstream oStream;
oStream << tX;
return oStream.str();
}
int main()
{
string sFour(ToString(4));
string sSixPointSeven(ToString(6.7));
string sA(ToString('A'));
cout << sFour << endl;
cout << sSixPointSeven << endl;
cout << sA << endl;
}
And its output:
4
6.7
A
Here's the source code for the second sample program:
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
template <typename T>
inline bool FromString(const string& sString, T &tX)
{
istringstream iStream(sString);
return (iStream >> tX) ? true : false;
}
int main()
{
double dX;
if (FromString("3.4", dX))
cout << dX << endl;
if (FromString("ABC", dX))
cout << dX << endl;
}
And its output:
3.4
I agree with sumanth, this is a fine tutorial indeed, I basically learned c++ from your tutorial.
I would also like to note a typo in one of the example codes,
I believe this should be 4:
This site is the best resource for learning C++ that i have come across in years. The concepts presented are arranged in a clear order without overlapping and the explanation and contents is simply marvellous.
A huge thanks to Alex for coming up with this site. I really appreciate your efforts. Keep up the good work. Waiting for the updates on chapter-16.
-sumanth
Thanks Alex, lots of new stuff I didn't know about. Especially the NULL part of string::string(const char *szCString, size_type unLength)...I wonder if they just forgot.... :D