Exercise 5-6-1 (getline, Sec. 1.9)

Chapter_5     Exercise_5-6 Exercise_5-6-2     Exercise_5-7







Exercise 5-6     K&R, p. 107


Exercise 5-6. Rewrite appropriate programs from earlier chapters and exercises with pointers instead of array indexing. Good possibilities include getline() (Chapters 1 and 4), atoi(), itoa(), and their variants (Chapters 2, 3, and 4), reverse(), (Chapter 3), and strindex() and getop() (Chapter 4).




CONTENTS:     longest.c     longline.c     prnln.c     trimfile  (trimfile1.ctrimfile2.c)     reverse.c     extlong.c     copy.c




Note:  See also getcalc.c in Exercise_5-6-10.




longest.c     K&R, p. 29  (ch1-longest)         download


#include <stdio.h> // for getchar(), putchar(), printf(), EOF

#define MAXLINE 1000 // maximum input line size

int getLine(char *line, int maxline); // getline() is declared in stdio.h
// int getLine(char *, int); // alternative declaration
void copy(char *to, char *from);
// void copy(char *, char *); // alternative declaration

int main()
{
int len; // current line length
int max; // maximum length seen so far
char line[MAXLINE]; // current input line
char longest[MAXLINE]; // longest line saved here

max = 0; // initialize
while((len = getLine(line, MAXLINE)) > 0)
{ // line containing only '\n' not empty
if (len > max)
{
max = len;
copy(longest, line);
}
}
if (max > 0) // there was a line
{
printf("%s", longest);
if (*(longest+max-1) != '\n')
{putchar('\n');} // line may not end with '\n'
}

return 0;
}

// getLine(): read a line into s[], return length
int getLine(char *s, int lim)
{
int c = EOF; // initialize
int i;
// getchar() is only executed if (i < (lim-1)):
for (i = 0; i < (lim-1) && (c = getchar()) != EOF && c != '\n'; i++)
{ // from 0 to lim-2; s[lim-2]='\n' or not, s[lim-1]='\0'
*(s+i) = c;
}
if (c == '\n') // i < (lim-1), getchar() executed
{
*(s+i) = c; // '\n'
i++;
}
*(s+i) = '\0'; // the null character ends a string

return i; // max(i) == (lim-1), assuming (lim-1) > 0
}

// copy *from into *to; assume *to is big enough:
void copy(char *to, char *from)
{
int i;

for (i = 0; (*(to+i) = *(from+i)) != '\0'; i++)
{} // ends after copying '\0'
}
/*
gcc longest.c -o longest
./longest // input from the keyboard
The sky is gray
A storm is coming
Rain fills the rivers // Enter, then EOF (Ctrl+D in Linux, Ctrl+Z+Enter in Windows)
Rain fills the rivers

./longest < longest.c // source file
Rain fills the rivers // Enter, then EOF (Ctrl+D in Linux, Ctrl+Z+Enter in Windows)

./longest < longest // binary file
ELF // line contains '\0', which ends copy() and printf ("%s")
*/











longline.c     K&R, p. 30  (Ex_1-16)         download


#include <stdio.h> // for getchar(), printf(), EOF

#define MAXLINE 1000 // maximum input line size printed

long getLine(char *line, int maxline); // getline() is declared in stdio.h
// long getLine(char *, int); // alternative declaration
void copy(char *to, char *from);
// void copy(char *, char *); // alternative declaration

// getLine() returns the size of an arbitrarily long line
// program prints longest line up to MAXLINE characters
int main()
{
long len; // current line length
long max; // maximum length seen so far
char line[MAXLINE]; // current input line
char longest[MAXLINE]; // longest line saved here

max = 0; // initialize
while((len = getLine(line, MAXLINE)) > 0)
{ // line containing only '\n' has length 1
if (len > max)
{
max = len;
copy(longest, line);
}
}
if (max > 0) // there was a line
{
printf("Length: %ld\n", max);
printf("%s\n", longest); // line may not end with '\n'
}

return 0;
}

// getLine(): read a line into *s up to MAXLINE-1 chars, return total length
long getLine(char *s, int lim)
{
int c = EOF; // initialize
long i; // length of an arbitrarily long line
// getchar() is only executed if (i < (lim-1)):
for (i = 0; i < (lim-1) && (c = getchar()) != EOF && c != '\n'; i++)
{ // from 0 to lim-2; s[lim-2]='\n' or not, s[lim-1]='\0'
*s++ = c;
}
if (c == '\n') // i < (lim-1), getchar() executed
{
*s++ = c; // '\n'
i++;
}
*s = '\0'; // the null character ends a string

if (c != EOF && c != '\n') // i == (lim-1) > 0
{
while ((c = getchar()) != EOF && c != '\n')
{i++;}
}

return i; // max(i) can exceed lim
}

// copy *from into *to; assume *to is big enough:
void copy(char *to, char *from)
{
for ( ; (*to = *from) != '\0'; to++, from++)
{} // ends after copying '\0'
}
/*
gcc longline.c -o longline
./longline < longline.c // source file
Length: 77
// getLine(): read a line into *s up to MAXLINE-1 chars, return total length

./longline < longline // binary file
Length: 4824
ELF // line contains '\0', which ends copy() and printf("%s")
*/





Note:  In main() we cannot write printf("%s", longest); if (*(longest+max-1) != '\n') {putchar('\n');} // line may not end with '\n' because max may exceed MAXLINE. That is actually the reason getLine() returns a long instead of an int, as in the previous program (longest).











prnln.c     K&R, p. 31  (Ex_1-17)         download


#include <stdio.h> // for getchar(), putchar(), printf(), EOF

#define LENGTH 80 // minimum input line length printed (without '\0')

int getLine(char *line, int maxline); // getline() is declared in stdio.h
// int getLine(char *, int); // alternative declaration
void prnln(char *line); // print line
// void prnln(char *); // alternative declaration

// print lines longer that LENGTH characters (including '\0')
int main()
{
int len; // current line length
char line[LENGTH+1]; // current input line
// +1 for ending '\0'
while((len = getLine(line, LENGTH+1)) > 0)
{ // line containing only '\n' has length 1
if (len > LENGTH) // len >= (LENGTH+1)
{prnln(line);}
}

return 0;
}

// getLine(): read a line into *s up to LENGTH chars, return length or LENGTH+1
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-s) < (lim-1), getchar() executed
{
*p++ = c; // '\n'
}
*p = '\0'; // the null character ends a string

if (c != EOF && c != '\n') // p-s == (lim-1) > 0
{return (p-s+1);} // (p-s+1) == lim (LENGTH+1)
// else return p-s;
return p-s; // max(p-s) == (lim-1)
}

// prnln(); print line, ending with first '\n' or EOF
void prnln(char *line)
{
int c;

printf("%s", line); // line does not end with '\n'

while ((c = getchar()) != EOF && c != '\n')
{putchar(c);}

putchar('\n'); // line may end with '\n' or EOF
}
/*
gcc prnln.c -o prnln
./prnln // input from the keyboard
12345678901234567890123456789012345678901234567890123456789012345678901234567890
12345678901234567890123456789012345678901234567890123456789012345678901234567890
// Ctrl+D in Linux, Ctrl+Z then Enter in Windows (EOF)

./prnln < prnln.c // source file
// getLine(): read a line into s[] up to LENGTH chars, return length or LENGTH+1
12345678901234567890123456789012345678901234567890123456789012345678901234567890
12345678901234567890123456789012345678901234567890123456789012345678901234567890

./prnln < prnln // binary file
*/











trimfile  (trimfile1.ctrimfile2.c)     K&R, p. 31  (Ex_1-18)




trimfile1.c         download


#include <stdio.h> // for getchar(), printf(), EOF

#define MAXLINE 1000 // maximum input line length

int getLine(char *line, int maxline); // getline() is declared in stdio.h
int trimline(char *line, int length);

// remove trailing blanks and tabs, delete blank lines
int main()
{
int len; // current line length
char line[MAXLINE]; // current input line
// line containing only '\n' has length 1:
while((len = getLine(line, MAXLINE)) > 0)
{
if (trimline(line, len) > 0) // nonempty line
{printf("%s\n", line);} // trimmed line doesn't end with '\n'
}

return 0;
}

// getLine(): read a line into *s up to MAXLINE-1 chars, return length
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-s) < (lim-1), getchar() executed
{
*p = c; // '\n'
p++;
}
*p = '\0'; // the null character ends a string

return p-s; // max(p-s) == (lim-1)
}

// remove trailing blanks, tabs, ending '\n', return new length
int trimline(char *line, int len)
{ // line pointer:
char *lp = line+len-1; // last char before ending '\0'

if (*lp == '\n')
{
*lp = '\0'; // remove ending '\n'
lp--;
}

while (lp >= line)
{
if (*lp == ' ' || *lp == '\t')
{
*lp = '\0';
lp--;
}
else break; // out of while()
}

if (lp < line) {return 0;} // blank line
// else return lp-line+1;
return lp-line+1; // new length
}
/*
gcc trimfile1.c -o trimfile1
./trimfile1 // input from the keyboard

./trimfile1 < trimfile1.c // source file

./trimfile1 < trimfile1 // binary file
*/











trimfile2.c         download


#include <stdio.h> // for getchar(), printf(), EOF

#define MAXLINE 1000 // maximum input line length

int getLine(char *line, int maxline); // getline() is declared in stdio.h
int trimline(char *line, int length);

// remove beginning and trailing blanks and tabs, delete blank lines
int main()
{
int len; // current line length
char line[MAXLINE]; // current input line
// line containing only '\n' has length 1:
while((len = getLine(line, MAXLINE)) > 0)
{
if (trimline(line, len) > 0) // nonempty line
{printf("%s\n", line);} // trimmed line doesn't end with '\n'
}

return 0;
}

// getLine(): read a line into *s up to MAXLINE-1 chars, return length
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-s) < (lim-1), getchar() executed
{
*p = c; // '\n'
p++;
}
*p = '\0'; // the null character ends a string

return p-s; // max(p-s) == (lim-1)
}

// remove beginning and ending whitespace, return new length
int trimline(char *line, int length) // length > 0
{
char *start = line, *end = line+length-1, *lp = line;

while (start <= end && (*start == ' ' || *start == '\t'))
{start++;}

if (start > end || *start == '\n')
{
*lp = '\0'; // empty trimmed line
return 0;
}

// from here on non-empty trimmed line (from the beginning)
if (*end == '\n')
{end--;} // remove ending '\n'

if (end >= start) // start >= line
{
while (*end == ' ' || *end == '\t')
{end--;}
}

if (start > line) // shift line to the beginning (remove beginning whitespace)
{
while (start <= end)
{*lp++ = *start++;}
}
else {lp = end+1;} // after the string
*lp = '\0'; // end line before trailing whitespace

return lp-line; // new length (lp points to null, after the string)
}
/*
gcc trimfile2.c -o trimfile2
./trimfile2 // input from the keyboard
Hello!
Hello!
Have a nice day!
Have a nice day!
// Ctrl^D in Linux, Ctrl^Z+Enter in Windows (EOF)

./trimfile2 < trimfile2.c // input from source file

./trimfile2 < trimfile2 // binary file
*/











reverse.c     K&R, p. 31  (Ex_1-19)         download


#include <stdio.h> // for getchar(), putchar(), printf(), EOF

#define MAXLINE 1000 // maximum input line length

int getLine(char *line, int maxline); // getline() is declared in stdio.h
void reverse(char *line, int length);

// reverse each line
int main()
{
int len; // current line length
char line[MAXLINE]; // current input line
// line containing only '\n' has length 1:
while((len = getLine(line, MAXLINE)) > 0)
{
reverse(line, len);
printf("%s", line);
if (*(line+len-1) != '\n') {putchar('\n');}
}

return 0;
}

// getLine(): read a line into 's' up to LENGTH chars, return length
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-s) < (lim-1), getchar() executed
{
*p++ = c; // '\n'
}
*p = '\0'; // the null character ends a string

return p-s; // max(p-s) == (lim-1)
}

// reverse a string of characters
void reverse(char *line, int len)
{ // line pointers:
char *start = line; // &line[0]
char *end = line+len-1; // last char before '\0'
if (*end == '\n') {end--;} // do not put '\n' on position 0
int temp; // temporary value

while (start < end)
{
temp = *start;
*start++ = *end;
*end-- = temp;
}
}
/*
gcc reverse.c -o reverse
./reverse // input from the keyboard
ana
ana
anna
anna
ab
ba
a
a
abc
cba
abcd
dcba
12345
54321
// Ctrl+D in Linux, Ctrl+Z then Enter in Windows (EOF)

./reverse < reverse.c // source file

./reverse < reverse // binary file
*/











extlong.c     K&R, p. 32-33  (ch1-extlong)         download


#include <stdio.h> // for getchar(), putchar(), printf(), EOF

#define MAXLINE 1000 // maximum input line size

int max; // maximum length seen so far
char line[MAXLINE]; // current input line
char longest[MAXLINE]; // longest line saved here

int getLine(void); // getline() is declared in stdio.h
void copy(void);

// print longest input line; specialized version
int main()
{
int len;
// extern int max;
// extern char longest[]; // extern char *longest; // compile error

max = 0;
while((len = getLine()) > 0)
{
if (len > max)
{
max = len;
copy();
}
}

if (max > 0) // there was a line
{
printf("%s", longest);
if (*(longest+max-1) != '\n')
{putchar('\n');} // longest may not end with '\n'
}

return 0;
}

// getLine(): specialized version
int getLine(void)
{
int c = EOF, i;
// extern char line[];
// getchar() is only executed if (i < (MAXLINE-1))
for (i = 0; i < (MAXLINE-1) && (c = getchar()) != EOF && c != '\n'; i++)
{ // from 0 to MAXLINE-2; line[MAXLINE-2]='\n' or not, line[MAXLINE-1]='\0'
*(line+i) = c; // *line++ = c; // compile error (constant pointer)
}

if (c == '\n') // i < (MAXLINE-1), getchar() executed
{
*(line+i) = c;
i++;
}
*(line+i) = '\0';

return i;
}

// copy(): specialized version
void copy(void)
{
int i;
// extern char line[], longest[];

i = 0;
while((*(longest+i) = *(line+i)) != '\0')
{i++;} // ends after copying '\0'
// for (i = 0; (*(longest+i) = *(line+i)) != '\0'; i++) {}
}
/*
gcc extlong.c -o extlong
./extlong // input from the keyboard
The sky is gray
A storm is coming
Rain fills the rivers
Rain fills the rivers // Enter, then Ctrl+D in Linux, Ctrl+Z+Enter in Windows (EOF)

./extlong < extlong.c // source file
Rain fills the rivers // Enter, then Ctrl+D in Linux, Ctrl+Z+Enter in Windows (EOF)

./extlong < extlong // binary file
*/











copy.c     K&R, p. 42  (Ex_2-2)         download


#include <stdio.h> // for getchar(), putchar(), printf(), EOF

#define MAXLINE 1000 // maximum input line size

int getLine(char *line, int maxline); // getline() is defined by stdio.h
// int getLine(char *, int); // alternative declaration

int main()
{
int len; // current line length
char line[MAXLINE]; // current input line

while((len = getLine(line, MAXLINE)) > 0)
{ // line containing only '\n' not empty
printf("%s", line);
if (*(line+len-1) != '\n')
{putchar('\n');} // line may not end with '\n'
}

return 0;
}

// getLine(): read a line into 's', return length
int getLine(char *s, int lim)
{
int c = EOF; // initialize
char *p;
// getchar() is only executed if ((p-si < (lim-1)):
for (p = s; (p-s) < (lim-1); p++)
{ // from 0 to lim-2; s[lim-2]='\n' or not, s[lim-1]='\0'
c = getchar();
if (c == EOF) // (p-s) < (lim-1), getchar() executed
{
*p = '\0'; // the null character ends a string
return p-s;
}
if (c == '\n') // (p-s) < (lim-1), getchar() executed
{
*p++ = c; // '\n'
*p = '\0'; // the null character ends a string
return p-s;
}
*p = c;
} // here c != EOF && c != '\n'

*p = '\0'; // max(p-s) == (lim-1)
return p-s;
}
/*
gcc copy.c -o copy
./copy < copy.c // source file

./copy < copy.c > copy2.c
gcc copy2.c -o copy2
./copy2 < copy2.c

./copy < copy // binary file
./copy < copy > copy2
./copy2 < copy2.c // some run-time error

rm copy2.c copy2 // clean
*/









Chapter_5     Exercise_5-6 BACK_TO_TOP Exercise_5-6-2     Exercise_5-7



Comments

Popular posts from this blog

Contents

Blogger Page Margins in Contempo