In order to use the fields procedures in this class, you should include the file fields.h, which can be found in the directory /blugreen/homes/plank/cs360/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/blugreen/homes/plank/cs360/includeWhen you link your object files to make an executable, you need to follow the directions in the Libfdr notes.
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 libfdr.a.
#define MAXLEN 1001
#define MAXFIELDS 1000
typedef struct inputstruct {
char *name; /* File name */
FILE *f; /* File descriptor */
int line; /* Line number */
char text1[MAXLEN]; /* The line */
char text2[MAXLEN]; /* Working -- contains fields */
int NF; /* Number of fields */
char *fields[MAXFIELDS]; /* Pointers to fields */
int file; /* 1 for file, 0 for popen */
} *IS;
extern IS new_inputstruct(/* FILENAME -- NULL for stdin */);
extern IS pipe_inputstruct(/* COMMAND -- NULL for stdin */);
extern int get_line(/* IS */); /* returns NF, or -1 on EOF. Does not
close the file */
extern void jettison_inputstruct(/* IS */); /* frees the IS and fcloses
the file */
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:
#include < stdio.h >
#include "fields.h"
main(argc, argv)
int argc;
char **argv;
{
IS is;
int i;
if (argc != 2) {
fprintf(stderr, "usage: printwords filename\n");
exit(1);
}
is = new_inputstruct(argv[1]);
if (is == NULL) {
perror(argv[1]);
exit(1);
}
while(get_line(is) >= 0) {
for (i = 0; i < is->NF; i++) {
printf("%d: %s\n", is->line, is->fields[i]);
}
}
jettison_inputstruct(is);
exit(0);
}
So, for example, if the file rex.in
contains the following three lines:
June: Hi ... I missed you! Rex: Same here! You're all I could think about! June: I was?Then running printwords on rex.in results in the following output:
UNIX> printwords rex.in 1: June: 1: Hi 1: ... 1: I 1: missed 1: you! 2: Rex: 2: Same 2: here! 2: You're 2: all 2: I 2: could 2: think 2: about! 3: June: 3: I 3: was? UNIX>
#include < stdio.h >
#include "fields.h"
main(argc, argv)
int argc;
char **argv;
{
IS is;
int i;
char *penultimate_word;
char *last_word;
if (argc != 2) {
fprintf(stderr, "usage: badword filename\n");
exit(1);
}
is = new_inputstruct(argv[1]);
if (is == NULL) {
perror(argv[1]);
exit(1);
}
penultimate_word = NULL;
last_word = NULL;
while(get_line(is) >= 0) {
penultimate_word = last_word;
if (is->NF > 0) {
last_word = is->fields[0];
} else {
last_word = NULL;
}
}
if (penultimate_word != NULL) printf("%s\n", penultimate_word);
jettison_inputstruct(is);
exit(0);
}
Why? Look at what happens when you execute it on rex.in:
UNIX> badword rex.in June: UNIX>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.
#include < stdio.h >
#include < string.h >
#include "fields.h"
main(argc, argv)
int argc;
char **argv;
{
IS is;
int i;
char *penultimate_word;
char *last_word;
if (argc != 2) {
fprintf(stderr, "usage: badword filename\n");
exit(1);
}
is = new_inputstruct(argv[1]);
if (is == NULL) {
perror(argv[1]);
exit(1);
}
penultimate_word = NULL;
last_word = NULL;
while(get_line(is) >= 0) {
if (penultimate_word != NULL) free(penultimate_word);
penultimate_word = last_word;
if (is->NF > 0) {
last_word = strdup(is->fields[0]);
} else {
last_word = NULL;
}
}
if (penultimate_word != NULL) printf("%s\n", penultimate_word);
jettison_inputstruct(is);
exit(0);
}
Field.o assumes that all input lines are less than 1000 characters.