/* COM1100 Fall 2000, Professor Futrelle * Solution(s) for Lab 7 on reading files. * This is the concatenation of all six of the files I developed * on the way to solving the entire lab, ending with a file * that does solve the entire lab (minus writing to a file). * * Output is appended to the files to indicate what the printed * to the screen, sometimes just excerpts, when many files were * printed. * * One important point about my solution process for this Lab: * I copied the 150games.txt file and edited the copy down * to just two entries, totalling six lines. Here's all of that * file: #HFrom Computer Gaming World's November 1996 Anniversary Edition #Uhttp://www.cdaccess.com/html/pc/150best.htm #N1. #TSid Meier's Civilization #PMicroprose #D1993 #CWhile some games might be equally addictive, none have sustained quite the level of rich, satisfying gameplay quite like Sid Meier's magnum.... #E #N2. #TUltima IV #POrigin #D1984#E * This little file included the first two lines, one entry with a two line * comment and one with no comment. At another point I created an entry with * a one-line comment to make sure they were handled correctly. By searching * for the title string "Civil" I could pick only the first entry, and "Ultima" * selected the second. A search for "i" selected both, since both titles * contain the character 'i'. * * This technique is a very general one: When asked to solve a problem, * don't jump in and try to do it all or use all the final data. Solve pieces * of the problem using only a small portion of the data. It's very easy to * spot what's going on if the entire file you're analyzing is only six lines long! */ // **** File 7a.cpp **************************************************** /* Solution for COM1100 Fall 2000 Lab 7 * Searching a file and returning requested results. * by Professor Futrelle 22 November 2000. * This is the first of a series of simple, exploratory programs * leading up to the full solution. * File: 7a.cpp * THIS IS A CODE WARRIOR EXPT, FIRST TRY, 11/24/2000 * * THIS FILE READS IN EACH LINE OF THE GAMES FILE AND PRINTS IT */ // **************** CODE BEGINS HERE ********************** #include // for input and output #include #include using namespace std; // GLOBALS // (note the handling of a long strings here) string ANNOUNCEMENT_TEXT = "This program prints out every line of the games file, unchanged.\n"; const string GAMES_FILE_NAME = "150games.txt"; string currentLineString = ""; istream & getline( istream & in, string & str, char delim ); istream & getline( istream & in, string & str ); void main() { // print the announcement cout << ANNOUNCEMENT_TEXT; // read in all lines and print them out ifstream fin; fin.open("150games.txt"); // (for c_str() use, see textbook, pg. 402) // loop over all lines in input file, printing out each. while( getline(fin, currentLineString, '\n')) { cout << currentLineString << endl; } fin.close(); } // main() // definitions of the two getline() functions istream & getline( istream & in, string & str, char delim ) { char ch; str = ""; // empty string, will build one char at-a-time while( in.get( ch ) && ch != delim ) str += ch; return in; } istream & getline( istream & in, string & str ) { return getline( in, str, '\n' ); } /* Output is just the original file. */ // **** File 7b.cpp **************************************************** /* Solution for COM1100 Fall 2000 Lab 7 * Searching a file and returning requested results. * by Professor Futrelle 22 November 2000. * This is one of a series of simple, exploratory programs * leading up to the full solution. * File: 7b.cpp * * THIS FILE READS IN EACH LINE OF THE GAMES FILE * BUT PRINTS OUT ONLY THOSE STARTING WITH #N. */ // **************** CODE BEGINS HERE ********************** #include // for input and output #include #include using namespace std; // GLOBALS // (note the handling of a long strings here) string ANNOUNCEMENT_TEXT = "This program prints out only those lines that begin with the #N tag\n"; const string GAMES_FILE_NAME = "150games.txt"; string currentLineString = ""; istream & getline( istream & in, string & str, char delim ); istream & getline( istream & in, string & str ); void main() { // print the announcement cout << ANNOUNCEMENT_TEXT; // read in all lines and print them out ifstream fin; fin.open(GAMES_FILE_NAME.c_str()); // (for c_str() use, see textbook, pg. 402) // loop over all lines in input file, printing only those starting with #N. while( getline(fin, currentLineString)) { if( currentLineString.find("#N") == 0 ) // #N are first characters on the line { cout << currentLineString << endl; } } } // main() // definitions of the two getline() functions istream & getline( istream & in, string & str, char delim ) { char ch; str = ""; // empty string, will build one char at-a-time while( in.get( ch ) && ch != delim ) str += ch; return in; } istream & getline( istream & in, string & str ) { return getline( in, str, '\n' ); } /* Output looks like this: This program prints out only those lines that begin with the #N tag #N1. Sid Meier's #TCivilization #PMicroprose #D1993 #N2. #TUltima IV #POrigin #D1984#E #N3. #TMule #PEA #D1983#E .... */ // **** File 7c.cpp **************************************************** /* Soluti on for COM1100 Fall 2000 Lab 7 * Searching a file and returning requested results. * by Professor Futrelle 22 November 2000. * This is one of a series of simple, exploratory programs * leading up to the full solution. * File: 7c.cpp * * THIS FILE READS IN EACH LINE OF THE GAMES FILE * BUT PRINTS OUT ONLY THE TITLES OF THE GAMES. * USES FUNCTIONS TO DO SOME TASKS. */ // **************** CODE BEGINS HERE ********************** #include // for input and output #include #include using namespace std; // GLOBALS string ANNOUNCEMENT_TEXT = "This program prints out only game titles.\n\n"; const string GAMES_FILE_NAME = "150games.txt"; string currentLineString = ""; istream & getline( istream & in, string & str, char delim ); istream & getline( istream & in, string & str ); bool isTitleLine(string); string getTitle(string); void printTitle(string); void main() { // print the announcement cout << ANNOUNCEMENT_TEXT; ifstream fin; fin.open(GAMES_FILE_NAME.c_str()); // (for c_str() use, see textbook, pg. 402) // loop over all lines in input file, printing only the titles. while( getline(fin, currentLineString)) { if( isTitleLine(currentLineString) ) // #N are first characters on the line { printTitle(getTitle(currentLineString)); } } } // main() // definitions of the three functions bool isTitleLine(string s) { return s.find("#N") == 0; } // simple enough! string getTitle(string s) { int start, finish; int len = s.length(); string title; start = s.find("#T"); finish = s.find("#P"); // do error check if((start > 0) && (start < len) && (finish > 0) && (finish < len)) { title.assign(s, start + 2, finish - start - 2); return title;} else return ""; } void printTitle(string s) { cout << "Title: " << s << endl; } // definitions of the two getline() functions istream & getline( istream & in, string & str, char delim ) { char ch; str = ""; // empty string, will build one char at-a-time while( in.get( ch ) && ch != delim ) str += ch; return in; } istream & getline( istream & in, string & str ) { return getline( in, str, '\n' ); } /* Output is: This program prints out only game titles. Title: Civilization Title: Ultima IV Title: Mule .... */ // **** File 7d.cpp **************************************************** /* Solution for COM1100 Fall 2000 Lab 7 * Searching a file and returning requested results. * by Professor Futrelle 22 November 2000. * This is one of a series of simple, exploratory programs * leading up to the full solution. * File: 7d.cpp * * THIS FILE READS IN EACH LINE OF THE GAMES FILE * BUT PRINTS OUT ONLY THE TITLES OF THE GAMES * ANY PART OF WHICH MATCHES A USER-SUPPLIED STRING. */ // **************** CODE BEGINS HERE ********************** #include // for input and output #include #include using namespace std; // GLOBALS // Note how a multi-line string is done here, by a '\' before // hitting return when typing in the string. string ANNOUNCEMENT_TEXT = "Input a string. It will be\ searched for in the game titles\n:"; const string GAMES_FILE_NAME = "150games.txt"; string currentLineString = ""; istream & getline( istream & in, string & str, char delim ); istream & getline( istream & in, string & str ); string getUserQuery(); bool isTitleLine(string); string getTitle(string); void printTitle(string); void main() { // print the announcement cout << ANNOUNCEMENT_TEXT; // read in all lines and print them out ifstream fin; fin.open(GAMES_FILE_NAME.c_str()); // (for c_str() use, see textbook, pg. 402) string query = getUserQuery(); string title; int pos; int len; // loop over all lines in input file, printing only those matching titles. while( getline(fin, currentLineString)) { if( isTitleLine(currentLineString) ) // #N are first characters on the line { title = getTitle(currentLineString); len = title.length(); pos = title.find(query); if((pos >= 0) && (pos < len)) { printTitle(title); } } } } // main() // definitions of the four functions string getUserQuery() { string inString; cin >> inString; return inString; } bool isTitleLine(string s) { return s.find("#N") == 0; } // simple enough! string getTitle(string s) { int start, finish; int len = s.length(); string title; start = s.find("#T"); finish = s.find("#P"); // do error check if((start > 0) && (start < len) && (finish > 0) && (finish < len)) { title.assign(s, start + 2, finish - start - 2); return title;} else return ""; } void printTitle(string s) { cout << "Title: " << s << endl; } // definitions of the two getline() functions istream & getline( istream & in, string & str, char delim ) { char ch; str = ""; // empty string, will build one char at-a-time while( in.get( ch ) && ch != delim ) str += ch; return in; } istream & getline( istream & in, string & str ) { return getline( in, str, '\n' ); } /* Input of "Star" and output is: Input a string. It will besearched for in the game titles :Star Title: Star Control 2 Title: Reach for the Stars Title: Starflight Title: Star Trek: Judgement Rites Title: Star Control Title: StarFleet I */ // **** File 7e.cpp **************************************************** /* Solution for COM1100 Fall 2000 Lab 7 * Searching a file and returning requested results. * by Professor Futrelle 22 November 2000. * This is one of a series of simple, exploratory programs * leading up to the full solution. * File: 7e.cpp * * THIS FILE READS IN EACH LINE OF THE GAMES FILE * AND PRINTS THE USER-SELECTED FIELD FOR EVERY ENTRY, * NOT FOR SELECTED ENTRIES, BUT EVERY ONE. * 'T'SELECTS TITLE, 'P' SELECTS PUBLISHER AND 'D' SELECTS DATE. */ // **************** CODE BEGINS HERE ********************** #include // for input and output #include #include using namespace std; // GLOBALS string ANNOUNCEMENT_TEXT = "Input 'T' to see titles, 'P' to see publishers \ and 'D' to see dates.\n:"; const string GAMES_FILE_NAME = "150games.txt"; const string TITLE_LABEL = "Title: "; const string PUB_LABEL = "Publisher: "; const string DATE_LABEL = "Date: "; string currentLineString = ""; int len; // length of currentLineString istream & getline( istream & in, string & str, char delim ); istream & getline( istream & in, string & str ); string getUserQuery(); bool isInfoLine(); bool checkStringFind(int, int, int); string getTitle(); string getPub(); string getDate(); void printInfo(string, string); void main() { // print the announcement cout << ANNOUNCEMENT_TEXT; // read in all lines and print them out ifstream fin; fin.open(GAMES_FILE_NAME.c_str()); // (for c_str() use, see textbook, pg. 402) string query = getUserQuery(); // loop over all lines in input file, printing requested field of every game. while( getline(fin, currentLineString)) { len = currentLineString.length(); if( isInfoLine() ) // "#N" are first characters on the line { switch (query[0]) // first character only { case 'T': printInfo(TITLE_LABEL, getTitle()); break; case 'P': printInfo(PUB_LABEL, getPub()); break; case 'D': printInfo(DATE_LABEL, getDate()); break; } } } } // main() // definitions of functions string getUserQuery() { string inString; cin >> inString; return inString; } // is "#N" at the beginning of the line? bool isInfoLine() { return currentLineString.find("#N") == 0; } // simple enough! bool checkStringFind(int start, int finish, int len) {return (start > 0) && (start < len) && (finish > 0) && (finish < len); } string getTitle() { int start, finish; string valueString; start = currentLineString.find("#T"); finish = currentLineString.find("#P"); // do error check if(checkStringFind(start, finish, len)) { valueString.assign(currentLineString, start + 2, finish - start - 2); return valueString;} else return ""; } string getPub() { int start, finish; string valueString; start = currentLineString.find("#P"); finish = currentLineString.find("#D"); // do error check if(checkStringFind(start, finish, len)) { valueString.assign(currentLineString, start + 2, finish - start - 2); return valueString;} else return ""; } string getDate() { int start; string valueString; start = currentLineString.find("#D"); // only need to look for preceding tag // do error check if(checkStringFind(start, start, len)) // only check the start position { valueString.assign(currentLineString, start + 2, 4); // all dates 4 digits long return valueString;} else return ""; } void printInfo(string label, string value) { cout << label << value << endl; } // definitions of the two getline() functions istream & getline( istream & in, string & str, char delim ) { char ch; str = ""; // empty string, will build one char at-a-time while( in.get( ch ) && ch != delim ) str += ch; return in; } istream & getline( istream & in, string & str ) { return getline( in, str, '\n' ); } /* Input of 'P' and output is: Input 'T' to see titles, 'P' to see publishers and 'D' to see dates. :P Publisher: Microprose Publisher: Origin Publisher: EA Publisher: Sierra .... */ // **** File 7f.cpp **************************************************** /* Solution for COM1100 Fall 2000 Lab 7 * Searching a file and returning requested results. * by Professor Futrelle 22 November 2000. * This is one of a series of simple, exploratory programs * leading up to the full solution. * File: 7f.cpp * * THIS FILE READS IN EACH LINE OF THE GAMES FILE * AND PRINTS ONLY THE COMMENT TEXT. * * THIS IS THE MESSIEST PART OF THE DESIGN, SINCE * COMMENT LINES BETWEEN #C AND #E MUST BE PRINTED, * AND THE TWO TAGS MAY EVEN BE ON THE SAME LINE. */ // **************** CODE BEGINS HERE ********************** #include // for input and output #include #include using namespace std; // GLOBALS string ANNOUNCEMENT_TEXT = "HERE ARE THE COMMENTS FOR EVERY GAME:\n"; const string GAMES_FILE_NAME = "150games.txt"; string currentLineString = ""; int len; // length of currentLineString istream & getline( istream & in, string & str, char delim ); istream & getline( istream & in, string & str ); bool isCommentStart(); bool isCommentEnd(); // may be same line as comment start bool commentInProgress = false; // true only when dealing with comment lines bool checkStringFind(int, int, int); void stripTag(string); void main() { // print the announcement cout << ANNOUNCEMENT_TEXT; ifstream fin; fin.open(GAMES_FILE_NAME.c_str()); // (for c_str() use, see textbook, pg. 402) // loop over all lines in input file, printing all comment lines. while( getline(fin, currentLineString)) { len = currentLineString.length(); if(isCommentStart()) // check for #C { cout << "COMMENTS ARE:\n"; commentInProgress = true; } if(commentInProgress) // for other lines in comment check, strip tags and print { commentInProgress = !isCommentEnd(); // check for #E and turn off flag if found stripTag("#C"); stripTag("#E"); cout << currentLineString << endl; } } } // main() // is "#C" at the beginning of the line? bool isCommentStart() {if(currentLineString.find("#C") == 0) return true; // signal beginning else return false; } // is '#E' in this line while we're in the comment line group? // -- a bit tricky bool isCommentEnd() { int pos = currentLineString.find("#E"); if(commentInProgress && (pos >= 0) && (pos < len)) return true; // signal end else return false; } // if tag is found erase it void stripTag(string tag) { int pos = currentLineString.find(tag); if ((pos >= 0) && (pos < len)) { currentLineString.erase(pos, 2); } } // definitions of the two getline() functions istream & getline( istream & in, string & str, char delim ) { char ch; str = ""; // empty string, will build one char at-a-time while( in.get( ch ) && ch != delim ) str += ch; return in; } istream & getline( istream & in, string & str ) { return getline( in, str, '\n' ); } /* Here are some of the comments printed out: COMMENTS ARE: In an industry dominated by Doom-clones, this shows that the view action game has a lot of very visceral appeal left. COMMENTS ARE: Sid's fascination with railroading begat a combination of SimCity, 1830 and the ultimate model railroad that will be a strategy game icon for years to come. */ // **** File 7.cpp **************************************************** /* Solution for COM1100 Fall 2000 Lab 7 * Searching a file and returning requested results. * by Professor Futrelle 24 November 2000. * This is one of a series of simple, exploratory programs * leading up to the full solution. * File: 7.cpp * * Works, as of 11/25/00, no print to file yet. * * THIS FILE ATTEMPTS TO PUT TOGETHER THE MAJOR PORTIONS * OF FILES 7a-7f TO SOLVE THE LAB 7 ASSIGNMENT. * BLOCKS OF LINES FROM THOSE FILES WERE PASTED INTO THIS * ONE TO GET THE VARIOUS FUNCTIONALITIES NEEDED. */ // **************** CODE BEGINS HERE ********************** #include // for input and output #include #include using namespace std; // GLOBALS string ANNOUNCEMENT_TEXT = "This program prints selected information from a file about 150 \ different computer games.\n\ You will be asked to enter one of the following:\n\ a T followed by some text that might be found in a game title, or\n\ a P followed by some text that might be in the name of a game publisher, or\n\ a D followed by date.\n\ You will be prompted to enter only one of the above items for each run of the program.\n\ Examples are:\n\ T Master\n\ D 1992\n\ P Activision\n\ \n\ Entering any input other than the three letters above \ will cause this text to be repeated.\nYou query: "; const string GAMES_FILE_NAME = "150games.txt"; const string OUT_FILE_NAME = "games-out.txt"; const string TITLE_LABEL = "Title: "; const string PUB_LABEL = "Publisher: "; const string DATE_LABEL = "Date: "; string currentLineString = ""; int len; // length of currentLineString istream & getline( istream & in, string & str, char delim ); istream & getline( istream & in, string & str ); string getUserQuery(); bool isInfoLine(); string getTitle(); string getPub(); string getDate(); bool checkItem(string, string); void printInfo(string, string, string); void handleCase(char, string, string, bool&); bool isCommentStart(); bool isCommentEnd(); // may be same line as comment start bool commentInProgress = false; bool checkStringFind(int, int, int); void stripTag(string); void main() { // print the announcement cout << ANNOUNCEMENT_TEXT; string query; char queryChar; bool goodQuery = false; do { query = getUserQuery(); queryChar = query[0]; if(((queryChar == 'T') || (queryChar == 'P') ||(queryChar == 'D')) && (query.length() > 2)) { goodQuery = true; cout << "Looking ..........\n"; } else cout << ANNOUNCEMENT_TEXT; } while(!goodQuery); // open the file for input ifstream fin; fin.open(GAMES_FILE_NAME.c_str()); // (for c_str() use, see textbook, pg. 402) query.erase(0,2); // toss tag and blank bool OK_Item = false; // loop over all lines in input file, requested material. while( getline(fin, currentLineString)) { string item; len = currentLineString.length(); if(isInfoLine()) { handleCase(queryChar, query, item, OK_Item); } // if OK_Item, print all fields from title line, but only once per item. if(isInfoLine() && OK_Item) { cout << endl; printInfo(TITLE_LABEL, getTitle(), " -- "); printInfo(PUB_LABEL, getPub(), " -- "); printInfo(DATE_LABEL, getDate(), "\n"); } if(OK_Item) { if(isCommentStart()) // check for #C { cout << "Comments: "; commentInProgress = true; } if(commentInProgress) // for other lines in comment check, strip tags and print { commentInProgress = !isCommentEnd(); // check for #E and turn off flag if found stripTag("#C"); stripTag("#E"); cout << currentLineString << endl; } } } cout << "\n....DONE\n"; int pause; cin >> pause; } // main() string getUserQuery() { string inString; getline(cin, inString); return inString; } // is "#N" at the beginning of the line? bool isInfoLine() { return currentLineString.find("#N") == 0; } // simple enough! bool checkStringFind(int start, int finish, int len) { return (start > 0) && (start < len) && (finish > 0) && (finish < len); } void handleCase(char queryChar, string query, string item, bool &OK_Item) { switch (queryChar) { case 'T': item = getTitle(); if(checkItem(query, item)) OK_Item = true; else OK_Item = false; break; case 'P': item = getPub(); if(checkItem(query, item)) OK_Item = true; else OK_Item = false; break; case 'D': item = getDate(); if(checkItem(query, item)) OK_Item = true; else OK_Item = false; break; default: OK_Item = false; // title line without a match. } } // handleCase() string getTitle() { int start, finish; string valueString; start = currentLineString.find("#T"); finish = currentLineString.find("#P"); // do error check if(checkStringFind(start, finish, len)) { valueString.assign(currentLineString, start + 2, finish - start - 2); return valueString;} else return ""; } string getPub() { int start, finish; string valueString; start = currentLineString.find("#P"); finish = currentLineString.find("#D"); // do error check if(checkStringFind(start, finish, len)) { valueString.assign(currentLineString, start + 2, finish - start - 2); return valueString;} else return ""; } string getDate() { int start; string valueString; start = currentLineString.find("#D"); // only need to look for preceding tag // do error check if(checkStringFind(start, start, len)) // only check the start position { valueString.assign(currentLineString, start + 2, 4); // all dates 4 digits long return valueString;} else return ""; } bool checkItem(string query, string item) { int len = item.length(); int pos = item.find(query); return (pos >= 0) && (pos < len); } void printInfo(string label, string value, string terminator) { cout << label << value << terminator; } // is "#C" at the beginning of the line? bool isCommentStart() {if(currentLineString.find("#C") == 0) return true; // signal beginning else return false; } // is '#E' in this line while we're in the comment line group? bool isCommentEnd() { int pos = currentLineString.find("#E"); if(commentInProgress && (pos >= 0) && (pos < len)) return true; // signal end else return false; } // if tag is found erase it void stripTag(string tag) { int pos = currentLineString.find(tag); if ((pos >= 0) && (pos < len)) { currentLineString.erase(pos, 2); } } // definitions of the two getline() functions istream & getline( istream & in, string & str, char delim ) { char ch; str = ""; // empty string, will build one char at-a-time while( in.get( ch ) && ch != delim ) str += ch; return in; } istream & getline( istream & in, string & str ) { return getline( in, str, '\n' ); } /* Here is the entire output when the date 1982 is entered: This program prints selected information from a file about 150 different computer games. You will be asked to enter one of the following: a T followed by some text that might be found in a game title, or a P followed by some text that might be in the name of a game publisher, or a D followed by date. You will be prompted to enter only one of the above items for each run of the program. Examples are: T Master D 1992 P Activision Entering any input other than the three letters above will cause this text to be repeated. You query: D 1982 Looking .......... Title: Loom -- Publisher: LucasArts -- Date: 1982 Comments: Loom featured one of the most beautiful scores ever to grace an adventure game and a musical staff interface that was most original. Title: Deadline -- Publisher: Infocom -- Date: 1982 Comments: Deadline was a tough text adventure that placed you in the midst of an intricate police procedural and let you wander around a mansion. ....DONE */