I am new to c++ and am still figuring out file streams. I am trying to put a character array into a file that I will be viewing with a hex editor.
I have done different strings, but whenever I put in a null byte, the file ends.
ofstream stream;
char charArray[256];
for (int i = 0; i <= 255; i++)charArray[i] = i;
stream.open("C:\\testfile.myimg");
if (!stream.is_open()) exit(1);
stream << charArray << endl;
return 0;
I want to output bytes with ascending values, but if I start with the null byte, then c++ thinks the character array ends before it starts
Instead of:
stream << charArray << endl;
use:
stream.write(charArray, sizeof(charArray));
stream.write("\n", 1); // this is the newline part of std::endl
stream.flush(); // this is the flush part of std::endl
The first one assumes that you are sending a null-terminated string (because you're passing a char* - see the end of the answer why). That's why when the code encounters the very first char with value 0, which is '\0' (the null-terminator), it stops.
On the other hand, the second approach uses an unformatted output write, which will not care about the values inside charArray - it will take it (as a pointer to its first element) and write sizeof(charArray) bytes starting from that pointer to the stream. This is safe since it's guaranteed that sizeof(char) == 1, thus sizeof(charArray) will yield 256.
What you need to consider is array decaying. It will work in this case (the sizeof thing), but it will not work if you simply pass a decayed pointer to the array's first element. Read more here: what's array decaying?
Related
Can anyone explain to me why the following code causing segmentation fault? buff should be long enough to hold 128 characters.
int main () {
char buff[16384];
char buff2[128];
sprintf(buff2, "MinPer(PatternName_Equal27_xxxxxxx_MasterPatSetup.PatternName_Equal27_xxxxxxx__default_WFT___WFTRef.ActualT0Period.UserPeriod_2_1)" );
strcat(buff, buff2);
std::cout << buff2 << endl;
std::cout << buff << endl;
return 0;
}
You have two major problems:
Your sprintf is shoving 131 bytes (130 characters plus a NUL) into a 128 byte buffer, meaning three unrelated stack bytes are getting overwritten with garbage. You need a larger buffer, or a smaller initialization string.
You call strcat to append said 131 characters to a buffer with undefined contents (no NUL to indicate where the string being concatenated to ends). This is trivially fixable, by either zero-initializing all of buff (char buff[16384] = {0};) or by inserting the NUL in the first byte (which is all you really need) adding buff[0] = '\0'; just before you strcat to it. Equivalently, you could replace strcat (which assumes a string to concatenate new data to exists in the destination) with strcpy (which ignores the existing contents of the destination) to avoid the problem.
Basically, your code is full of undefined behavior and buffer overruns. Given you're using C++, can I recommend just using std::string to avoid the hassle of C strings?
buff is uninitialized. It needs to contain a null terminated string so that strcat knows where to begin the concatenation. One way to do this is with strcpy:
strcpy(buff, ""); // initialize with empty null terminated string
strcat(buff, buff2); // add to it
strcat needs 'dest' to be a string ending with '\0'. So buff should be initialized manually.
I am writing a C++ application which receives an input from a socket. This input comes as a rawdata string and so, it contains lots of "\0" in its body.
My question is, how can I determine its length/size without stoping at the "\0"s, so I would be able read the complete socket response? The response itsef is 148 long, but the size() retuns 2.
size() returns the actual length of the string and does not consider null bytes to end the string. The reason you're getting a size of two is because there are different ways to set the string's value and some of them do consider null bytes to be the string terminator. So you've mistakenly set the value of the string to be a string of two characters rather than set it to hold the complete response data, and size() is accurately reflecting that mistake.
The solution is to initialize or set the string using a method that does not consider null bytes:
char buffer[] = "abcd\0efg";
std::string s(buffer, 8);
std::cout << s.size() << '\n'; // outputs "8"
std::string s2(buffer);
std::cout << s2.size() << '\n'; // outputs "4"
I always get a garbage value like this 'Íýýýý««««««««îþîþ' at the end when i output my array. What am I doing wrong?
void func()
{
const int size = 100;
char * buffer = new char[size];
for(int i=0; i<size; i++)
buffer[i] = ' ';
cout<<buffer;
}
However if I use a for loop to output the buffer, there is no garbage value.
Because you don't null terminate your buffer, std::cout.operator<<(char*) will try to find \0 as its terminating character.
As pointed out in comments, feel free to append that \0 to the end of your buffer :).
ScarletAmaranth is right. C style strings (an array of char) must finish with the char '\0'. That's the way functions that play with char arrays (cout in this case) know when the string finish in memory. If you forget the '\0' character at the end of the array, cout prints all the chars in the array and then goes on printing any data in memory after the array. These other data is rubbish, and that's why you see these strange characters.
If you use the string type (more C++ style) instead of char arrays, you won't have this problem because string type don't use '\0' as a string delimiter.
On the other hand, you don't see rubbish when use a loop to iterate over the 100 elements of the array just because you only print these 100 chars. I mean, you control exactly what you are printing and know when to stop, instead of leaving the cout function figure out when to stop printing.
I have a small school assignment. My output is not correct. Can you see if I'm doing anything wrong?
//1. Create a char pointer named cp
char *cp;
//2. Dynamically allocate a char and store its address in cp
char dynamicChar = 'A';
cp = &dynamicChar;
//3. Write the character 'x' into the char
*cp = 'x';
//4. Print out the value of the char using cout
cout << cp << endl;
The print out statement prints A## instead of just A. I'm not sure what I'm doing wrong.
Try
cout << *cp << endl;
You want to print the character, not the pointer to it. When you hand it the pointer, cout thinks you're telling it to print out a character array starting there.
Sadly, from its origins of the C programming language, char * (i.e. pointers to characters) are not treated as just a pointer to a type like int * (pointer to int) or float * (pointer to a float), but many library functions treat these as NUL-character terminated strings. By "string" we mean text.
Therefore, there are lots of library functions that treat char* as special case and treats them as a "nul-terminated string", meaning it's gonna treat that pointer as an ARRAY of (i.e. multiple contiguous) charactes, until it reaches a NUL character (i.e. numeric value 0, not the character '0' which has a numeric byte value of 48 or 0x30).
So, if in your code you have
char *sz = "123";
this will allocate 4 characters, the 3 you see plus the NUL character
Addr:0x00050014 0x31 // ASCII char '1'
Addr:0x00050015 0x32 // ASCII char '2'
Addr:0x00050016 0x33 // ASCII char '3'
Addr:0x00050017 0x00 // ASCII char nul
sz (a pointer to a character, representing an address) will have the value 0x00050014 (note that the starting address value is determined by your computer via multiple steps via the compiler, then the linker, then the loader, then possibly the progrma itself).
When you do
cout << sz << endl;
the program will interpret the pointer to a character as a pointer to a nul-terminated buffer of characters and dump the character string
123
to the output stream cout. It looks at the value at address 0x00050014 and sees if its NUL (i.e. 0), if not, it dumps out the character, then looks at the next address. If 0x00050015 is not a NUL, it dumps IT out. Then the value at 0x00050016, sees its not a NUL, dumps it out, then it gets to 0x00050017 and sees that it IS NUL, and does NOT dump it out, and stops looking at addresses and returns to YOUR code just after where you did the output of sz, specifically in this code it will return to the point where it will dump the endl (end of line) to cout;
You will eventually learn better ways to represent text than the old C-style char* mechanism, but for now, you just need to understand the legacy behavior that exists.
C++ (or, more specificaly, ostream in this case), will automatically treat a char* as a (C style) string. You need to explicitly cast it to the type you want, such as:
cout << (void*)cp << endl;
if you want the pointer value, or
cout << *cp << endl;
if you want the character itself (as your question seems to indicate).
NoobQuestion:
I heard that filling a char array can be terminated early with the null char. How is this done?
I've searched every single google result out there but still have come up empty handed.
Do you mean something like this:
char test[11] = "helloworld";
std::cout << test << std::endl;
test[2] = 0;
std::cout << test;
This outputs
helloworld
he
?
That's a convention called "null-terminated string". If you have a block of memory which you treat as a char buffer and there's a null character within that buffer then the null-terminated string is whatever is contained starting with the beginning of the buffer and up to and including the null character.
const int bufferLength = 256;
char buffer[bufferLength] = "somestring"; //10 character plus a null character put by the compiler - total 11 characters
here the compiler will place a null character after the "somestring" (it does so even if you don't ask to). So even though the buffer is of length 256 all the functions that work with null-terminated strings (like strlen()) will not read beyond the null character at position 10.
That is the "early termination" - whatever data is in the buffer beyond the null character it is ignored by any code designed to work with null-terminated strings. The last part is important - code could easily ignore the null character and then no "termination" would happen on null character.