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

Popular posts from this blog

Contents

Blogger Page Margins in Contempo