C++ string appending problems - c++

I'm having some issues right now, attempting to append a char array onto a c++ string after setting some of the values of the c++ string, and I don't see why. I was wondering if any of you know what's going.
Here's the code I'm trying to run:
string test = "";
test.resize(1000);
char sample[10] = { "Hello!" };
test[0] = '1';
test[1] = '2';
test[2] = '3';
test[3] = '4';
test += sample;
Running it through a debugger, it seems that test is just "1234", and the "Hello" is never added.
Thanks in advance!

It is added, but after the 1000 characters you already have in the string (4 of them are the 1234, and 996 are '\0' characters)`.
The resize function does allocate 1000 characters for the string object, but also sets the length to 1000. That's why sometimes what you want to do instead is use reserve
This is normally what I would do:
string test = "";
test.reserve(1000); // length still 0, capacity: 1000
char sample[10] = { "Hello!" };
test.push_back('1'); // length is 1
test.push_back('2'); // length is 2
test.push_back('3'); // length is 3
test.push_back('4'); // length is 4
test += sample; // length is now 10
Or if you want to do it your way:
string test = "";
test.resize(1000); // length is 1000
char sample[10] = { "Hello!" };
test[0] = '1'; // length is 1000
test[1] = '2'; // length is 1000
test[2] = '3'; // length is 1000
test[3] = '4'; // length is 1000
test.resize(4); // length is now 4, but the internal buffer still has a capacity of 1000 characters
test += sample; // length is now 10

I think the problem is when you did test.resize(1000) it added 1000 null characters ('\0') to the string. The debugger probably sees null characters as end-of-string markers. So any text added after those null characters won't get displayed.
Say text equals this ('_' = null character end of line marker):
test = "1234_______________Hello!";
^
Debugger thinks text ends here

Related

How to add elements at the beginning of an Arduino String. Similar to JS unshift();

I have an unknown size String, but with a maximum size of 8 and I want to make sure its size will always be 8 by adding 0(zeroes) at the beginning of the String.
For example the inputted String is "5687" and I have to add 0 until it's size is 8: "00005687".
String str = "5687";
while(str.length() < 8) {
// add 0 at the beginning of str
}
Unlike JavaScript, Arduino C++ doesn't have anything like unshift() or does it ?
How can I achieve my goal ? Thank you.
P.S: I am using an ESP32 and only a couple of Strings, because the handler of ESPAsyncWebServer usually return String parameters.
String str = "5687";
while(str.length() < 8) {
str = String("0") + str;
}

Initial Check to see if a Substring is within range

I am in the beginnings of learning C++ and I am wondering if there is a way to assert that a substring can be created from a String, given a range. My String will vary in size each iteration. I am trying to create six substrings from that original String. With this variation in size, I am sometimes trying to access indexes of the String that do not exist for that particular iteration.
For example, if my String in iteration 1 is 11 characters
My first substring is from 3 characters - valid
My second substring is the next 3 characters - valid
My third substring is the next 5 characters - valid
My fourth substring is the next 4 characters - not valid - crashes program
My fifth substring - not valid, out of range
My sixth substring - not valid, out of range
I am wondering if there is a small check I can do to assert the length is valid. It's worth noting, I suppose, that I have not set any default values to these substrings. They are declared as:
string subS1
string subS2
string subS3
...
...
string subS6
Would setting all 6 substrings to null upon declaration alleviate this issue and for any valid substring, the value will just be overwritten?
Thanks in advance
subS1 = str.substr(0, 3); // Could be valid range
subS2 = str.substr(3, 3); // Could be valid range
subS3 = str.substr(6, 5); // Could be valid range
subS4 = str.substr(11, 4); // Could be valid range
subS5 = str.substr(15, 4); // Could be valid range
subS6 = str.substr(19); // from the nineteenth character to the end
Algorithm--->
step 1: Get the length of string in current iteration in variable size.
step 2: Write this code in itertaion.
int i=0;
i= str.substr(start,end).length();
if( i>size) then,
std::cout<<"index exceeded";
Either check the size of str before extracting the string, or rely on std::string::substr's len parameter:
Number of characters to include in the substring (if the string is
shorter, as many characters as possible are used). A value of
string::npos indicates all characters until the end of the string.
Example:
#include <iostream>
#include <string>
int main ()
{
std::string str="Alexander the Great";
std::string str2 = str.substr (16, 25);
std::cout << str2 << '\n'; // eat
return 0;
}
It won't crash, it will just use as many characters as possible.
This however:
std::string str2 = str.substr (20, 25);
should crash, so do it like this in this case:
std::string str2 = ""; // initialise to empty string, that is the NULL you are saying I guess
if(str.size() > 20)
str2 = str.substr (20, 25);
// 'str2' will be an empty string

Assign a fixed length character array to a string

I have a fixed length character array I want to assign to a string. The problem comes if the character array is full, the assign fails. I thought of using the assign where you can supply n however that ignores \0s. For example:
std::string str;
char test1[4] = {'T', 'e', 's', 't'};
str.assign(test1); // BAD "Test2" (or some random extra characters)
str.assign(test1, 4); // GOOD "Test"
size_t len = strlen(test1); // BAD 5
char test2[4] = {'T', 'e', '\0', 't'};
str.assign(test2); // GOOD "Te"
str.assign(test2, 4); // BAD "Tet"
size_t len = strlen(test2); // GOOD 2
How can I assign a fixed length character array to a string correctly for both cases?
Use the "pair of iterators" form of assign.
str.assign(test1, std::find(test1, test1 + 4, '\0'));
Character buffers in C++ are either-or: either they are null terminated or they are not (and fixed-length). Mixing them in the way you do is thus not recommended. If you absolutely need this, there seems to be no alternative to manual copying until either the maximum length or a null terminator is reached.
for (char const* i = test1; i != test1 + length and *i != '\0'; ++i)
str += *i;
You want both NULL termination and fixed length? This is highly unusual and not recommended. You'll have to write your own function and push_back each individual character.
For the first case, when you do str.assign(test1) and str.assign(test2), you have to have /0 in your array, otherwise this is not a "char*" string and you can't assign it to std::string like this.
saw your serialization comment -- use std::vector<char>, std::array<char,4>, or just a 4 char array or container.
Your second 'bad' example - the one which prints out "Tet" - actually does work, but you have to be careful about how you check it:
str.assign(test2, 4); // BAD "Tet"
cout << "\"" << str << "\"" << endl;
does copy exactly four characters. If you run it through octal dump(od) on Linux say, using my.exe | od -c you'd get:
0000000 " T e \0 t " \n
0000007

Set a for loop to loop through untill null byte is detected

I have a question about a string in C++. As per below code, I would like to know where will the loops stop at. Will it take the null in index 3 or index 4?
#include <cstdio>
int main ( ) {
char name [20] = "Foo";
name [4] = '\0';
for (int i = 0; name[i] != '\0'; i++) {
printf("This is the value of i so far in the loop : %d \n",i);
}
printf("This is the value of i : %d \n",i);
return 0;
}
the reason I am asking this is,I don't understand why in my homework they gave us something like this. Is there any reason to make '\0' in index 4?
"Foo" is actually {'F','o','o','\0'}, and fits index 0,1,2,3.
Index 4 up to 19 are default initialized (hence 0-ed). And index 4 is assigned later with '\0'.
The loop ends when the first '\0' is matched, so that value 0,1,2 are printed.
Out of the loop i shold ... ahem .. be undefined! (it is declared inside the loop scope), but if your compiler didn't clean up you most likely will print 3.
A typycal example of C++ (note #include<cstdio>, but no std never referenced...) taught by a C instructed teacher.
Give my congrats to him!
Is there any reason to make '\0' in index 4?
Absolutely none.
This line:
char name [20] = "Foo";
Initializes the array as follows:
name[0] <-- 'F' First char of "Foo"
name[1] <-- 'o' Second char of "Foo"
name[2] <-- 'o' Third char of "Foo"
name[3] <-- '\0' Fourth char of "Foo"
name[4..19] <-- 0 Extra spaces in array get zero-filled
So, this line:
name [4] = '\0';
writes a zero to a location already guaranteed to be zero.
So, there is a zero at index 3 (it is the final char in "Foo"). There is a zero in all of the locations 4-19 (since the initializer is smaller than the array). And, redundantly, there is a zero written to index 4.
I think it should be 3:
name[0]='F' name[1]='o' name[2]='o' name[3]='\0' name[4]='\0'

array in C++ inside forloop

What is happening when i write array[i] = '\0' inside a for loop?
char arrayPin[256];
for(int i = 0; i<256; i++)
{
arrayPin[i] = '\0';
}
The program attempts to access memory at the location of <base address of 'array'> + (<sizeof array element> * 'i') and assign the value 0 to it (binary 0, not character '0'). This operation may or may not succeed, and may even crash the application, depending upon the state of 'array' and 'i'.
If your array is of type char* or char[] and the assignment operation succeeds, then inserting the binary 0 at position 'i' will truncate the string at that position when it is used with things that understand C-style strings (printf() being one example).
So if you do this in a for loop across the entire length of the string, you will wipe out any existing data in the string and cause it to be interpreted as an empty/zero-length string by things that process C-style strings.
char arrayPin[256];
After the line above, arrayPin in an uninitialized array whose contents are unknown (assuming it is not a global).
----------------------------
|?|?|?|?|?|?|?|?|?|?|...|? |
----------------------------
byte: 0 1 2 3 4 5 6 7 8 9 255
Following code:
for(int i = 0; i<256; i++)
{
arrayPin[i] = '\0';
}
initializes every arrayPin element to 0:
----------------------------
|0|0|0|0|0|0|0|0|0|0|...|0 |
----------------------------
byte: 0 1 2 3 4 5 6 7 8 9 255
I suppose you have something like char *array. In this case It will write character with the code 0x00 into ith position.
This is quite useful when you work with ANSI strings. \0 indicates the end of the string. For example:
char str[] = "Hello world";
cout << str << endl; // Output "Hello world"
str[5] = '\0';
cout << str << endl; // Output just "Hello"