Проблемы с указателями - PullRequest
0 голосов
/ 19 апреля 2009

Кто-нибудь знает, как хранить указатели в многомерном массиве? Я думаю, что это может быть проблема, которую я имею в основном:

// 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_;
}

Моя цель - прочитать все слова из файла в моем g_wordArray[wrdCount]->SomeFunction(), не будучи зависимым от цикла чтения файла.

Что я пытался сделать:

  • В файле реализации в разделе getFirstLetterLower: каждый раз добавлять закрытый член char *_ptr в новую переменную. как someCharVar[0] = firstWord, someCharVar[1] = secondWord ...

  • Чтение содержимого файла в одну переменную. Перебирая все это в каждом конкретном случае, что мне нужно.

Мне нравится эта идея, но я не понял, как это сделать. Есть предложения?

Ответы [ 6 ]

1 голос
/ 19 апреля 2009

Ваша индексация в ваших массивах всегда неверна:

g_wordArray[wrdCount]->GetFirstLetterLower();

Здесь «wrdCount» - это количество элементов в «g_wordArray», поэтому результирующий «g_wordArray [wrdCount]» обращается к элементу один за концом массива.

Помните, что массивы C / C ++ индексируются с 0 и, следовательно, имеют допустимые элементы 0 -> (wrdCount -1)

1 голос
/ 19 апреля 2009

Это распространенный анти-шаблон для чтения файла.
Обратите внимание, что wrdCount всегда будет единичным, так как вы обнаруживаете конец файла (EOF), находясь внутри цикла при чтении слова в tmpArray.

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

Используйте это вместо:

/*
 * 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];
}
1 голос
/ 19 апреля 2009

IIUC, вы пытаетесь прочитать файл и при желании удалить некоторые слова, которые начинаются с определенной буквы. Вот краткий пример, без даже элементарной обработки ошибок , о том, как вы можете добиться того же, используя STL и некоторые шаблоны:

#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;
}
1 голос
/ 19 апреля 2009

Пожалуйста, напишите минимальный код, который может воспроизвести вашу проблему. Это выглядит довольно туманно прямо сейчас. Я полагаю, есть много проблем с этим кодом

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

        }

Вы сильно теряете память здесь. Что происходит с ранее выделенным «g_wordArray»?

Кроме того, когда вы размещаете n элементов, вы не можете получить доступ к n-му индексу. Объем памяти занимает от 0 до (n-1).

g_wordArray[wrdCount]

Пожалуйста, проверьте код еще раз, попробуйте отладить, а затем отправьте минимальный код.

0 голосов
/ 19 апреля 2009

Вы теряете память повсюду.
Вы должны попробовать и использовать стандартные контейнеры STL для обработки вещей такого типа.

Word** g_wordArray;

Это, вероятно, будет лучше представлено:

std::vector<Word>  g_wordArray;

Тогда вместо того, чтобы выделять пространство для массива, вот так:

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

И последнее добавление новых элементов изменений заключается в следующем:

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();

Теперь ваш код больше не использует никаких неприятных новых операторов, и, следовательно, вы не потеряете память.

0 голосов
/ 19 апреля 2009

Какой именно у вас вопрос? Где вы получаете сообщение об ошибке?

Рассматривали ли вы вопрос об уменьшении main() и переводе работы в другие функции? Этот код очень трудно читать. Кроме того, цикл do ... while действительно плох в использовании, рассмотрите возможность переключения на цикл while. Вам понадобится какое-то логическое значение, но оно того стоит для удобства чтения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...