For example,
std::string_view strv{ "Hello" };
strv.remove_prefix(1);
The original string should be "Hello".
I tried using strv.data() and std::string str(strv.begin(), strv.end());
I can only get "ello" instead of "Hello".
I only found two methods right now.
use a variable(e.g. string str) to store original string then use use string_view. When you need the original string, use str.
use a variable(e.g. int removed_len) to record the length of removed prefixes. Then when you need the original string strv.data() - removed_len is the start place of the original string.
The "Hello" you use to construct strv is your original string. However, you never actually instantiate that string, making it a prvalue. If you want to keep a copy of your original string, try something like:
std::string str{"Hello"};
std::string_view strv{str};
strv.remove_prefix(1);
str will hold your original string.
Related
This can be marked solved. The problem was the print macro. ESP_LOGx can't put out c++ Strings.
I'm trying to convert an uin8_t array to a string in c++.
The array is defined in a header file like this:
uint8_t mypayload[1112];
Printing the array itself works, so I'm sure it's not empty.
now I'm trying to convert it to a string:
string qrData;
std::string qrData(reinterpret_cast<char const*>(mypayload), sizeof mypayload);
I also tried:
qrData = (char*)mypayload;
printing the string results in 5 random chars.
Does anybody have hint where I made a mistake?
The only correct comment so far is from Some programmer dude. So all credits go to him.
The comment from Ian4264 is flat wrong. Of course you can do a reinterpret_cast.
Please read here about the constructors of a std::string. You are using constructor number 4. The description is:
4) Constructs the string with the first count characters of character string pointed to by s. s can contain null characters. The length of the string is count. The behavior is undefined if [s, s + count) is not a valid range.
So, even if the string contains 0 characters, the C-Style string-"terminator", all bytes of the uint8_t arrays will be copied. And if you print the string, then it will print ALL characters, even the none printable characters after the '\0'.
That maybe your "random" characters. Because the string after your "terminator" does most probably contain uninitialized values.
You should consider to use the constructor number 5
5) Constructs the string with the contents initialized with a copy of the null-terminated character string pointed to by s. The length of the string is determined by the first null character. The behavior is undefined if [s, s + Traits::length(s)) is not a valid range.
And if you need to add bytes, also possible. The std::string can grow dynamically.
BTW: you do define your "std::string qrData" double, which will not compile
Since you know the size of your data in another variable, why are you using sizeof? It will give you the size of the array, not the size of your data.
This should give you the right result, assuming no other errors in your code
std::string qrData(reinterpret_cast<char const*>(mypayload), data->payload_len);
Incidentally in the code you quoted why is qrData declared twice? That seems a bit suspicious.
qrData = (const char*)mypayload;
string is accept only const char*.
String s = String((char *)data, len); //esp32
I am making a PONG clone in C++/SDL, and I have all of my images in the directory in which the program starts. I am successfully able to find that path using GetCurrentDirectory() and open the file using strcat() to append the actual image and it will load fine, but this will change the original value, which makes it useless when I try to load the next image. How would I pass the path without changing the original value, or another way to work around this problem.
My current code:
TCHAR openingdirectorytemp [MAX_PATH];
bgtexturesurf = SDL_LoadBMP(strcat(openingdirectorytemp, "\\bg.bmp"));
Use actual C++ strings:
#include <string>
using std::string;
void child(const string str)
{
str += ".suffix"; // parameter str is a copy of argument
}
void parent()
{
string parents_string = "abc";
child(parents_string);
// parents_string is not modified
}
If you must work with TCHAR in the Windows API world, use std::basic_string<TCHAR>:
typedef std::basic_string<TCHAR> str_t; // now use str_t everywhere
and so the code becomes something like
void my_class::load_bg_bmp(const str_t &dir_path)
{
str_t file_path = dir_path + _T("\\bg.bmp")l
bgtexturesurf = SDL_LoadBMP(file_path.c_str()));
// ...
}
The TCHAR type allows for build times switching between narrow and wide characters. It is pointless to use TCHAR, but then use unwrapped narrow character string literals like "\\bg.tmp".
Also, note that strcat to an uninitialized array invokes undefined behavior. The first argument to strcat must be a string: a pointer to the first-element of a null terminated character array. An uninitialized array is not a string.
We can avoid such low-level nasties by using the C++ string class.
Although you can use C++ string as suggested by other answers, you can still keep your C approach.
What you need to do is just to create another string by copying the contents from the original, and use it for strcat:
TCHAR openingdirectorytemp [MAX_PATH];
TCHAR path [MAX_PATH];
strcpy(path, openingdirectorytemp);
bgtexturesurf = SDL_LoadBMP(strcat(path, "\\bg.bmp"));
By doing so, you create string path with a separate memory space, so strcat won't affect openingdirectorytemp
You need to make a copy of the string before concatenating if you are worried about things getting changed. In other words
string1 = "abc"
string2 = "def"
strcat(string1, string2);
Results in
string1 = "abcdef"
since that is what you asked the program to do. Instead, add
strcpy(string3, string1)
strcat(string3, string2);
Now you will have
string1 = "abc"
string3 = "abcdef"
Of course you need to make sure enough space is allocated, etc.
Once you are using c++, you can use string to compose your final pathname:
string pathname(path);
pathname += "\\bg.bmp";
bgtexturesurf = SDL_LoadBMP(pathname.c_str());
I am wondering is this way of reversing a string is safe?
void ReverseString( std::string & stringToReverse )
{
stringToReverse.assign( stringToReverse.rbegin(), stringToReverse.rend() );
}
According to ยง21.4.6.3/20, assign(first,last) (with iterators first and last) is equivalent to
assign(string(first,last))
Hence it first creates a new string object and then assigns it. There is no risk that the string you copy from (in reverse) is being modified while you still copy (if that is what you were afraid of).
However, using std::reverse(begin(str),end(str)) as suggested by the others is better and potentially more efficient.
I don't know if this is a request to have your code reviewed, or you don't know about other options, but you should just use std::reverse from <algorithm>
std::string str = "Hello world!";
std::reverse(str.begin(), str.end());
This reverses the string in place. If you wanted to create a new string, you're essentially doing what you have in you code using assign() but with the std::string constructor:
std::string reversed(str.rbegin(), str.rend());
As suggested by others, what you did, in fact, reverses the char sequence.
The fact this actually reverses the string depends on what the concept of "reverse" and "string" and "char" are meant to be.
An std::string is a sequence of char that are 8 bit long (at least on the most platforms).
A Japanese string (but even a French or Italian or German one) can contain codepoints that are outside the 0..127 range, and hence need to be encode somewhat to be represented into 8 bit characters, so a "character" may keep more than 1 char. An putting the char-s in reverse order doesn't reverse the text, it just mess it out completely.
Assuming 1 character <=> 1 char is true only for pure ASCII text.
when I use strtok to tokenize a c++ string, it happens a confusing problem, see the simple code below:
void a(string s){
strtok((char*)s.c_str(), " ");
}
int main(){
string s;
s = "world hello";
a(s);
cout<<s<<endl;
return 0;
}
the program outputs "world".
Shouldn't it output "world hello"? Because I pass the string as a value parameter to function a, the strtok shouldn't modify the original s...
Can anyone explain this trick.
thank you.
The problem is (char*)s.c_str(), you are casting the constness away and modified the string contents in a way that you are not supposed to. While the original s should not be modified, I pressume you may have been hit by a smart optimization that expects you to play by the rules. For instance, a COW implementation of string would happen to show that behavior.
c_str() returns a const pointer, which is a promise to the compiler that the thing being pointed at won't be modified. And then you're calling strtok which modifies it.
When you lie to the compiler, you will be punished.
That's the way strtok() works. It use the first parameter as a buffer. By casting it to a char*, you allow it to modify the string. strtok() does not known about the original std::string. It also store the string pointer in a static variable, that's why you have to call it with a null pointer the next times to continue to parse the same string.
By the way, in c++, you should use std::istringstream instead. It does not use an internal static variable, which is not thread-safe. And you can extract the parameters directly into int, double, etc like we do with cin. std::ostringstring replace sprintf().
I am very confused about when to use string (char) and when to use string pointers (char pointers) in C++. Here are two questions I'm having.
which one of the following two is correct?
string subString;
subString = anotherString.sub(9);
string *subString;
subString = &anotherString.sub(9);
which one of the following two is correct?
char doubleQuote = aString[9];
if (doubleQuote == "\"") {...}
char *doubleQuote = &aString[9];
if (doubleQuote == "\"") {...}
None of them are correct.
The member function sub does not exist for string, unless you are using another string class that is not std::string.
The second one of the first question subString = &anotherString.sub(9); is not safe, as you're storing the address of a temporary. It is also wrong as anotherString is a pointer to a string object. To call the sub member function, you need to write anotherString->sub(9). And again, member function sub does not exist.
The first one of the second question is more correct than the second one; all you need to do is replace "\"" with '\"'.
The second one of the second question is wrong, as:
doubleQuote does not refer to the 10th character, but the string from the 10th character onwards
doubleQuote == "\"" may be type-wise correct, but it doesn't compare equality of the two strings; it checks if they are pointing to the same thing. If you want to check the equality of the two strings, use strcmp.
In C++, you can (and should) always use std::string (while remembering that string literals actually are zero-terminated character arrays). Use char* only when you need to interface with C code.
C-style strings need error-prone manual memory management, need to explicitly copy strings (copying pointers doesn't copy the string), and you need to pay attention to details like allocating enough memory to have the terminating '\0' fit in, while std::string takes care of all this automagically.
For the first question, the first sample, assuming sub will return a substring of the provided string.
For the second, none:
char doubleQuote = aString[9];
if( doubleQuote == '\"') { ... }
Erm, are you using string from STL?
(i.e. you have something like
#include <string>
#using namespace std;
in the beginning of your source file ;) )
then it would be like
string mystring("whatever:\"\""");
char anElem = mystring[9];
if (anElem=="\"") { do_something();}
or you can write
mystring.at(9)
instead of square brackets.
May be these examples can help.