Pinsickle
Pinsickle

Reputation: 633

pass array by reference

I cant figure out where I am messing up. I am passing an array of character pointers. Inside the function I am trying to use strtok to break up a string into smaller pieces to be assigned to the char * array. I can try printing it off in the function and it all shows up correctly. As soon as I try to print it back in main I just get garbage.

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

#define CMDLEN 100
#define MAXARG 5
void prompt();
int getCommand (char* cmdAndParameters[]);

int main() {
     int numArgs = 0;
     char* cmdAndParameters [MAXARG];

     while (true){
          prompt ();
          numArgs = getCommand (cmdAndParameters);
     }
}

void prompt() {
     printf("shell> ");
}

int getCommand(char* cmdAndParameters[]){
     int argNum = 0;
     bool foundArg = true;
     char* delimiters = " \t\n";
     char userRequest[CMDLEN];

     fgets(userRequest,sizeof(userRequest), stdin); 

     if ((cmdAndParameters[argNum] = strtok(userRequest, delimiters)) != NULL)
     {  
          argNum++;

          for (; argNum < MAXARG && foundArg; argNum++) {
               if ((cmdAndParameters[argNum] = strtok(NULL,delimiters))
                         == NULL) 
               {
                    foundArg = false;
               }
               // merely to test output remove later
               else {printf("%s\n", cmdAndParameters[argNum]);}
          } 

     }

     return argNum;
}

Upvotes: 1

Views: 366

Answers (2)

Charlie Martin
Charlie Martin

Reputation: 112356

In this case, your inner array of chars is allocated "automatic", which is to say, on the stack. When you do the strtok, you're assigning a pointer to memory allocated on the stack, and then returning -- which means the memory is no longer allocated.

Move the userRequest array into file scope (ie, outside a block) or make the allocation 'static' and you'll have a better shot.

Update

Well, it's a little more than that, now that I look again.

First of all, you can clean it up considerably if you use a while loop, something like

argNum = 0;
while((cmdAndParameters[argNum++] = strtok(userRequest, delimiters)) != NULL)
    ;  /* all the work is happening in the conditional part of the while */

or even a for loop as

for(argNum = 0; 
    (cmdAndParameters[argNum] = strtok(userRequest, delimiters)) != NULL);
    argNum++)
    ; /* still all the work is in the for */

and now if argNum > 0 you know you found something.

Second, you need to think about how and when you're allocating memory. Your cmdAndParameters array is allocated when main starts (on the stack, it's "automatic") so it's around as long as your program, you're okay there. But your userRequest array is allocated auto in getCommand; when getCommand returns, the memory is deallocated; the stack pointer moves back over it and you have no guarantees any longer. So when you do the strtok, you're saving pointers into stack, which can lead to no good.

Upvotes: 4

dinwal
dinwal

Reputation: 467

Do you want

for (; argNum < MAXARG && foundArg; argNum++)

or something like

for(argCntr = argNum; argCntr < MAXARG && foundArg; argCntr++)

Hope that helps.

Upvotes: 0

Related Questions