Thread: C: array of string - understanding

  1. #1
    Registered User
    Join Date
    Oct 2013
    Posts
    87

    C: array of string - understanding

    gcc -v
    gcc version 4.9.2 (GCC)

    Compiling code:
    Code:
    gcc -g -Wall -Wextra *.c -o program_parse -pedantic -std=gnu99
    I've a function which takes in a character array, parses it by tab. And want to Store words.

    Function definition:
    Code:
    void array_of_str(char *, unsigned int);
    Code:
    void array_of_str(char *line, unsigned int count){                                                                                                                                             
                                                                                                                                                                                                   
      unsigned int i=0;                                                                                                                                                                            
                                                              
      char *p;/*hold strtok output*/                                                                                                                                                               
      char **h=malloc(count*sizeof(char *)); /*2D array */                         
    
    //create **h - number of strings                                                                                                             
      char *y[count]; /*2D array, too*/                                                                                                                                                            
                                                                                                       
      p=strtok(line,"\t");                                                                                                                                                                         
                                                                                                       
                                                                                                                                                                                                   
      while(p!=NULL){                                                                                                                                                                              
                                                                                                         
        h[i]=malloc(sizeof(p)*sizeof(char));                                                 
    
         //allocate memory of the length of string
                                                                  
        y[i]=p;                                                                                                                                                                                    
        h[i++]=p;                                                                                                                                                                                  
        p=strtok(NULL,"\t");                                                                                                                                                                       
      }                                                                                                                                                                                            
                                                                                                                                                                                                   
      /*                                                                                                                                                                                           
       * Print to make sure values are correct                                                                                                                                                     
       */                                                                                                                                                                                          
      while(i--!=1){                                                                                                                                                                               
        printf("value is %s\t%s\n",h[i-1],y[i-1]);                                                                                                                                                 
                                                                                                                                                                                                   
      }                                                                                                                                                                                            
       /*
    * Free ** pointer 
    */
                                                                                                                                                                                                   
    }
    When I use ** pointer for character I've to allocate memory 2 times:
    - the number of strings I plan to hold
    - the length of each string
    - Free my pointer

    However, if I use * pointer, I do not have to allocate any such memories but one the number of string I intend to hold.
    But not the length of string.

    Yet both work completely fine, as of now, or in my case.

    Questions:
    - Why single pointer doesn't need length of string?
    - Do I need to free * pointer at some point alike ** pointer?
    - When do I use which if any general rule of thumb is there?

    Thank you for your time, and patience to my post.

  2. #2
    Registered User
    Join Date
    Oct 2013
    Posts
    87
    I can have 2D array as:

    1)
    Code:
    char *p[10];
    Or,

    2)
    Code:
    char *p = malloc(10*sizeof(char*));
    If I'm not wrong both would work as intended, as long as malloc is able to allocate memory.
    Is there any preference of one over other?

    Sorry for multiple questions. But these questions are really causing havoc in my mind.

  3. #3
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    This does not make sense:
    Code:
    h[i]=malloc(sizeof(p)*sizeof(char));
    You either want to allocate space for a copy of the token, or you want h[i] to point to the first character of the token. For the former, you would do something like this:
    Code:
    p = strtok(line, "\t");
    while (i < count && p != NULL) {
        h[i] = malloc(strlen(p) + 1);
        strcpy(h[i], p);
    
        y[i] = malloc(strlen(p) + 1);
        strcpy(y[i], p);
    
        i++;
        p = strtok(NULL, "\t");
    }
    For the latter, you would do something like this:
    Code:
    p = strtok(line, "\t");
    while (i < count && p != NULL) {
        h[i] = p;
    
        y[i] = p;
    
        i++;
        p = strtok(NULL, "\t");
    }
    Notice that the actions taken for both h[i] and y[i] are respectively the same in each case.

    Quote Originally Posted by deathmetal
    When I use ** pointer for character I've to allocate memory 2 times:
    - the number of strings I plan to hold
    - the length of each string
    - Free my pointer
    As I have shown, whether you dynamically allocate just once or whether you also dynamically allocate within the loop depends on which approach you decide to take. If you dynamically allocate just once, it means you have a dynamic array of pointers, each of which points to the first character of a string within the original array. If you dynamically allocate within the loop, you can then store copies of these tokens.

    Quote Originally Posted by deathmetal
    However, if I use * pointer, I do not have to allocate any such memories but one the number of string I intend to hold.
    But not the length of string.
    As I have shown, you can dynamically allocate memory within the loop even when you have a variable length array of pointers, i.e., if you want each pointer to point to the first element of a copy of the token, rather than to characters within the original array.

    Quote Originally Posted by deathmetal
    - Why single pointer doesn't need length of string?
    It is not a "single pointer": y is a variable length array of pointers. When you cause each pointer to point to the first character of a token within the original array, you do not need to allocate space for each token since the original array provides the storage for the tokens.

    Quote Originally Posted by deathmetal
    - Do I need to free * pointer at some point alike ** pointer?
    No, variable length arrays will be automatically destroyed when they go out of scope. However, if you dynamically allocate space for each token, then you need to free the space for each token before the variable length array goes out of scope (unless you also save the pointers elsewhere).

    Quote Originally Posted by deathmetal
    - When do I use which if any general rule of thumb is there?
    If you only need the array to exist within the scope of the function then a variable length array is appropriate. However, because they are less well supported, you might choose to create a dynamic array with malloc instead anyway.

    EDIT:
    This is wrong:
    Code:
    char *p = malloc(10*sizeof(char*));
    You probably wanted to write:
    Code:
    char *p = malloc(10 * sizeof(char));
    You should use this pattern instead, except when you have a pointer to void:
    Code:
    char *p = malloc(10 * sizeof(*p));
    Though since sizeof(char) == 1, you could also write:
    Code:
    char *p = malloc(10);
    Quote Originally Posted by deathmetal
    If I'm not wrong both would work as intended, as long as malloc is able to allocate memory.
    Is there any preference of one over other?
    They are entirely different: the former is an array of 10 pointers to char; the latter is a pointer to char that points to the first element of an array of 10 char. Perhaps you had in mind:
    Code:
    char **p = malloc(10 * sizeof(*p));
    In which case they can be used similiarly, but of course for the latter 10 can be replaced by a variable, whereas for the former it must be a constant unless you want a variable length array.
    Last edited by laserlight; 03-17-2016 at 09:07 AM.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  4. #4
    Registered User
    Join Date
    Oct 2013
    Posts
    87
    Hi laser,
    Thanks much for your reply, and explaining in detail.
    I'm still trying to absorb what you've said.

    I've fixed my code or malloc.

    Thank you again.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Understanding String Functions
    By YannB in forum C Programming
    Replies: 1
    Last Post: 01-30-2014, 07:27 AM
  2. Replies: 3
    Last Post: 12-20-2013, 05:44 PM
  3. Replies: 2
    Last Post: 12-02-2012, 05:25 AM
  4. Understanding an array eample
    By alter.ego in forum C Programming
    Replies: 8
    Last Post: 06-03-2011, 06:11 AM
  5. Understanding strtok from string.h library
    By yougene in forum C Programming
    Replies: 6
    Last Post: 03-07-2008, 01:14 AM

Tags for this Thread