Thread: Arrays of pointers...

  1. #46
    Programming Ninja In-T...
    Join Date
    May 2009
    Posts
    827
    Quote Originally Posted by tabstop View Post
    You're joking, right? I mean, surely you can see that there is literally no code between
    Code:
    object.anotherStr = NULL; //reset this pointer
    and (the next time through the for loop)
    Code:
    *object.anotherStr += object.str->at(i2);
    Yeh, I was joking.
    I saw it and I fixed it.
    And I got it working now, using vectors.

    Thanks everyone.

  2. #47
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Quote Originally Posted by Programmer_P View Post
    And of course, I think you mean "delete [] arrayOfPointers;" not "delete [] object.arrayOfPointers" since we're inside the member function destructor, and "object" is a "stringStruct" object created inside the "doStuff" function.
    Ah yes, a copy and paste error on my part. Forgot to give the "untested" disclaimer on that code.

    One more thing: Although you're noted that you don't need a resizeable array. You can see that you are having to perform two passes over the data instead. Once to count the newlines, and then once to get the pointer to the strings. If you use a vector, then you can do it all in one pass. For each newline you find, you can just push_back the string immediately.
    Efficiency wise there's probably not much difference, but if you can do it in less code then there's less room for bugs.

    Are you writing an interpreter or someting like that?
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  3. #48
    Programming Ninja In-T...
    Join Date
    May 2009
    Posts
    827
    Quote Originally Posted by iMalc View Post
    Ah yes, a copy and paste error on my part. Forgot to give the "untested" disclaimer on that code.

    One more thing: Although you're noted that you don't need a resizeable array. You can see that you are having to perform two passes over the data instead. Once to count the newlines, and then once to get the pointer to the strings. If you use a vector, then you can do it all in one pass. For each newline you find, you can just push_back the string immediately.
    Not sure if that's what you really meant, but I wasn't *counting* new-line characters. I was only using them as a separation character between individual strings contained in a single string. So I simply was looping through the string, and adding characters to anotherStr as long as the current character was not a newline character. This is done in a while loop inside a for loop. Once the while loop completes each iteration of the for loop, I was simply pointing at the string being pointed at by anotherStr with the current element pointer of the array of pointers. As for vector:ush_back(), I'm not sure exactly what you mean by that either. What that function does is appends to the end of the string, and performs the same function as the += operator of the string class, and I wasn't wanting to add the new-line characters to the anotherStr, before pointing at the resulting anotherStr with the current element of the array of pointers, because the result strings weren't supposed to contain any new-line characters.
    Efficiency wise there's probably not much difference, but if you can do it in less code then there's less room for bugs.

    Are you writing an interpreter or someting like that?
    Not exactly. I was originally writing a program for web coding in various languages, but then I had need of a function which could get the string names of an enum member, and I went looking for that, without finding anything for that. So I then decided to write my own program which could take a file containing an enum (or multiple enums) and output some kind of interface to file which would make retrieving enum value string names a piece of cake, regardless of what the enum is. That is when I decided I wanted a function which would return a const char* array of which each element is pointed at the relevant string of the enum value name, which resulted in this current thread.

    Anyway, I got the code to work using an array of pointers finally (even though I decided to go with vectors instead):
    Code:
    #include <iostream>
    #include <string>
    
    using namespace std;
    
    struct stringStruct {
        stringStruct() : arrayOfPointers(NULL) { initialize(); }
        void initialize();
        string* str;
        string* anotherStr;
        const char** arrayOfPointers;
    };
    
    void stringStruct::initialize() {
        str = NULL;
        anotherStr = NULL;
    }
    
    void doStuff();
    
    int main() {
      doStuff();
      cout<< "\nHaha, you got to press Enter."<<endl;
      cin.get();
      return 0;
    }
    
    void doStuff() {
      stringStruct object;
      object.str = new string;
      *object.str = "Yes, a string...\n";
      *object.str += "Yes, another string...\n";
      *object.str += "Yes, even another string...\n";
      int sizeOfStr = object.str->size();
      object.anotherStr = new string;
      int sizeOfArrayOfPointers = 3;
      object.arrayOfPointers = new const char*[sizeOfArrayOfPointers];
      int i2 = 0;
      for (int i = 0; i < sizeOfStr; i++) {
        if (object.anotherStr == NULL) {
            object.anotherStr = new string;
        }
    
        if (object.str->at(i2) == '\n') { //we're at a new-line character
            i2++; //increment so as to skip the new-line character to the next character, which wont be a new-line character
        }
    
        if (i == sizeOfArrayOfPointers - 1) { //we're at the last element of the array of pointers
            for (int num = i; num < sizeOfStr; num++) { //continue looping through object.str...
                if (object.str->at(i2) == '\n') { //we're at a new-line character
                    i2++; //increment so as to skip the new-line character to the next character, which wont be a new-line character
                }
    
                while (object.str->at(i2) != '\n') {
                    *object.anotherStr += object.str->at(i2);
                    i2++;
                }
                object.arrayOfPointers[num] = object.anotherStr->data();
                object.anotherStr = NULL;
                for (int i = 0; i < sizeOfArrayOfPointers; i++) {
                    cout<< object.arrayOfPointers[i] <<endl;
                }
                delete object.str;
                delete object.anotherStr;
                delete [] object.arrayOfPointers;
                return;
            }
        }
    
        while (object.str->at(i2) != '\n') { //iterate till the next new-line character
          *object.anotherStr += object.str->at(i2); //add characters to the "anotherStr"
          i2++;
        }
    
        object.arrayOfPointers[i] = object.anotherStr->data();
        object.anotherStr = NULL; //reset this pointer
      }
    
    }
    This works as expected, and outputs:
    Yes, a string...
    Yes, another string...
    Yes, even another string...

  4. #49
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Not sure if that's what you really meant, but I wasn't *counting* new-line characters.
    Yes you were. How else do you know how large to allocate arrayOfPointers?!
    I was only using them as a separation character between individual strings contained in a single string. So I simply was looping through the string, and adding characters to anotherStr as long as the current character was not a newline character. This is done in a while loop inside a for loop. Once the while loop completes each iteration of the for loop, I was simply pointing at the string being pointed at by anotherStr with the current element pointer of the array of pointers.
    I love how you are able to use the word "simply" in there. Using that word does not make it true.
    What's more, it probably isn't actually doing what you think it's doing. I know this both because your descriptions don't quite make sense and because you've still failed to realise why allocating those strings dynamically does not do anything good for that piece of code. If you understood how it really worked you'd realise this. I've already shown how that unnecessary complication can be avoided in a code example.
    As for vector::push_back(), I'm not sure exactly what you mean by that either.
    I mean exactly what anyone else who mentions it means. The mere mention of it to most C++ programmers should immediately put you both into a state of mutual understanding. You don't know about much of the most commonly used stuff in the standard C++ Library and that is most unfortunate for you as your job will be that much harder without it.
    What that function does is appends to the end of the string, and performs the same function as the += operator of the string class, and I wasn't wanting to add the new-line characters to the anotherStr, before pointing at the resulting anotherStr with the current element of the array of pointers, because the result strings weren't supposed to contain any new-line characters.
    It makes sense that your description would be as convoluted as your code is. They both come from the same thought process. You need to learn to think about the effect you are trying to achieve at a higher level.

    Well, what you've ended up with is far from pretty. It has memory leaks and usage of string::data() that is almost certainly going to mean trouble in your real code. Any attempt to return an array of const char *'s along the lines of what you've been doing is pretty much going to guarantee a memory leak or accessing deleted memory.
    Do you realise that you have a for-loop there that will never loop? In other words, it's equivalent to just an if-statement.

    Well it's all for your own benefit. Perhaps if you get stuck in and learn more about the language you'll come to look back on this code one day and realise how far you've come. If that happens - mission accomplished.
    Last edited by iMalc; 05-22-2010 at 10:01 PM.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  5. #50
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Quote Originally Posted by Programmer_P View Post
    This works as expected
    Only because you got lucky. Consider:

    Code:
        object.arrayOfPointers[i] = object.anotherStr->data();
        object.anotherStr = NULL; //reset this pointer
    Can you see a problem with this code? If not, I would highly recommend that you stick with the pre-made stl objects (std::string, std::vector, etc) until you've got a really firm grasp on how pointers work, their implications, etc.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  6. #51
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    It seems to me that this would be a good time for you to learn about the STL and the power, and responsibility, it brings. The STL is a truly a life saver and has so many benefits that it is almost criminal not to leverage it at some point.

    I highly recommend learning about the STL. The only book I know for the STL is Effective STL but I cannot really recommend it to you since you are quite new to the STL. That book is really geared towards those that have been using it but want ways to use it more effectively. You might be able to learn how to use the STL from it but that is not the goal of the book.

    Perhaps others here could recommend a beginner book for learning the STL.

  7. #52
    Programming Ninja In-T...
    Join Date
    May 2009
    Posts
    827
    Quote Originally Posted by iMalc View Post
    Yes you were. How else do you know how large to allocate arrayOfPointers?!
    I was originally iterating through object.str, and incrementing the sizeOfArrayOfPointers only if the current character of the string was not a new-line character. That's not counting new-lines...
    Then I realized that wasn't the size that I wanted for the array of pointers, because each pointer is supposed to point at an individual string. And there are three of those...
    Yes, a string...
    Yes, another string...
    Yes, even another string...
    So I rewrote the code to create the array of pointers with a size of 3, and that's how I have it now.
    I love how you are able to use the word "simply" in there. Using that word does not make it true.
    What's more, it probably isn't actually doing what you think it's doing. I know this both because your descriptions don't quite make sense and because you've still failed to realise why allocating those strings dynamically does not do anything good for that piece of code. If you understood how it really worked you'd realise this. I've already shown how that unnecessary complication can be avoided in a code example.I mean exactly what anyone else who mentions it means. The mere mention of it to most C++ programmers should immediately put you both into a state of mutual understanding. You don't know about much of the most commonly used stuff in the standard C++ Library and that is most unfortunate for you as your job will be that much harder without it.It makes sense that your description would be as convoluted as your code is. They both come from the same thought process. You need to learn to think about the effect you are trying to achieve at a higher level.
    I do understand how it works, and I also understand that I don't have to point object.anotherStr at a "new" allocation in memory each loop. The reason I did it that way is because my code in my real program also does it that way, and the reason for that is the anotherStr (named differently in my real program) is a member of a class, and I just prefer to do it that way. And, my class destructor takes care of deleting every "new" thing, so no memory leaks there.
    Well, what you've ended up with is far from pretty. It has memory leaks and usage of string::data() that is almost certainly going to mean trouble in your real code. Any attempt to return an array of const char *'s along the lines of what you've been doing is pretty much going to guarantee a memory leak or accessing deleted memory.
    Do you realise that you have a for-loop there that will never loop? In other words, it's equivalent to just an if-statement.
    No, it doesn't. I delete all the "new"s at the end of the doStuff() function. And what is wrong with my usage of string::data()? Each element of my array of pointers is being assigned the memory location of each anotherStr->data(), and I don't delete anything until I've outputted the strings contained at those memory locations.
    As for returning a const char* array in my real program, that also is not a problem, because I make sure to only delete with my class destructor.
    Well it's all for your own benefit. Perhaps if you get stuck in and learn more about the language you'll come to look back on this code one day and realise how far you've come. If that happens - mission accomplished.
    Yes, and I do appreciate that. And I do plan on learning more of the language. I have a few programming books that I've been planning to read. I am far from being an expert at programming, I know.
    Last edited by Programmer_P; 05-23-2010 at 07:58 PM.

  8. #53
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Programmer_P
    No, it doesn't. I delete all the "new"s at the end of the doStuff() function.
    You forgot to use a try/catch block to handle cases where an exception (e.g., std::bad_alloc) is thrown before those delete statements can be reached.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  9. #54
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Ya know in the time it has taken to build this code and the time that would be wasted for other developers to figure out what in the world you were trying to do you could have used the STL in several places and been done. As well your code would be much clearer to anyone later who was tasked with maintaining and/or integrating your code into a code line.

    Programming isn't just about what works.

  10. #55
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Not only does your inner for-loop never loop, but your outer one is looping up to the wrong constant.

    Here's another leak:
    Code:
    object.anotherStr = NULL; //reset this pointer
    You've just thrown away your only pointer to anotherStr. No way to free it now.

    I certainly see why you want to use pointers to strings. It's because you don't want their actual contents to be freed at all, since the app is broken and would cause accessing data after it was freed. Using data() at all is really pushing you into doing bad things. You should really be using .c_str() if you must avoid directly having an array of strings.

    There are two ways to write code. Such that:
    • there are no obvious bugs, or
    • there are obviously no bugs

    Many people mistakenly aim for the first one
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  11. #56
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    I must confess I am baffled by all this convoluted code to do such a simple task.

  12. #57
    Programming Ninja In-T...
    Join Date
    May 2009
    Posts
    827
    Quote Originally Posted by Bubba View Post
    Ya know in the time it has taken to build this code and the time that would be wasted for other developers to figure out what in the world you were trying to do you could have used the STL in several places and been done. As well your code would be much clearer to anyone later who was tasked with maintaining and/or integrating your code into a code line.

    Programming isn't just about what works.
    You're right. I understand this...
    More coding, less posting is what I'll do in the future. Perfect practice of programming will make an almost-perfect programmer. I got it.

    Btw, thanks everyone for the support. Hopefully soon once I get really good at programming, it'll be me who's the one providing support for other programmers, not the other way around, though I suppose I'll never know everything there is to know about programming, and will still occasionally need assistance and advice. That's what makes us human.

  13. #58
    Programming Ninja In-T...
    Join Date
    May 2009
    Posts
    827
    Quote Originally Posted by iMalc View Post
    Not only does your inner for-loop never loop, but your outer one is looping up to the wrong constant.
    Well, yes, I obviously noticed that when I first wrote the code (i.e. that the loop would only be entered once), just wasn't thinking as straight as I should have. Guess I should have used an if statement instead. As for the outer loop, I don't really see a problem with that, because once the if statement, and then the inner for loop, is entered, we then just move on from the current index of 'i', wherever 'i' is, and continue iterating through the rest of the string. And then inside the if statement, I delete the stuff I created on the heap, then return out of the function. What would your suggestion be in regards to this? Please post some example code.
    Here's another leak:
    Code:
    object.anotherStr = NULL; //reset this pointer
    You've just thrown away your only pointer to anotherStr. No way to free it now.
    You're right. I was thinking that by keeping a pointer to each string with an element of the array of pointers, I could then delete those new objects in memory by doing:

    Code:
    delete [] object.arrayOfPointers;
    But I see now where I made my error.
    I certainly see why you want to use pointers to strings. It's because you don't want their actual contents to be freed at all, since the app is broken and would cause accessing data after it was freed. Using data() at all is really pushing you into doing bad things. You should really be using .c_str() if you must avoid directly having an array of strings.

    There are two ways to write code. Such that:
    • there are no obvious bugs, or
    • there are obviously no bugs

    Many people mistakenly aim for the first one
    Yep, and I'll shoot for Way #2 next time around.
    Last edited by Programmer_P; 05-23-2010 at 08:15 PM.

  14. #59
    Programming Ninja In-T...
    Join Date
    May 2009
    Posts
    827
    Quote Originally Posted by Bubba View Post
    I must confess I am baffled by all this convoluted code to do such a simple task.
    The task I was trying to achieve was not just to output a few strings. The task was to test working with arrays of pointers, and to see if I could achieve the task of outputting the strings being pointed at by the elements of the array of pointers.

    Obviously, I understand now a lot more about arrays of pointers, and also about vectors, and about coding in generally. But fortunately, I managed to sort all of the bugs out eventually, thanks to all y'all's help.

  15. #60
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    More coding, less posting is what I'll do in the future.
    Actually more listening is what I was after. The reason we suggest to you option A or B is b/c we are trying to save you the pain that we have gone through once before trying to do a similar task.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Issue with arrays, pointers, and structs.
    By RexInTheCity in forum C Programming
    Replies: 5
    Last Post: 03-29-2010, 03:30 PM
  2. Pointers As 2D arrays
    By TieFighter in forum C Programming
    Replies: 29
    Last Post: 03-22-2010, 06:46 AM
  3. pointers to arrays
    By rakeshkool27 in forum C Programming
    Replies: 1
    Last Post: 01-24-2010, 07:28 AM
  4. Array of Pointers to Arrays
    By Biozero in forum C Programming
    Replies: 2
    Last Post: 04-19-2007, 02:31 PM
  5. Pointers and multi dimensional arrays
    By andrea72 in forum C++ Programming
    Replies: 5
    Last Post: 01-23-2007, 04:49 PM