174

I have a single char value, and I need to cast/convert it to a std::string. How can I do this?

I know how to go the opposite way, to retrieve a char from a std::string object: you just need to index the string at the appropriate location. For example: str[0] will retrieve the first character in the string.

But how do I go the other way? I want something like:

char c = 34;
std::string s(c);

…but this doesn't work (the string is always empty).

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
weeo
  • 2,619
  • 5
  • 20
  • 29

9 Answers9

252

You can use any/all of the following to create a std::string from a single character:

  • std::string s(1, c);
    
    std::cout << s << std::endl;
    
  • std::string s{c};
    
    std::cout << s << std::endl;
    
  • std::string s;
    s.push_back(c);
    
    std::cout << s << std::endl;
    
Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
Massa
  • 8,647
  • 2
  • 25
  • 26
99

std::string has a constructor that takes a number and a character. The character will repeat for the given number of times. Thus, you should use:

std::string str(1, ch);
Daniel Gallagher
  • 6,915
  • 25
  • 31
  • 20
    This is the right answer. But what I don't like about this constructor is that I don't use it enough to remember the order of the parameters. And if you get them switched, it still compiles. – Fred Larson Jan 18 '11 at 21:10
  • 3
    @Fred Larson This is of course what just happened to me as I was trying this solution. – pythonic metaphor Jan 18 '11 at 21:13
  • It only works for the case of one char though. What if you have `char x[] = { 'a', 'b', 'c' }`? ) – Maxim Egorushkin Jan 18 '11 at 21:27
  • 4
    For an array of chars, @Maxim, use the constructor that takes a pointer and the number of chars. In your case, `std::string(x, 3)`. – Rob Kennedy Jan 18 '11 at 21:33
  • 1
    @Rob: but that is another constructor, I was referring to the limitation of the fill constructor. You could do as well `std::string(&ch, 1)`. – Maxim Egorushkin Jan 18 '11 at 21:37
  • 1
    Well, yeah, @Maxim. The class provides multiple constructors. My point is that we should use the right one for the job. – Rob Kennedy Jan 18 '11 at 21:59
  • @Fred: std::string is an implementation kitchen-sink all around; however, it helps to remember that all sequences have a constructor taking a count and value parameter, with the value defaulted to T(). – Fred Nurk Jan 18 '11 at 22:10
  • 4
    Horrible order of parameters. And why not just allow one char and no count parameter? – Jonny May 25 '16 at 02:28
  • Lack of char constructor also means lack of conversion. So, e.g., while you can pass a `char*` to a function that takes `const std::string` argument, you can't pass a `char` -- which seems unnecessarily limiting. – John H. Dec 17 '20 at 17:19
  • Dang I meant `const std::string&`. – John H. Dec 17 '20 at 17:35
12

You can try stringstream. An example is below:

#include <sstream>
#include <string>

std::stringstream ss;
std::string target;
char mychar = 'a';
ss << mychar;
ss >> target;
Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
Mallen
  • 262
  • 2
  • 9
  • This solution works, however using stringstream (``) is not necessary since it will include the whole library in the project, slowing down the compilation process. Try to avoid including unnecessary dependencies to your project. – Cristian Feb 24 '20 at 12:47
  • I would argue that that is an over-complex rather than "easy" solution. That said the problem itself may be an over-simplification and using a string stream might be appropriate in other cases (where other types are to be inserted into the string). – Clifford Mar 28 '22 at 22:53
11

This solution will work regardless of the number of char variables you have:

char c1 = 'z';
char c2 = 'w';
std::string s1{c1};
std::string s12{c1, c2};
santahopar
  • 2,933
  • 2
  • 29
  • 50
4

You still can use the string constructor taking two iterators:

char c = 'x';
std::string(&c, &c + 1);

Update:

Good question James and GMan. Just searched freely downloadable "The New C Standard" by Derek M. Jones for "pointer past" and my first hit was:

If the expression P points to an element of an array object and the expression Q points to the last element of the same array object, the pointer expression Q+1 compares greater than P... even though Q+1 does not point to an element of the array object...

On segmented architectures incrementing a pointer past the end of a segment causes the address to wrap segmented architecture around to the beginning of that segment (usually address zero). If an array is allocated within such a segment, either the implementation must ensure that there is room after the array for there to be a one past the end address, or it uses some other implementation technique to handle this case (e.g., if the segment used is part of a pointer’s representation, a special one past the end segment value might be assigned)...

The C relational operator model enables pointers to objects to be treated in the same way as indexes into array objects. Relational comparisons between indexes into two different array objects (that are not both subobjects of a larger object) rarely have any meaning and the standard does not define such support for pointers. Some applications do need to make use of information on the relative locations of different objects in storage. However, this usage was not considered to be of sufficient general utility for the Committee to specify a model defining the behavior...

Most implementations perform no checks prior to any operation on values having pointer type. Most processors use the same instructions for performing relational comparisons involving pointer types as they use for arithmetic types. For processors that use a segmented memory architecture, a pointer value is often represented using two components, a segment number and an offset within that segment. A consequence of this representation is that there are many benefits in allocating storage for objects such that it fits within a single segment (i.e., storage for an object does not span a segment boundary). One benefit is an optimization involving the generated machine code for some of the relational operators, which only needs to check the segment offset component. This can lead to the situation where p >= q is false but p > q is true, when p and q point to different objects.

Community
  • 1
  • 1
Maxim Egorushkin
  • 131,725
  • 17
  • 180
  • 271
  • 3
    Is this strictly valid? Can you treat a scalar object as a one-element array and then use the one-past-the-end pointer? – James McNellis Jan 18 '11 at 21:05
  • 2
    Absolutely. An array of one element and a scalar have the same layout and alignment. In fact, sizeof(element) is defined as a multiple of element's alignment, so that there is no padding between the elements of an array. – Maxim Egorushkin Jan 18 '11 at 21:25
  • 2
    @Maxim: How do we know that? A pointer one past the end of an array is valid (though cannot be dereferenced), but I don't think a pointer one past an element is, like @James says. – GManNickG Jan 18 '11 at 21:27
  • 2
    @GMan: we know it because it is common knowledge. Why could not be an object treated like a one element array? – Maxim Egorushkin Jan 18 '11 at 21:34
  • 3
    @Maxim: An appeal to common knowledge is the same as "because I think so, I hope so, and it should be"; that doesn't make it so. No, it's not "common knowledge" or James and I wouldn't be asking. I really doubt that this answer has defined behavior. – GManNickG Jan 18 '11 at 21:37
  • 8
    §5.7/4 "For the purposes of these operators, a pointer to a nonarray object behaves the same as a pointer to the first element of an array of length one" It's OK. – Cheers and hth. - Alf Jan 18 '11 at 21:58
  • 1
    @Alf: Thank you, that's more like it. – GManNickG Jan 18 '11 at 22:29
  • @MaximEgorushkin Your first sentence should rather read: "You still can use the string constructor taking two *pointers*:" – Artur Opalinski Jan 17 '22 at 15:58
3

This works on gcc C++ 4.9.2 (http://ideone.com/f3qhTe)

#include <iostream>
using namespace std;

int main() {
    // your code goes here
    std::string test;

    test = (char) 76;
    test += (char) 77;
    test += (char) 78;
    test += (char) 79;

    std::cout << "test contains: " << test << std::endl;
    return 0;
}
Sascha
  • 986
  • 10
  • 30
3

In most cases you can just use {ch}.

std::string s = {ch}; // works
infix.push({ch}); // works

This utilises the std::initializer_list constructor of std::string.

n. m. could be an AI
  • 112,515
  • 14
  • 128
  • 243
1

I don't know Java that much, but the closest in C++ to your ch + "" is probably std::string{} + ch. Note, that "" is not a std::string, and you cannot overload operators for fundamental types, hence ch+"" cannot possibly result in a std::string.

However, std::string{} + ch involves 2 strings. I suppose the temporary can be optimized away by the compiler, though to construct a string from one character this is perfectly fine: std::string(1,ch).

For other constructors of std::string I refer you to https://en.cppreference.com/w/cpp/string/basic_string/basic_string.

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
0

You can set a string equal to a char.

#include <iostream>
#include <string>

using namespace std;

int main()
{
   string s;
   char one = '1';
   char two = '2';
   s = one;
   s += two;
   cout << s << endl;
}

./test
12

JayS
  • 2,057
  • 24
  • 16