Text Line Editor Program as of April 26
// File Editor Demonstration Program
// Jim Engel
// Version April 26, 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.
// FUNCTION DECLERATIONS or PROTOTYPES
int lineCount ( char text[][LINE_LEN]);
void displayText ( char text[][LINE_LEN] );
int getint ( char *text);
// 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
char fileParm[FNAME_LEN] = "ParmFile.txt"; // file name for operational parameters
for ( mark = 0; mark < LINE_CNT; ++mark ) { // Initialize our main text storage
txtLns[mark][0] = 0;
}
/***************** 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.
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" ;
}
else
{ parmFile.getline ( filename, LINE_LEN );
cout << "Parm File Name: " << filename << endl ;
parmFile.close();
}
cout << "\nTHE HANDY DANDY TEXT LINE EDITOR version April 26,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( !strcmp(cmdWord, "hel")) /*** HELP Command ***/
{ 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";
cout << "File name: " << filename << endl;
}
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( !strcmp(cmdWord, "sav")) /*** 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")) /*** SYSTEM Command ***/
{ 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 );
}
}
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, "end")) /*** END Command ***/
{ break;
}
else
cout << "The command " << inLine <<" (" << cmdWord << ") is NOT valid!\n";
}
/***************** WRITE SYSTEM PARAMATER FILE ****************/
ofstream parfFileOut;
parfFileOut.open( fileParm ); // Open the file
if (parfFileOut.fail () )
{ cout << "File open Fails for paramater output!\n\n" ;
}
else
{ parfFileOut << filename << endl;
parfFileOut.close();
cout << "Paramaters saved...\n";
}
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 *text )
{ char txtline[64];
while ( true )
{ cout << text ;
cin.getline( txtline, CMD_SZ ); // read in text
if ( isdigit ( txtline[0]) )
return atoi( txtline ); // and convert it to an integer value.
}
}