ioExamp.cpp

URL: https://mirkwood.cs.edinboro.edu/~bennett/class/cmsc3100/spring2026/notes/files/code/ioExamp.cpp
 
#include <iostream>
#include <fstream>

using namespace std;

void PrintChar(char ch);

class StringReader {
   public:
       StringReader(string fileName){
          file.open(fileName);
          if (!file) {
             cout << "Could not open the file "<< endl;
             state = StateT::END_OF_FILE;
          }
       }

       ~StringReader() {
           file.close();
       }

       string GetWord() {
          theString = "";
          DoWordRead();
          return theString;
       }

       string Getline(size_t length) {
          theString = "";
          DoGetline(length);
          return theString;
       }
   
       bool AtEOF() {
          return state == StateT::END_OF_FILE;
       }

       char Get() {
          char ch;

          switch (state) {
              case StateT::EMPTY_BUFFER_START:
              case StateT::WS_SKIP:   // should not happen
              case StateT::WORD_READ:   // should not happen
              case StateT::LINE_READ:  // should not happen but
                   file.get(ch);
                   if (!file) {
                       state = StateT::END_OF_FILE;
                   }
                   break;

              case StateT::BUFFER_START:
                   ch = buffer;
                   state = StateT::EMPTY_BUFFER_START;
                   break;

              case StateT::END_OF_FILE:
                   break;
                   // throw an exception
          }
          return  ch;
       }

   private:

      void DoGetline(size_t length) {
         bool done = false;
         char ch;

         while (!done and theString.length() < length) {
             switch(state) {
                 case StateT::EMPTY_BUFFER_START :
                 case StateT::WS_SKIP : // can't be here.
                 case StateT::WORD_READ : // can't be here.
                     state = StateT::LINE_READ;
                     break;

                 case StateT::BUFFER_START :
                     if (buffer == '\n') {
                         state = StateT::EMPTY_BUFFER_START;
                         done = true;
                     } else {
                         theString += buffer;
                         state = StateT::LINE_READ;
                     }
                     break;

                 case StateT::LINE_READ:
                     file.get(ch);
                     if (!file) {
                         state = StateT::END_OF_FILE;
                         done =  true;
                     } else {
                         // getline stops at a \n and consumes it
                         if (ch == '\n') {
                            state = StateT::EMPTY_BUFFER_START;
                            done = true;
                         } else {
                            theString += ch;
                         }
                     }
                     break;

                 case StateT::END_OF_FILE :
                     done =  true;
                     break;
             }
         }
         if (theString.length() == length) {
             state = StateT::EMPTY_BUFFER_START;
         }
      }

      void DoWordRead () {
         bool done{false};
         char ch;

         while (!done) {
            switch (state) {
               case StateT::EMPTY_BUFFER_START:
                   file.get(ch);
                   if (file) {
                       if (isspace(ch)) {
                           state = StateT::WS_SKIP;
                       } else {
                           theString += ch;
                           state = StateT::WORD_READ;
                       }
                   } else {
                      state = StateT::END_OF_FILE;
                      done = true;
                   }
                   break; 

               case StateT::WS_SKIP:
                   file.get(ch);
                   if (file) {
                       if (!isspace(ch)) {
                          theString += ch;
                          state = StateT::WORD_READ;
                       }
                   } else {
                      state = StateT::END_OF_FILE;
                      done = true;
                   }
                   break;

               case StateT::WORD_READ:
                   file.get(ch);
                   if(file) {
                      if (isspace(ch)) {
                         buffer = ch; 
                         state = StateT::BUFFER_START;
                         done = true;
                      } else {
                         theString += ch;
                      }
                   } else {
                       state = StateT::END_OF_FILE;
                       done = true;
                   }
                   break;

               case StateT::LINE_READ:  // should not happen but
                   state = StateT::EMPTY_BUFFER_START;
                   break;

               case StateT::BUFFER_START:
                   if (isspace(buffer)) {
                       theString = "";
                       state = StateT::WS_SKIP;
                   } else {
                       theString = buffer;
                       state = StateT::WORD_READ;
                   }
                   break;

               case StateT::END_OF_FILE:
                  done = true;
                  break;
            }
         }
      }

      enum class StateT {EMPTY_BUFFER_START, WS_SKIP, WORD_READ, 
                         BUFFER_START, LINE_READ, END_OF_FILE};

      StateT state {StateT::EMPTY_BUFFER_START};
      char buffer;
      string theString;
      ifstream file;
};

void WordTest();
void CharTest();
void MixedTest();
void Getline1();
void Getline2();

int main()  {

    cout << "Word Test " << endl;
    WordTest();
    cout << endl << endl;
   
    cout << "Letter Test " << endl;
    CharTest();
    cout << endl << endl;

    cout << "Mixed Test" << endl; 
    MixedTest();
    cout << endl << endl;

    cout << "Getline Test" << endl; 
    Getline1();
    cout << endl << endl;

    cout << "Getline/Word Mixed Test" << endl; 
    Getline2();
    cout << endl << endl;

    return 0;
}

void WordTest() {
    StringReader sr{"data.txt"};

    string input;

    input = sr.GetWord();
    while (not sr.AtEOF()) {
         cout  << '"' << input << '"' << endl;
         input = sr.GetWord();
    }

    cout << endl;
}

void CharTest() {
    StringReader cr{"data.txt"};
    char ch;
    ch = cr.Get();
    while (not cr.AtEOF()){
        PrintChar(ch);
        ch = cr.Get();
    }
    cout << endl;
}


void MixedTest() {
    StringReader mx{"data.txt"};
    string input;
    char ch;

    input = mx.GetWord();
    ch = mx.Get();
    while(not mx.AtEOF()) {
       cout << "Got \"" <<  input << "\" and " ;
       PrintChar(ch);
       cout << endl;
       input = mx.GetWord();
       ch = mx.Get();
    }
    cout << endl;
}

void PrintChar(char ch){
        if (isspace(ch) or !isprint(ch)) {
           cout << hex <<" 0x" << static_cast<unsigned short>(ch) << " " << dec;
        } else {
           cout << ch;
        }
}

void Getline1() {
    StringReader mx{"data.txt"};
    string input;

    input = mx.Getline(10);
    while (not mx.AtEOF() ) {
       cout << '"' << input << '"' << endl;
       input = mx.Getline(10);
    }
  
}

void Getline2() {
    StringReader mx{"data.txt"};
    string input;
    string word;

    word = mx.GetWord();
    input = mx.Getline(10000);
    while (not mx.AtEOF() ) {
       cout <<'"' << word << "\" and \"" << input << '"' << endl;
       word = mx.GetWord();
       input = mx.Getline(10000);
    }
}