Due: Tuesday, April 29, 2007 at 9 pm
The purpose of this assignment is to gain some experience with C programming
by implementing a utility program that is similar to grep
, but without the
ability to process regular expressions. In particular, in this assignment,
you will:
This assignment does not include any particularly complicated algorithms, but it will require you to organize your code well and make effective use of the C language and libraries.
Implement in C a Unix utility program gasp
. The command
gasp [options] STRING FILE...
should read the listed files (FILE...
) and copy each line from an input file
to stdout
if
it contains STRING
. Each output line should be preceded by the
name of the file that contains it. The argument STRING
may be
any sequence of characters (as expanded, of course, by the shell depending
on how it is quoted). There are two available options,
which may appear in any order if both are present:
-i
Ignore case when searching for lines that contain STRING
.
If the -i
option is used, the strings "this
", "This
", "THIS
", and "thiS
"
all match; if -i
is not used, they are all considered different.-n
Number lines in output. Each line copied to stdout
should
include the line number in the file where it was found in addition to the
file name. The lines in each file are numbered from 1.(This is basically the same output produced by grep
if
the STRING
argument is treated as literal data and not as a regular
expression.)
Besides the general specification given above, your program should meet the following requirements to receive full credit.
\0
). This number should not be hard-wired in
the code, but should be specified with an appropriate #define
preprocessor
command so it can be changed easily. Your program is allowed to produce incorrect
results or fail if presented with input data containing lines longer than
this limit.malloc
and
return the storage with free
when you are done with it. The
amount allocated should be based on the actual size needed, not some arbitrary
size that is
assumed to be "large enough". Exception: you may allocate a
character array or two that is large enough for the largest input line (see
#1) and reuse it if needed to process each input line, without having to
count the characters in each input line and (re-)allocate a new array for
each
one.strcpy
in <string.h>
can
be used to copy \0
-terminated
strings; you should not be writing loops to copy such strings one character
at a time.tolower(c)
function
(or, alternatively,
toupper(c)
) in <ctype.h>
.stderr
and continue processing
any remaining files on the command line.gcc -Wall
on attu.As with any program you write, your code should be readable and understandable to anyone who knows C. In particular, for full credit your code must observe the following requirements.
main
function that does everything.
If you wish, you may include all of your functions in a single C source file,
since the total size of the program will be fairly small. Be sure to include
appropriate function prototypes near the beginning of the file.void
functions
that perform an action without returning a value. Variables of local significance
like
loop counters
or
indices should be given simple names like i
or n
,
and do not require further comments.-i
or -n
options
are selected or not.STRING
argument
to lower- or upper-case, make a copy of it and translate that copy once;
don't do this repeatedly for each input line or even for each input file.
Don't use malloc
or free
excessively - they are
expensive. Don't make unnecessary copies of large data structures; use
pointers. (Copies of int
s,
pointers, and similar things are cheap; copies of arrays and large structs
are expensive.)stdout
before you add
the code to search for the STRING
argument and selectively print
lines containing it. Be able to search for exact matches before adding the -i
option
to ignore case. Add the -n
option sometime when you're not trying
to get something else to work.printf
is your
friend here to print values while debugging.<stdio.h>
, <string.h>
, <ctype.h>
and
<stdlib.h>
libraries.-i
option is to translate both the STRING
argument
and each input line to lowercase, then search for the translated STRING
in the translated input line.A small amount of extra credit will be awarded for adding the following extensions to an already complete, working assignment. No extra credit will be awarded if the basic program is not fully implemented and substantially bug-free.
stdin
.
This should be fairly easy to add if your code is organized as a well-designed
collection of functions.-n
option to count line numbers incorrectly.
However you decide to implement this, long input lines should not cause your
program to fail or crash.STRING
parameter anywhere in the line. If you read arbitrarily
long input lines in chunks that have only part of an input line, be sure
you can correctly handle situations where the string in the search spans
two parts of the line instead of falling entirely inside one chunk of the
line.