#include #include #include /* The C Programming Language: 2nd Edition * * Exercise 7-2: Write a program that will print arbitrary input in a sensible * way. As a minimum, it should print non-graphic characters in octal or * hexadecimal according to local custom, and break long text lines. * * Notes: I spent some time thinking about this one. I'm somewhat picky in how * I expect text to be handled, but the requirements are Spartan. Therefore, I * will provide a Spartan solution. :) * * Linux printf formats don't seem to allow for truncation of hex or octal, * so there wasn't an (easy, cat-zero friendly) way to work with the widths * produced by the format strings. However, the program compiles, it has * argument switches, it smartly breaks lines, and expands non-printable * characters. It does exactly what it's supposed to. :) */ #define MAXLINELEN 81 #define MAXBUF 102400 #define HEX 16 #define OCT 8 int fmt; int mygetline(char s[], int max) { int c, i; i = 0; while (max-- > 0 && (c = getchar()) != EOF && c != '\n') { s[i++] = c; } if (c == '\n') { s[i++] = c; } s[i] = '\0'; return i; } void fmt_print(char *s) { int i = 0; while (s[i] != '\0') { if (isprint(s[i]) || s[i] == '\n') { putchar(s[i]); } else { if (fmt == HEX) { printf("%4X", s[i]); } else { printf("%3o", s[i]); } } i++; } } void break_lines(char *s) { int fmt = HEX; int c, nl, space; for (c = 0, nl = 0, space = 0; s[c] != '\0'; c++) { /* The position of the last space */ if (isspace(s[c])) { space = c; } /* Position of the last new line */ if (s[c] == '\n') { nl = c; } if (c == (nl + MAXLINELEN - 1)) { if (space > nl) { s[space] = '\n'; nl = space; } } } } void parse_args(int argc, char *argv[]) { int i; while (argc > 1) { --argc; if (argv[argc][0] == '-') { if (argv[argc][1] == 'o' && argv[argc][1] != '\0') { fmt = OCT; } else if (argv[argc][1] == 'h') { fmt = HEX; } } } } int main(int argc, char **argv) { char buffer[MAXBUF]; parse_args(argc, argv); while (mygetline(buffer, MAXBUF)) { break_lines(buffer); fmt_print(buffer); } }