exercise 7-2

2026-10-14

#include <stdio.h>
#include <ctype.h>      //isprint
//compile with: gcc -Wall -Wextra cc-c.c -o cc-c
//run with:     printf 'tab\there, bell\a, esc\033[0m\n' | ./cc-c
//              head -c 200 /dev/urandom | ./cc-c       # raw binary
//              ./cc-c < cc-c.c                         # ordinary text

//K&R2 exercise 7-2: print arbitrary input "in a sensible way".
//Graphic characters (isprint) go through as-is; anything else except
//newline is shown as a C-style octal escape, \ooo -- octal is the Unix
//custom (od, \033 in C strings, cat -v's cousin). Lines longer than
//MAXCOL columns are broken, and an escape is never split across a break.

#define MAXCOL  80      //maximum output columns per line
#define OCTLEN  4       //width of one escape: backslash + 3 octal digits

int inc(int pos, int n);

int main(void)
{
    int c;
    int pos = 0;                        //columns used on the current line

    while ((c = getchar()) != EOF)
        if (c == '\n') {                //a real line end: keep it, reset
            putchar('\n');
            pos = 0;
        } else if (isprint(c)) {
            pos = inc(pos, 1);
            putchar(c);
        } else {
            //getchar returns an unsigned char value (0..255) as an int,
            //so it never needs more than 3 octal digits (255 = \377).
            //%03o pads with zeros: 7 -> "007", so every escape is 4 wide
            pos = inc(pos, OCTLEN);
            printf("\\%03o", c);
        }
    return 0;
}

//inc: room for n more columns? If not, break the line first.
//Returns the new column position.
int inc(int pos, int n)
{
    if (pos + n > MAXCOL) {
        putchar('\n');
        return n;
    }
    return pos + n;
}

win@DESKTOP-MEIH88T:~/webdev-projects$ gcc -Wall -Wextra cc-c.c -o cc-c
win@DESKTOP-MEIH88T:~/webdev-projects$ printf 'tab\there, bell\a, esc\033[0m\n' | ./cc-c
tab\011here, bell\007, esc\033[0m