Starter Code for Lab 5 Plus Sample Output
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <signal.h>
#include <time.h>
#include "perry.h"
#define MAXIDENT 80
#define MAXLINE 256
typedef struct node NODE;
typedef struct line LINE;
struct line
{
long linenum;
LINE *next;
};
struct node
{
char *identifier;
NODE *left, *right;
LINE *front, *rear;
};
main(int argc, char *argv[])
/***************************************************************************/
/* */
/* This program reads a C program file as input, parses identifiers and */
/* places them in a binary tree. Each tree node has an identifier, */
/* the usual "left" and "right" pointers to other tree nodes, and "front" */
/* and "rear" pointers to a queue of line number nodes. Line number */
/* nodes contain a line number where the identifier occurred and a, of */
/* course, a pointer to the next line number node. */
/* */
/* After the tree is formed, the user is prompted to see if he wants an */
/* alphabetized cross-reference listing (followed by the original source */
/* file with line numbers). If so, such a file is created with a time */
/* stamp at its top. Each line of the cross-reference shows an identi- */
/* fier followed by all lines where it can be found in the source file. */
/* */
/* After this, the user is prompted for an identifier (until he types */
/* "quit program"). The program will then output all source lines (with */
/* line numbers in the leftmost column) containing that identifier. Thus, */
/* the program allows interactive references to the source code. */
/* */
/***************************************************************************/
{
NODE *tree = NULL;
NODE *parse_file_into_ident_tree(FILE *infile);
NODE *find_identifier(char *identifier, NODE *tree);
void check_program_args(int argc, char *argv[],FILE **infile,FILE **outfile),
printtree(NODE *tree, FILE *outfile),
printprog(FILE *infile, FILE *outfile),
print_time_stamp(FILE *outfile);
FILE *infile, *outfile;
check_program_args(argc, argv, &infile, &outfile);
tree = parse_file_into_ident_tree(infile);
print_time_stamp(outfile);
printtree(tree, outfile); /* Prints cross-reference table. */
printprog(infile, outfile); /* Prints input program with line numbers in
left column. */
}
/***************************************************************************/
/* */
/* This function checks to see that a filename argument was supplied by */
/* the user when invoking this program. It also makes sure that the */
/* filename is that of a C source file (name ends with .c) and that the */
/* source file exists. */
/* */
/***************************************************************************/
void check_program_args(int argc, char *argv[], FILE **infile, FILE **outfile)
{
int filename_len;
if (argc > 3)
{
perror("Wrong number of command line arguments!");
exit(1);
}
filename_len = strlen(argv[1]);
if (argv[1][filename_len - 1] != 'c' || argv[1][filename_len - 2] != '.')
{
printf("C source file names must end with \".c\". Aborting!\n\n");
exit(1);
}
*infile = Fopen(argv[1],"r");
*outfile = Fopen(argv[2],"w");
}
/*************************************************************************/
/* */
/* THIS IS THE MOST IMPORTANT FUNCTION IN THE PROGRAM. It reads the */
/* input file byte-by-byte. If a byte starts a quoted string or */
/* comment, a function is called to read until the end of the quoted */
/* string or comment. If a newline is encountered, the byte offset of */
/* the start of the next line is registered in the array "offsets". */
/* If the beginning of an identifier is found, the identifier is com- */
/* pleted and its name is placed in the identifier tree (if it is new). */
/* If the identifier is already in the tree, the line number where the */
/* identifier was encountered is added to the line number queue which */
/* is attached to each node of the identifier tree. */
/* */
/*************************************************************************/
NODE *parse_file_into_ident_tree(FILE *infile)
{
long linenum = 1;
int c, noreadflag = 0;
char identifier[MAXIDENT], line[MAXLINE];
NODE *tree = NULL;
void get_ident(int *lastchar, char *ident, FILE *infile),
insert(char *ident, long linenum, NODE **tree);
long find_close_comment(long linenum, FILE *infile),
find_close_quote(char c, long linenum, FILE *infile);
while ( noreadflag || (c = getc(infile)) != EOF)
{
noreadflag = 0;
switch (c)
{
case '\'':
case '"' :
linenum = find_close_quote(c, linenum, infile);
break;
case '/' :
c = getc(infile);
if ( c == '*') linenum = find_close_comment(linenum,
infile);
else noreadflag = 1;
break;
case '\n':
linenum++;
break;
default:
if (isalpha(c) || c == '_')
{
get_ident(&c,identifier, infile);
insert(identifier,linenum,&tree);
if (strcmp(identifier,"include") == 0)
{
fgets(line,MAXLINE,infile);/* Ignore rest of line */
linenum++;
}
else noreadflag = 1; /* Analyze char after ident */
}
} /* end of switch */
} /* end of while -- let's return and get out!! */
return tree;
}
/****************************************************************/
/* */
/* Prints input program with line numbers in left column. */
/* */
/****************************************************************/
void printprog(FILE *infile, FILE *outfile)
{
int linecount = 0;
char line[MAXLINE];
rewind(infile);
fprintf(outfile,"\v");
while ( fgets(line,MAXLINE,infile) != NULL)
{
fprintf(outfile,"%-6d: %s",++linecount,line);
}
Fclose(outfile);
}
Cross reference listing made at: Mon Nov 29 15:19:30 2004
FILE 19 20 21 22 32 55 90
MAXCITIES 5 18
MAXLINE 6 58 60
NULL 40 46 71
argc 16 20 24 32 34
argv 16 24
char 10 16 20 32 58 71
checkArgs 20 24 32
city 58 62 63 71 76
count 12 21 22 25 26 57 63 66 67
68 70 76 80 81 85 90 94 96
define 5 6
else 66 78
exit 37 43 49 74
fgets 60
fin 19 20 21 22 24 25 32 40 55
60
first 57 65
float 96
fopen 40 46
for 94
fout 19 20 24 26 32 46 90 95
fprintf 95
highTemp 57 62 67 80
highTemps 18 21 25 26 55 63 67 68 70
76 80 81 90 95 96
hightemps 22
i 92 94 95 96
if 34 40 46 63 65 70
include 1 2 3 4
infile 20 32 40
int 11 12 16 20 21 22 32 55 57
90 92
line 58 60 62
main 16
malloc 71
outfile 20 32 46
perror 42 48 73
printf 36
readIntoWeatherStructs21 25 55
return 85
sscanf 62
statecity 10 63 70 76 95
strcmp 63
strcpy 76
strlen 71
struct 8 18 21 22 55 90
tempsum 11 67 80 96
void 20 22 32 90
weather 8 18 21 22 55 90
while 60
writeAveragesToOutput22 26 90
1 : #include <stdio.h>
2 : #include <stdlib.h>
3 : #include <string.h>
4 : #include <ctype.h>
5 : #define MAXCITIES 100
6 : #define MAXLINE 80
7 :
8 : struct weather
9 : {
10 : char *statecity;
11 : int tempsum;
12 : int count;
13 : };
14 :
15 :
16 : int main(int argc, char **argv)
17 : {
18 : struct weather highTemps[MAXCITIES] = {{"", 0, 0}};
19 : FILE *fin, *fout;
20 : void checkArgs(int argc,char *infile,char *outfile,FILE **fin,FILE **fout);
21 : int readIntoWeatherStructs(struct weather *highTemps, FILE *fin), count;
22 : void writeAveragesToOutput(struct weather *hightemps, int count, FILE *fin);
23 :
24 : checkArgs(argc, argv[1], argv[2], &fin, &fout);
25 : count = readIntoWeatherStructs(highTemps, fin);
26 : writeAveragesToOutput(highTemps, count, fout);
27 : }
28 :
29 :
30 :
31 :
32 : void checkArgs(int argc, char *infile, char *outfile, FILE **fin, FILE **fout)
33 : {
34 : if (argc != 3)
35 : {
36 : printf("Wrong number of arguments on command line!\n");
37 : exit(1);
38 : }
39 :
40 : if ((*fin = fopen(infile, "r")) == NULL)
41 : {
42 : perror("Cannot open input file");
43 : exit(1);
44 : }
45 :
46 : if ((*fout = fopen(outfile, "w")) == NULL)
47 : {
48 : perror("Cannot open output file");
49 : exit(1);
50 : }
51 : }
52 :
53 :
54 :
55 : int readIntoWeatherStructs(struct weather *highTemps, FILE *fin)
56 : {
57 : int count = 0, first = 1, highTemp;
58 : char city[MAXLINE], line[MAXLINE];
59 :
60 : while (fgets(line, MAXLINE, fin))
61 : {
62 : sscanf(line, "%s %d", city, &highTemp);
63 : if (strcmp(city, highTemps[count].statecity) != 0)
64 : {
65 : if (first) first = 0;
66 : else count++;
67 : highTemps[count].tempsum = highTemp;
68 : highTemps[count].count = 1;
69 :
70 : if ((highTemps[count].statecity =
71 : (char *) malloc(strlen(city) + 1)) == NULL)
72 : {
73 : perror("Malloc error!");
74 : exit(1);
75 : }
76 : strcpy(highTemps[count].statecity, city);
77 : }
78 : else
79 : {
80 : highTemps[count].tempsum += highTemp;
81 : highTemps[count].count++;
82 : }
83 : }
84 :
85 : return count;
86 : }
87 :
88 :
89 :
90 : void writeAveragesToOutput(struct weather *highTemps, int count, FILE *fout)
91 : {
92 : int i;
93 :
94 : for (i = 0; i <= count; i++)
95 : fprintf(fout, "%s %-5.1f\n", highTemps[i].statecity,
96 : (float) highTemps[i].tempsum/highTemps[i].count);
97 : }