Aaron Jones
Aaron Jones

Reputation: 1170

Weird Multidimensional Array Values After Exiting Loop

I'm currently working on a project where I am reading in all the lines in a text file and splitting up all the words by whitespaces.

The sample text file

var int testInt = 5
var int testIntTwo = 6

My get lines function works fine, and for each line I pass it to a function that splits the string up and stores each item in a multidimensional array.

//My two global variables
char *output[50][50];

//Variable to count how many variables have been declared
int variableCount = 0;

The function I use to divide the string up by its whitespaces.

void DeclareVariable(char *input)
{

   char delim[] = " ";

   //Get the first value between whitespace
   char *pch = strtok(input, delim);

   //Initalize the counter starting at zero
   int counter = 0;

   //Keep getting all values in between whitespaces
   while (pch != NULL)
   {
      //Get the next value between whitespaces
      pch = strtok(NULL, delim);

      //Add the value to the array
      //Don't need to add the first pch found outside of the 
      //while loop becuase we already know it begins with 'var'
      if (pch != NULL)
      {
         output[variableCount][counter] = pch;

         printf("Values: %s\n", output[variableCount][counter]);
      }

      //Increase the counter
      counter++;
   }
}

Since I have two lines, this function gets called two times, with the variable variableCount increasing by one before the next instance is called.

When I print the values, everything looks fine with the correct values stored in the right indexes of the array.

output[0][0] is int
output[0][1] is testInt
output[0][2] is =
output[0][3] is 5
output[1][0] is int
output[1][1] is testIntTwo
output[1][2] is =
output[1][3] is 6

However, once I try and print the same values outside of the function, I end up getting weird values that weren't in the same indexes as before.

If I print output[0][2] and output[1][2], I get the following values.

output[0][2] is wo
output[1][2] is =

I'm using the same values for the index both inside and outside of the function, but I can't seem to understand why it won't give me the correct values. I believe it might have something to do with the array pointer, but I'm not 100% sure.

Upvotes: 0

Views: 72

Answers (2)

caf
caf

Reputation: 239011

The values stored in the output array are pointers. This means that it stores references to existing strings, but doesn't actually store the strings themselves.

When you return from the DeclareVariable() function, it has stored into output some references into the string pointed to by the input argument it was passed. Presumably you have then re-used that string area to read the next line of input, which means those references are now referring to parts of the new line of input, not the old one.

To solve this you will need to create some space to actually store all of the strings after you have parsed them. One way to do this is to use malloc() to allocate some space at the point that you add the string to the output array:

  if (pch != NULL)
  {
     char *string_storage;

     string_storage = malloc(strlen(pch) + 1);

     if (string_storage != NULL)
     {
         strcpy(string_storage, pch);
     }
     else
     {
         /* Failed to allocate space to store the string - handle this
          * error condition here. */
     }
     output[variableCount][counter] = string_storage;

     printf("Values: %s\n", output[variableCount][counter]);
  }

With this change, the output array pointers are references to the various blocks of space allocated by malloc(), which contain the string copies that were made with strcpy().

(Note that if you are programming for a POSIX environment, the strdup() function exists to do that malloc-and-strcpy in one step).

Upvotes: 3

Paul Keister
Paul Keister

Reputation: 13077

strtok doesn't allocate memory, it operates on the buffer that you pass in, which in this case means the buffer that input points at. It's not clear how this buffer is managed from the code that you've posted, but based on the test results it is clear that the buffer memory is being overwritten and possibly the memory has been de-allocated.

There are two possible solutions: make sure the buffer you pass in as the input parameter is not de-allocated or overwritten for the lifetime of the process, or the lifetime of the output matrix values at least. Or, you could allocate memory for each string you identify, strncpy the tokens into each allocated buffer, and store pointers to the new buffers instead of the pointers into input. I would definitely consider the former option since it should be simpler, more efficient, and easier to implement correctly.

Upvotes: 2

Related Questions