// ENGR 131, Monday 3:30 Recitation // HW #11 - Files and Strings // (Solution) #include #include #include #include //#include //#include using std::cout; using std::cin; using std::endl; using std::ifstream; using std::ofstream; using std::string; using std::getline; //using aer::GetInteger; string GetString(string prompt); void openfile(ifstream& in, string infilename); string FindReplace(ifstream& in, string search, bool replace); void DispStats(ifstream& in); int GetInteger(const string& prompt, int min, int max); bool Ask(const string& prompt); int main() { ifstream in; ofstream out; string infilename; int choice; string tofind; bool replace; string newfile; for(;;) // main program loop { cout << "\nWhat would you like to do?\n" << "1. Open a new file\n" << "2. Find every instance of a given word\n" << "3. Calculate the file's statistics (# words, etc.)\n" << "4. Quit\n"; choice = GetInteger("Enter choice", 1, 4); switch(choice) { case 1: infilename = GetString("What file would you like to open?"); openfile(in, infilename); break; case 2: if(!in.is_open()) { infilename = GetString("What file would you like to open?"); openfile(in, infilename); } tofind = GetString("What string would you like to search for?"); replace = Ask("Would you like to replace it with another string"); newfile = FindReplace(in, tofind, replace); in.ignore(1024); in.clear(); in.close(); out.open(infilename.c_str()); out << newfile; out.close(); openfile(in, infilename); break; case 3: if(!in.is_open()) { infilename = GetString("What file would you like to open?"); openfile(in, infilename); } DispStats(in); in.ignore(1024); in.clear(); in.close(); openfile(in, infilename); break; case 4: break; } if(choice == 4) break; } return 0; } void openfile(ifstream& in, string infilename) { for(;;) { in.open(infilename.c_str()); if(!in.is_open()) { cout << "\nThe file could not be opened. This could be because it:\n" << "- does not exist\n" << "- is in use by another application\n" << "- is in the incorrect directory (it must either be in this\n" << " directory, or include a full path)\n" << "Enter a new filename.\n\n"; infilename = GetString("What file would you like to open?"); } else break; } } string GetString(string prompt) { string input; for(;;) { cout << prompt << ": "; getline(cin, input); if(cin.fail()) cout << "\nThat was an invalid entry. Try again.\n"; else break; } cin.clear(); cin.ignore(1024,'\n'); return input; } int GetInteger(const string& prompt, int min, int max) { int num; for(;;) { cout << prompt << ": "; cin >> num; if(cin.fail() || num < min || num > max) { cout << "That was an invalid entry. Try again.\n"; cin.clear(); cin.ignore(1024,'\n'); } else break; } cin.clear(); cin.ignore(1024, '\n'); return num; } void DispStats(ifstream& in) //Displays the number of words, number of sentences, number of lines, and average sentence length { int words = 0, sentences = 0, lines = 0; //int period, space; char current = '\0', prev = '\0'; string line, complete = ""; // read in file, counting lines and adding each line to the entire string for(;;) { getline(in, line); if(in.fail()) break; lines++; //count words and sentences for(int i = 0; i < line.length(); i++) { current = line[i]; if(i != 0) prev = line[i-1]; if(isspace(current) && !isspace(prev) && prev != '.') words++; else if(current == '.') { sentences++; if(!isspace(prev)) words++; } } prev = '\n'; } cout << "\nStatistics calculated:" << "\nWords: " << words << "\nSentences: " << sentences << "\nLines: " << lines << endl; if(sentences > 0) cout << "Average sentence length: " << double(words)/double(sentences) << " words\n"; } string FindReplace(ifstream& in, string search, bool replace) { string line = ""; int i, begin; bool replacethis, changed = false, found = false; string file = ""; string replacewith = ""; if(replace) { string prompt = "What word would you like to replace " + search + " with?"; replacewith = GetString(prompt); } for(;;) { getline(in, line); if(in.fail()) break; begin = 0; for(;;) { if(line.find(search, begin) == string::npos) // find doesn't occur on this line break; found = true; begin = line.find(search, begin); cout << endl << line << endl; for(i = 0; i < begin; i++) cout << ' '; for(i = 0; i < search.size(); i++) cout << '^'; cout << endl; if(replace) { cout << "Would you like to replace this occurrence of "; replacethis = Ask(search); if(replacethis) { changed = true; line.replace(begin, search.size(), replacewith); cout << "The line is now:\n" << line << endl; begin += replacewith.size(); } else { begin += search.size(); } } else { begin += search.size(); } } file += line + '\n'; } cout << "\nDone searching file.\n"; if(!found) cout << "No instances of " << search << " found in this file\n"; return file; } bool Ask(const string& prompt) { char ans; for(;;) { cout << prompt << "? "; cin >> ans; if(cin.fail() || (toupper(ans) != 'Y' && toupper(ans) != 'N')) { cout << "That was an invalid response. Only enter 'Y' or 'N', please\n"; cin.clear(); cin.ignore(1024,'\n'); } else break; } cin.clear(); cin.ignore(1024,'\n'); return (toupper(ans) == 'Y'); }