I have a small problem, but I can't figure out why..
I have a std::wstring text with a value of L"test"
I then try to print its first character like this:
OutputDebugString(&text[0]);
but the result is test..
when I use OutputDebugString(&text[1]);
The result is est
I thought that array access should give me the character at a specified location..
Could anybody tell me what I should do or am doing wrong?
I also tried .at(i); with the same result.
Got it:
wchar_t st = text[0];
OutputDebugString(&st);
Alex Reinking stated that this a a better and more safe solution: (as the string then contains a null terminator)
wchar_t st[3] = { text[0], 0x0 };
OutputDebugString(&st[0]);
Thanks for the help
It's because, in memory, the string looks something like this:
V-- &text[0]
addr: 0x80000000 0x80000001 0x80000002 0x80000003 0x80000004
text: t, e, s, t, 0x00
^-- text[0]
So when you ask for the address of text[1] what you get is:
V-- &text[1]
addr: 0x80000001 0x80000002 0x80000003 0x80000004
text: e, s, t, 0x00
^-- text[1]
Which leaves you with e,x,t,NULL or the string "ext". The function you're calling will use all the characters up until the terminator.
A string is a series of characters followed by a null terminator.
The OutputDebugString function (and most functions in C and in WinAPI which take strings) accept a pointer to the first character of such a string. The the function keeps printing characters from that location and subsequent locations until it hist the null terminator.
If you only want to act on a single character you either need to call a function which expects a single character, or build a string of length 1 containing that character and a null terminator.
OutputDebugString takes a string, therefore it will start with the address you have given and go all the way until it hits a NULL. To address your specific issue you have to write your own function that will take one character from the string, then put it into a new string, then output that new string.
OutputDebugStringW(text.c_str()); should do what you want
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
In my code, I have a string variable named ChannelPacket.
when I print Channelpacket in gdb, it gives following string :
"\020\000B\001\237\246&\b\000\016\000\002\064\001\000\000\005\000\021\002\000\000\006\000\f\001\001\000\000sZK"
But if i print Channelpacket.c_str(), it gives just "\020 output.
Please help me.
c_str() returns a pointer to char that's understood to be terminated by a NUL character ('\0').
Since your string contains an embedded '\0', it's seen as the end of the string when viewed as a pointer to char.
When viewed as an actual std::string, the string's length is known, so the whole thing is written out, regardless of the embedded NUL characters.
The second byte is a zero, which means the end of the string. If you want to output the raw bytes, rather than treating them as a null-terminated string, you can't use cout << Channelpacket.c_str() - use cout << Channelpacket instead.
I can't understand what the '\0' in the two different place mean in the following code:
string x = "hhhdef\n";
cout << x << endl;
x[3]='\0';
cout << x << endl;
cout<<"hhh\0defef\n"<<endl;
Result:
hhhdef
hhhef
hhh
Can anyone give me some pointers?
C++ std::strings are "counted" strings - i.e., their length is stored as an integer, and they can contain any character. When you replace the third character with a \0 nothing special happens - it's printed as if it was any other character (in particular, your console simply ignores it).
In the last line, instead, you are printing a C string, whose end is determined by the first \0 that is found. In such a case, cout goes on printing characters until it finds a \0, which, in your case, is after the third h.
C++ has two string types:
The built-in C-style null-terminated strings which are really just byte arrays and the C++ standard library std::string class which is not null terminated.
Printing a null-terminated string prints everything up until the first null character. Printing a std::string prints the whole string, regardless of null characters in its middle.
\0 is the NULL character, you can find it in your ASCII table, it has the value 0.
It is used to determinate the end of C-style strings.
However, C++ class std::string stores its size as an integer, and thus does not rely on it.
You're representing strings in two different ways here, which is why the behaviour differs.
The second one is easier to explain; it's a C-style raw char array. In a C-style string, '\0' denotes the null terminator; it's used to mark the end of the string. So any functions that process/display strings will stop as soon as they hit it (which is why your last string is truncated).
The first example is creating a fully-formed C++ std::string object. These don't assign any special meaning to '\0' (they don't have null terminators).
The \0 is treated as NULL Character. It is used to mark the end of the string in C.
In C, string is a pointer pointing to array of characters with \0 at the end. So following will be valid representation of strings in C.
char *c =”Hello”; // it is actually Hello\0
char c[] = {‘Y’,’o’,’\0′};
The applications of ‘\0’ lies in determining the end of string .For eg : finding the length of string.
The \0 is basically a null terminator which is used in C to terminate the end of string character , in simple words its value is null in characters basically gives the compiler indication that this is the end of the String Character
Let me give you example -
As we write printf("Hello World"); /* Hello World\0
here we can clearly see \0 is acting as null ,tough printinting the String in comments would give the same output .
First, I'd like to say that I'm new to C / C++, I'm originally a PHP developer so I am bred to abuse variables any way I like 'em.
C is a strict country, compilers don't like me here very much, I am used to breaking the rules to get things done.
Anyway, this is my simple piece of code:
char IP[15] = "192.168.2.1";
char separator[2] = "||";
puts( separator );
Output:
||192.168.2.1
But if I change the definition of separator to:
char separator[3] = "||";
I get the desired output:
||
So why did I need to give the man extra space, so he doesn't sleep with the man before him?
That's because you get a not null-terminated string when separator length is forced to 2.
Always remember to allocate an extra character for the null terminator. For a string of length N you need N+1 characters.
Once you violate this requirement any code that expects null-terminated strings (puts() function included) will run into undefined behavior.
Your best bet is to not force any specific length:
char separator[] = "||";
will allocate an array of exactly the right size.
Strings in C are NUL-terminated. This means that a string of two characters requires three bytes (two for the characters and the third for the zero byte that denotes the end of the string).
In your example it is possible to omit the size of the array and the compiler will allocate the correct amount of storage:
char IP[] = "192.168.2.1";
char separator[] = "||";
Lastly, if you are coding in C++ rather than C, you're better off using std::string.
If you're using C++ anyway, I'd recommend using the std::string class instead of C strings - much easier and less error-prone IMHO, especially for people with a scripting language background.
There is a hidden nul character '\0' at the end of each string. You have to leave space for that.
If you do
char seperator[] = "||";
you will get a string of size 3, not size 2.
Because in C strings are nul terminated (their end is marked with a 0 byte). If you declare separator to be an array of two characters, and give them both non-zero values, then there is no terminator! Therefore when you puts the array pretty much anything could be tacked on the end (whatever happens to sit in memory past the end of the array - in this case, it appears that it's the IP array).
Edit: this following is incorrect. See comments below.
When you make the array length 3, the extra byte happens to have 0 in it, which terminates the string. However, you probably can't rely on that behavior - if the value is uninitialized it could really contain anything.
In C strings are ended with a special '\0' character, so your separator literal "||" is actually one character longer. puts function just prints every character until it encounters '\0' - in your case one after the IP string.
In C, strings include a (invisible) null byte at the end. You need to account for that null byte.
char ip[15] = "1.2.3.4";
in the code above, ip has enough space for 15 characters. 14 "regular characters" and the null byte. It's too short: should be char ip[16] = "1.2.3.4";
ip[0] == '1';
ip[1] == '.';
/* ... */
ip[6] == '4';
ip[7] == '\0';
Since no one pointed it out so far: If you declare your variable like this, the strings will be automagically null-terminated, and you don't have to mess around with the array sizes:
const char* IP = "192.168.2.1";
const char* seperator = "||";
Note however, that I assume you don't intend to change these strings.
But as already mentioned, the safe way in C++ would be using the std::string class.
A C "String" always ends in NULL, but you just do not give it to the string if you write
char separator[2] = "||". And puts expects this \0 at the ned in the first case it writes till it finds a \0 and here you can see where it is found at the end of the IP address. Interesting enoiugh you can even see how the local variables are layed out on the stack.
The line: char seperator[2] = "||"; should get you undefined behaviour since the length of that character array (which includes the null at the end) will be 3.
Also, what compiler have you compiled the above code with? I compiled with g++ and it flagged the above line as an error.
String in C\C++ are null terminated, i.e. have a hidden zero at the end.
So your separator string would be:
{'|', '|', '\0'} = "||"
How will various functions that take printf format string behave upon encountering the %c format given value of \0/NULL?
How should they behave? Is it safe? Is it defined? Is it compiler-specific?
e.g. sprintf() - will it crop the result string at the NULL? What length will it return?
Will printf() output the whole format string or just up to the new NULL?
Will va_args + vsprintf/vprintf be affected somehow? If so, how?
Do I risk memory leaks or other problems if I e.g. shoot this NULL at a point in std::string.c_str()?
What are the best ways to avoid this caveat (sanitize input?)
Any function that takes a standard C string will stop at the first null, no matter how it got there.
When you use the %c in a format and use 0 for the character value, it will insert a null into the output. printf will output the null as part of the output. sprintf will also insert the null into the result string, but the string will appear to end at that point when you pass the output to another function.
A std::string will happily contain a null anywhere within its contents, but when you take the c_str method to pass it to a function see the above answer.
What happens when you output a NUL depends on the output device.
It is a non printing character, i.e. isprint('\0') == 0; so when output to a display device, it has no visible affect. If redirected to a file however (or if calling fprintf()), it will insert a NUL (zero byte) into the file; the meaning of that will depend on how the file is used.
When output to a C string, it will be interpreted as a string terminator by standard string handling functions, although any other subsequent format specifiers will still result in data being placed in the buffer after the NUL, which will be invisible to standard string handling functions. This may still be useful if ultimately the array is not to be interpreted as a C string.
Do I risk memory leaks or other problems if I e.g. shoot this NULL at a point in std::string.c_str()?
It is entirely unclear what you mean by that, but if you are suggesting using the pointer returned by std::string.c_str() as the buffer for sprintf(); don't! c_str() returns a const char*, modifying the string through such a pointer is undefined. That however is a different problem, and not at all related to inserting a NUL into a string.
What are the best ways to avoid this caveat (sanitize input?)
I am struggling to think of a circumstance where you could "accidentally" write such code, so why would you need to guard against it!? Do you have a particular circumstance in mind? Even though I find it implausible, and probably unnecessary, what is so hard about:
if( c != 0 )
{
printf( "%c", c ) ;
}
or perhaps more usefully (since there are other characters you might want to avoid in the output)
if( isgraph(c) || isspace(c) )
{
printf( "%c", c ) ;
}
which will output only visible characters and whitespace (space, '\t','\f','\v','\n','\r').
Note that you might also consider isprint() rather than isgraph(c) || isspace(c), but that excludes '\t','\f','\v','\n' and '\r'
printf() and sprintf() will continue past a '\0' character inserted with %c, because their output is defined in terms of the content of the format string, and %c does not denote the end of the format string.
This includes their count; thus:
sprintf(x, "A%cB", '\0')
must always return 3 (although strlen(x) afterwards would return 1).