0

I've run across this problem: I implemented a function whish converts a string into a structure. I've got this structure:

typedef struct {
   unsigned a, b;
   unsigned c, d; 
   } struct_t;

The heading of the function is the following:

struct_t * string_to_struct (char * g)

\retval p pointer to new structure created; \retval NULL if the conversion is not successful. The convertion is not successful for strings such as "5 8 10 10" (I'm given a segmentation fault error) but is successful for strings such as "5 6 6 7" or "4 5 6 8". I think the problem lies within the allocation of memory for pointer to structure p. I thought about first allocating memory for p in this way:

p = (struct_t*)malloc(sizeof(struct_t));

And then I thought about reallocating memory for p due to make it room for the string (some strings are about 8 bytes and everything works fine, but if the string is about 10 bytes I get a segmentation fault, because by allocating memory for p as above I make room for only 8 bytes), using function realloc() to enlarge the memory where to put the structure and make it the size of the string, but I don't know how to do it properly. Here it is how I attempted to implement the function, not using realloc():

struct_t * string_to_struct (char * g){

struct_t * p; /* pointer to new structure*/
int n;
n = sizeof(g); 

if(sizeof(g) > sizeof(struct_t)) 
    p = (struct_t*)malloc(n*sizeof(struct_t));
else
    p = (struct_t*)malloc(sizeof(struct_t));

if(g[0] == '\0' ) /* trivial */
    return NULL;
else                
        (*p).a = g[0];
        (*p).b = g[2];
        (*p).c = g[4];
        (*p).d = g[6];

            if((*p).a <= (*p).c && (*p).b <= (*p).d)  /* check, the elements of the structure must satisfy those relations.*/
                return p;
            else
                return NULL; /* convertion not successful */

}

But it's not working. Thanks in advance for any help.

Chiara
  • 17
  • 1
  • 5
  • No definition for struct_t, no language tag (C or C++), no code, no real question. I'm sorry but this is really *unclear* and likely to soon be closed. – Serge Ballesta Nov 28 '17 at 08:35
  • The allocation (apart from the unnecessary cast) is fine. The error is most likely in the parsing. Show the full body of the `string_to_struct` function. – dbush Nov 28 '17 at 14:38
  • `sizeof(g)` is very different than `strlen(g)` – William Pursell Nov 28 '17 at 14:48
  • 1
    Ackkk. `(*p).a` is so ugly that it got its own special notation: `p->a` – William Pursell Nov 28 '17 at 14:49
  • Given `char *g`, just what do you think you get from `sizeof(g);`? – Andrew Henle Nov 28 '17 at 14:50
  • Possible duplicate of [size of character array and size of character pointer](https://stackoverflow.com/questions/17260242/size-of-character-array-and-size-of-character-pointer) – Andrew Henle Nov 28 '17 at 14:51
  • Do not name your struct `*_t`. Names ending in `_t` are reserved. https://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-a-c-identifier/228797#228797 – William Pursell Nov 28 '17 at 14:51
  • I'm not the one who named the structure. I'm working on a project, I can't rename the structure because my professor named it `*_t`. – Chiara Nov 28 '17 at 14:54
  • Your function uses `s`, but it's not defined anywhere. – dbush Nov 28 '17 at 14:57
  • @AndrewHenle required memory storage space? – Chiara Nov 28 '17 at 14:57
  • @dbush I'm sorry. I changed the names of pointers, variabiles and etc. from the actual code and I forgot to change that. Anyway I just corrected – Chiara Nov 28 '17 at 14:59

1 Answers1

0

First, this bit of logic is unnecessary:

int n;
n = sizeof(g); 

if(sizeof(g) > sizeof(struct_t)) 
    p = (struct_t*)malloc(n*sizeof(struct_t));
else
    p = (struct_t*)malloc(sizeof(struct_t));

The correct amount of memory to allocate for one instance of your struct is always sizeof(struct_t). The length of the string doesn't matter. Also, sizeof(g) is giving you the size of the pointer, not the length of the string. You get the string length with strlen(g). You can replace the above with:

p = malloc(sizeof(struct_t));

The main problem is here:

    (*p).a = g[0];
    (*p).b = g[2];
    (*p).c = g[4];
    (*p).d = g[6];

What this does is store the ASCII value (assuming your system uses ASCII) of a particular character in the string into your struct as an integer. Given your example input of "5 6 6 7", g[0] contains the character '5'. This has an ASCII value of 53, so p->a has the value 53. When your input is all single digit numbers, the indexes you use correspond to where the digits are in the string, so you end up with the ASCII values of each digit. And because the ASCII values of the characters '0' to '9' are consecutive, the comparisons you do work as expected.

When you use a string like "5 8 10 10", the above assumption about the location of the digits breaks. So a gets '5' (53), b gets '8' (56), c gets '1' (49), and d gets a space (ASCII 32). Then your comparison (*p).b <= (*p).d) fails because 56 is not less than 32, so your function returns NULL. You're probably getting a segfault because the calling function isn't checking if NULL was returned.

To parse the string correctly, use strtok to break the string up into tokens, then use atoi or strtol to convert each substring to an integer.

dbush
  • 205,898
  • 23
  • 218
  • 273