Exercise 8-1 (cat - Concatenate files)

Chapter_8     cp_(copy_files) lseek     Exercises_8-2,3







Exercise 8-1     K&R, p. 174


Exercise 8-1. Rewrite the program ch7-cat from Chapter_7 using read, write, open, and close instead of their standard library equivalents. Perform experiments to determine the relative speeds of the two versions.




cat.c     K&R, p. 162, 171-174         download


#include <stdio.h> // BUFSIZ, fprintf(), vfprintf(), fopen(), fclose(),
// ferror(), getc(), putc(), stdin, stdout, stderr, FILE, EOF, NULL
#include <stdlib.h> // for exit()
#include <time.h> // for clock_t, clock(), CLOCKS_PER_SEC
#include <fcntl.h> // for open(), O_RDONLY
#include <unistd.h> // for read(), write(), fd 0 (stdin), 1 (stdout)

#define PERM 0666 // RW for owner, group, others

void filecopy(FILE *, FILE *);

void error(char *, ...);

// concatenate files, high-level and low-level versions
int main(int argc, char *argv[])
{
FILE *fp; // file pointer
int fd; // file descriptor
int i, n;

char buf[BUFSIZ]; // 8192 bytes
char *prog = argv[0]; // program name

clock_t start, end;
double time;

start = clock();
// high-level version
if (argc == 1) // no command-line args, just program name
{ // copy standard input to standard output
filecopy(stdin, stdout);
}
else
{
for (i = 1; i < argc; i++) // start after argv[0], program name
{ // open file for reading
if ((fp = fopen(argv[i], "r")) == NULL)
{
fprintf(stderr, "%s: can't open \"%s\"\n", prog, *argv);
exit(1); // end program, signalling error
}
// else // fp != NULL, file open for reading
filecopy(fp, stdout);
fclose(fp); // close file, free fp
}
}
if (ferror(stdout))
{
fprintf(stderr, "%s: error writing stdout\n", prog);
exit(2); // end program, signal other error code
}
end = clock();
time = ((double) (end - start)) / CLOCKS_PER_SEC;
fprintf(stderr, "Execution time for high-level version: %f\n", time);

start = clock();
// low-level version
if (argc == 1) // no command-line args, just program name
{ // copy standard input to standard output
// read from file descriptor 0 (stdin) into buf[]
while ((n = read(0, buf, BUFSIZ)) > 0)
{write(1, buf, n);}
// write n bytes from buf[] into file descriptor 1 (stdout)
}
else
{
for (i = 1; i < argc; i++) // start after argv[0], program name
{ // open file for reading
if ((fd = open(argv[i], O_RDONLY, 0)) == -1) // 0 - permissions
{error("%s: can't open \"%s\"", prog, argv[i]);}
// else // fd != -1, file open for reading
while ((n = read(fd, buf, BUFSIZ)) > 0)
if (write(1, buf, n) != n)
{error("%s: write error on stdout", prog);}
close(fd); // close file, free fd
}
}
end = clock();
time = ((double) (end - start)) / CLOCKS_PER_SEC;
fprintf(stderr, "Execution time for low-level version: %f\n", time);

exit(0); // end program normally
}

// copy from ifp (input) to ofp (output)
void filecopy(FILE *ifp, FILE *ofp)
{
int c;

while ((c = getc(ifp)) != EOF)
{putc(c, ofp);}
}


#include <stdarg.h> // for va_list, va_start, va_end

// print an error message and die (end program)
void error(char *fmt, ...)
{
va_list args;

va_start(args, fmt);
fprintf(stderr, "Error: ");
vfprintf(stderr, fmt, args);
fprintf(stderr, "\n");
va_end(args);
exit(1); // end program from outside main()
}

/*
gcc cat.c -o cat
./cat
Hello! // Enter
Hello!
What's up? // Enter
What's up?
// Ctrl^D in Linux, Ctrl^Z+Enter in Windows (EOF)
Execution time for high-level version: 0.000130
// Ctrl^D in Linux, Ctrl^Z+Enter in Windows (EOF)
Execution time for low-level version: 0.000015

./cat me.txt > copyme.txt
Execution time for high-level version: 0.005651
Execution time for low-level version: 0.000764

./cat me.txt me.txt me.txt me.txt me.txt > copyme.txt
Execution time for high-level version: 0.030387
Execution time for low-level version: 0.003533

rm copyme.txt // clean
*/





Note:  For the contents of text file me.txt see Martin_Eden on Project_Gutenberg.









Chapter_8     cp_(copy_files) BACK_TO_TOP lseek     Exercises_8-2,3



Comments

Popular posts from this blog

Contents

Blogger Page Margins in Contempo