aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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;
+}
02:55:21 -0700'>2018-09-03Branch off from master with pytest, tox, clickzlg16-778/+779 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