#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); } }