tags:

views:

218

answers:

6

Anyone know how to store pointers in a multi-dimensional array? I think that might be the problem that i am having in main:

// main.cpp
#ifdef  _DEBUG
#define _CRTDBG_MAP_ALLOC
#include <iostream>
#include <fstream>
#include <string>
#endif
#include "Word.h"
using namespace std;

const int WORD_SZ = 100;
Word** g_wordArray;
int g_arrSz;

static char filePath[ FILE_PATH_SZ ] = {};
void FreeWordArray();

int main( const int argc, const char **argv )
{
    int 
     wrdCount = 0;
    char 
     usrMenuOption     = 0,
     getFirstLetter   = 0,
     tmpArray[WORD_SZ] = {},
     *getWord = new char;
    string 
     str, 
     str2;
    ifstream 
     inFile, 
     inFile2;
    do 
    {
     cout << "Please make a selection: \n\
a) Read a text file\n\
b) Remove words starting with letter\n\
c) Print words to console\n\
d) Quit\n";
     cin  >> usrMenuOption;
     switch( usrMenuOption )
     {
     case'A':
     case'a':
      cout << "Enter a file name: ";
      cin.sync();
      cin  >> filePath;
      inFile.open( filePath );
      if ( !inFile ) return -1;
      inFile >> tmpArray; // prime the eof flag.
      while ( !inFile.eof() )
      { 
       inFile >> tmpArray;
       wrdCount++;
       g_wordArray = new Word *[wrdCount];

      }
     inFile.close();
     inFile2.open( filePath );
     while( !inFile2.eof()  )
     { 
      inFile2 >> tmpArray;
      // supplies the member functions with information from the file
      g_wordArray[wrdCount] = new Word( tmpArray );
      g_wordArray[wrdCount]->GetFirstLetterLower();
      g_wordArray[wrdCount]->GetWord();
     }
     cout << wrdCount << " Words read from the file " << endl;
     inFile2.close();
     break;
     case'B':
     case'b':
     // information not found returning null
       g_wordArray[wrdCount]->GetFirstLetterLower();
     break;
     case'C':
     case'c':
       g_wordArray[wrdCount]->GetWord();
     break;
     case'D':
     case'd':
     cout << "Quit Requested. " << endl;
     break;
     default:
     cout << '"' << usrMenuOption << '"' << " Not Defined! " << endl;
     }

    } while ( usrMenuOption != 'D' && usrMenuOption != 'd' );


#ifdef _DEBUG
    _CrtDumpMemoryLeaks();
#endif
    cin.ignore();
    return 0;
}

void FreeWordArray()
{
    delete[ ] g_wordArray;
    return;
}


// Word.cpp
#define _CRT_SECURE_NO_WARNINGS // disable warnings for strcpy
#define ARRY_SZ 100
#include <iostream>
#include <fstream>
#include "Word.h"
#include <vector>


using namespace std;

// No paramaters.
// Is this what im missing?
// I just threw it in because of an error.
Word::Word() 
{
}

Word::Word( const char* word )
{
    ptr_ = new char[ strlen( word ) + 1 ];
    strcpy( ptr_, word  ); 
    len_ = strlen( ptr_ );
}

Word::~Word()
{
    delete[ ] ptr_;
    ptr_ = NULL;
    len_ = NULL;
}

char Word::GetFirstLetterLower()
{
    char myChar = tolower( ptr_[0] );
    return myChar;

}

char* Word::GetWord()
{
    Word *objectOne = new Word;
    objectOne->ptr_ = ptr_;
    strcpy( objectOne->ptr_, ptr_ );
    return objectOne->ptr_;
}

My Goal is to have all the words read from the file in my g_wordArray[wrdCount]->SomeFunction() without being dependent in the file reading loop.

What i've been trying to do:

  • In the Implementation File, under the getFirstLetterLower: to add the char *_ptr private member to a new variable each time. like someCharVar[0] = firstWord, someCharVar[1] = secondWord...

  • Reading the contents of the file into a single varaible. Looping through that varaible in each case that i need.

I like that idea, but haven't figured out how to do it. Any suggestions?

A: 

What exactly is your question? Where are you getting an error?

Have you considered making main() shorter and putting your work in other functions? This code is very difficult to read. In addition, the do...while loop really is bad to use, consider switching to a while loop instead. You'll need some sort of boolean value, but it's worth it for readability.

rlbond
+1  A: 

Please post minimal code which can reproduce your problem. It looks quite hazy right now. I suppose there are a lot of problems with this code

        inFile >> tmpArray;     // prime the eof flag.
        while ( !inFile.eof() )
        {       
                inFile >> tmpArray;
                wrdCount++;
                g_wordArray = new Word *[wrdCount];

        }

You are leaking memory badly here. What happens to the previously allocated 'g_wordArray'?

Also, when you allocate 'n' elements, you cannot access 'nth' index. The memory footprint spans from 0 - (n-1).

g_wordArray[wrdCount]

Kindly re-check the code, try to debug and then post minimal code.

Abhay
+1  A: 

IIUC, you are trying to read in a file and optionally remove some words that start with a particular letter. Here's a short example, without even rudimentary error handling, on how you may achieve the same using STL and some templates:

#include <iterator>
#include <string>
#include <vector>
#include <algorithm>
#include <fstream>
#include <iostream>

struct starts_with {
    char mC;
    starts_with(char c) : mC(c) {}
    bool operator()(std::string const& s) { return s[ 0 ] == mC; }
};

// uses commandline parameters for input arguments
// usage:
//    ./test.exe "path/to/file" letter
// 
// (assumes the file to be read is the first such parameter
// the character to be checked for is the second parameter)
int main(int argc, char *argv[ ]) {
    using namespace std;
    vector<string> v;
    ifstream fStm(argv[ 1 ]);
    istream_iterator<string> b(fStm), e;

    remove_copy_if(b, e, back_inserter(v), starts_with(argv[ 2 ][ 0 ]));

    copy(v.begin(), v.end(), ostream_iterator<string>(cout, "\n"));

    return 0;
}
dirkgently
What about 'remove_copy_if'. I'm sure I've used that (for the first time) just this week. It has the same params as your copy_if.
quamrana
yeah, sure. Thanks, I just had this ready for some other purpose ;-)
dirkgently
+1  A: 

This is a common anti-pattern for reading a file.
Please note that wrdCount is always going to be one off as you detect the end of file (EOF) while inside the loop while reading the word into tmpArray.

inFile >> tmpArray;     // prime the eof flag.
while ( !inFile.eof() )
{       
    inFile >> tmpArray;
    wrdCount++;
    g_wordArray = new Word *[wrdCount];
}

Use this instead:

/*
 * The result of the >> operator is a reference to a stream.
 *
 * When a stream is used in a boolean context (like a while loop)
 * it has a cast method that automatically returns an object
 * of a type that can be used as a boolean.
 *
 * The value of the boolean will be true if the file is still valid
 * and false if something went wrong (like reading past the end of file).
 *
 * So the loop will NOT be entered when you read past the EOF but will
 * be entered for every valid word that is read from the file.
 */
while ( inFile >> tmpArray )
{       
    wrdCount++;
    g_wordArray = new Word *[wrdCount];
}
Martin York
+1  A: 

Your indexing into your arrays is always wrong:

g_wordArray[wrdCount]->GetFirstLetterLower();

Here 'wrdCount' is the number of elements in 'g_wordArray' so the resulting 'g_wordArray[wrdCount]' is accessing the element one beyond the end of the array.

Remember that C/C++ arrays are indexed from 0 and thus have valid elements 0 -> (wrdCount -1)

Martin York
A: 

You are leaking memory all over the place.
You should try and use the STL standard containers to handle this type of thing.

Word** g_wordArray;

This would probably be better represented by:

std::vector<Word>  g_wordArray;

Then rather than allocating space for the array like this:

g_wordArray = new Word *[wrdCount];
-----
g_wordArray.reserve(wrdCount);

And lastely adding new elements changes lie this:

g_wordArray[wrdCount] = new Word( tmpArray );
g_wordArray[wrdCount]->GetFirstLetterLower();
g_wordArray[wrdCount]->GetWord();

------

g_wordArray.push_back(Word( tmpArray ));
g_wordArray[wrdCount].GetFirstLetterLower();    // Note we use . not ->
g_wordArray[wrdCount].GetWord();

Now your code no longer uses any nasty new operators and thus you are not going to leak any memory.

Martin York