0

So this is more a plea for explanations and resources than anything. I've done some searching on here and online, and haven't found anything that really answers the question.

I was given an assignment to parse a string into tokens, implemented using the following prototype verbatim: int makearg(char *s, char ***args);

I did so using something like the following:

int makearg(char *s, char ***args){
  char temp[255];
  int count = 0;

  ///////
  //Count words in string
  ///////

  *args = calloc( count , sizeof(char*));
  //OR: *args = (char**) malloc(count * sizeof(char*));

  count = 0; 

  while( //Not at end of s// ){

    //Copy word into temp
    if( //end of word// ){
      *args[count]=calloc( strlen(temp),  sizeof(char));
      //OR: *args[count] = (char*) malloc(count * sizeof(char));

      strcpy(*args[count],temp);

      count++;
    }
  }
return count;
}

int main(){
  char inp[255];
  char **tokens = NULL;
  int count;

  printf("ENTER COMMAND: ");
  fgets(inp,255,stdin);
  count = makearg(inp,&tokens);

  printf("Number of arguments:%d\nArguments:",count);
  int i = 0;
  for(i=0;i<count;i++)
    printf("\n%s", tokens[i]);
  printf("\n");
  return 0;
}

If I gave something like "testcommand" the program appeared to work, but if I gave an input with two or more words, such as "This is my test command", it would start segfaulting on the second calloc/malloc line. Poking around with GDB showed that *args[0] returned as expected ("This"), but *args[1] was attempting to access a point in memory it shouldn't.

I got it working using the following:

int makearg(char *s, char ***args){
  char temp[255];
  int count = 0;
  char** tempargs;

  ///////
  //Count words in string
  ///////

  tempargs = calloc( count , sizeof(char*));

  count = 0; 

  while( //Not at end of s// ){

    //Copy word into temp
    if( //end of word// ){
      tempargs[count]=calloc( strlen(temp),  sizeof(char));

      strcpy(tempargs[count],temp);

      count++;
    }
  }
 *args = tempargs;
 return count;
}

My question is, what's the difference here? From my understanding, *args should be the same as using tokens, especially for the purposes of malloc. The bit at the end with *args = tempargs is just setting tokens to point at the same chunk of memory as tempargs. How is this different from pointing *args at the malloc memory in the first place?

My professor described the above solution as the way he usually does it, but didn't give a better explanation than "it strips off a layer of redirection in the body of the function". This makes sense, and is a convention I've seen elsewhere on here while trying to find answers, but doesn't help me understand. I asked around a bit in person, but the best answer I got was "eh. Scope/compiler shenanigans probably. It looks the same?".

Where should I go to find more on this?

  • 2
    `*args[count] = ...` - that doesn't do what you think it does. Look carefully at the [operator precedence table for C](http://en.cppreference.com/w/c/language/operator_precedence) – WhozCraig Sep 28 '16 at 06:58
  • Since your code compiles, could you provide us with a [Minimal, Complete, and Verifiable Example](/help/mcve)? –  Sep 28 '16 at 06:59
  • Warning: when allocation memory to store words, you're missing the last `\0` : `strlen` does not include the `\0` `strcpy` takes care of it. – Mathieu Sep 28 '16 at 07:37
  • @WhozCraig Thank you! Something stupidly obvious now that I know where the issue is. – Quiksilv26 Sep 28 '16 at 15:12
  • @purplepsycho I've actually got that in the working version. Oops. Thank you. – Quiksilv26 Sep 28 '16 at 15:15

0 Answers0