aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzlg <zlg@zlg.space>2017-02-20 03:21:59 -0800
committerzlg <zlg@zlg.space>2017-02-20 03:21:59 -0800
commit729b54b9f6921ca9a4ee91ddb743a6fb7203658c (patch)
tree02fa3224af2da0e107682c3bf626e8d00158fcf6
parentSolve Exercise 7-7: Match pattern in files (diff)
downloadknr-729b54b9f6921ca9a4ee91ddb743a6fb7203658c.tar.gz
knr-729b54b9f6921ca9a4ee91ddb743a6fb7203658c.tar.bz2
knr-729b54b9f6921ca9a4ee91ddb743a6fb7203658c.tar.xz
knr-729b54b9f6921ca9a4ee91ddb743a6fb7203658c.zip
Solve Exercise 7-8: Paged file print-outs
-rw-r--r--ch7/7-08_print-file-pages.c91
1 files changed, 91 insertions, 0 deletions
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 <stdio.h>
+#include <string.h>
+
+/* 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;
+}