ch5-Index program (lines)
Chapter_5 Exercise_5-17 | declare Exercise_5-18 |
CONTENTS: fdnsort.txt index.c index.txt
Note: Program lines in Exercise_5-17 created the file fdnsort.txt, which was almost like an index:
fdnsort.txt download
++ increment operator 18
++ increment operator 46
++ increment operator 106
++ increment operator 203
<< left shift operator 49
<< left shift operator 206
<= less or equal operator 41
<= less or equal operator 206
< less than operator 41
< less than operator 206
alloc function 101
a.out 6
a.out 70
call by reference 27
call by value 27
call by value 95
call by value 202
command-line arguments 114
command-line arguments 115
command-line arguments 116
command-line arguments 117
command-line arguments 118
<ctype.h> header 43
<ctype.h> header 248
default label 58
default label 222
#define, multi-line 89
#define with arguments 89
definition, function 25
definition, function 69
definition, function 225
increment operator, ++ 18
increment operator, ++ 46
increment operator, ++ 106
increment operator, ++ 203
left shift operator, << 49
left shift operator, << 206
less than operator, < 41
less than operator, < 206
pointer initialization 102
pointer initialization 138
pointer, null 102
pointer, null 198
pointer to function 118
pointer to function 147
pointer to function 201
\t tab character 8
\t tab character 11
\t tab character 38
\t tab character 193
temperature conversion program 8
temperature conversion program 9
temperature conversion program 12
temperature conversion program 13
temperature conversion program 15
UNIX file system 169
UNIX file system 179
Note: We use the index program below (index.c) to turn fdnsort.txt into index.txt with proper index entries.
index.c download
#include <stdio.h> // for getchar(), printf(), EOF, NULL, FILE, fopen(), fclose()
#include <string.h> // for strcmp(), strcat(), strcpy(), strlen()
#define MAXLINES 5000 // max no of lines to be sorted
#define MAXLEN 1000 // max line length
#define MAXFNLEN 100 // max file name length
#define MAXNODIG 15 // max no of digits of a page number
#define MAXPGNOS 1000 // max no of page numbers for an index entry
int readlines (char *lineptr[], int nlines);
unsigned getPgNo(char *); // read a line, return page number
int utoa (unsigned , char *); // unsigned to string, return length
void writelines (char lines[][MAXLEN], int nlines, char *filename);
int main()
{
char *lineptr[MAXLINES];
int nlines; // no of input lines read
char indexLines[MAXLINES][MAXLEN];
char number[MAXNODIG];
int i, j, k, pgnos; // no of page numbers read from lines
unsigned numbers[MAXPGNOS];
int indLines; // index lines
if ((nlines = readlines(lineptr, MAXLINES)) >= 0)
{
i = 0;
indLines = 0; // index of the first index line
// if nlines == 1, there is only one line, which needs no processing
while (i < nlines-1)
{ // there are at least two lines left
if (i > 0) // not the first iteration
{ // ungetch()
numbers[0] = numbers[pgnos];
pgnos = 1, i++;
numbers[pgnos] = getPgNo(lineptr[i]);
}
else // first iteration, i == 0
{
pgnos = 0;
numbers[pgnos] = getPgNo(lineptr[i]);
strcpy(indexLines[indLines], lineptr[i]); // first index line
pgnos++, i++;
numbers[pgnos] = getPgNo(lineptr[i]);
}
while (i < nlines && strcmp(lineptr[i], indexLines[indLines]) == 0)
{
++pgnos, ++i;
if (i < nlines)
{numbers[pgnos] = getPgNo(lineptr[i]);}
}
// pgnos holds no of 'equal' lines
for (j = 0; j < pgnos; j++)
{
if (j == pgnos-1) // last page number
{
if (pgnos > 1)
{strcat(indexLines[indLines], ", ");}
else {strcat(indexLines[indLines], " ");} // 2 spaces after string
utoa(numbers[j], number);
strcat(indexLines[indLines], number);
break; // out of for()
}
k = j;
while (numbers[j+1]-numbers[j] == 1)
{
j++;
if (j == pgnos-1)
{break;} // out of while()
}
if (k > 0)
{strcat(indexLines[indLines], ", ");}
else {strcat(indexLines[indLines], " ");} // 2 spaces after string
utoa(numbers[k], number);
strcat(indexLines[indLines], number);
if (j > k) // at least two consecutive numbers
{
strcat(indexLines[indLines], "-"); // or dash
utoa(numbers[j], number);
strcat(indexLines[indLines], number);
}
}
strcat(indexLines[indLines], "\n");
indLines++; // no of index lines 'read' so far
if (i < nlines) // there are unprocessed lines
{
strcpy(indexLines[indLines], lineptr[i]); // last processed line
if (i == nlines - 1) // last line
{ // rebuild processed line
strcat(indexLines[indLines], " "); // 2 spaces after string
utoa(numbers[pgnos], number);
strcat(indexLines[indLines], number);
strcat(indexLines[indLines], "\n");
indLines++; // no of index lines
i++; // end while()
}
}
}
writelines(indexLines, indLines, "index.txt");
}
else
{
printf("Error: input too big to sort\n");
return 1; // exit program, signalling error
}
return 0;
}
int getLine(char *, int); // getline() is declared in stdio.h
char* alloc(int); // allocate storage
int readlines (char *lineptr[], int maxlines) // read input lines
{
int len; // length of line
int nlines; // no of input lines read
char *p, line[MAXLEN*2]; // index entry,
// substring followed by a sequence of page numbers
nlines = 0;
while ((len = getLine(line, MAXLEN)) > 0)
{ // allocate enough space for an index entry
if (line[0] == '\n') // do not add empty lines
{continue;} // go to the next iteration of while()
if(nlines >= maxlines || (p = alloc(len + 1)) == NULL)
{return -1;} // (+1 for ending '\0')
else
{
strcpy(p, line);
lineptr[nlines++] = p;
}
}
return nlines;
}
int getLine(char *s, int lim)
{
int c = EOF; // initialize
char *p;
// getchar() is only executed if ((p-s) < (lim-1)):
for (p = s; (p-s) < (lim-1) && (c = getchar()) != EOF && c != '\n'; p++)
{ // from 0 to lim-2; s[lim-2]='\n', s[lim-1]='\0'
*p = c;
}
if (c == '\n')
{*p++ = c;}
*p = '\0'; // the null character ends a string
return p-s; // max(p-s) == (lim-1)
}
#define ALLOCSIZE (MAXLINES * MAXLEN)
static char allocbuf[ALLOCSIZE]; // storage for alloc()
static char *allocp = allocbuf; // next free position
char* alloc(int n) // return pointer to n chars
{
if (allocbuf + ALLOCSIZE - allocp >= n) // it fits
{
allocp += n;
return allocp-n; // old pointer
}
else {return 0;} // null pointer
}
void afree(char *p) // free storage pointed to by p
{
if (p >= allocbuf && p < allocbuf + ALLOCSIZE)
{allocp = p;}
}
#include <ctype.h> // for isdigit()
void reverse(char *s, int len); // reverse string s, knowing its length
unsigned atou(char *s);// string to unsigned
unsigned getPgNo(char *str) // read a line, return page number
{
int len = 0;
char pgno[MAXNODIG];
char *p = str+strlen(str)-1; // last char of str before '\0'
if (*p == '\n') {p--;} // last char of str before '\n'
while (isdigit(*p))
{
pgno[len++] = *p;
p--;
}
pgno[len] = '\0'; // end string
*p = '\0'; // shrink str to contain only a string
reverse(pgno, len); // page number
return atou(pgno);
}
void reverse(char *s, int len) // reverse string s, knowing its length
{
char *start = s, *end = s+len-1;
char temp;
while (start < end)
{
temp = *start;
*start++ = *end;
*end-- = temp;
}
}
// string to unsigned
unsigned atou(char *s)
{
unsigned n = 0; // number
while (*s != '\0' && isdigit(*s))
{
n = n * 10 + (*s - '0');
s++;
}
return n;
}
int utoa (unsigned n, char *s) // unsigned to string
{
char *p = s;
do
{ // get the digits in reverse order:
*p++ = n % 10 + '0'; // get next (last read) digit
} while (n /= 10); // while ((n /= 10) != 0); // delete last digit
*p = '\0'; // end the string
reverse(s, p-s);
return p-s;
}
// write output lines
void writelines (char lines[][MAXLEN], int nlines, char *filename)
{
FILE *f = fopen(filename, "w"); // open for writing
while (nlines-- > 0)
{fprintf(f, "%s", *lines++);}
fclose(f);
}
/*
gcc index.c -o index
./index < fdnsort.txt // created file "index.txt"
meld fdnsort.txt index.txt // compare files
*/
index.txt K&R, p. 263-271 (Index) download
++ increment operator 18, 46, 106, 203
<< left shift operator 49, 206
<= less or equal operator 41, 206
< less than operator 41, 206
alloc function 101
a.out 6, 70
call by reference 27
call by value 27, 95, 202
command-line arguments 114-118
<ctype.h> header 43, 248
default label 58, 222
#define, multi-line 89
#define with arguments 89
definition, function 25, 69, 225
increment operator, ++ 18, 46, 106, 203
left shift operator, << 49, 206
less than operator, < 41, 206
pointer initialization 102, 138
pointer, null 102, 198
pointer to function 118, 147, 201
\t tab character 8, 11, 38, 193
temperature conversion program 8-9, 12-13, 15
UNIX file system 169, 179
Chapter_5 Exercise_5-17 | BACK_TO_TOP | declare Exercise_5-18 |
Comments
Post a Comment