简体   繁体   中英

Printing command line argument tokens using strtok function. How to return a pointer to pointer using this function

I am trying to print the tokens of the command line argument using a function that uses the strtok function. The point is that the return statement does not recognize the pointer returned.

#include <stdio.h>
#include <conio.h>
#include <iostream>
#include <string.h>
#include<time.h>
#include<math.h>
#include<ctype.h>
#include <malloc.h>
#include <Windows.h>
#include<string>


using namespace std;
char **makeargv(char *s);
int main()
{
int i;
char **myargv;
char mytest[] = "This is a test";

if((myargv = makeargv(mytest)) == NULL)
    fprintf(stderr,"Failed to construct an argument array\n");
else
    for (i=0;myargv[i]!=NULL;i++)
        printf("%d:%s\n",i,myargv[i]);
system("pause");

 return 0;
  }

 char **makeargv(char *mytest)
{
char *pch;
printf("Splitting string \%s\ into tokens:\n",mytest);
pch = strtok(mytest," ");
while(pch != NULL)
{
    printf("%s\n",pch);
    pch = strtok(NULL," ");
}
      pch = strtok(mytest," ");
char *s = pch;
return &s;
}
 char *s = pch;

s is a pointer to character, but in return **s; statement, you are dereferencing twice, which is wrong. Your intended usage is

return &s;

this will return a pointer to pointer to character ( char** ).

But your overall program is ill-defined in terms of pointer usage. For example, you are returning pointer to a local variable on the stack, which will be destroyed once the method returns, and accessing it in the caller is UB .

And before returning pch will be NULL , so will s , so basically you are taking and returning address of a NULL pointer .

Define char *myargv[MAXARGV] , and pass that into your makeargv function, and store pch in that. Return number of arguments found.

This will always make pch point to NULL after the loop since that is your ending condition.

while(pch != NULL)
{
    printf("%s\n",pch);
    pch = strtok(NULL," ");
}
char *s = pch; // pch is NULL

if you want to return the last token you could just do a search for last space manually

also as Rakibul already mentioned you should not dereference the string twice, what you need to return is the address of the string ie pch itself.

if you have strrev on your system you could write something like

strrev( mytest ); // reverse string
char* pch = strtok( mytest, " " ); // extract token
if ( pch != NULL )
{
  puts( strrev(pch) ); // back to original
}

EDIT

You wrote

I have made a small change to the function but i am getting bad pointer exception error

char **makeargv(char *mytest) 
{ 
  char *pch; 
  printf("Splitting string %s\ into tokens:\n",mytest); 
  pch = strtok(mytest," "); 
  while(pch != NULL) 
  { 
    printf("%s\n",pch); 
    pch = strtok(NULL," "); 
  } 
  pch = strtok(mytest," "); 
  char *s = pch; 
  return &s; 
}

You still try to return the address of the pointer as well you seem not know that strtok modifies its argument, the original string is modified when you pass it to the strtok function.

Instead try something like this

char **makeargv(char *mytest) 
{ 
  // setup an array of pointers to strings, 20 is an arbitrary value
  const int maxtokens = 20;
  char**tokens = malloc( sizeof(char*) * maxtokens );
  for ( int i = 0; i < maxtokens; ++i )
  {
    tokens[i] = NULL;
  }

  printf("Splitting string %s\ into tokens:\n",mytest); 
  char *pch = strtok(mytest," "); 
  int found = 0;
  // the maxtokens - 1 will ensure that at least one pointer is null 
  // in the array
  while(pch != NULL && found < maxtokens - 1) 
  { 
    printf("%s\n",pch); 
    tokens[found++] = strdup(pch); // allocate and copy token
    pch = strtok(NULL," "); 
  } 
  return tokens; 
}

now you get an array with the tokens

char arg[] = "this is a test";
char** tokens = makeargv(arg);
int i = 0;
for (i = 0; tokens[i] != NULL; ++i)
  puts( tokens[i] );

don't forget to free the memory later

for (i = 0; tokens[i] != NULL; ++i)
  free( tokens[i] );

free( tokens );

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM