c++ string constructed as char array [duplicate] - c++

This question already has answers here:
I can't double characters inside string with function
(3 answers)
Closed 2 years ago.
currently learning strings, i have the following:
string s;
s[0]='a'; s[1]='b';
cout<<s;
string s; s.clear();
s+='a'; s+='b';
cout<<s;
I get empty string as output from 1st example, and the 2nd works fine. I get that the 1st is undef behavior and that we 'push' an element the second time instead of assigning a value.
Any more clarification will be appreciated

string s;
creates empty string
s[0]='a'; s[1]='b';
this is undefined behavior, since empty string have size zero, so required buffer may not exists.
It "works" since all major compilers are using Small String Optimization (SSO). In this optimization size of string object, allows to keep small string inside that object not on a heap. As a result minimum capacity of std::string is none zero (15 in gcc if I remember correctly).
cout<<s;
Now deeding on how this stream operator is implemented it can print empty string (size size of string is zero) or "ab" or "ab<some thrash>".
On gcc it prints nothing.
To fix it you can:
resize string first s.resize(2)
use push_back API

Related

Why does string concatenation fail when resize is used in cpp? [duplicate]

This question already has answers here:
What is an off-by-one error and how do I fix it?
(6 answers)
Closed 1 year ago.
I came across a scenario where string concatenation is failing in C++. But I don't see a reason for it to fail.
Code sample is as below:
int main()
{
std::string a;
std::string b = "bbbbbbb";
a.resize(10);
for (int i = 0; i <= 5; i++) {
a[i] = 'a';
}
a = a+b;
printf("\n%s\n", a.c_str());
}
It is outputting aaaaaa.
I was expecting it to output aaaaaabbbbb. If I change a.resize(10); to a.resize(5); I am getting the expected output.
Would be helpful if someone could help me in understanding the behaviour?
In addition to the off-by-one error, after concatenation, the contents of a in main are:
aaaaa\0\0\0\0\0bbbbb
So: five 'a' bytes, then five zero bytes, then five 'b' bytes. The string is fifteen bytes long.
printf, like other C functions, doesn't know about this size, and instead takes the length of the string to be until the first zero byte. In your case, that is "aaaaa".
To print the entire string, use something like std::cout. If you're certain you want printf, it is also possible to pass a length to that with the %.*s specifier.
std::string a;
a.resize(10);
gives you a string of size 10 but whose content is undefined.
You set the first 5 character to something specific and append some more characters to the end. But characters 5-10 never get set to something.
In the execution you are seeing, these characters happen to be zero, but printf – as a C style function — considers the appearance of a null character the end of the string. Therefore it stops printing.

c++ creating string using char array

currently learning strings, i have the following cases :
string s;
s[0]='a'; s[1]='b';
cout<<s;
string s; s.clear();
s+='a'; s+='b';
cout<<s;
I get empty string as output from 1st example, and the 2nd works fine.
I get that the 1st is undef behavior and that we 'push' an element the second time instead of assigning a value.
Any more clarification will be appreciated.
The operator [] returns a reference to the character at position pos in the string, it does reading value rather than insert and resize std::string.
You cannot insert to null assigned value, thats why you get undefined behaviour. First resize the string and then try to insert using [] the operator.

convert uint8_t array to string in c++

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

string function not returning string? c++ [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I'm sorry. I'm a bit new here and I'm not really sure where to post it. But I'm making a packet parser.
The program is suppose to open a file(that is in binary string) and then convert it into numbers(for the IP) and letters( the poem lines itself)
I'm stuck at my string function which takes a string from the file and then converts it into a sentence. I tested my binary to ascii converter and it works fine. I also tested returning a set string("string line=" banana") in my string poem_line function and it returns it just fine too.
I also tested the loop and it prints the binary string of the line needed to be changed just right.
I don't know what else is wrong.
string poem_Line(int packe,int datal, char p){
int m=0;
int start_where=0;
string line;
string transformed;
start_where=packe-datal; //this is the 32+32+16+16+16
ifstream inFile_data("cases_random.in");
if(inFile_data.is_open()){
for(m=0; m<packe; m++){
inFile_data>>p;
if(m>=start_where){
int q=0;
line[q]=p;
q++;
}
}
inFile_data.close();
transformed=binaryAscii(line);
}
else
cout<<"is not open"<<endl;
return transformed;
}
full code!
This line:
string line;
Creates an empty string.
This line:
line[q]=p;
Tries to write to string at position that is not allocated (memory you don't own, and your string object would not know about because its managed string size is 0. This is undefined behaviour)
I suggest you .resize() your string after creation, if you know target size, or simply use += p to add chars to it:
line += p;
Your line length equals to zero. Do line.push_back(p); instead of line[q]=p;. push_back resizes string and increase its length. line[q]=p; - in this case you are writing to another memory which doesn't belong to line, you can rewrite something important data by your overwriting.

Why dont c++ strings work with scanf and printf [duplicate]

This question already has answers here:
How to read and write a STL C++ string?
(3 answers)
Closed 4 years ago.
string a;
scanf("%s",&a);
gives me an error "unhandled exception :Access violation writing location 0x000EEFFEE" when i run the program and enter the string for expression.
whereas
char a[20];
scanf("%s",a);
works fine.
Is it only because scanf and printf are inherited from C.
What methods can I use to fix the error.
Is it possible at all to make printf scanf work with c++ strings.
The reasons std::string can't be used with printf is that std::string is not a sequence of characters.
The printf function expects a sequence of characters terminated by '\0'.
For all we know the std::string class could be implemented as:
class string
{
unsigned int capacity;
unsigned int size;
char * p_char_sequence;
};
As you can see, the first two items are not characters.
Also, there are not printf format specifiers for std::string.
In summary, there is no guarantee that the first items in memory of a std::string are the characters; it could be a class or structure.
There is a mitigation, the std::string::c_str() method. This method returns a pointer to a C-Style string equivalent of the std::string contents.
Edit 1: scanf
The scanf function is more interesting. The scanf function requires a pointer to an array of characters. There is no guarantee that the first memory address in a std::string is a sequence of characters. See printf explanation above.
Also, there is no guarantee that the pointer returned by std::string::c_str() is valid for receiving characters. It could be a temporary area in memory, used only for output. Thus it can't be used for scanf.
The scanf function will write characters to the array locations until the input is terminated. This means that if you allocate space for 3 characters and the User inputs 20 characters, the scanf function will start overwriting the array and write to whatever follows it. This could trigger a system error (such as writing outside your program's area) or write to hardware addresses. This is why most references say to use fscanf where a limit or capacity can be specified.
You need to use c-strings with scanf not c++ strings. Redeclare expression as char expression[N]; where N is a large enough number of characters to store the entire word. Also you would not need the & infront of it when you pass it to scanf since arrays are converted to pointers automatically.
An even better approach would be to replace scanf with cin >> expression; And replace printf with cout << expression; that is the way to do it in c++.