From 729b54b9f6921ca9a4ee91ddb743a6fb7203658c Mon Sep 17 00:00:00 2001 From: zlg Date: Mon, 20 Feb 2017 03:21:59 -0800 Subject: Solve Exercise 7-8: Paged file print-outs --- ch7/7-08_print-file-pages.c | 91 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 ch7/7-08_print-file-pages.c (limited to 'ch7') diff --git a/ch7/7-08_print-file-pages.c b/ch7/7-08_print-file-pages.c new file mode 100644 index 0000000..8f259b9 --- /dev/null +++ b/ch7/7-08_print-file-pages.c @@ -0,0 +1,91 @@ +#include +#include + +/* The C Programming Language: 2nd Edition + * + * Exercise 7-8: Write a program to print a set of files, starting each new one + * on a new page, with a title and a running page count for each file. + * + * Notes: This could be done using functions written in exercise 7-2, but I + * decided to go with library functions when I could. A caveat to keep in mind + * on a real system is that the modern way to print some of the output is with + * snprintf, which doesn't exist in ANSI C. There are places where, to be safe, + * you should check bounds. Both line buffers are the same size here, however, + * so I didn't bother since I know they can hold each others' contents. + * + * If you were to do this correctly, it would be a lot like the `less` program. + */ + +/* The dimensions of a "page". Using a classic size because reasons. */ +#define PAGE_WIDTH 80 +#define PAGE_HEIGHT 24 + +int lineno = 0; +int pageno = 0; +FILE *fp; +char buffer[PAGE_WIDTH]; +char line[PAGE_WIDTH]; + +void page_break() { + while (lineno < (PAGE_HEIGHT - 1)) { + printf("\n"); + lineno++; + } +} + +int endswith_nl(char *s) { + int i; + for (i = 0; s[i] != '\0'; i++) { + } + if (i > 0 && s[i - 1] == '\n') { + return 1; + } + return 0; +} + +void print_header(char *path) { + pageno++; + lineno++; + char *prefix = "FILE:"; + sprintf(line, "%-*s %-*s", (int) strlen(prefix), prefix, (PAGE_WIDTH - ((int)strlen(prefix))), path); + printf("%s\n", line); +} + +void print_footer(void) { + page_break(); + sprintf(line, "Page %d\n", pageno); + printf("%*s", PAGE_WIDTH, line); + lineno = 0; +} + +int main(int argc, char *argv[]) { + int i = 0; + char c; + while (argc > 1) { + i++; + argc--; + if ((fp = fopen(argv[i], "r"))) { + while ((c = fgetc(fp)) != EOF) { + ungetc(c, fp); + print_header(argv[i]); + while (fgets(buffer, PAGE_WIDTH, fp)) { + sprintf(line, "%s", buffer); + printf("%s", line); + if (!endswith_nl(line)) { + printf("\n"); + } + lineno++; + if (lineno == (PAGE_HEIGHT - 1)) { + break; + } + } + print_footer(); + } + fclose(fp); + pageno = 0; + } else { + printf("err: could not open file '%s' for reading.\n", argv[i]); + } + } + return 0; +} -- cgit v1.2.3-70-g09d2 eft'>FilesLines 2018-09-03Branch off from master with pytest, tox, clickzlg1-0/+0 2018-03-18Flesh out filter types and ownership statuszlg3-82/+144 2018-03-18README.mdown: break line correctlyzlg1-1/+1 2018-03-18add 'playlog' list filterzlg2-2/+9 2018-03-13Update helpers a bitzlg1-2/+9 2018-03-13Make VGSTASH_DB_LOCATION point to a filezlg2-21/+20 2016-11-18Remove settings from helpers.shZe Libertine Gamer1-5/+0 2016-11-15Correct phrasing in README.Ze Libertine Gamer1-4/+4 2016-11-13DerpZe Libertine Gamer1-0/+1 2016-11-03Improve error handling in shell scriptsZe Libertine Gamer4-3/+23 2016-10-24Correct run_again, add recursionZe Libertine Gamer1-0/+4 2016-10-21Add quotes to correct behavior for arglistZe Libertine Gamer1-1/+1 2016-10-14updater.sh: add recursion, error handlingZe Libertine Gamer1-43/+101 2016-10-14Correct pipe-handling behaviorZe Libertine Gamer1-1/+9 2016-10-12Clarify a method to move between platformsZe Libertine Gamer1-2/+5