I am trying to read 4 characters at a specific position from a file. The code is simple but the result is really confusing:
fstream dicomFile;
dicomFile.open(argv[1]);
dicomFile.seekg(128,ios::beg);
char * memblock = new char [4];
dicomFile.read(memblock,4);
cout<<"header is "<<memblock<<endl;
Ideally the result should be "DICM" but the actual result from the console was "DICM" plus weird characters, as shown in the picture. What's more, every time I run it, the characters are different. I suppose this may be something about ASCII and Unicode, I tried to change project property from Unicode to multibytes and then change back, no difference.
Does anyone know what's happening here and how do I solve it please? Thanks very much!
C style (char *) strings use the concept of null-terminators. This means strings are ended with a '\0' character in their last element. You are reading in exactly 4 characters into a 4 character buffer, which does not include a null character to end the string. C and C++ will happily run right off the end of your buffer in search for the null terminator that signifies the end of the string.
Quick fix is to create a block of length + 1, read in length data, then set str[length] = '\0'. In your case it would be as below.
char * memBlock = new char [5];
// populate memBlock with 4 characters
memBlock[ 4 ] = '\0';
A better solution is to use std::string instead of char * when working with strings in C++.
You could also initialize the buffer with zeros, putting null-terminators at every location.
char * memblock = new char [5](); // zeros, and one element longer
Fairly inefficient though.
Related
I currently have the following code
char my_stream[800];
std::string my_string;
iResult = recv(clntSocket,my_stream,sizeof(my_stream),0);
my_string = std::string(my_stream);
Now when I attempt to convert the char array to string I get the present of weird characters in the string any suggestions on what I might be doing wrong
You're getting weird characters because your strings length is not equal to the number of bytes received.
You should initialize the string like so:
char* buffer = new char[512];
ssize_t bytesRead = recv(clntSocket,buffer,512,0);
std::string msgStr = std::string(buffer,bytesRead);
delete buffer;
The most common solution is to zero every byte of the buffer before reading anything.
char buffer[512];
buffer = { 0 };
If you're reading in a zero-terminated string from your socket, there's no need for a conversion, it's already a char string. If it's not zero-terminated already, you'll need some other kind of terminator because sockets are streams (assuming this is TCP). In other words, you don't need my_string = std::string(my_stream);
have you tried to print my_stream directly without converting to string.
According to me it may be the case of mismatch in format of data sent and received.
data on other side may be in other format like Unicode and you may be trying to print it as single byte array
if only part of string is in weird characters than it is definitely error related to null terminator at the end of my_stream missing tehn increase the size of array of my_stream.
I wrote a dll application that is hooked into a process. It works but it ONLY shows the FIRST letter.
I wanted to get the whole string. The string could vary from 2 letters to 32 letters.
//READING MEMORY
HANDLE ExeBaseAddress = GetModuleHandleA(0);
char uNameAddr = *(char*)((char*)ExeBaseAddress + 0x34F01C);
printf("%c \n", uNameAddr);
I also wanted to understand the parts:
*(char*)((char*) //<-- what this is for.
And if it is possible to use this if using multilevel pointers:
char multipoint = *(char*)((char*)ExeBaseAddress + 0x34F01C + 0x123 + 0x321 + 0x20);
UPDATE
I guess something is wrong here:
if(uNameAddr == "omnicient")
cout << "YOU ARE OMNI" << endl;
I used the username name omnicient but it did not cout YOU ARE OMNI. I guess my compare is wrong?
%c displays chars (single characters), %s displays NULL-terminated char*s (strings):
HANDLE ExeBaseAddress = GetModuleHandleA(0);
char *uNameAddr = (char*) ExeBaseAddress + 0x34F01C;
printf("%s \n", uNameAddr);
Notice that I also tidied up the pointer casting, but the important thing is I got rid of the final dereference (* at the front) and assigned it to a char* (pointer) instead of a char.
If your string isn't NULL-terminated (unlikely), you will need to use %.*s and pass the length of your string too.
As for the second part of your question:
*(char*)((char*) ExeBaseAddress + 0x34F01C)
let's break it down. Inside the brackets (therefore the first thing to be evaluated) is this:
(char *) ExeBaseAddress + 0x34F01C
Well that's a C cast (casting the HANDLE to a char*) followed by an addition. In other words, it says "Treat this thing as if it is a pointer to some memory, then look ahead by 0x34F01C bytes of memory" (char is always 1 byte). It is now a pointer to a new position in memory.
Then we get out of the brackets and cast to char* again... needlessly. It could have been:
*((char*) ExeBaseAddress + 0x34F01C)
and finally we dereference (the * at the front), which says "Now tell me what the bit of memory you're pointing to is". But in this case you don't want that, because you want the whole string, not just the first letter (inside printf, it loops along the memory you send it printing each character until it finds a 0, aka \0 aka NULL).
char uNameAddr is a character, you need a list of chars (or char*)
try this instead:
char* name= (char*)((char*)ExeBaseAddress + 0x34F01C);
printf("%s \n", name);
What does *(char*)((char*) mean?
(char*)ExeBaseAddress treat ExeBaseAddress as a pointer to some data of type char
((char*)ExeBaseAddress + 0x34F01C) means add 0x34F01C to the above pointer to offset it by 0x34F01C chars
(char*)((char*)ExeBaseAddress + 0x34F01C) means treat this new address as pointer to some chars
*(char*)((char*)ExeBaseAddress + 0x34F01C) take the contents of the first char at that location
char uNameAddr = *(char*)((char*)ExeBaseAddress + 0x34F01C); means put that character into the char sized variable called uNameAddr.
So basically you had a pointer, you offset it, and then took the first character and printed it.
In the example I gave note how I don't take the firat character, and I put it a pointer variable.
Then I used %s in the printf to make it print out all the chars potnted to by name.
I have a small query regarding reading a set of characters from a structure. For example: A particular variable contains a value "3242C976*32" (char - type). How can I get only the first 8 bits of this variable. Kindly help.
Thanks.
Edit:
I'm trying to read in a signal:
For Ex: $ASWEER,2,X:3242C976*32
into this structure:
struct pg
{
char command[7]; // saves as $ASWEER,2,X:3242C976*32
char comma1[1]; // saves as ,2,X:3242C976*32
char groupID[1]; // saves as 2,X:3242C976*32
char comma2[1]; // etc
char handle[2]; // this is the problem, need it to save specifically each part, buts its not
char canID[8];
char checksum[3];
}m_pg;
...
When memcopying buffer into a structure, it works but because there is no carriage returns it saves the rest of the signal in each char variable. So, there is always garbage at the end.
you could..
convert your hex value in canID to float(depending on how you want to display it), e.g.
float value1 = HexToFloat(m_pg.canID); // find a conversion script for HexToFloat
CString val;
val.Format("0.3f",value1);
the garbage values aren't actually being stored in the structure, it only displays it as so, as there is no carriage return, so format the message however you want to and display it using the CString val;
If "3242C976*3F" is a c-string or std::string, you can just do:
char* str = "3242C976*3F";
char first_byte = str[0];
Or with an arbitrary memory block you can do:
SomeStruct memoryBlock;
char firstByte;
memcpy(&firstByte, &memoryBlock, 1);
Both copy the first 8bits or 1 byte from the string or arbitrary memory block just as well.
After the edit (original answer below)
Just copy by parts. In C, something like this should work (could also work in C++ but may not be idiomatic)
strncpy(m_pg.command, value, 7); // m.pg_command[7] = 0; // oops
strncpy(m_pg.comma, value+7, 1); // m.pg_comma[1] = 0; // oops
strncpy(m_pg.groupID, value+8, 1); // m.pg_groupID[1] = 0; // oops
strncpy(m_pg.comma2, value+9, 1); // m.pg_comma2[1] = 0; // oops
// etc
Also, you don't have space for the string terminator in the members of the structure (therefore the oopses above). They are NOT strings. Do not printf them!
Don't read more than 8 characters. In C, something like
char value[9]; /* 8 characters and a 0 terminator */
int ch;
scanf("%8s", value);
/* optionally ignore further input */
while (((ch = getchar()) != '\n') && (ch != EOF)) /* void */;
/* input terminated with ch (either '\n' or EOF) */
I believe the above code also "works" in C++, but it may not be idiomatic in that language
If you have a char pointer, you can just set str[8] = '\0'; Be careful though, because if the buffer is less than 8 (EDIT: 9) bytes, this could cause problems.
(I'm just assuming that the name of the variable that already is holding the string is called str. Substitute the name of your variable.)
It looks to me like you want to split at the comma, and save up to there. This can be done with strtok(), to split the string into tokens based on the comma, or strchr() to find the comma, and strcpy() to copy the string up to the comma.
I am using C Style strings for a project, and I am confusing myself a bit. I am checking strings to see what they are prepended with (zone_, player_, etc) then getting the rest of the string after that.
else if(strncmp(info, "zone_", 5) == 0)
{
int len = strlen(info);
char *zoneName = new char[len];
strncpy(zoneName, &info[5], len-5);
Msg("Zone Selected: %s\n", zoneName);
delete zoneName;
}
When I print out the zoneName variable though, it is correct except it is followed by a bunch of gibberish. What am I doing wrong? (I realize that the gibberish is the rest of the char array being empty, but I don't know a better way to do this)
See strncpy description :
No null-character is implicitly
appended to the end of destination, so
destination will only be
null-terminated if the length of the C
string in source is less than num.
You have to remember that C-style strings are terminated with a NUL character. You've allocated enough space in zoneName, but you only need len-5 plus one:
char *zoneName = new char[len - 5 + 1];
Then, you can actually use strcpy() to copy the tail of the string:
strcpy(zoneName, &info[5]);
You don't need to specify the length because the source string is NUL terminated.
C strings are zero terminated - so they occupy len bytes (chars to be precise) plus one more with value zero known as the 'zero terminator'. You need to allocate one more character, and either copy one more from the source (since it should be zero terminated) or just set the last char of the destination to 0.
int len = strlen(info);
char *zoneName = new char[len - 5 + 1];
strncpy(zoneName, &info[5], len - 5 + 1);
C-style strings has to be finished with a byte with zero value. You should modify your code like this:
char *zoneName = new char[len-5+1];
strncpy(zoneName, &info[5], len-5);
/* correct string ending */
zoneName[len]=0;
/* Now, it's safe to print */
Msg("Zone Selected: %s\n", zoneName);
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.