0
#include <stdio.h>
#include <stdlib.h>

void populateArray(char* line, char** cmd){
    printf("INPUT LINE: %s\n", line);
    char *  token    = strtok (line, " ");
    int n_spaces = 0, i;

    /* split string and append tokens to 'cmd' */

    while (token) {
      *cmd = realloc (*cmd, sizeof (char*) * ++n_spaces);

      if (*cmd == NULL)
        exit (-1); /* memory allocation failed */

     *cmd[n_spaces-1] = token;

      token = strtok (NULL, " ");
    }

    /* realloc one extra element for the last NULL */

    *cmd = realloc (*cmd, sizeof (char*) * (n_spaces+1));
    *cmd[n_spaces] = 0;

    /* print the cmd */

    for (i = 0; i < (n_spaces+1); ++i)
      printf ("cmd[%d] = %s\n", i, cmd[i]);
}    

int main (int argc, char* argv[])
{
    char *cmd1 = NULL;
    char * line = "ls -l";
    populateArray(line, &cmd1);
}

I know that C is pass by value but is there anyway to emulate it to pass by reference? I need to pass cmd1 to populateArray(char* line, char** cmd) as a reference. I did some research and to pass by reference in C, it seem like I need to do something like this: I tried but still cant make it work for the array pointer.

void byreference_func(int* n){
    *n = 20;
}
int main(int argc, char *argv[])
{
    int i = 10;
    printf("before the call the value of i is %d\n", i);
    byreference_func(&i);
    printf("after the call the value of i is %d\n", i);
    return 0;
}

EDIT: Error code

anon@turing:~/csce3613/assign3$ gcc gg.c
gg.c: In function âpopulateArrayâ:
gg.c:6:24: warning: initialization makes pointer from integer without a cast [enabled by default]
gg.c:17:23: warning: assignment makes integer from pointer without a cast [enabled by default]
gg.c:19:13: warning: assignment makes pointer from integer without a cast [enabled by default]
anon@turing:~/csce3613/assign3$ ./a.out
INPUT LINE: ls -l
Segmentation fault (core dumped)
Thanh Nguyen
  • 11
  • 1
  • 2

4 Answers4

0

cmd1 is an array. Arrays cannot be reallocated. You can only use realloc on a null pointer, or a pointer returned by a previous call to a malloc family function.

Instead you will need to do :

int main() 
{
    char *cmd1 = NULL;
    populateArray( line, &cmd1 );
}

and then inside your function, change cmd to (*cmd). It is exactly analogous to your int example, except everywhere you have int in that example you need to change it to char *. You correctly write *n = 20; in your int example but then you forget to do that in your real code.

BTW if you are always going to free before returning , then you are not really populating an array, and.

M.M
  • 138,810
  • 21
  • 208
  • 365
0

I cannot find the declaration of line in your code snippet. May it be part of your troubles? Can you also add the error that you are getting?

gmas80
  • 1,218
  • 1
  • 14
  • 44
  • It was part of my big project so i forgot to put it in the post but line is there. Suppose char *line = "ls -l -a"; will edit the post. – Thanh Nguyen Oct 26 '14 at 03:22
0

When you do char * line = "ls -l -a"; your line is actually a const char *, not a char *

You should do

char *line = strdup("ls -l -a");

Or do

char line[] = "ls -l -a";

( this works, read here What is the difference between char s[] and char *s?)

strtok() tries to modify your line so it cannot be a const char*

And I don't do char *cmd1[64]; I do

char **cmd1 = (char**)malloc(sizeof(char*));
cmd1[0] = (char*)malloc(sizeof(char) * 64);

Here is the working code : http://pastebin.com/TTsTpdgU

Community
  • 1
  • 1
tmh1999
  • 63
  • 5
0

All strings in C are referenced by pointers (addresses), therefore you are passing the address of the string in every function call using char * as the parameter definition. There is no need to pass it as char ** a simple char * will do. To return the value to main, simply declare populateArray as char * and return a pointer to cmd1.

Next as indicated, you are declaring line as a constant string literal. In order to make use of it in the way you are, it should be declared as an array of characters. (e.g. char line[] = "ls -al").

As for your program logic, you are making things a bit difficult reallocating for every char you add. It is far easier to use a couple of functions already providing in string.h, namely strcat. Here is an example. (Note there are many, many different ways to do this, but allocating cmd with calloc instead of malloc initializes a string of NULL chars which makes strcat a snap and insures the resulting string is always null-terminated.)

Updated (I didn't like the first one)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define CMDSZ 256

char *populateArray (char *line, char *cmd) /* declare as 'char *' and return pointer */
{
    printf ("\nINPUT LINE: %s\n\n", line);

    char *token = strtok (line, " ");
    int i = 0;

    cmd = calloc (CMDSZ, sizeof (cmd));  /* allocate command string to CMDSZ         */

    while (token)                        /* split string and append tokens to 'cmd'  */
    {
        if (strlen (cmd) > 0)            /* if not first command add space           */
            strcat (cmd, " ");

        strcat (cmd, token);             /* add token to cmd    */

        token = strtok (NULL, " ");      /* get next token      */
    }

    for (i = 0; i < (strlen (cmd)); ++i)        /* print each character in cmd */
        printf ("  cmd[%d] = %c\n", i, cmd[i]);

    printf ("\n  cmd: %s\n\n", cmd);            /* print final command         */

    return cmd;
}

int main () {

    char *cmd1 = NULL;
    char line[ ] = "ls -l -a -x -y -z";

    cmd1 = populateArray (line, cmd1);  /* return a pointer to cmd1                 */

    printf ("In main():\n\n  cmd1: %s\n\n", cmd1);

    if (cmd1) free (cmd1);              /* free memory allocated in populateArray   */

    return 0;
}

Note: int main(....) is an integer function -- it should return a value.

output:

$ ./bin/poparray

INPUT LINE: ls -l -a -x -y -z

  cmd[0] = l
  cmd[1] = s
  cmd[2] =
  cmd[3] = -
  cmd[4] = l
  cmd[5] =
  cmd[6] = -
  cmd[7] = a
  cmd[8] =
  cmd[9] = -
  cmd[10] = x
  cmd[11] =
  cmd[12] = -
  cmd[13] = y
  cmd[14] =
  cmd[15] = -
  cmd[16] = z

  cmd: ls -l -a -x -y -z

In main():

  cmd1: ls -l -a -x -y -z
David C. Rankin
  • 81,885
  • 6
  • 58
  • 85