Enhanced feature set.
This version has:
local system paramater file feature
delete line feature
find text string
You can just cut this program and paste it into Visual Studio:
// File Editor Demonstration Program // Jim Engel // Version May 9, 2011 /* This is a class project intended to demonstrate a primitiave line by line text editor, including command dispatcher operation. This editor is of course not a replacement for the many text editors in use, primarily because it stores text line by line with no provision for fold over. In principle, it could maintain a list style of text file. NEW special change line command !!! append command delete command To do's: Put the command functions in functions for flexibility. create an "match" function for the command dispatcher ***************************************************/ #include <iostream> #include <cstring> #include <fstream> // necessary for file in/out using namespace std; const int LINE_LEN = 81; // length of each text line const int LINE_CNT = 14; // max number of lines in edited text const int FNAME_LEN = 64; // size of the file name variable. const int CMD_SZ = 40; // size of the command string. char fileParm[FNAME_LEN] = "ParmFile.txt"; // FUNCTION DECLERATIONS or PROTOTYPES int lineCount ( char text[][LINE_LEN]); void displayText ( char text[][LINE_LEN] ); int getint ( char *text); int LoadParm ( char *filename ); int saveParm ( char *filename ); void syscommand(); void showhelp(); int cmdchk ( char *tar, char *src, int count); // MAIN PROGRAM int main( ) { int mark; // General purpose counter int line; // Line marker int count; // used as line counter char inLine[CMD_SZ]; // User enterted text srring char cmdWord[10]; char txtLns[LINE_CNT][LINE_LEN]; // Text lines being manipulated char filename[FNAME_LEN] = "MasterFile.txt"; // file name for edited file for ( mark = 0; mark < LINE_CNT; ++mark ) { // Initialize our main text storage txtLns[mark][0] = 0; } LoadParm ( filename ); cout << "\nTHE HANDY DANDY TEXT LINE EDITOR final version May 9,2011 .....\n"; /***************** COMMAND DISPATCH LOOP ****************/ while ( true ) { cout << "\nEnter a command: "; cin.getline(inLine, CMD_SZ); for ( mark =0; mark <= 2; ++mark) cmdWord[mark] = tolower( inLine[mark] ); cmdWord[3] = 0; // Limit string to 3 char. if( cmdchk(cmdWord, "hel" , 3)) showhelp(); /*** HELP Command ***/ else if( !strcmp(cmdWord, "loa")) /*** LOAD Command ***/ { for ( mark = 0; mark < LINE_CNT; ++mark ) { // Clean out text data txtLns[mark][0] = 0; } cout << "\nFile Load Operation: " << filename << endl; ifstream inFile; // create input file object inFile.open( filename); // Open the file if (inFile.fail () ) // see if open was successful { cout << "File open for " << filename << " Fails!\n\n" ; continue; } for ( mark = 0; mark < LINE_CNT; ++mark ) { inFile.getline ( txtLns[mark], LINE_LEN ); // read the line of text. if ( !inFile ) { // check for end of file. cout << "End of file found, line " << mark << endl; break; } cout << txtLns[mark] << endl; // display line just read } inFile.close(); } else if( cmdchk(cmdWord, "sav" , 3)) /*** SAVE Command ***/ { count = 0; cout << "\nFile Save Operation: " << filename << endl; ofstream outFile; // create input file object outFile.open( filename); // Open the file if (outFile.fail () ) { cout << "File open Fails for output!\n\n" ; continue; } count = lineCount ( txtLns ); // see how many lines. for ( mark = 0; mark < count; ++mark ) { // Write text lines to file outFile << txtLns[mark] << endl; } cout << count << "lines to file: " << filename << endl; outFile.close(); } else if( !strcmp(cmdWord, "lis")) /*** LIST Command ***/ { count = lineCount ( txtLns ); for ( line = 0; line < count; ++line ) { cout << line << ": " << txtLns[line] << endl; } cout << "Number of lines: " << count << endl; } /**************************** special CHANGE or LINE Command ***************************/ // allows line number on command line as in: // enter command: change 4 else if( !strcmp(cmdWord, "cha") || !strcmp(cmdWord, "lin") // allow CHANGE,LINE or ENTER || !strcmp(cmdWord, "ent") ) { while ( !isdigit(inLine[0]) && inLine[0] > 0 ) { // cout << inLine << endl; // DIAGNOSTIC code, remove when code correct strcpy ( inLine, inLine + 1 ); } if ( isdigit ( inLine[0]) ) // if it is a diget, get it { line = atoi ( inLine ); } else // ask for the digit { while ( true ) { cout << "Number of Line to change:"; cin.getline( inLine, CMD_SZ); // Read in text line = atoi( inLine ); // and convert it to an integer value. if ( line >= 0 && line < LINE_CNT ) break; } } if ( line >= 0 && line < LINE_CNT ) { cout << line << ": " ; cin.getline ( txtLns[line], LINE_LEN ); } else cout << "Error Line = " << line << endl; } /******************************************************************************************/ else if( !strcmp(cmdWord, "app")) /*** APPEND Lines Command ***/ { line = lineCount ( txtLns ); cout << "Existing lines: " << line << endl; while ( true ) { cout << line << ": " ; cin.getline ( txtLns[line], LINE_LEN ); if ( txtLns[line][0] == 0 || txtLns[line][0] == ' ' ) break; ++line; } cout << "Entry complete. \n"; } else if( !strcmp(cmdWord, "fil")) /*** FILE Name Command ***/ { cout << "File name: "; cin.getline(filename, CMD_SZ); cout << "New file name: " << filename << endl; } else if( !strcmp(cmdWord, "sys")) syscommand(); /*** SYSTEM Command ***/ else if( !strcmp(cmdWord, "cle")) /*** CLEAR Screen Command ***/ { system ( "cls" ); } else if( !strcmp(cmdWord, "fin")) /*** FIND text string Command ***/ { int matchCount = 0; cout << "\nEnter string to find: "; cin.getline(inLine, CMD_SZ); count = lineCount ( txtLns ); for ( line = 0; line < count; ++line ) { if ( strstr (txtLns[line],inLine) ) { cout << line << ": " << txtLns[line] << endl; ++matchCount; } } cout << endl << "Number of lines with \"" << inLine << "\": " << matchCount << endl; } else if( !strcmp(cmdWord, "del")) /*** DELETE Line Command ***/ { line = getint ( "Line to delete:"); count = lineCount ( txtLns ); if ( line < 0 || line >= count ) { cout << "Invalid line: " << line << endl; } else { for ( line = line; line <= count - 1; ++line ) { strcpy ( txtLns[line], txtLns[line+1] ); } txtLns[count][0] = 0; displayText ( txtLns ); } } else if( !strcmp(cmdWord, "ins")) /*** INSERT Line Command ***/ { line = getint ( "Line to insert:"); int mark; count = lineCount ( txtLns ); if ( line < 0 || line >= count ) { cout << "Invalid line: " << line << endl; } else { cout << "count: " << count<< endl; cout << "line: " << line<< endl; --line; // we are counting from 0, not 1 for ( mark = count; mark >= line ; mark-- ) { cout << mark << endl; strcpy ( txtLns[mark+1], txtLns[mark] ); } txtLns[line][0] = 0; displayText ( txtLns ); } } else if ( !strcmp(cmdWord, "end")) /*** END Command ***/ { break; } else cout << "The command " << inLine <<" (" << cmdWord << ") is NOT valid!\n"; } saveParm ( filename); cout << "\nDats all folks.....\n\n"; return 0; } /****************************************************************************************/ /***************************** UTILITY FUNCTIONS *****************************/ /****************************************************************************************/ // lineCount is a function to return the number of text lines in use, // including blank or empty lines followed by non blank lines. // Notice that // the first line is at text[0][LINE_LEN] // the last line is at text[count - 1][LINE_LEN] int lineCount ( char text[][LINE_LEN] ) { int mark, count; for ( count = 0, mark = 0; mark < LINE_CNT; ++mark) { // Find out how many lines, if ( text[mark][0] != 0 ) // including empty lines. count = mark + 1 ; } return count; } // Function to display existing text on the console. void displayText ( char text[][LINE_LEN] ) { int line; for ( line = 0; line < lineCount( text ); ++line ) { cout << line << ": " << text[line] << endl; } } // Function to get an integer and deal with the case where the // user enters alphabetic characters. int getint ( char *prompt ) { char txtline[64]; while ( true ) { cout << prompt ; cin.getline( txtline, CMD_SZ ); // read in text if ( isdigit ( txtline[0]) ) return atoi( txtline ); // and convert it to an integer value. } } /***************** OPERATIONAL FUNCTIONS ******************/ /***************** LOAD SYSTEM PARAMATER FILE ****************/ // This file stores the name of the file to be edited. It would also be the // normal place to save user preferences from one session to another. This // file is written at the end of this module each time the program shuts down // normally. int LoadParm ( char *filename ) { ifstream parmFile; // Create the file object parmFile.open( fileParm ); // Open the actual file if (parmFile.fail () ) { cout << "File open Fails for paramataer file!\n\n" ; return 77; } else { parmFile.getline ( filename, LINE_LEN ); cout << "Parm File Name: " << filename << endl ; parmFile.close(); } return 0; } /***************** WRITE SYSTEM PARAMATER FILE ****************/ int saveParm ( char * filename) { ofstream parfFileOut; cout << "in saveParm" << filename << endl; parfFileOut.open( fileParm ); // Open the actual file if (parfFileOut.fail () ) { cout << "File open Fails for paramater output!\n\n" ; return 99; } else { parfFileOut << filename << endl; parfFileOut.close(); cout << "Paramaters saved...\n"; } return 0; } void syscommand() { char inLine[100]; cout << "Use the 'end' command to get out of this sub dispatcher\n" "Try the help command and the 'dir' command. 'type' displays a file ..." << endl; while (true) { cout << "\nEnter system command: "; cin.getline(inLine, CMD_SZ); if ( inLine[0] == 0 || inLine[0] == ' ' ) break; if ( !strcmp(inLine, "end")) break; system ( inLine ); } } void showhelp() { cout << "\nCommands are: \n" "HELP Display commands\n" "LOAD text from a file\n" "SAVE this text to the file\n" "LIST current text lines\n" "CHANGE a line of text\n" "APPEND append lines of text.\n" "FILE change the file name.\n" "SYSTEM sys command sub dispatcher\n" "CLEAR clears the screen\n" "FIND find strings in text.\n" "DELETE delete one line of text.\n" "END Exit from this program\n" "\n"; } int cmdchk ( char *tar, char *src, int count) { int mk; for ( mk = 0; mk < 3; ++mk) { if ( toupper(tar[mk]) != toupper(src[mk] )) return false; } return true; }