void ReplaceCharInBuffer(bufferADT buffer, char oldch, char newch);
When this function is called, it should start searching from the current cursor position, looking
for the next occurrence of the character oldch in the rest of the buffer.
If it finds it, simply replace oldch with newch. Search should leave the cursor after the last
character replaced in the buffer.
If oldch does not occur between the cursor and the end of the buffer, then there is nothing to
replace and thus search should leave the cursor unchanged (in the original place)
int SearchStrBuffer(bufferADT buffer, char* str);
When this function is called, it should start searching from the current cursor position, looking
for the next occurrence of the string str in the rest of the buffer.
If it finds it, search should leave the cursor after the found string and return the value TRUE or 1
If the string str does not occur between the cursor and the end of the buffer, then search should
leave the cursor unchanged and return FALSE or 0
First, you need to add the above prototypes into buffer.h.
Second, you need to implement them in listbuf.c
Third, you need to update editor.c so that you can call those functions. So include the following
in editor.c:
o If user enters: Rxy, your editor.c should call ReplaceCharInBuffer (buffer, \'x\', \'y\') to replace
all the occurrences of character \'x\' with character \'y\' after the cursor.
o If user enters: Sxyz, your editor.c should call SearchStrBuffer (buffer, \"xyz\") to search string
\"xyz\" in the buffer after the cursor.
Solution
/*
* File: editor.c
* --------------
* This program implements a simple character editor, which
* is used to test the buffer abstraction. The editor reads
* and executes simple commands entered by the user.
*/
#include
#include
#include \"genlib.h\"
#include \"buffer.h\"
#include \"simpio.h\"
#include \"string.h\"
/* Private function prototypes */
static void ExecuteCommand(bufferADT buffer, string line);
static void HelpCommand(void);
/* Main program */
main()
{
bufferADT buffer;
buffer = NewBuffer();
while (TRUE) {
printf(\"*\");
ExecuteCommand(buffer, GetLine());
DisplayBuffer(buffer);
}
FreeBuffer(buffer);
}
/*
* Function: ExecuteCommand
* Usage: ExecuteCommand(buffer, line);
* ------------------------------------
* This function parses the user command in the string line
* and executes it on the buffer.
*/
static void ExecuteCommand(bufferADT buffer, string line)
{
int i;
switch (toupper(line[0])) {
case \'R\':
if(strlen(line) >= 3) {
ReplaceCharInBuffer(buffer, line[1], line[2]);
} else {
printf(\"Illegal command\ \");
}
break;
case \'S\':
SearchStrBuffer(buffer, &line[1]);
break;
case \'I\': for (i = 1; line[i] != \'\\0\'; i++) {
InsertCharacter(buffer, line[i]);
}
break;
case \'D\': DeleteCharacter(buffer); break;
case \'F\': MoveCursorForward(buffer); break;
case \'B\': MoveCursorBackward(buffer); break;
case \'J\': MoveCursorToStart(buffer); break;
case \'E\': MoveCursorToEnd(buffer); break;
case \'H\':.
1. void ReplaceCharInBuffer(bufferADT buffer, char oldch, char newch);
When this function is called, it should start searching from the current cursor position, looking
for the next occurrence of the character oldch in the rest of the buffer.
If it finds it, simply replace oldch with newch. Search should leave the cursor after the last
character replaced in the buffer.
If oldch does not occur between the cursor and the end of the buffer, then there is nothing to
replace and thus search should leave the cursor unchanged (in the original place)
int SearchStrBuffer(bufferADT buffer, char* str);
When this function is called, it should start searching from the current cursor position, looking
for the next occurrence of the string str in the rest of the buffer.
If it finds it, search should leave the cursor after the found string and return the value TRUE or 1
If the string str does not occur between the cursor and the end of the buffer, then search should
leave the cursor unchanged and return FALSE or 0
First, you need to add the above prototypes into buffer.h.
Second, you need to implement them in listbuf.c
Third, you need to update editor.c so that you can call those functions. So include the following
in editor.c:
o If user enters: Rxy, your editor.c should call ReplaceCharInBuffer (buffer, 'x', 'y') to replace
all the occurrences of character 'x' with character 'y' after the cursor.
o If user enters: Sxyz, your editor.c should call SearchStrBuffer (buffer, "xyz") to search string
"xyz" in the buffer after the cursor.
Solution
/*
* File: editor.c
* --------------
* This program implements a simple character editor, which
* is used to test the buffer abstraction. The editor reads
* and executes simple commands entered by the user.
*/
#include
#include
#include "genlib.h"
#include "buffer.h"
2. #include "simpio.h"
#include "string.h"
/* Private function prototypes */
static void ExecuteCommand(bufferADT buffer, string line);
static void HelpCommand(void);
/* Main program */
main()
{
bufferADT buffer;
buffer = NewBuffer();
while (TRUE) {
printf("*");
ExecuteCommand(buffer, GetLine());
DisplayBuffer(buffer);
}
FreeBuffer(buffer);
}
/*
* Function: ExecuteCommand
* Usage: ExecuteCommand(buffer, line);
* ------------------------------------
* This function parses the user command in the string line
* and executes it on the buffer.
*/
static void ExecuteCommand(bufferADT buffer, string line)
{
int i;
switch (toupper(line[0])) {
case 'R':
if(strlen(line) >= 3) {
ReplaceCharInBuffer(buffer, line[1], line[2]);
} else {
printf("Illegal command ");
}
break;
case 'S':
3. SearchStrBuffer(buffer, &line[1]);
break;
case 'I': for (i = 1; line[i] != '0'; i++) {
InsertCharacter(buffer, line[i]);
}
break;
case 'D': DeleteCharacter(buffer); break;
case 'F': MoveCursorForward(buffer); break;
case 'B': MoveCursorBackward(buffer); break;
case 'J': MoveCursorToStart(buffer); break;
case 'E': MoveCursorToEnd(buffer); break;
case 'H': HelpCommand(); break;
case 'Q': exit(0);
default: printf("Illegal command "); break;
}
}
/*
* Function: HelpCommand
* Usage: HelpCommand();
* ---------------------
* This function lists the available editor commands.
*/
static void HelpCommand(void)
{
printf("Use the following commands to edit the buffer: ");
printf(" I... Inserts text up to the end of the line ");
printf(" F Moves forward a character ");
printf(" B Moves backward a character ");
printf(" J Jumps to the beginning of the buffer ");
printf(" E Jumps to the end of the buffer ");
printf(" D Deletes the next character ");
printf(" R Replaces the specified character with the new character ");
printf(" S Searches to find the text up to the end of line ");
printf(" H Generates a help message ");
printf(" Q Quits the program ");
}
4. buffer.h
/*
* File: buffer.h
* --------------
* This file defines the interface for an editor buffer abstraction.
*/
#ifndef _buffer_h
#define _buffer_h
#include "genlib.h"
/*
* Type: bufferADT
* ---------------
* This type defines the abstract type used to represent
* an editor buffer.
*/
typedef struct bufferCDT *bufferADT;
/* Exported entries */
/*
* Function: NewBuffer
* Usage: buffer = NewBuffer();
* ----------------------------
* This function dynamically allocates enough memory for the
* underlying representation of a bufferADT and initializes
* it to represent an empty buffer.
*/
bufferADT NewBuffer(void);
/*
* Function: FreeBuffer
* Usage: FreeBuffer(buffer);
* --------------------------
* This function frees the storage associated with the buffer.
*/
void FreeBuffer(bufferADT buffer);
/*
* Functions: MoveCursorForward, MoveCursorBackward
5. * Usage: MoveCursorForward(buffer);
* MoveCursorBackward(buffer);
* ----------------------------------
* These functions move the cursor forward or backward one
* character, respectively. If you call MoveCursorForward
* at the end of the buffer or MoveCursorBackward at the
* beginning, the function call has no effect.
*/
void MoveCursorForward(bufferADT buffer);
void MoveCursorBackward(bufferADT buffer);
/*
* Functions: MoveCursorToStart, MoveCursorToEnd
* Usage: MoveCursorToStart(buffer);
* MoveCursorToEnd(buffer);
* -------------------------------
* These functions move the cursor to the start or the
* end of the buffer, respectively.
*/
void MoveCursorToStart(bufferADT buffer);
void MoveCursorToEnd(bufferADT buffer);
/*
* Function: InsertCharacter
* Usage: InsertCharacter(buffer, ch);
* -----------------------------------
* This function inserts the single character ch into the
* buffer at the current cursor position. The cursor is
* positioned after the inserted character, which allows
* for consecutive insertions.
*/
void InsertCharacter(bufferADT buffer, char ch);
/*
* Function: DeleteCharacter
* Usage: DeleteCharacter(buffer);
* -------------------------------
* This function deletes the character immediately after
* the cursor. If the cursor is at the end of the buffer,
6. * this function has no effect.
*/
void DeleteCharacter(bufferADT buffer);
/*
* Function: DisplayBuffer
* Usage: DisplayBuffer(buffer);
* -----------------------------
* This function displays the current contents of the buffer
* on the console.
*/
void DisplayBuffer(bufferADT buffer);
/*
* Function: ReplaceCharInBuffer
* Usage: ReplaceCharInBuffer(buffer, oldch, newch);
* -----------------------------
*/
void ReplaceCharInBuffer(bufferADT buffer, char oldch, char newch);
/*
* Function: SearchStrBuffer
* Usage: SearchStrBuffer(buffer, str);
* -----------------------------
*/
int SearchStrBuffer(bufferADT buffer, char* str);
#endif
listbuf.c
/*
* File: listbuf.c
* ---------------
* This file implements the buffer.h abstraction using a linked
* list to represent the buffer.
*/
#include
#include "genlib.h"
#include "strlib.h"
7. #include "buffer.h"
/* Types */
typedef struct cellT {
char ch;
struct cellT *link;
} cellT;
struct bufferCDT {
cellT *start;
cellT *cursor;
};
/*
* Implementation notes: NewBuffer
* -------------------------------
* This function allocates an empty editor buffer, represented
* as a linked list. To simplify the link list operation, this
* implementation adopts the useful programming tactic of
* keeping an extra "dummy" cell at the beginning of each list,
* so that the empty buffer has the following representation:
*
* +-------+ +------+
* | o---+-----====>| |
* +-------+ / +------+
* | o---+---/ | NULL |
* +-------+ +------+
*/
bufferADT NewBuffer(void)
{
bufferADT buffer;
buffer = New(bufferADT);
buffer->start = buffer->cursor = New(cellT *);
buffer->start->link = NULL;
return (buffer);
}
/*
* Implementation notes: FreeBuffer
* --------------------------------
8. * FreeBuffer must free every cell in the buffer as well as
* the buffer storage itself. Note that the loop structure
* is not exactly the standard idiom for processing every
* cell within a linked list, because it is not legal to
* free a cell and later look at its link field. To avoid
* selecting fields in the structure after it has been freed,
* you have to copy the link pointer before calling FreeBlock.
*/
void FreeBuffer(bufferADT buffer)
{
cellT *cp, *next;
cp = buffer->start;
while (cp != NULL) {
next = cp->link;
FreeBlock(cp);
cp = next;
}
FreeBlock(buffer);
}
void MoveCursorForward(bufferADT buffer)
{
if (buffer->cursor->link != NULL) {
buffer->cursor = buffer->cursor->link;
}
}
void MoveCursorBackward(bufferADT buffer)
{
cellT *cp;
if (buffer->cursor != buffer->start) {
cp = buffer->start;
while (cp->link != buffer->cursor) {
cp = cp->link;
}
buffer->cursor = cp;
}
}