IN C++ language Write a simple word processor that will accept text and commands
ID: 3936608 • Letter: I
Question
IN C++ language
Write a simple word processor that will accept text and commands as input. The commands it should respond to are:
Substitute/oldstring/newstring/
Copy #
Locate/string/
Delete #
Move #
Type #
Pastes Insert #
Replace #
Quit
The program should be able to open an existing file or create a new one. It should keep track of where the user is in the file at any time. Each command is followed by a number which indicates the number of line (the current line & those following) upon which the command should act. Each command should operate on the specified line or lines of the file.
Explanation / Answer
#include <iostream>
#include <fstream>
#include <cmath>
#include <string>
using namespace std;
const bool DEBUG = false;
const int MAX = 100;
struct file // This contains the file information and contents
{
string contents[MAX];
string fileName;
int currentLineIndex;
int total;
bool markupHighlighting;
};
int NumberInputReader(string); // Reads the numbers from user input
void Help(); // Prints out a help menu
void Markup(file&, int); // Does HTML highlighting
void MarkupApply(file&, string, int); // Applies the HTML highlighting to the file
//void Substitute(file&, string); // substitutes portions of lines of text
//void Type(file&, int); // prints text to the screen
//void Copy(file, string[], int&); // copies text
//void Paste(file&, string[], int, int); // pastes text
//void Locate(file &, string); // finds text
//void Insert(file &, int); // inputs text to the array
//void Delete(file &, int); // deletes text
//void Replace(file &, int); // replaces while lines of text text
//void Move(file &, int); // moves the current line
//void Quit(file); // quits the program, asks the users if they want to save.
void Open(file &); // allows the user to open a file
void New(file &); // allows the user to create a file
void Save(file); // saves the array to a file.
void IndexPrint(file); // for debugging, this prints the contents of the array.
int main() // Main program
{
file txtFile;
txtFile.currentLineIndex=-1;
txtFile.total=0;
int inputValue=0, copyNumber;
string inputString, openYN, copyQue[MAX];
char inputChar, openYNtemp;
// ANIMATION LOOP GOES HERE
cout<<"~~~[1;32m Welcome [0m~~~ "; // first use of colors in the program
cout<<"Would you like to open an existing file? "
<<endl;
getline(cin, openYN);
if(openYN == "") // if the user simply presses enter, a new file is automatically created
{ // because if the user really did this, they were probably trolling.
cout<<"[1;31m-You'll have to be more specific next time.-[0m "<<endl;
New(txtFile);
}
else // Wow, the user entered valid input.
{
openYNtemp=openYN.at(0);
openYNtemp=toupper(openYNtemp);
switch(openYNtemp)
{
case 'Y':
Open(txtFile);
break;
default:
New(txtFile);
break;
}
}
inputChar=' '; // Initializes variable as a space just as an entry point.
while(inputChar!='Q') // Main event loop. //"if not quit"
{
switch(inputChar)
{
case ' ':
break;
case 'S':
Substitute(txtFile,inputString);
break;
case 'T':
Type(txtFile, inputValue);
break;
case 'C':
copyNumber=NumberInputReader(inputString); // Special variable for copy
// because it is used again with paste.
Copy(txtFile, copyQue, copyNumber);
break;
case 'P':
Paste(txtFile, copyQue, copyNumber, inputValue);
break;
case 'L':
Locate(txtFile, inputString);
break;
case 'I':
Insert(txtFile, inputValue);
break;
case 'D':
Delete(txtFile, inputValue);
break;
case 'R':
Replace(txtFile, inputValue);
break;
case 'M':
Move(txtFile, inputValue);
break;
case 'O':
Open(txtFile);
break;
case 'N':
New(txtFile);
break;
case '<': // Highlight
txtFile.markupHighlighting=true; // highlights the markup in the file '</>'
Markup(txtFile, inputValue);
break;
case '>': // Unhighlight
txtFile.markupHighlighting=false; // if false, it'll go through the motions
Markup(txtFile, inputValue); // again, but revert to the original array
break; // afterward.
case '*': // * saves file to disk
Save(txtFile);
break;
case '?':
Help(); // "I seem to be having difficulty with my lifestyle." -Arthur Dent
break;
case'.': // default for re-looping
break;
default:
cout<<"[1;31m'"<<inputString<<"'[0m"
<<" is not a valid command. "
<<endl
<<"Enter '?' for a list of valid commands. "
<<endl;
break;
}
if(DEBUG)
{
cout<<"[1;31m";
cout<<"--(DEBUG)--> total: "<<txtFile.total<<endl;
cout<<"--(DEBUG)--> currentLineIndex: "<<txtFile.currentLineIndex<<endl;
IndexPrint(txtFile);
cout<<"[0m";
}
cout<<"Command? "<<endl;
getline(cin, inputString);
if(inputString == "")
{
cout<<"[1;31m-You'll have to be more specific.-[0m "<<endl;
inputChar='.'; // resets the loop because the user was being unfriendly
}
else if(inputString.length()>=80) // If it takes up the entire default width of
{ // the window.
cout<<"[1;31m-That's a very long command, "
<<"I'm just but a humble Line Editor.-[0m "<<endl;
inputChar='.'; // resets the loop because the user was being unfriendly
}
else
{
inputChar=inputString.at(0);
inputChar=toupper(inputChar);
inputValue=NumberInputReader(inputString);
}
}
Quit(txtFile); // calls quit function, Y or N to save.
cout<<"Have a nice day!"<<endl;
return 0;
}
void Markup(file &txtFile, int inputColor) // Locates the markup and changes the color based on
{ // user input. Then calls MarkupApply.
int i, openFind, closeFind, len;
bool end = false;
string beginColor, endColor = "[0m";
string toBeReplaced, replacement, finalString;
fabs(inputColor);
if(inputColor<=-1 or inputColor>=8)
{
inputColor=0; // Default color
cout<<"[1;31m-Invalid color. Color set to default.-[0m"<<endl;
}
switch(inputColor)
{
case 0:
beginColor="[1;32m"; // colors two and zero are switched
break;
case 1:
beginColor="[1;31m";
break;
case 2:
beginColor="[1;30m"; // because if no colors are entered the
break; // default should be color two
case 3:
beginColor="[1;33m";
break;
case 4:
beginColor="[1;34m";
break;
case 5:
beginColor="[1;35m";
break;
case 6:
beginColor="[1;36m";
break;
case 7:
beginColor="[1;37m";
break;
default:
cout<<"[1;31m-There seems to have been an error.-[0m"<<endl;
break;
}
i=0;
while(i<=txtFile.total-1) // or reaches end, or none on the line
{
end = false;
openFind=0;
closeFind=0;
while(end != true)
{
openFind = txtFile.contents[i].find('<', closeFind);
closeFind = txtFile.contents[i].find('>', openFind)+1;
len=closeFind-openFind;
if(openFind >= 0 and closeFind >= 0)
{
toBeReplaced = txtFile.contents[i].substr(openFind, closeFind);
replacement=beginColor+toBeReplaced+endColor;
//finalString="|"+toBeReplaced+"|"+replacement+"|";
//MarkupApply(txtFile, finalString, i);
txtFile.contents[i].replace(openFind, len, replacement);
}
end = true;
}
i++;
}
if(txtFile.markupHighlighting = false)
{
// UNHIGHLIGHTING GOES HERE
}
}
void Substitute(file &txtFile, string input_string) // substitutes '/string/' with '/other string/'
{
int pos, pos_2, pos_3, pos_old_string, txtfile_length, i;
int new_string_length, old_string_length, start_from;
bool check, exit;
char indicator;
// Substitute works with all characters, not just '/'
indicator = input_string.at(input_string.length()-1);
pos = input_string.find(indicator);////////////////////////
string temp_1, new_string, temp_2, old_string;
temp_1 = input_string.substr(pos + 1);
pos_2 = temp_1.find_last_of(indicator);////////////////////////////
old_string = temp_1.substr(0,pos_2);
temp_2 = temp_1.substr(pos_2+1);
new_string = temp_2.substr(0,temp_2.length()-1);
old_string_length = old_string.length();
new_string_length = new_string.length();
i = txtFile.currentLineIndex;
start_from = 0;
check = true;
exit = false;
string the_original_string = txtFile.contents[i];
if(txtFile.contents[i].find(old_string) == -1)//to show if no match string for the old_string.
{
cout<<"[1;31m-'"<<old_string<<"'[0m does not occur on line [1;31m"
<<i<<"[0m.- "<<endl;
}
if(txtFile.contents[i].empty() == true)//to leave if it empty.
{
cout<<"[1;31m-Line number "<<i+1<<" is empty.-[0m"<<endl;
check = false;
}
txtfile_length = txtFile.contents[i].length();
while(check and not exit)
{
txtfile_length = txtFile.contents[i].length();
pos_old_string = txtFile.contents[i].find(old_string,start_from);
//the position of the old_string in the string.
if(pos_old_string == -1)
{
exit=true;
}
else
{
if(new_string.empty())
{
txtFile.contents[i].replace(pos_old_string,old_string_length,"");
start_from = 0;
}
else
{
txtFile.contents[i].replace(pos_old_string,old_string_length,new_string);
if(txtFile.contents[i].at(pos_old_string + new_string_length - 1) == '')
{
check = false;
}
else
{
start_from = pos_old_string + new_string_length;
}
}
}
}
if(txtFile.contents[i] != the_original_string)
cout<<"Text from current line: "<<endl
<<"[1;36m>[0m "<<txtFile.contents[i]<<endl;
}
void Type(file &txtFile, int type_number) // prints to the screen.
{
int i;
int otherCounter=0;
bool exit=false;
type_number=fabs(type_number);
if(type_number==0)
{
type_number = 1;
}
if(txtFile.currentLineIndex<=0)
{
txtFile.currentLineIndex=0;
}
i=txtFile.currentLineIndex;
while(i<=txtFile.currentLineIndex+type_number-1 and exit !=true)
{
if(i<= txtFile.total-1)
{
cout<<"[1;36m>[0m "<<txtFile.contents[i]<<endl;
i++;
}
else
{
cout<<"[1;31m-End of document.-[0m "<<endl;
exit = true;
}
}
txtFile.currentLineIndex=i-1;
}
void Copy(file txtFile, string copyQue[], int ©Number) // copies text
{
int i;
copyNumber=fabs(copyNumber);
if(copyNumber==0)
{
copyNumber = 1;
}
while(copyNumber+txtFile.currentLineIndex-1>=txtFile.total)
{
copyNumber--;
}
for(i=0; i<=copyNumber-1; i++)
{
copyQue[i]="";
}
for(i=0; i<=copyNumber-1; i++)
{
copyQue[i]=txtFile.contents[i+txtFile.currentLineIndex];
}
}
void Paste(file &txtFile, string copyQue[], int copyNumber, int pasteNumber) // pastes text
{
int i, ii;
for(ii=0; ii<=pasteNumber-1; ii++)
{
if(copyNumber+txtFile.total-1>=MAX)
{
cout<<"[1;31m-You cannot exceed the total number of lines.- [0m"<<endl;
}
else
{
for(i=txtFile.total-1; i>=txtFile.currentLineIndex+1; i--)
{
txtFile.contents[i+copyNumber]=txtFile.contents[i];
}
for(i=txtFile.currentLineIndex+1; i<=txtFile.currentLineIndex+copyNumber; i++)
{
txtFile.contents[i]=copyQue[i-txtFile.currentLineIndex-1];
}
txtFile.total=txtFile.total+copyNumber;
txtFile.currentLineIndex=i-1;
}
}
}
void Locate(file &txtFile, string inputString) // finds text.
{
int firstPosition, secondPosition, found, i=txtFile.currentLineIndex;
char indicator;
// Locate works with all characters, not just '/'
indicator = inputString.at(inputString.length()-1);
string tempOne, searchString;
firstPosition = inputString.find(indicator);
tempOne = inputString.substr(firstPosition + 1);
secondPosition = tempOne.find(indicator);
searchString = tempOne.substr(0, secondPosition);
found = -1;
while(found == -1 and i<=txtFile.total)
{
found=txtFile.contents[i].find(searchString);
i++;
}
if(found == -1)
{
cout<<"[1;31m-No instance of '"<<searchString<<"' was found.-[1;31m "<<endl;
}
else
{
txtFile.currentLineIndex=i-1;
}
cout<<"[1;36m>[0m "<<txtFile.contents[txtFile.currentLineIndex]<<endl;
}
void Insert(file &txtFile, int insert_number) // inserts text
{
int i, reductionDifference=0;
bool reduction=false;
insert_number=fabs(insert_number);
if(insert_number==0)
{
insert_number=1;
}
if(txtFile.total==0 and txtFile.currentLineIndex<=0)
{
txtFile.currentLineIndex=-1;
}
while(txtFile.currentLineIndex+insert_number-1>=MAX-1)
{
insert_number--;
reduction=true;
}
if(reduction==true and insert_number>=1)
{
cout<<"[1;31m-You may only add "<<insert_number
<<" more lines.-[1;31m "<<endl;
}
else if(reduction==true and insert_number<=0)
{
cout<<"[1;31m-You have reached the maximum number of lines.-[1;31m "<<endl;
}
for(i=txtFile.total-1; i>=txtFile.currentLineIndex+1; i--)
{
txtFile.contents[i+insert_number]=txtFile.contents[i];
}
for(i=txtFile.currentLineIndex+1; i<=insert_number+txtFile.currentLineIndex; i++)
{
cout<<"[1;36m>[0m ";
getline(cin,txtFile.contents[i]);
}
txtFile.total = txtFile.total + insert_number;
txtFile.currentLineIndex = insert_number + txtFile.currentLineIndex;
}
void Delete(file &txtFile, int delete_number) // deletes text and moves
{ // the other text to the top of the array
int i;
delete_number=fabs(delete_number);
if(delete_number==0)
{
delete_number=1;
}
while(delete_number+txtFile.currentLineIndex-1>=txtFile.total)
{
delete_number--;
}
for(i=txtFile.currentLineIndex+delete_number; i<=txtFile.total-1; i++)
{
txtFile.contents[i-delete_number]=txtFile.contents[i];
}
while(txtFile.total<=0)
{
txtFile.total++;
}
txtFile.total = txtFile.total - delete_number;
if(txtFile.currentLineIndex==txtFile.total)
{
txtFile.currentLineIndex--;
}
}
void Replace(file &txtFile, int replace_number) // replaces text
{
int i;
bool reduced;
replace_number=fabs(replace_number);
if(replace_number==0)
{
replace_number=1;
}
if(txtFile.currentLineIndex==-1)
{
txtFile.currentLineIndex=0;
}
while(replace_number+txtFile.currentLineIndex-1>=txtFile.total)
{
replace_number--;
reduced=true;
}
if(replace_number<=0 and reduced==true)
{
cout<<"[1;31m-You cannot replace lines that do not exist.-[0m"<<endl;
}
for(i=txtFile.currentLineIndex; i<=txtFile.currentLineIndex+replace_number-1; i++)
{
cout<<"[1;36m>[0m ";
getline(cin,txtFile.contents[i]);
}
if(reduced==true)
{
cout<<"[1;31m-No more replaceable lines exist past this point.-[0m"<<endl;
}
if(txtFile.currentLineIndex+replace_number>=txtFile.total)
{
txtFile.total=txtFile.currentLineIndex+replace_number;
}
txtFile.currentLineIndex=txtFile.currentLineIndex+replace_number-1;
}
void Move(file &txtFile, int move_number) // moves text
{
if(txtFile.currentLineIndex + move_number <= -1)
{
txtFile.currentLineIndex = 0;
}
else if(txtFile.currentLineIndex + move_number >= txtFile.total)
{
txtFile.currentLineIndex = txtFile.total-1;
}
else
{
txtFile.currentLineIndex = txtFile.currentLineIndex + move_number;
}
cout<<"Text from current line: "<<endl<<"[1;36m>[0m "<<txtFile.contents[txtFile.currentLineIndex]<<endl;
}
void Quit(file txtFile) // Quit function uses recusion to make sure the user does not
// accidently make a typo when answering "would you like to save first"
// and lose their work because of it.
{
string yesNo;
char yesNoTemp;
cout<<"You have asked to quit, "
<<"would you like to save first? "
<<endl;
getline(cin, yesNo);
if(yesNo == "")
{
cout<<"[1;31m-You didn't enter a command.-[0m "<<endl;
Quit(txtFile);
}
else
{
yesNoTemp=yesNo.at(0);
yesNoTemp=toupper(yesNoTemp);
switch(yesNoTemp)
{
case 'Y':
Save(txtFile);
break;
case '*':
Save(txtFile);
break;
case 'S':
Save(txtFile);
break;
case 'N':
cout<<"Your file [1;31mHAS NOT[0m been saved. "<<endl;
break;
default:
cout<<"Saving is serious business and "
<<"[1;31m'"<<yesNo<<"'[0m"
<<" is not an appropriate response. "<<endl
<<"Please enter an appropriate response. "<<endl;
Quit(txtFile);
break;
}
}
}