0

I would like to allocate a char***. I have a got a sentence like this: "This is a command && which I || need to ; split" I need to put in each box a full sentence just like that:

cmd[0] = "This is a command"
cmd[1] = "wich I"
cmd[2] = "need to"
cmd[3] = "split"

Sentences are separated by tokens like &&, ||, ;, |.
My problem is that I don't know how to allocate my triple dimension array. I always get a Segmentation Fault.

This is what I do :

for(k = 0; k < 1024; k++)
   for( j = 0; j < 1024; j++)
       cmd[k][j] = malloc(1024);

But a few line later, in an other loop :

»           cmd[k][l] = array[i];

I get a segfault here.

How can I do this please ? Thanks in advance

Grijesh Chauhan
  • 57,103
  • 20
  • 141
  • 208
user2145240
  • 95
  • 1
  • 3
  • 9
  • 1
    Splitting a string into a number of sub-strings just requires an array of strings, which is not a 3D structure. – unwind Jul 05 '13 at 12:53
  • 1
    Read: [Allocate memory to char `***` in C: Matrix of String or/ 3D char array:](http://stackoverflow.com/questions/16522035/allocate-memory-to-char-in-c/16522223#16522223) – Grijesh Chauhan Jul 05 '13 at 12:53
  • why do you want 3D? char *arr[4] will solve your problem.To tokenize your string you may need to call [strtok](http://www.cplusplus.com/reference/cstring/strtok/). – Dayal rai Jul 05 '13 at 13:06
  • I just note a few things in the posted code to hopefully shed some light on that how it gone wrong. For that allocation loop I assume cmd was declared as something like "char* cmd[1024][1024];", otherwise it just wouldn't work (it may compile however depending on what you did, and may not even segfault during alloc'ing). When you do your "few line later" thing array should be like "char* array[SOME_SIZE];" or "char array[SOME_SIZE0][SOME_SIZE1];" so you assign compatible pointers there. Even then you are leaking memory there. – Jubatian Jul 06 '13 at 14:17

2 Answers2

1

Please keep in mind that a 2/3D array in C is not the same as a char ***.

If all you wish is to have a 1024^3 character array then you will be good with

char array[1024][1024][1024];

But keep in mind that this will allocate 1 GB of space on your stack which may or may not work.

To allocate this much on the heap you need to type it correctly:

char (*array)[1024][1024] = malloc(1024*1024*1024);

In this scenario array is a pointer to an array of 2D 1024x1024 character matrices.

If you really want to work with char *** (which I do not recommend if your array lengths are static) then you need to allocate all intermediary arrays too:

char *** cmd = malloc(sizeof(char **) * 1024);
for(k = 0; k < 1024; k++) {
    cmd[k] = malloc(sizeof(char *) * 1024);
    for( j = 0; j < 1024; j++)
           cmd[k][j] = malloc(1024);
}
Sergey L.
  • 21,822
  • 5
  • 49
  • 75
  • Thank you for your answer. Okay I assume this is not the right way to do it. Without using strtok, what's the best way to split my string into a array of string delimited by tokens ? – user2145240 Jul 05 '13 at 14:24
  • @user2145240 Since you are splitting by a delimited that is longer then a single character then I am not sure if there is a better way of doing it then by substring search for each delimiter. See my other answer for a suggestion. – Sergey L. Jul 05 '13 at 15:30
0

If you are going to be splitting your string by delimiters that are longer then a single character then this is how you could do it with string search.

The following function will accept an input string and a delimiter string. It will return a char ** which has to be freed and it will destroy your input string (reusing it's memory to store the tokens).

char ** split_string(char * input, const char * delim) {
    size_t num_tokens = 0;
    size_t token_memory = 16; // initialize memory initially for 16 tokens
    char ** tokens = malloc(token_memory * sizeof(char *));

    char * found;
    while ((found = strstr(input, delim))) { // while a delimiter is found
        if (input != found) { // if the strind does not start with a delimiter

            if (num_tokens == token_memory) { // increase the memory array if it is too small
                void * tmp = realloc(tokens, (token_memory *= 2) * sizeof(char *));
                if (!tmp) {
                    perror("realloc"); // out of memory
                }
                tokens = tmp;
            }

            tokens[num_tokens++] = input;
            *found = '\0';
        }
        // trim off the processed part of the string
        input = found + strlen(delim);
    }

    void * tmp = realloc(tokens, (num_tokens +1) * sizeof(char *));
    if (!tmp) {
        perror("realloc"); // something weird happened
    }
    tokens = tmp;

    // this is so that you can count the amount of tokens you got back
    tokens[num_tokens] = NULL;

    return tokens;
}

You will need to recursively run this to split by more then one delimiter.

Sergey L.
  • 21,822
  • 5
  • 49
  • 75