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).
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;
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);
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;
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};
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.
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;
}
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.
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.
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
Related
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).
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;
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);
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;
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};
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.
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;
}
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.
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.
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
int i = ("aac" > "aab");
cout << i;
The above code does not give me the output as 1 (as it should be). But when I assign "aac" and "aab" to two separate string variables and use the variables instead of using strings directly (code attached below), I get the desired output.
Could anyone help me please?
string s1 = "aac";
string s2 = "aab";
int i = (s1 > s2);
cout << i;
Literal constants like "aac" aren't std::string objects; rather, they are just data in (read-only) memory that evaluate, in most 'access' cases, to the address of their first element (i.e. a char* pointer); so, a comparison between them will be a comparison between those addresses — something you are unlikely to be able to control or predict.
To get an inline comparison, in your case, you can use inline std::string constructors (sometimes knows as "wrappers"), like this:
int i=(string("aac")>string("aab"));
Or, using the more 'modern' "curly-brace" initializer syntax:
int i = (string{ "aac" } > string{ "aab" });
For more brevity, you can make use of the fact that std::string has versions of the > (and similar) operators that take a string literal as one of the arguments; thus, you need only 'wrap' one of the literals, and could reduce the above code to something like:
int i = (string{ "aac" } > "aab");
If you use C-style char * / char [] strings, you need to use strcmp like:
int i = strcmp("aac", "aab");
Otherwise, you are just comparing addresses of the first elements of both of strings.
I've been using:
string letters = THESAMELENGTH; // Assign for allocation purposes.
Reason being, if I:
string letters[THESAMELENGTH.length()];
I get a non constant expression complaint.
But if I:
string letters[12];
I'm at risk of needing to change every instance if the guide const string changes size.
But it seems foolish to assign a string when I won't use those entries, I only want my newly assigned string to be the same length as the previously assigned const string, then fill with different values.
How do you recommend I do this gracefully and safely?
You can
string letters(THESAMELENGTH.length(), ' '); // constructs the string with THESAMELENGTH.length() copies of character ' '
BTW: string letters[12]; doesn't mean the same as you expected. It declares a raw array of string containing 12 elements.
I only want my newly assigned string to be the same length as the previously assigned const string, then fill with different values.
Part of the reason the string class/type exists is so you don't have to worry about trying to manage its length. (The problem with arrays of char.)
If you have a const std::string tmp then you can't just assign anything to it after it has already been initialized. E.g.:
const std::string tmp = "A value"; // initialization
tmp = "Another value"; // compile error
How do you recommend I do this gracefully and safely?
If you really want to keep strings to a specific size, regardless of their contents, you could always resize your string variables. For example:
// in some constants.h file
const int MAX_STRING_LENGTH = 16;
// in other files
#include "constants.h"
// ...
std::string word = ... // some unknown string
word.resize(MAX_STRING_LENGTH);
Now your word string will have a length/size of MAX_STRING_LENGTH and anything beyond the end gets truncated.
This example is from C++ Reference
// resizing string
#include <iostream>
#include <string>
int main ()
{
std::string str ("I like to code in C");
std::cout << str << '\n';
unsigned sz = str.size();
str.resize (sz+2,'+');
std::cout << str << '\n';
str.resize (14);
std::cout << str << '\n';
return 0;
}
// program output
I like to code in C
I like to code in C++
I like to code
You can't just ask a string variable for its length at compile-time. By definition, it's impossible to know the value of a variable, or the state of any given program for that matter, while it's not running. This question only makes sense at run-time.
Others have mentioned this, but there seems to be an issue with your understanding of string letters[12];. That gives you an array of string types, i.e. you get space for 12 full strings (e.g. words/sentences/etc), not just letters.
In other words, you could do:
for(size_t i = 0; i < letters.size(); ++i)
letters[i] = "Hello, world!";
So your letters variable should be renamed to something more accurate (e.g. words).
If you really want letters (e.g. the full alphabet on a single string), you could do something like this:
// constants.h
const std::string ALPHABET_LC = "abc...z";
const std::string ALPHABET_UC = "ABC...Z";
const int LETTER_A = 0;
const int LETTER_B = 1;
// ...
// main.cpp, etc.
char a = ALPHABET_LC[LETTER_A];
char B = ALPHABET_UC[LETTER_B];
// ...
It all depends on what you need to do, but this might be a good alternative.
Disclaimer: Note that it's not really my recommendation that you do this. You should let strings manage their own length. For example, if the string value is actually shorter than your limit, you're causing your variable to use more space/memory than needed, and if it's longer, you're still truncating it. Neither side-effect is good, IMHO.
The first thing you need to do is understand the difference between a string length and an array dimension.
std::string letters = "Hello";
creates a single string that contains the characters from "Hello", and has length 5.
In comparison
std::string letters[5];
creates an array of five distinct default-constructed objects of type std::string. It doesn't create a single string of 5 characters. The reason for the non-constant complaint when doing
std::string letters[THESAMELENGTH.length()];
is that construction of arrays in standard C++ is required to use a length known to the compiler, whereas the length of a std::string is determined at run time.
If you have a string, and what to create another string of the same length, you can do something like
std::string another_string(letters.length(), 'A');
which will create a single string containing the required number of letters 'A'.
It is largely pointless to do what you are seeking as a std::string can dynamically change its length anyway, as needed. There is also nothing stopping a std::string from allocating more than it needs (e.g. to make provision for multiple increases in its length).
If I want to construct a std::string with a line like:
std::string my_string("a\0b");
Where i want to have three characters in the resulting string (a, null, b), I only get one. What is the proper syntax?
Since C++14
we have been able to create literal std::string
#include <iostream>
#include <string>
int main()
{
using namespace std::string_literals;
std::string s = "pl-\0-op"s; // <- Notice the "s" at the end
// This is a std::string literal not
// a C-String literal.
std::cout << s << "\n";
}
Before C++14
The problem is the std::string constructor that takes a const char* assumes the input is a C-string. C-strings are \0 terminated and thus parsing stops when it reaches the \0 character.
To compensate for this, you need to use the constructor that builds the string from a char array (not a C-String). This takes two parameters - a pointer to the array and a length:
std::string x("pq\0rs"); // Two characters because input assumed to be C-String
std::string x("pq\0rs",5); // 5 Characters as the input is now a char array with 5 characters.
Note: C++ std::string is NOT \0-terminated (as suggested in other posts). However, you can extract a pointer to an internal buffer that contains a C-String with the method c_str().
Also check out Doug T's answer below about using a vector<char>.
Also check out RiaD for a C++14 solution.
If you are doing manipulation like you would with a c-style string (array of chars) consider using
std::vector<char>
You have more freedom to treat it like an array in the same manner you would treat a c-string. You can use copy() to copy into a string:
std::vector<char> vec(100)
strncpy(&vec[0], "blah blah blah", 100);
std::string vecAsStr( vec.begin(), vec.end());
and you can use it in many of the same places you can use c-strings
printf("%s" &vec[0])
vec[10] = '\0';
vec[11] = 'b';
Naturally, however, you suffer from the same problems as c-strings. You may forget your null terminal or write past the allocated space.
I have no idea why you'd want to do such a thing, but try this:
std::string my_string("a\0b", 3);
What new capabilities do user-defined literals add to C++? presents an elegant answer: Define
std::string operator "" _s(const char* str, size_t n)
{
return std::string(str, n);
}
then you can create your string this way:
std::string my_string("a\0b"_s);
or even so:
auto my_string = "a\0b"_s;
There's an "old style" way:
#define S(s) s, sizeof s - 1 // trailing NUL does not belong to the string
then you can define
std::string my_string(S("a\0b"));
The following will work...
std::string s;
s.push_back('a');
s.push_back('\0');
s.push_back('b');
You'll have to be careful with this. If you replace 'b' with any numeric character, you will silently create the wrong string using most methods. See: Rules for C++ string literals escape character.
For example, I dropped this innocent looking snippet in the middle of a program
// Create '\0' followed by '0' 40 times ;)
std::string str("\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00", 80);
std::cerr << "Entering loop.\n";
for (char & c : str) {
std::cerr << c;
// 'Q' is way cooler than '\0' or '0'
c = 'Q';
}
std::cerr << "\n";
for (char & c : str) {
std::cerr << c;
}
std::cerr << "\n";
Here is what this program output for me:
Entering loop.
Entering loop.
vector::_M_emplace_ba
QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
That was my first print statement twice, several non-printing characters, followed by a newline, followed by something in internal memory, which I just overwrote (and then printed, showing that it has been overwritten). Worst of all, even compiling this with thorough and verbose gcc warnings gave me no indication of something being wrong, and running the program through valgrind didn't complain about any improper memory access patterns. In other words, it's completely undetectable by modern tools.
You can get this same problem with the much simpler std::string("0", 100);, but the example above is a little trickier, and thus harder to see what's wrong.
Fortunately, C++11 gives us a good solution to the problem using initializer list syntax. This saves you from having to specify the number of characters (which, as I showed above, you can do incorrectly), and avoids combining escaped numbers. std::string str({'a', '\0', 'b'}) is safe for any string content, unlike versions that take an array of char and a size.
In C++14 you now may use literals
using namespace std::literals::string_literals;
std::string s = "a\0b"s;
std::cout << s.size(); // 3
Better to use std::vector<char> if this question isn't just for educational purposes.
anonym's answer is excellent, but there's a non-macro solution in C++98 as well:
template <size_t N>
std::string RawString(const char (&ch)[N])
{
return std::string(ch, N-1); // Again, exclude trailing `null`
}
With this function, RawString(/* literal */) will produce the same string as S(/* literal */):
std::string my_string_t(RawString("a\0b"));
std::string my_string_m(S("a\0b"));
std::cout << "Using template: " << my_string_t << std::endl;
std::cout << "Using macro: " << my_string_m << std::endl;
Additionally, there's an issue with the macro: the expression is not actually a std::string as written, and therefore can't be used e.g. for simple assignment-initialization:
std::string s = S("a\0b"); // ERROR!
...so it might be preferable to use:
#define std::string(s, sizeof s - 1)
Obviously you should only use one or the other solution in your project and call it whatever you think is appropriate.
I know it is a long time this question has been asked. But for anyone who is having a similar problem might be interested in the following code.
CComBSTR(20,"mystring1\0mystring2\0")
Almost all implementations of std::strings are null-terminated, so you probably shouldn't do this. Note that "a\0b" is actually four characters long because of the automatic null terminator (a, null, b, null). If you really want to do this and break std::string's contract, you can do:
std::string s("aab");
s.at(1) = '\0';
but if you do, all your friends will laugh at you, you will never find true happiness.
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).
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;
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);
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;
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};
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.
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;
}
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.
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.
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