Fri Sep 25 09:41:52 EDT 1998
The fields library is a suite of routines that make reading input
easier than using getchar(), scanf() or gets().
This is a library that I wrote -- it is not standard in Unix, but it
should work with any C compiler (this includes on DOS/Windows).
If you want to take the fields library with you after class, go
ahead and do so. You can get the source code
at http://www.cs.utk.edu/~plank/plank/fields/fields.html.

In order to use the fields procedures in this class,
you should include the file
fields.h,
which can be found in the directory /home/bvz/cs140/include.
Instead of including the full
path name in your C file, just do:

#include "fields.h"

and then compile the program with:

gcc -I/home/bvz/cs140/include

Also when you link your object files to make an executable, you need to
include
/home/bvz/cs140/objs/libfdr.a.

The
makefile
in this directory does both of these things for you.
When you look over the file
printwords.c,
make sure you figure out how
to compile it so that it finds fields.h, and so that the compilation
links with either fields.o or libj.a.

An Aside on on the -I Flag

The -I flag tells gcc the location of additional directories that it
can use to find .h files that you have defined. Recall from your
introductory
CS course that include files come in two flavors: 1) system-defined .h
files, such as stdio.h, that you include using braces (<&gt), and
2) user-defined .h files, such as fields.h, that you include using
quotes (""). By default gcc looks in certain system-defined locations
for system-defined include files. By default gcc looks in the current
directory for user-defined .h files. However, you will often want to
include .h files that are not defined in the current directory, such
as fields.h. In that case you must tell gcc where it can find these
files. The -I flag allows you to do just that. You can include
multiple -I flags in the same gcc command. For example:

gcc -I/home/cs140/spring-2004/include -I/home/bvz/include

The fields library defines and implements a data structure that simplifies
input processing in C. The data structure consists of a type definition
and four procedure calls. All are defined in fields.h:

To read a file with the fields library,
you call new_inputstruct() with the proper filename.
New_inputstruct()
takes the file name as its argument (NULL for standard input), and
returns an IS as a result. Note that the IS is a pointer
to a struct inputstruct. This is malloc()'d for you
in the new_inputstruct() call. If
new_inputstruct()
cannot open the file, it will return NULL, and you can call
perror() to print out the reason for the failure (read the man
page on perror() if you want to learn about it).

Once you have an IS, you call get_line() on it to read a line.
Get_line() changes the state of the IS to reflect the
reading of the line. Specifically:

It puts the contents of the line in text1.

It breaks up the line into words. The NF field contains
the number of words in the field. The first NF slots
of the fields array point to each of the NF words
(and these words are null-terminated).

The line field contains the line number of the line.

Get_line() returns the NF field as its return value.

It returns -1 when it reaches the end of the file.

Jettison_inputstruct() closes the file associated with the IS
and deallocates (frees) the IS. Do not worry about
pipe_inputstruct() for now.

These procedures are very convenient for processing input files. For
example, the following program (in
printwords.c)
prints out every word of an input file prepended with its line number:

One important thing to note about fields.o is that onlynew_inputstruct() calls malloc(). Get_line()
simply fills in the fields of the IS structure --- it does not
perform memory allocation. Therefore, suppose you wanted to print out
the first word on the second-to-last line. The
following program
(badword.c)
would not work:

It prints ``June:'' instead of ``Rex:'' because get_line()
does not allocate any new memory. Both penultimate_word and
last_word end up pointing to the same thing. Make sure you understand
this example, because you can get yourself into a mess of trouble otherwise.
The correct version of the program is in
goodword.c:
(note that this
is a very inefficient program because of all the strdup() and
free() calls. You could do better if you wanted to.

tailanyf

Now, as another example, let's write tailany from the
PointMalloc lecture using the fields
library. This simply uses the fields library and is->text1
instead of gets(). Everything else is pretty much the same.
The code is in
tailanyf.c.