1

Here is my code. I was struggling at why strncpy() cant copy the string into a struct, since it was works perfectly in my previous assignment. Also, I have second question: suppose I have a struct contains another struct, how to assign the value to the inside struct:

struct _field {
    char fieldName[50];
    char fieldType[50];
    int fieldLength;
};
struct _table {
    char *tableFileName;
    int reclen;
    int fieldcount;
    struct _field fields[100]; 
};

typedef enum { false, true } bool;

bool loadSchema(struct _table *table) {

    printf("%s\n", "*** LOG: Loading table fields...");

    FILE *fp = NULL;
    char lines[1000];
    char s[2] = " ";

    fp = fopen("in.txt", "r+");

    while (fgets(lines, sizeof(lines), fp) != NULL) {
        char *token;
        token = strtok(lines, s);

        if (token != NULL) {
            if (strcmp(token, "CREATETABLE") == 0) {
                token = strtok(NULL, s);
                if (token != NULL) {
                    token[strlen(token)-1] = '\0';
                    strcat(token, ".bin");
                    //table->tableFileName = token; // this line can write the value into struct
                    strncpy(table->tableFileName, token, 20);// this line cant write the value into struct
                }
                printf("*** LOG: Table name is [%s]\n", table->tableFileName);
            }
            /*if (strcmp(token, "ADD") == 0) {
                token = strtok(NULL, s);
                if (token != NULL) {    
                   strncpy((*table).fields. fieldName, token, 50);      
                }// Q2: how to give a value into a struct of a struct?
            }*/
        }
    }
    return 1;
}

Input file looks like this:

CREATETABLE people
ADD id char 50
ADD lname char 50
chqrlie
  • 131,814
  • 10
  • 121
  • 189
jiaru zhu
  • 31
  • 4
  • O/T, but recommend `#include stdbool.h` rather than you're own `typedef` – yano Sep 11 '17 at 21:30
  • `table->tableFileName` points to nothing (or at least the allocation is not shown). – Eugene Sh. Sep 11 '17 at 21:30
  • 2
    Where did `20` come from? It should have been a clue that you just made it up out of thin air. The length passed to strncpy must be the size of the destination buffer. In your case this is 0 since you never allocated any space. – stark Sep 11 '17 at 21:35
  • 1
    Possible duplicate of [strncpy leading to segmentation fault](https://stackoverflow.com/questions/14065391/strncpy-leading-to-segmentation-fault) – tonythewest Sep 11 '17 at 21:37
  • **Do not** use homebrew boolean (or other) types if there are standard ones and definitively not the standard macro names! C has a built-in boolean type and macros for `bool` and constants are available in `stdbool.h`. Use them! – too honest for this site Sep 11 '17 at 22:04

2 Answers2

0

Question 1: You're trying to copy into a string that has no allocated space. table->tableFilename is just a pointer. You'll either need to allocate space for it dynamically or declare a fixed width of the array.

The assignment table->tableFilename=token will work fine since it is just assigning the pointer a vaule, it's not trying to copy data into unallocated space.

Question 2: In your declaration table->_fields is an array so you need to index a specific instance to assign a value to its members. E.g. table->fields[0].fieldName.

  • *assignment table->tableFilename=token will work fine* - it will go to the weeds once out of that function. – Eugene Sh. Sep 11 '17 at 21:43
0

You are getting the segmentation fault because in the code you are trying to access the pointer table for which their is no memory allocated so it points to null. Hence the crash. solution to the problem would be to copy these lines

table = (struct _table*)(malloc (sizeof(struct _table)));

table->tableFileName = (char *)(malloc (sizeof(char) * 20));
strncpy(table->tableFileName, token, 20);

and remember to free them. to answer your second question You just need to assign value directly outer_struct.innerstruct.field1 = value outer_struct.innerstruct.field2 = value

or if the inner structure is a pointer you need to initialize memory for it first and then you can either assign or directly use memcpy.

pradeep bisht
  • 66
  • 1
  • 5
  • Your explanation is almost correct: the member `tableFileName` might not be `NULL` if `table` points to an uninitialized structure: such as an object with automatic storage in the caller's scope or one allocated with `malloc()`. `table` might even be an invalid pointer... – chqrlie Sep 12 '17 at 05:54
  • Yes it is better to memset the memory after allocating using malloc. But in this scenario we don't have the memory allocated for structure _table itself and in my solution i am allocating memory and than assigning it the value of token so it is safe untill unless other uninitialized variable are accessed. – pradeep bisht Sep 12 '17 at 06:21
  • Using `calloc()` is a safer and simpler approach. – chqrlie Sep 12 '17 at 07:14
  • I wont say calloc () is simpler. Both are simpler but yes if you want your data allocated and initialize with 0 in a single statement agree calloc does that. But malloc is fine as far as you are doing the memset or you are not worried about garbage in you structure as you are going to initialize them or assign values to them. – pradeep bisht Sep 12 '17 at 19:26
  • I meant `calloc()` is simpler than `malloc()` + `memset()`, also potentially faster and safer as there is no chance for a size mismatch between the allocation and the clearing calls. – chqrlie Sep 12 '17 at 19:35
  • Yes that is true that `calloc()` will be potentially faster than `malloc() + memset()`. But `malloc()` is a touch faster than calloc() if you really do not care about the initialization of the memory and we are going to assign. So in that case `malloc()` statement as in the above solution is faster than the `calloc()` and also allocation and clearing there is always chance of mismatch in both if we do not free () the memory. – pradeep bisht Sep 12 '17 at 19:56