0

General information about the task:

I need to write the function on C language which takes a byte array (it reperesents package) parse it, do some stuff and return a changed byte array.

My approach:

"filename.h"
    char* ParsePackage(const char* byteArray);
typedef struct
{
    char name[4];
    float value;
} packageStructure;

I use the struct packageStructure to which a byteArray is casted, then I am trying to get data by accessing fields of that struct: "filename.cpp"

include "filename.cpp"
char* ParsePackage(const char* byteArray)
{
    packageStructure* tmp = (packageStructure*) byteArray;
    // get values of structure fields and do some staff with them:
    tmp->name;
    tmp->value;
    return (char*)modifiedByteArray;
}

I am not satisfied with the result, because the whole data from byte array is written to the first field of the struct, which is a name, to the second filed goes some random value;

So expected questions here are: that I am doing wrong (how to alter my approach to make it work)? Can you offer other methods of parsing byte array?

thanks in advance!

2
  • How is the "byte array" created and populated? Commented Oct 8, 2012 at 9:03
  • int main(void) { ParsePackage("tex123"); return 0; } Commented Oct 8, 2012 at 9:05

4 Answers 4

3

I'm guessing that "tex" should be the name and 123 should be the value. However as you can see it doesn't work that way, especially with floating point values. You can't convert a number in a string to a floating point value just by casting.

Instead you have to extract the first three characters from the string and put into name, then you have to extract the next three characters and as a string use e.g. strtof to convert the string to a floating point number.

When creating a string again, you can use snprintf for that.

You have to do something like this:

char* ParsePackage(char* byteArray)
{
    packageStructure tmp;

    /* Extract values from string, first the name */
    memcpy(tmp.name, byteArray, sizeof(tmp.name) - 1);
    tmp.name[sizeof(tmp.name) - 1] = '\0';  /* Make sure it's terminated */

    /* Then the value */
    tmp.value = strtof(&byteArray[3], NULL);

    /* Now do whatever you need to do with the structure... */

    /* Convert back to a string */
    /* For that we need a string */
    static char output[16];

    /* Then put the data from the structure into the string */
    snprintf(output, sizeof(output), "%s%3.0f", tmp.name, tmp.value);

    /* Return the string */
    return output;
}

However, instead of doing this work yourself you should find a library for serialization, which will handle all the gory details for you.

Sign up to request clarification or add additional context in comments.

5 Comments

"tex123" is a string literal right???... as per @spin_eight's function invocation.
@rjayavrp char* ParsePackage(const char* byteArray);
@Joachim Pileborg. am I right that to use a serialization I need to include additional libraries(like boost) that arent presented in C standart library. I want to solve my task only by means of C standart library. Also I am searching for the approach where I can get all needed values at ones from data stream into structure, and I wonder if it is possible, if not I need to understand why.
@spin_eight You can of course implement your own serialization using only standard C, pointer arithmetic and standard functions. Basic serialization is not tha hard, you just have to make sure that the serialized format is well defined. If it's only one structure like in your example, it's very easy by having fixed-sized fields in the "byte stream" (string), otherwise you will have to store the types and possible the field lengths inside the string.
Thanks for the link on serialization, I shall spend my time on reading about it. I have already faced with serialization, but it was much easier for me because I was free to use any libraries, and I used Qt with it`s QData stream where serialization and deserialization is a piece of cake compared to one in C language.
1

I am not sure what do you want exactly, but it seems that you want to use the name as a string and the value as a float when the input is a string.

I would do it something like this:

packageStructure ParsePackage(char* byteArray)
{
    char *modifiedByteArray = malloc(100);
    packageStructure tmp;
    strncpy( tmp.name, byteArray, 3 );
    tmp.name[3] = 0;
    tmp.value = atof(byteArray+4);
    return tmp;
}

2 Comments

input is byte array, which I got from server, that array(package) is formed in certain format to parse array I am trying to use struct. I know how to parse it unit by unit, but actually i am interested if it is possible to get values from that array using cast to struct
@spin_eight, yes, you can, but the representation of float in memory is not as simple as "123", you can read this: en.wikipedia.org/wiki/IEEE_floating_point
0
int main(void) { ParsePackage("tex123"); return 0; }

As per code, Your text "tex123" is read-only.

.LFE0:
        .size   ParsePackage, .-ParsePackage
        .section        .rodata
.LC0:
        .string "tex123"
        .text
        .globl  main
        .type   main, @function
main:
.LFB1:
        .cfi_startproc
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, 
        ....
        ....

so trying to alter that string literal is a bad idea.

1 Comment

ok, thanks for pointing it out. Can you give me some info on casting byte array to struct, can I solve my task by doing this?
0

During my experiments I found that it is possible to cast a byte array to a struct. And this allows to solve task with deserialization in more elegant(my own opinion) way.

My first tries failed because I tested them on the wrong input which was a string literal. Here is the working example:

".h"
typedef struct Test
    {
        char name[2] ;
        float number;
    } Test;

".c"
char* TestStruct(char* byteArray)
{
    Test str;

    str = *(Test*)byteArray;
    return byteArray;
}
"main.c"
int main(void)
{
    Test str;
    strcpy(str.name,"asd\0");
    str.number = 0.25;
    TestStruct((char*)&str);
    return 0;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.