Preferred conversion from char (not char*) to std::string

31,358

Solution 1

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);

Solution 2

To add to the answer, you can simply use initializer list

std::string str = {ch};

Solution 3

just use the overload that takes a char?

i.e. string(1, 'A')

Solution 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.

Solution 5

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;
}
Share:
31,358
pythonic metaphor
Author by

pythonic metaphor

Updated on January 30, 2022

Comments

  • pythonic metaphor
    pythonic metaphor about 2 years

    I have a char, a plain old character, that I would like to turn into an std::string. std::string(char) doesn't exist of course. I could create an char array and copy it in, I could go through string streams, or many other little roundabout routes. Currently, I prefer boost::lexical_cast, but even that seems too verbose for this simple task. So what's the preferred way?

  • James McNellis
    James McNellis about 13 years
    Is this strictly valid? Can you treat a scalar object as a one-element array and then use the one-past-the-end pointer?
  • Drew Delano
    Drew Delano about 13 years
    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.
  • pythonic metaphor
    pythonic metaphor about 13 years
    @Fred Larson This is of course what just happened to me as I was trying this solution.
  • Maxim Egorushkin
    Maxim Egorushkin about 13 years
    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
    Maxim Egorushkin about 13 years
    It only works for the case of one char though. What if you have char x[] = { 'a', 'b', 'c' }? )
  • GManNickG
    GManNickG about 13 years
    @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.
  • Rob Kennedy
    Rob Kennedy about 13 years
    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).
  • Maxim Egorushkin
    Maxim Egorushkin about 13 years
    @GMan: we know it because it is common knowledge. Why could not be an object treated like a one element array?
  • Maxim Egorushkin
    Maxim Egorushkin about 13 years
    @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).
  • GManNickG
    GManNickG about 13 years
    @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.
  • Cheers and hth. - Alf
    Cheers and hth. - Alf about 13 years
    §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.
  • Rob Kennedy
    Rob Kennedy about 13 years
    Well, yeah, @Maxim. The class provides multiple constructors. My point is that we should use the right one for the job.
  • Fred Nurk
    Fred Nurk about 13 years
    @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().
  • GManNickG
    GManNickG about 13 years
    @Alf: Thank you, that's more like it.
  • Jonny
    Jonny almost 8 years
    Horrible order of parameters. And why not just allow one char and no count parameter?
  • John H.
    John H. over 3 years
    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.
    John H. over 3 years
    Dang I meant const std::string&.
  • Artur Opalinski
    Artur Opalinski over 2 years
    @MaximEgorushkin Your first sentence should rather read: "You still can use the string constructor taking two pointers:"