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.
Program:
#include <iostream>
using namespace std;
int main() {
string str;
str[0] = 'a';
str[1] = 'b';
str[2] = 'c';
cout << str;
return 0;
}
Output:
No output.
If I replace cout << str; with cout << str[1], I get a proper output.
Output:
b
And if I change the data type of the variable to a character array, I get the desired output. (Replacing string str; with char str[5];
Output:
abc
Why is my program behaving like this? How do I alter my code to get the desired output without changing the data type?
Your program has undefined behavior.
string str;
creates an empty string. It has length 0.
You are trying to write to the first three elements of this string with
str[0] = 'a';
str[1] = 'b';
str[2] = 'c';
These do not exist. Indexing a std::string out-of-bounds causes undefined behavior.
You can add characters to a string with any of the following methods:
str += 'a';
str += "a";
str.push_back('a');
str.append("a");
or you can resize the string first to the intended length before you index into any of its elements:
str.resize(3);
As pointed out by #Ayxan in a comment under this answer, you are also missing #include<string>. Without it it is unspecified whether your program will compile since it uses std::string which is defined in <string>. It is unspecified whether including one standard library header will include another one if there isn't a specific exception. You should not rely on unspecified behavior that may break at any point.
In addition to walnut's answer, here's what's going on under the hood:
An std::string contains at least two members, a data pointer (type char*) and a size. The [] operator does not check the size, it only indexes into the memory behind the data pointer. Also, the [] operator does not modify the size member of the string.
The << operator that streams the string to cout, however, does interpret the size member. It does so to be able to output strings containing null characters. Since the size member is still zero, nothing is printed.
You may wonder why the memory access within str[0] even succeeds, after all, the string never had any reason to allocate any memory for its data yet. This is due to the fact that virtually all std::string implementations use the small-string-optimization: The std::string object itself is a bit larger than it needs to be, and the space at its end is used instead of an allocation on the heap unless the string becomes longer than that space. As such, the default constructor will just point the data pointer to that internal storage to have it initialized, and your memory accesses are directed to existing memory. This is why you don't get a SEGFAULT unless you access the string's data way out of bounds. Doesn't change the fact that already your expression str[0] is undefined behavior, though. The symptoms may appear benign, but the disease is fatal.
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
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).