Practice Assignment

(replacestr.c)

Information

  1. For this practice assignment, you will write a program that will print out lines of a text file. However, instead of just simply reading in the lines of text and writing them to stdout, you will substitute certain substrings with a different string. The name of the function you will create is replacestr and this is the prototype:
    enum FILE_ERR replacestr(const char *filename, const char *oldstr, const char *newstr);  
    
    For example, if you are given a text file named poem.txt that contains these 4 lines of text:
    Roses are red.
    Violets are blue.
    Some poems rhyme.
    But not this one.
    
    and you are to replace each occurrence of the string are with the string may be, this is how you would call the function:
    enum FILE_ERR result = replacestr("poem.txt", "are", "may be");
    
    and this is what would be printed out on the screen:
    Roses may be red.
    Violets may be blue.
    Some poems rhyme.
    But not this one.
    
    Here is a header file that you should use (replacestr.h):
    /* Max length of a line */
    #define LINE_MAX 2048
    
    /* Possible file errors */
    enum FILE_ERR {feNONE, feINPUT};
    enum FILE_ERR replacestr(const char *filename, const char *oldstr, const char *newstr);
    
    Here is a driver file: (main.c, HTML Text) You must specify the filename, old string, and new string on the command line like this:
    replacestr poem.txt are "may be"
    

    If you don't provide 3 arguments to the program, it will display this message:

    Usage:  replacestr filename oldstring newstring
    
    where:  filename is the file to search through
            oldstring is the text to search for
            newstring is the text to replace oldstring with
    
    Example: poem.txt are "may be"
    
    If either of the strings contain spaces, it must be surrounded by quotes.
    

    The name of your implementation file should be replacestr.c and the command to compile it will look like this:

    gcc -O -Werror -Wall -Wextra -ansi -pedantic main.c replacestr.c -o replacestr
    
    Here is a skeleton for replacestr.c to get you started:
    #include <stdio.h>  
    #include <string.h> 
    #include "replacestr.h"
    
    static void print_replace(const char *string, 
                              const char *oldstr, 
                              const char *newstr)
    {
    
    }
    
    enum FILE_ERR replacestr(const char *filename, 
                             const char *oldstr, 
                             const char *newstr)
    {
    
    }
    

    Here are some sample outputs using the input file: input1-LF.txt. Windows version is here: input1-CRLF.txt

    1. output1.txt with this command:
    2. ./replacestr input1-LF.txt one ONE > output1.txt
      
    3. output2.txt with this command:
    4. ./replacestr input1-LF.txt one Wubalubadubdub! > output2.txt
      
    5. output3.txt with this command:
    6. ./replacestr input1-LF.txt "one one one one one one one one" XXX > output3.txt
      
    7. output4.txt with this command:
    8. ./replacestr input1-LF.txt "one one" XXX > output4.txt
      

    Here's another test using input2-LF.txt. Windows version: input2-CRLF.txt using this command:

    ./replacestr input2-LF.txt the THE
    

    Output: output5.txt

    Another test:

    ./replacestr input2-LF.txt " " "" > output6.txt
    
    Output: output6.txt

    A bigger test using doi-100-2-LF.txt and the Windows version: doi-100-2-CRLF.txt

    ./replacestr doi-100-2-LF.txt "of" "X X X" > output7.txt
    
    Output: output7.txt

    A stress test using stress-LF.txt and the Windows version: stress-CRLF.txt

    ./replacestr stress-LF.txt one X > output8.txt
    
    Output: output8.txt

    With Windows, use the CRLF version of the input files on the command lines and replace ./replacestr with replacestr.

    All of the files in one zip: all-in-out-files.zip

    Approximate number of lines of code: 30.

Notes

  1. You should break this program into 2 functions. The first function, replacestr does all of the file I/O, and the second function (let's call it print_replace), should do the printing and substituting. Remember, 1 task per function. These two tasks are not related at all, so they should not be in the same function. This is the prototype:
    static void print_replace(const char *string, const char *oldstr, const char *newstr);
    
  2. Before doing any file I/O, make sure you can do the printing and substituting, as that is the only difficult part of this assignment. For example, you should make sure that you can print_replace these lines of text (replacing red with yellow)
    Red monkeys play in the big red tent with three blue elephants that turned red
    
    The output should look like this:
    Red monkeys play in the big yellow tent with three blue elephants that turned yellow
    
    Notice that the strings are case-sensitive, e.g. UPPERCASE is not the same as lowercase.
  3. Use the strstr function to locate the substring in the line of text. You'll need to do this in a loop so you can find every occurrence.
  4. You can assume that no line will be longer than LINE_MAX, which is defined in the header file. Just create a buffer (array) of that size to read the lines from the file. You are only reading 1 line at a time. DO NOT try to load the entire file. It may be too large to fit into memory.
  5. DO NOT create any extra buffers (static or dynamic) besides the one you need above to read a line from the file. Since you are not storing the new text, you don't need any extra memory. You are just doing the substitutions as you print out the line. You should start learning to be memory-efficient with your code.
  6. You should be using pointer notation in print_replace, not array notation. It will be easier and clearer if you use pointers. It will also give you some good practice.
  7. You are reading from a file, but writing to stdout. Do not attempt to write to any files.
  8. You should open the input file in text/translate mode. If you can't open the file (for whatever reason), you should just return feINPUT to the caller.

    We are going to assume that, if you can open the file, then you can read all of the lines. It is possible to get a read error during the process, but you don't have to handle that at this point.

  9. You are not allowed to include any other files than are already included in the skeleton.