views:

553

answers:

3

I am trying to work with an array of char pointers.
Let's say I dynamically declare such an array like so:

int numrows=100;  
char** array = new char*[numrows];  

And then I populate it by using getline to get strings from a file, converting the strings to char arrays, then setting a pointer in my array to point to said char array like so:

string entry;  
int i=0;
while (getline(file,entry)){  
  char* cstring = new char[entry.length()];  
  array[i]=strncpy(cstring,entry.c_str(),entry.length());  
  free(cstring);  
  i++;  
}

(this works, but is there a better way to do this?)
The problem is, I don't know how to grow the array once i becomes greater than numrows. I know how to do this for a single-dimensional array, but the two-dimensionality is throwing me off.

I'm thinking I should be able to grow it the way you would grow a single-dimension array, right?

if (i==numrows){  
  char** temp = new char*[numrows+numrows];  
  for (int j=0;j<i;j++){  
    char* cstring = new char[strlen(array[i])];  
    temp[i]=strncpy(cstrin,array[i],strlen(array[i]));  
    free(cstring);
  }
  delete [] array;
  array = temp;
}

So if the current array becomes full, make a second array that is twice the size of the current array and fill it with the contents of the current array. Then delete array and let array point to temp. I'm fine up to making temp the new array. I can get the contents of array into temp, but when I delete array and set array = temp, the contents of array aren't the contents of temp.

So my question is how can/should I be growing this dynamic array of char pointers?

+5  A: 

use std::vector - it is your friend

 std::vector<std::string> arr;
 while(getline(file, entry))
   {
       arr.push_back(entry);
  }

done

sort can be done using vector sort with custom compare

 bool less3(const std::string &s1, const std::string &s2)
 {
      return s1.compare(0, 3, s2, 0, 3) == 0;
 }

 std::sort(arr.begin(), arr.end(), less3);

I bet that less3 could be made more efficient but readability wins unless you really suffer

edit fixed as per nice comment from gman

pm100
@pm100 thanks, I wasn't aware of the substr() function until now. This will make things a lot easier. I have question about the error handling of substr, though.Lets say I have a string s="Hello"; it's length is 5.If I call s.substr(4,6) what would happen?
zebraman
@zebraman: It will clamp it. That is, you get "o". If index is `>= size()`, an `out_of_range` exception is thrown.
GMan
@pm100: Your comparison is less efficient than necessary. You're going to allocate room for 2 strings of size 3, copy the sub-strings into it, compare them, then delete the memory. Rather, use the `compare` function: `return s1.compare(0, 3, s2, 0, 3) == 0;`
GMan
@zeb - aha - exceptions, a whole new world awaits your discovery
pm100
@GMan how does the compare function handle indexes out of range?
zebraman
@zebra: The same way. If the start index (the 0's is the code above) is `>= size()`, it throws an exception. If the range (the 3's) is greater than `size()`, it gets clamped.
GMan
A: 

Apart from the remarks by Tyler McHenry, and the fact that you should use the STL, the problem is most likely that you are freeing each cstring after having copied it. Perhaps you intended to free the original string instead?

  for (int j=0;j<i;j++){  
    char* cstring = new char[strlen(array[i])];  
    temp[i]=strncpy(cstring,array[i],strlen(array[i]));  
    delete[] array[i];
  }

When you first populate the array, DO NOT call free() on the string. First of all, you should use delete[], but more importantly, you still want to access that string later, right?

Frederik Slijkerman
Indeed. This is for a class, and no STL is allowed.
zebraman
@zebraman I've tagged this with the "homework" tag. Please do so yourself in the future when posting problems from school. (What you posted is fine, though, since you showed what you had already tried)
Tyler McHenry
A: 

now i see you say that this is a class that does allow you to use STL. A class teaching c++ that forbids one of the major language features! - anyway passing along

You do not need to be copying the strings to resize the array , you just need to copy the pointers.

 if (i==numrows){  
   char** temp = new char*[numrows+numrows];  
   for (int j=0;j<i;j++){  
     temp[j]=array[j];
    }
    delete [] array;
    array = temp;
 }

i am sure there are still out by ones there - left as homework

pm100