// // Program name: better_paste // Author: B. Massingill // // Purpose: simplified version of Unix "paste" command (but less // simplified than the simplified_paste program) // // Input: // how many input files, their names, and name of an output file, // from standard input // Output: // none to standard output // output file has been created, with each line being the // concatenation of the corresponding lines of the // input files, separated by a tab character. // if the input files don't have the same numbers of lines, // "missing" lines are filled in with empty lines. // #include <iostream.h> #include <fstream.h> // has ifstream, ofstream #include <iomanip.h> // has setw() const int MaxFileNameLength = 1000; // maximum length of filename // **** function prototypes **** // // function to prompt for an input file name and open an input stream // // precondition: // descrip is a description of the file (e.g., "input file") // postcondition: // user has been prompted to enter a filename // input stream instream has been opened for the specified filename // (if the filename entered by the user cannot be opened, prompts // again, and continues to prompt until the user enters // a filename that can be opened) // void obtainInputFile(const char descrip[], ifstream& instream); // // function to prompt for an output file name and open an output stream // // precondition: // descrip is a description of the file (e.g., "output file") // postcondition: // user has been prompted to enter a filename // output stream outstream has been opened for the specified filename // (if the filename entered by the user cannot be opened, prompts // again, and continues to prompt until the user enters // a filename that can be opened) // void obtainOutputFile(const char descrip[], ofstream& outstream); // // function to prompt for a filename // // precondition: // descrip is a description of the file whose name is to be // entered // MaxLength is the length of array fName // postcondition: // user has been prompted with prompt string, and fName contains // the string entered in response // void obtainFileName(const char descrip[], char fName[], const int MaxLength); // // function to see if there is anything more to read in an input stream // // precondition: // instream is an input stream, successfully opened // postcondition: // return value is true if there is at least one character left to // read in instream, false if not // bool moreToRead(ifstream& instream); // function to apply moreToRead to multiple input streams // // precondition: // postcondition: bool moreInSomeFile(ifstream instream[], const int numFiles); // // function to copy a line, up to but not including end-of-line // // precondition: // instream is an input stream, successfully opened // outstream is an output stream, successfully opened // postcondition: // characters have been copied from instream to outstream, up to // but not including the next '\n' (end of line) character. // the '\n' character is read but discarded. // // note: this function can still be called even if instream has reached // end of file; no characters will be copied in that case. // void copyLine(ifstream& instream, ofstream& outstream); // // **** main program **** // int main() { const int MaxFiles=10; int numFiles; ifstream infiles[MaxFiles]; ofstream out; cout << "How many input files? (maximum of " << MaxFiles <<")\n"; cin >> numFiles; if (numFiles > MaxFiles) { cout << "Too many!\n"; exit(1); } for (int i=0; i<numFiles; i+=1) obtainInputFile("next input file", infiles[i]); obtainOutputFile("output file", out); while (moreInSomeFile(infiles, numFiles)) { for (int i=0; i<numFiles; i+=1) { if (i > 0) cout << '\t'; copyLine(infiles[i], out); } out << endl; } for (int i=0; i<numFiles; i+=1) infiles[i].close(); out.close(); return 0 ; } // // **** function definitions **** // (see prototypes for comments) // void obtainInputFile(const char descrip[], ifstream& instream) { char fName[MaxFileNameLength]; bool gotFile = false; while (!gotFile) { obtainFileName(descrip, fName, MaxFileNameLength); instream.open(fName); if (instream.fail()) cerr << "Unable to open file " << fName << endl; else gotFile = true; } return; } void obtainOutputFile(const char descrip[], ofstream& outstream) { char fName[MaxFileNameLength]; bool gotFile = false; while (!gotFile) { obtainFileName(descrip, fName, MaxFileNameLength); outstream.open(fName); if (outstream.fail()) cerr << "Unable to open file " << fName << endl; else gotFile = true; } return; } void obtainFileName(const char descrip[], char fName[], const int MaxLength) { cerr << "Please enter the name of the " << descrip << " (maximum of " << MaxLength << " characters): "; cin >> setw(MaxLength) >> fName; } bool moreToRead(ifstream& instream) { char c; if (instream.eof()) return false; else { if (instream.get(c)) { instream.putback(c); return true; } else return false; } } void copyLine(ifstream& instream, ofstream& outstream) { char c; while (instream.get(c) && c != '\n') { outstream.put(c); } } bool moreInSomeFile(ifstream instreams[], const int numFiles) { bool foundSome = false; for (int i=0; i<numFiles; i+=1) if (moreToRead(instreams[i])) foundSome = true; return foundSome; }