# C: Array of pointers problem



## Regicide (Aug 8, 2003)

I am writing a program that takes in an input string and then tokenizes it through an array of pointers. Meaning, that the program puts a null character at the end of every word and a pointer points to the beginning of the word. The problem is that after the second time through the loop that does this, the first word becomes corrupt. Through debuging I have found that the line of code that somehow changes the first word is:

```
argv[curr_arg] = &input[c];
```
 input is a string of characters and argv is an array of pointers. I am sure that curr_arg is incrementing after every word and does not equal 0. I am really confused as to how the first element in the array is being altered by that line of code. If anyone has any ideas, it would be greatly appreciated.


----------



## IMM (Feb 1, 2002)

Just a question before I try and guess what you are doing.
I see you are using _argv[curr_arg]_
Is this stuff actually the program arguments ,or did you use argv again, or is the main() in this prototyped as
_int main(void)_ or something rather than
_int main(int argc, char* argv[])_?

Can you post it in context (more code)


----------



## Regicide (Aug 8, 2003)

Well, below is the code for the program. It is pretty self explanitory, but to answer your question: argv is not inside of the main() function. I used both the names argv and argc in the functions to tokenize the input. 

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

int main(int, char**);
int get_argc(char*);
int tonkenize(char*, char**, int);

int main(int argc, char **argv)
{
	int arg_count;
	char test_cmd[255] = "first second \"third with space\" fourth";
	char **kf_args;
	
	
	arg_count = get_argc(test_cmd);
	
	if(arg_count < 0)
		printf("Error while parsing input\n");
	else
		printf("Found %d arguments\n", arg_count);
	
	kf_args = malloc(arg_count * sizeof(char*));
	
	if(tokenize(&test_cmd, &kf_args, arg_count) < 0)
		printf("Error while tokenizing!\n");
	
	int c;
	for(c = 0; c < arg_count; c++)
		printf("%d: %s\n", c, kf_args[c]);
		
	printf("input: %s\n", test_cmd);
	
	free(kf_args);
	
	return 0;
}

int tokenize(char *input, char **argv, int argc)
{
	int curr_arg = 0, input_len = strlen(input), c;
	
	for(c = 0; c < input_len; c++)
	{
		/* Find beginning of argument */
		while((c < input_len) && isspace(input[c]))
			c++;
		
		
		if(input[c] == '\"') /* if beginning of quoted argument */
		{
			c++;
			
			/* Point element of array to the character after the quote */
			argv[curr_arg] = &input[c];
			
			while((c < input_len) && (input[c] != '\"'))
				c++;
			
			if(c == input_len)
				return -1;
			
			input[c] = '\0';
			
		}
		else
		{
			/* Point element of array to the character after the space */
			argv[curr_arg] = &input[c];
			
			/* if normal argument, find the end of it */
			while((c < input_len) && !isspace(input[c]))
				c++;
				
			input[c] = '\0';
			
		}
		
		curr_arg++;
	}
	
	return 0;
}

int get_argc(char *input)
{
	int argc = 0, input_len = strlen(input), c;
	
	for(c = 0; c < input_len; c++)
	{
		/* Find beginning of argument */
		while((c < input_len) && isspace(input[c]))
			c++;
		
		if(input[c] == '\"') /* if beginning of quoted argument */
		{
			c++;
			
			while((c < input_len) && (input[c] != '\"'))
				c++;
			
			if(c == input_len)
				return -1;
			
			c++;
		}
		else
		{
			/* if normal argument, find the end of it */
			while((c < input_len) && !isspace(input[c]))
				c++;
		}
		
		argc++;
	}
	
	return argc;
}
```


----------



## IMM (Feb 1, 2002)

Ignoring the fact that argv[0] will likely point at the program_path - is this where you are headed with it?
I tried not to modify it too much.

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

int get_argc(char*);
int tokenize(char*, char**, int);

int main(int argc, char **argv)
{
  int arg_count;
  char test_cmd[255] = "first second \"third with space\" fourth\0";
  char **kf_args;

  printf("Input: %s\n\n", test_cmd);  ///modified (moved to a point before the tokenizer adds string terminating \0's to it)
  arg_count = get_argc(test_cmd);

  if(arg_count < 0)
    printf("Error while parsing input\n");
  else
    printf("Found %d arguments\n", arg_count);

  kf_args = (char**)malloc(arg_count * sizeof(char*));    ///modified

  if(tokenize((char*)&test_cmd, kf_args, arg_count) < 0)  ///modified
    printf("Error while tokenizing!\n");

  int c;
  for(c = 0; c < arg_count; c++)
    printf("%d: %s\n", c, kf_args[c]);

  free(kf_args);

  return 0;
}


int tokenize(char *input, char **argv, int argc)
{
  int curr_arg = 0, input_len = strlen(input), c;

  for(c = 0; c < input_len; c++)
  {
    /* Find beginning of argument */
    while((c < input_len) && isspace(input[c]))
      c++;

    if(input[c] == '\"') /* if beginning of quoted argument */
    {
      c++;

      /* Point element of array to the character after the quote */
      argv[curr_arg] = &input[c];

      while((c < input_len) && (input[c] != '\"'))
        c++;

      if(c == input_len)
        return -1;
      input[c] = '\0';
    }
    else
    {
      /* Point element of array to the character after the space */
      argv[curr_arg] = &input[c];

      /* if normal argument, find the end of it */
      while((c < input_len) && !isspace(input[c]))
        c++;
      input[c] = '\0';
    }
    curr_arg++;
  }
  return 0;
}

int get_argc(char *input)
{
  int argc = 0, input_len = strlen(input), c;

  for(c = 0; c < input_len; c++)
  {
    /* Find beginning of argument */
    while((c < input_len) && isspace(input[c]))
      c++;

    if(input[c] == '\"') /* if beginning of quoted argument */
    {
      c++;

      while((c < input_len) && (input[c] != '\"'))
        c++;

      if(c == input_len)
        return -1;

      c++;
    }
    else
    {
      /* if normal argument, find the end of it */
      while((c < input_len) && !isspace(input[c]))
        c++;
    }
    argc++;
  }
  return argc;
}
```


----------



## Regicide (Aug 8, 2003)

Wow, thank you so much! Works perfectly!


----------



## IMM (Feb 1, 2002)

One further note. I left the ampersand in this line
_if(tokenize((char*)&test_cmd, kf_args, arg_count) < 0)_
but one would normally write
_if(tokenize(test_cmd, kf_args, arg_count) < 0)_
The (char*) cast in the first one is because char* != char (*)[255] (as types) when you use the 'address of' form as you did.

It doesn't matter to the compiler which way you do it, as the value of _test_cmd_ is the same as _&test_cmd_
(it does look a little odd  )

You could also have written the array as
char test_cmd[] = "first second \"third with space\" fourth\0";
to save a little space.


----------

