Проблемы с чтением из файла. Создается преждевременное достижение EOF - PullRequest
0 голосов
/ 20 ноября 2010

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

Я могу прочитать всю информацию вплоть до последнего предложения, а затем у меня ошибка.Есть мысли?

/**
 *  Programmer: fryeguy
 *  Course: 
 *  Program: TxtCrawl for MicroSearch
 *
 *  Algorithm:
 *  TxtCrawl is the component of MicroSearch that reads text
 *  documents for search terms and stores them for
 *  indexing
 *
 *  1. Count words in doc, then initialize
 *     wordsFromDoc array to wordCount
 *  2. Initiate output file for writing.
 *  3. Open input file for reading words.
 *  4. Until reaching EOF:
 *     4.a. Set value for start "get pointer" in startSentence (.tellg()).
 *     4.b. Store value for end "get pointer" in endSentence (.tellg()).
 *     4.c. Reset "get pointer" to startSentence location.
 *     4.d. Until reaching endSentence, Read into the
 *          array theWord, wordPos, startSent, and endSent
 *  5. Write wordsFromDoc array to file
 *  6. When EOF is reached close the files.
 */

#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>   

using namespace std;

struct wordProps        // stores word info to be placed in array
{
    string  theWord;    // stores the word
    int     wordPos;    // stores the position of word
    int     startSent;  // stores the start point of the sentence
    int     endSent;    // stores the end point of the sentence
};

void countWords(string, int&, int&);

int main()
{

    ifstream iFile; // file stream for reading in data
    ofstream oFile; // file stream for writing data

    string  iFileName = "TextFile2.txt";    // name of test file to read from
    string  oFileName = "OutputFile.txt";   // name of test file to write to
    string  aLine = "";                     // stores a line preceeding a newline character (\n)
    string  aWord = "";                     // stores words from doc for indexing
    int     charCount = 0;                  // count of characters in doc
    int     wordCount = 0;                  // count of words in doc
    int     aLineWordCount = 0;             // count of words in a single line being processed
    int     wordBegin = 0;                  // stores location of word in doc
    int     startSentence = 0;              // stores pointer value for start of sentence
    int     endSentence = 0;                // stores pointer value for end of sentence

    /**
     * 1. Count words in doc, then initialize
     *    wordsFromDoc array to wordCount
     */
    countWords(iFileName, charCount, wordCount);
    cout << "charCount: " << charCount << endl; // DEBUG CODE
    cout << "wordCount: " << wordCount << endl; // DEBUG CODE
    wordProps wordsFromDoc[wordCount];
    cout<< "length of array: " << (sizeof(wordsFromDoc) / sizeof(*wordsFromDoc)) << endl;  // DEBUG CODE

    /**
     * 2. Initiate output file for writing
     */
    oFile.open (oFileName.c_str()); // setup output file and write header
    oFile << setw(20) << left << "File Name: " << iFileName << endl;
    oFile << setw(20) << "---------------------------------------" << endl << endl;

    /**
     * 3. Open input file for reading words
     */
    iFile.open (iFileName.c_str());
    if (!iFile.is_open())
        cout << "No such file exists!" << endl;
    else
    {
        /**
         * 4. Until reaching EOF:
         */
        // I have been attempting different counting methods assuming the eof was being reached prematurely
        // The results really have not varied with this code
        // while (iFile.tellg() != charCount) 
        while (!iFile.eof())
        {
            //cout << "count: " << count << endl;
            /**
             * 4.a. Set value for start "get pointer" in startSentence (.tellg()).
             */
            startSentence = iFile.tellg();
            cout << "startSentence: " << startSentence << endl; // DEBUG CODE

            /**
             * 4.b. Store value for end "get pointer" in endSentence (.tellg()).
             */
            getline(iFile, aLine, '.');
            cout << aLine << endl; // DEBUG CODE
            endSentence = iFile.tellg();
            aLine.clear();
            cout << "endSentence: " << endSentence << endl; // DEBUG CODE

            if (!iFile.is_open())
            {
                cout << "The if, iFile.tellg(): " << iFile.tellg() << endl; // DEBUG CODE
                iFile.close();
                iFile.open (iFileName.c_str());
            }

            /**
             * 4.c. Reset "get pointer" to startSentence location.
             */
            iFile.seekg(startSentence);
            cout << "iFile.tellg(): " << iFile.tellg() << endl; // DEBUG CODE

            /**
             * 4.d. Until reaching endSentence, Read into the
             *      array theWord, wordPos, startSent, and endSent
             */

             // As the last line is about to be read there is an error of some sort.
             // My guess is that somehow I exceed the end of the file but my startSentence
             // and endSentence variables are pointing where I think they should.

            for ( ; iFile.tellg() < endSentence; aLineWordCount++)
            {
                wordsFromDoc[aLineWordCount].wordPos = iFile.tellg();
                cout << "wordPos: " << wordsFromDoc[aLineWordCount].wordPos << endl; // DEBUG CODE
                iFile >> wordsFromDoc[aLineWordCount].theWord;
                cout << "theWord: " << wordsFromDoc[aLineWordCount].theWord << endl; // DEBUG CODE
                wordsFromDoc[aLineWordCount].startSent = startSentence;
                cout << "startSent: " << wordsFromDoc[aLineWordCount].startSent << endl; // DEBUG CODE
                wordsFromDoc[aLineWordCount].endSent = endSentence;
                cout << "endSent: " << wordsFromDoc[aLineWordCount].endSent << endl << endl; // DEBUG CODE
                cout << "aLineWordCount: " << aLineWordCount << endl;
            } // end for

        } // end while !=iFile.eof

            // THIS section of code is never reached because of the hang up above.
            /**
             * 5. Write wordsFromDoc array to file
             */
            for (int count = 0; count < aLineWordCount; count++)
            {
                oFile << setw(20) << left
                << wordsFromDoc[count].theWord << " "
                << wordsFromDoc[count].wordPos << " "
                << wordsFromDoc[count].startSent << " "
                << wordsFromDoc[count].endSent << endl;
            }

    } // end else

    /**
     * 6. When EOF is reached close the files.
     */
    iFile.close();
    oFile.close();

// DEBUG CDODE for verifying results
//  for (int count = 0; count < wordCount; count++) {
//      cout << "theWord: " << wordsFromDoc[count].theWord << endl;
//      cout << "wordPos: " << wordsFromDoc[count].wordPos << endl;
//      cout << "startSent: " << wordsFromDoc[count].startSent << endl;
//      cout << "endSent: " << wordsFromDoc[count].endSent << endl << endl;
//  }

}

/**
 * Implement countWords function
 */
void countWords(string theFileName, int &charCount, int &wordCount)
{
    string  theWord = "";
    char    theChar = ' ';
    fstream inFile;

    //count the chars
    inFile.open (theFileName.c_str());
    if (!inFile.is_open())
        cout << "No such file exists!" << endl;
    else
    {
        inFile.get(theChar);
        while (!inFile.eof())
        {
            charCount++;
            inFile.get(theChar);
        }
    }
    inFile.close();

    // count the words
    inFile.open (theFileName.c_str());
    if (!inFile.is_open())
        cout << "No such file exists!" << endl;
    else
    {
        while (!inFile.eof())
        {
            inFile >> theWord;
            wordCount++;
        }
    }
    inFile.close();
}

1 Ответ

1 голос
/ 21 ноября 2010

Istream

Я проверил. Istream не имеет воплощения get или getline обработка нескольких разделителей одновременно 1 .

У других была такая же проблема 2 . Char-by-char IO был самым практическое решение. Другие решения включали кодирование улучшенных версий текущих методов Istream.

Идея

  1. Читайте полный файл сразу в память.
  2. Удалить переводы строк (любые CR или LF).
  3. Разделить документ на строки, оканчивающиеся на каждом из специальных полная остановка разделителей путем размещения непротиворечивого маркера (LF или ETX '\ 003') после каждого из этих разделителей при записи документа обратно на диск.
  4. Теперь документ можно обрабатывать как обычно; но используя вместо этого известный маркер периода в качестве разделителя.
  5. Удалить временный файл, содержащий документ с разделителями.

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

ПРИМЕЧАНИЯ

1 Istream :: get
2 Несколько разделителей с getline (обсуждение в Code Guru)

...