So I have some binary data that I read, process and need to "split" into different variables, like this:
int *buffer;
buffer = malloc(size);
fread(buffer,size,1,file);
buffer = foo(buffer);
The result looks something like this in my debugger:
01326A18 5F4E8E19 5F0A0000
I want the first byte ( 01 ) to be int a.
The following 4 bytes are the first timestamp b (should be 5F186A32)
The following 4 bytes are the second timestamp c (should be 5F198E4E)
The 0A is supposed to be int d.
My Problem is that I can put the 1 into a, with (*buffer) & 0xff;, but I'm not able to read the first timestamp correctly since its from second to 5th byte and not align with the int declaration of the buffer.
If I print *(buffer +1) it gives me the second int and prints "198E4E5F"
It would be better if I were able to target n byte from every position in my data.
thx in advance.
Something like this will work on most little-endian platforms. Just fread the same way.
struct {
uint8_t a;
uint32_t timeStamp1;
uint32_t timeStamp2;
uint8_t d;
} buffer __attribute__((packed));
assert(sizeof buffer == 10); /* check packing */
If you set your buffer type as char* this will make it point to the 1 byte of chunks. Then if try to get buffer+2, it will return the second byte of the buffer, unlike int pointer which will return the 8th byte of the buffer. Do not forget to update your size in malloc call, since you get your memory with 1 byte chunks in this case. Also this link may be helpful.
Related
data - > Start address of the buffer to store the received data[here, received data is hello]
length -> Size of the buffer
readfunction(uint8_t * data, size_t length)
int main()
{
uint8_t ch;
readfunction(&ch , 1);
}
When I execute the program, ch is getting the first-byte 'data'[i.e., h]
and I am not able to read all the characters from data. How should I increment ch in such a way it would give me all the values[hello]
I tried incrementing the size of the buffer but I was not successful. Any method to do this?
Many, thanks.
You'll need an array. Not sure what you tried to increase the size of the buffer, but if I interpret your readfunction correctly, you'll want something like this:
uint8_t ch[6];
readfunction(ch , 6);
Note that the buffer space allocated is one greater than the amount of characters to be read, to account for the null-terminator of C-strings.
Also note that the first argument to readfunction is now ch rather than &ch, as an array is essentially a pointer to its first element (you could also pass &ch[0] instead).
char buf[512] = { 0 };
int ret = recv(gSock, buf, 512, 0);
typedef struct _STRUCT {
int package;
int version;
char string[512];
} STRUCT, *PSTRUCT;
PSTRUCT ok;
ok = (PSTRUCT)buf;
I am trying to accept a buffer from a socket (Code not here, but it is working). It accepts it and places it into buf. I then want to cast this buf as a structure STRUCT. I want the first 4 bytes to go into the first member, second 4 bytes into the second member, and then the remaining data to go into the last member. However this is not working like I expected. I am getting weird large numbers that are not what I am receiving.
I entered 1111111111 (10) and the results I got back were;
package = 825307441
version = 825307441
string = 11\n
I did a decimal to hex conversion on the package number and it comes back as '31313131', which is my first 4 1's. So I am not to sure why it is going from integer, to hex back to a integer. I want just exactly what sends to go into the structure.
You have to review the following functions:
htonl, htons, ntohl, ntohs - convert values between host and network byte order.
So I'm writing an RLE compressor, and basically, you take the runs of a file (the continuous strings of the same byte) and convert it to a packet. For example, if the file contains:
0xFF 0xFF 0xFF 0xFF 0xBB 0xBB 0xBB you would convert it into packets, containing a length and the data: It would turn out 0x04FF 0x03BB. You get the idea.
I use a structure to define the packet. (byte is a typedefd type for an unsigned 8 bit type)
typedef struct /* Each packet has a length and a data byte */
{
byte length; /* how many elements of data there is */
byte data; /* whatever byte is being repeated */
} PACKET;
and I have my writeData function:
void writeData(FILE* f, int offset, PACKET p)
{
fseek(f,offset,SEEK_SET); /* move to the offset to write */
fwrite(&p,sizeof(PACKET),sizeof(PACKET),f); /* write the packet to the given offset */
}
And here is the code that calls the function
offsetCounter = 0x0; /* reset offset counter */
for(i = 0; i < nPackets; i++) /* nPackets is the total amount of packets created */
{
writeData(fDest,offsetCounter,packet[i]);
printf("Wrote %d:0x%X to 0x%X\n",packet[i].length,packet[i].data,offsetCounter);
offsetCounter += 0x02; /* skip 2 bytes to write the next packet */
}
When I run the program, everything works fine, and the packets are written to the file correctly, except for some reason, at the very end of the file, there are 2 0x00 bytes that are automatically added on. So, for some reason, it just adds 2 extra empty bytes.
However, when I write the writeData function like this:
void writeData(FILE* f, int offset, PACKET p)
{
fseek(f,offset,SEEK_SET);
fwrite(&p.length,sizeof(byte),sizeof(byte),f);
fwrite(&p.data,sizeof(byte),sizeof(byte),f);
}
, which writes each byte of the structure separately, it no longer adds 2 extra empty bytes to the end of the file..
I'm really confused as to why when I write the structure, it works fine, but adds 2 extra bytes at the end, but when I write each element of the structure separately, it doesn't add them.
Could somebody help me figure this out?
You have the incorrect line
fwrite(&p,sizeof(PACKET),sizeof(PACKET),f);
The structure size is 2 so you are writing 2 of them and this is where your two extra bytes are coming from. It should be
fwrite(&p,sizeof(PACKET),1,f);
The reason why the extra bytes only show up at the end of the file, is because you use fseek() to position the file pointer, which is incremented correctly by 2. NB. When you are writing sequentially to a file, you don't need to use fseek() anyway. Also, you have hard-coded with offsetCounter += 0x02; instead of using offsetCounter += sizeof(PACKET).
This might already have been discussed, but I couldn't find any related topic.
I want to read short values from a file and store them in a buffer of int values using fread. So basically I want to do this:
int *data; //int buffer
data = (int *) malloc(1000 * sizeof(int));
fread(data, sizeof(short), 1000, infile); //infile is organized in 2-byte chunks
Data are stored in a file in 2-byte chunks (short). But when I read those data, I want to put them into an int buffer. How can I do that without copying from a short buffer to an int buffer? fread gets void pointer, so it doesn't care about the type of buffer.
The fread function doesn't know about types, that's correct. That's why it cant read raw bytes and convert them, it just puts them as-is into the provided buffer. And as you know, a short on most platforms is two bytes while int is four. So that will not work as fread has not idea about that.
You either read one short at a time, putting it into the int buffer, or read into a temporary short buffer then loop and copy value by value into the int buffer.
Naja, you have to do that "copying from a short buffer to an int buffer", because if you just read your infile into data, it will just copy byte by byte from your file to the memory called data thus writing 2 shorts into one int.
1) You can use fscanf with %hu and this works if the actual values are in text format, not binary.
unsigned short a
fp = fopen("myfile","r");
while(fscanf(fp,"%hu",&a))
{
// put a in the array of unsigned short
}
2) You can use fscanf with %c and this works if the actual values are in binary format.
unsigned short a;
char b,c;
fp = fopen("myfile","r");
while(fscanf(fp,"%c",&b) && fscanf(fp,"%c",&c))
{
a = (unsigned short) b;
a = a << 8;
a+= (unsigned short) c;
// put a in the array of unsigned short
}
I am working an embedded project which involves reading/writing a struct into EEPROM. I am using sprintf to make it easy to display some debugging information.
There are two problems with this code for some reason. The first; sprintf is printing a very strange output. When I print 'addr++' it will follow a pattern '0, 1, 2, 3, 4, 32, ...' which doesn't make sense.
void ee_read(char * buf, unsigned int addr, unsigned int len) {
unsigned int i;
sprintf(bf1, "Starting EEPROM read of %u bytes.\r\n", len); // Debug output
debugr(bf1);
IdleI2C1();
StartI2C1();
WriteI2C1(EE_ADDR | EE_W);
IdleI2C1();
WriteI2C1((unsigned char)addr>>8); // Address to start reading data from
IdleI2C1();
WriteI2C1((unsigned char)addr&0xFF);
IdleI2C1();
RestartI2C1();
WriteI2C1(EE_ADDR | EE_R);
IdleI2C1();
for (i=0; i<len; i++) {
buf[i] = ReadI2C1(); // Read a byte from EEPROM
sprintf(bf1, "Addr: %u Byte: %c\r\n", addr, buf[i]); // Display the read byte and the address
debugr(bf1);
addr++; // Increment address
IdleI2C1();
if (i == len-1) { // This makes sure the last byte gets 'nAcked'
NotAckI2C1();
} else {
AckI2C1();
}
}
StopI2C1();
}
The output from the above is here: https://gist.github.com/3803316 Please note that the about output was taken with %x for the address value (so addr is hex)
The second problem, which you may have noticed with the output, is that it doesn't stop when i > len. It continues further than the output I have supplied, and doesn't stop until the microcontroller's watch dog restarts.
Edit:
Calling the function
Location loc;
ee_read(&loc, 0, sizeof(Location));
Declarations:
struct location_struct {
char lat[12]; // ddmm.mmmmmm
char latd[2]; // n/s
char lon[13]; // dddmm.mmmmmm
char lond[2]; // e/w
char utc[11]; // hhmmss.sss
char fix[2]; // a/v
};
typedef struct location_struct Location;
char bf1[BUFFER_SIZE];
I don't think it's a race condition. I disable the interrupts which use bf1. Even then, it would corrupt the whole debug string if that happened, and it certainly wouldn't be so repeatable.
Edit
The value of addr starts as zero, which can be seen here: https://gist.github.com/3803411
Edit
What this is supposed to do it copy the location structure byte by byte into the EEPROM, and then recall it when it is needed.
Closure
So I never did solve this problem. The project moved away from the EEPROM, and I have since changed OS, compiler and IDE. It's unlikely I will replicate this problem.
I'll tell you one thing wrong with your code, this line:
(unsigned char)addr>>8
doesn't do what you seem to need.
It converts the value in addr into an unsigned char which (assuming 8-bit char and either 16-bit int or only using the lower 16 bits of a wider int), will will always give you the lower eight bits.
If you then right shift that by eight bits, you'll always end up with zero.
If your intent is to get the upper eight bits of the address, you need to use:
(unsigned char)(addr>>8)
so that the shift is done first.