1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
|
#include <stdio.h>
#include <ctype.h>
#include <string.h>
/* 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);
}
}
|