Skip to content

Commit 761ef74

Browse files
committed
rewrite code
1 parent 17cef27 commit 761ef74

File tree

1 file changed

+77
-89
lines changed

1 file changed

+77
-89
lines changed

chapter05/5-13.c

Lines changed: 77 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -3,130 +3,118 @@
33
* input. By default, n is set to 10, let us say, but it can be changed by an
44
* optional argument so that
55
*
6-
* tail -n
6+
* tail -n
77
*
88
* prints the last n lines. The program should behave rationally no matter how
9-
* unreasonable the input or value of n. Write the program so it makes the
10-
* best use of available storage; lines should be stored as in the sorting
11-
* program of section 5.6, not in a two-dimensional array of fixed size.
9+
* unreasonable the input or value of n. Write the program so it makes the best
10+
* use of available storage; lines should be stored as in the sorting program
11+
* of section 5.6, not in a two-dimensional array of fixed size.
12+
*
1213
* By Faisal Saadatmand
1314
*/
1415

1516
#include <stdio.h>
16-
#include <string.h>
1717
#include <stdlib.h>
18-
#include <ctype.h>
18+
#include <string.h>
19+
20+
#define MAXLEN 1000 /* max length of any input line */
21+
#define MAXLINES 5000 /* max #lines to be stored */
22+
#define ALLOCSIZE 10000 /* size of available space */
23+
24+
static char allocbuf[ALLOCSIZE]; /* storage for alloc */
25+
static char *allocp = allocbuf; /* next free position */
1926

20-
#define MAXLINES 5000 /* max #lines to be stored */
21-
#define MAXLEN 1000 /* max length of any input line */
22-
#define ALLOCSIZE 100000 /* storage for alloc */
23-
#define N 10 /* default value of last lines to print */
2427

2528
/* functions */
26-
int readlines(char *[], int);
27-
int getLine(char *, int);
29+
int getLine(char *, int);
2830
char *alloc(int);
29-
int isDigitStr(char *[]);
31+
int readlines(char *[], int);
32+
void writelines(char *[], int);
33+
int expandArg(int, char **, int *);
3034

31-
/* globals */
32-
char *lineptr[MAXLINES]; /* pointers to text lines */
33-
static char allocbuf[ALLOCSIZE]; /* storage for alloc */
34-
static char *allocp = allocbuf; /* next free position */
35+
/* getLine function: read a line into s, return length */
36+
int getLine(char *s, int lim)
37+
{
38+
int c;
39+
char *len;
40+
41+
len = s;
42+
while (--lim > 0 && (c = getchar()) != EOF && c != '\n')
43+
*s++ = c;
44+
if (c == '\n')
45+
*s++ = c;
46+
*s = '\0';
47+
return strlen(len);
48+
}
49+
50+
/* alloc: return pointer to n characters */
51+
char *alloc(int n)
52+
{
53+
if (allocbuf + ALLOCSIZE - allocp >= n) { /* it fits */
54+
allocp += n;
55+
return allocp - n; /*old p */
56+
}
57+
return NULL; /* not enough room */
58+
}
3559

3660
/* readlines: read input lines */
37-
int readlines(char *lineptr[], int maxlines)
61+
int readlines(char *linerptr[], int maxlines)
3862
{
3963
int len, nlines;
4064
char *p, line[MAXLEN];
4165

4266
nlines = 0;
43-
while ((len = getLine(line, MAXLEN)) > 0)
67+
while ((len = getLine(line, MAXLEN)) > 0) {
4468
if (nlines >= maxlines || (p = alloc(len)) == NULL)
4569
return -1;
46-
else {
47-
line[len - 1] = '\0'; /* delete newline character */
48-
strcpy(p, line);
49-
lineptr[nlines++] = p;
50-
}
51-
return nlines;
52-
}
53-
54-
/* getLine: get line into s, return length of s -- pointer version */
55-
int getLine(char *s, int lim)
56-
{
57-
int c, len;
58-
59-
len = 0;
60-
while (--lim > 0 && (c = getchar()) != EOF && c != '\n') {
61-
*s++ = c;
62-
++len;
63-
}
64-
if ( c == '\n') {
65-
*s++ = c;
66-
++len;
70+
line[len - 1] = '\0'; /* delete newline */
71+
strcpy(p, line);
72+
linerptr[nlines++] = p;
6773
}
68-
*s = '\0';
69-
return len;
74+
return nlines;
7075
}
7176

72-
/* alloc: allocate memory */
73-
char *alloc(int n) /* return pointer to n characters */
77+
/* writelines: write output lines */
78+
void writelines(char *lineptr[], int nlines)
7479
{
75-
if (allocbuf + ALLOCSIZE - allocp >=n) { /* it fits */
76-
allocp += n;
77-
return allocp - n; /* old p */
78-
} else /* not enough room */
79-
return 0;
80+
while (nlines-- > 0)
81+
printf("%s\n", *lineptr++);
8082
}
8183

82-
/* isDigitStr: check if string is made of positive integers characters. Return
83-
* 1 if true; 0 if false */
84-
int isDigitStr(char *s[])
84+
int expandArg(int count, char **list, int *n)
8585
{
86-
int i;
86+
char *prog = *list, *end;
8787

88-
for (i = 0; (*s)[i]; ++i) /* omitted '\0', since s is a pointer */
89-
if (!isdigit((*s)[i]))
88+
while (--count > 0)
89+
if (!strcmp(*++list, "-n")) {
90+
end = NULL;
91+
if (!(*n = strtol(*++list, &end, 10)) || *end) {
92+
printf("%s: invalid number of lines: %s\n", prog, *list);
9093
return 0;
94+
}
95+
*n = abs(*n); /* treat negative numbers as positives */
96+
--count;
97+
} else {
98+
printf("Usage: %s [-n lines]\n", prog);
99+
return 0;
100+
}
91101
return 1;
92102
}
93103

94104
int main(int argc, char *argv[])
95105
{
96-
int nlines; /* number of input lines read */
97-
int type; /* type of argument operator */
98-
int i; /* index variable */
99-
int n; /* cli argument value of n */
100-
101-
while (--argc > 0) {
102-
type = *(++argv)[0];
103-
switch (type) {
104-
case ('-'):
105-
n = *++argv[0];
106-
if (isDigitStr(argv)) {
107-
n = atoi(*argv);
108-
argc = 0; /* signal to exit loop */
109-
}
110-
else {
111-
n = 0; /* signal invalid value */
112-
argc =0;
113-
}
114-
break;
115-
default:
116-
n = 0; /* signal invalid input */
117-
argc = 0;
118-
break;
119-
}
120-
}
106+
char *lineptr[MAXLINES]; /* pointers to text lines */
107+
int nlines; /* number of read lines */
108+
int n = 10; /* default last n lines to print */
121109

122-
if ((nlines = readlines(lineptr, MAXLINES)) >= 0) {
123-
if (n <= 0 || n > nlines) /* check input or value of argument */
124-
n = N; /* default to N, if unreasonable */
125-
for (i = 0; i < n; ++i)
126-
printf("%s\n", lineptr[(nlines - n) + i]);
127-
return 0;
128-
} else {
129-
printf("error: input too big to sort\n");
130-
return 1;
110+
if (!expandArg(argc, argv, &n))
111+
return -1;
112+
if ((nlines = readlines(lineptr, MAXLINES)) < 0) {
113+
printf("Error: input is too big\n");
114+
return -1;
131115
}
116+
if (n > nlines) /* max limit check */
117+
n = nlines; /* print entire input, not more */
118+
writelines(lineptr + nlines - n, n);
119+
return 0;
132120
}

0 commit comments

Comments
 (0)