diff options
author | zlg <zlg@zlg.space> | 2013-07-23 05:10:32 -0500 |
---|---|---|
committer | zlg <zlg@zlg.space> | 2013-07-23 05:10:32 -0500 |
commit | 4d373709427451e6a5523453812bb84e6c0be72d (patch) | |
tree | eb2971e498ee28f65beb78cfdc0a79050c4fa1bf /ch1 | |
parent | Solve Exercise 4-13: Recursive reverse() (diff) | |
download | knr-4d373709427451e6a5523453812bb84e6c0be72d.tar.gz knr-4d373709427451e6a5523453812bb84e6c0be72d.tar.bz2 knr-4d373709427451e6a5523453812bb84e6c0be72d.tar.xz knr-4d373709427451e6a5523453812bb84e6c0be72d.zip |
Correct Exercise 1-22's solution
Tabs are now handled properly and the instructions are better followed.
Diffstat (limited to 'ch1')
-rw-r--r-- | ch1/1-22_wordwrap.c | 115 |
1 files changed, 64 insertions, 51 deletions
diff --git a/ch1/1-22_wordwrap.c b/ch1/1-22_wordwrap.c index eaf6aff..8cb940e 100644 --- a/ch1/1-22_wordwrap.c +++ b/ch1/1-22_wordwrap.c @@ -8,67 +8,80 @@ * long lines, and if there are no blanks or tabs before the specified column. * * Answer: So... Quite a hefty requirement. In a nutshell, our goal is to - * create sane hard-wrapping. This is a common function in text editors, and - * it's important to get it right or the results are wonky. + * create line-wrapping. The simplest approach is to take every character until + * EOF, like a stream. Spaces and tabs need special treatment. If your input + * isn't a newline or a blank, it will just be printed. Spaces and tabs only + * print if the next non-blank is before the end of the line length limit. To + * make things prettier, I opted to ignore leading whitespace as well. * - * TODO: get_line() is not fully correct. When it hits a \t, it counts it as - * one character and has no concept of display count. I'll fix this later on. */ -// For tradition's sake, let's wrap at 80 columns -#define MAXLEN 80 +#define LINEWIDTH 20 -char data[MAXLEN]; -int i, j, k; - -int get_line(char s[], int lim) { - /* Put as much as possible into a temp string, and count its length */ - int c, i; - - for (i = 0; i < lim && (c = getchar()) != EOF && c != '\n'; ++i) { - s[i] = c; - } - if (c == '\n') { - s[i] = c; - ++i; - } - s[i] = '\0'; - return i; -} +int main() { + int c, tmp, ts; + int spaces = 0; + int col = 0; -/* Find the first blank character, starting from the end of the string. Returns - * the position of the blank, or -1 if one wasn't found. - */ -int b_find_blank(char s[], int lim) { - // Start at the end of the string and go backwards. - for (i = lim; i >= 0; i--) { - // Simply replace the first blank with a newline. - if (s[i] == ' ' || s[i] == '\t') { - return i; + printf("Just type. It'll wrap to %d characters per line.\n", LINEWIDTH); + while ((c = getchar()) != EOF) { + if (col >= LINEWIDTH) { + putchar('\n'); + col = 0; } - } - return -1; -} - -int main() { - while (j = get_line(data, MAXLEN)) { - if (j == 80) { - // We know it's a long line now. Let's make sure we're breaking in - // the right place - k = b_find_blank(data, MAXLEN); - //printf("%d\n", k); - if (k > -1) { - data[k] = '\n'; - data[MAXLEN] = '\0'; - printf("%s", data); + if (c == ' ') { + if (col == 0) { continue; + } + spaces = 1; + while ((tmp = getchar()) == ' ') { + spaces++; + } + if (col + spaces < LINEWIDTH) { + while (spaces > 0) { + putchar(' '); + col++; + spaces--; + } } else { - data[MAXLEN] = '\0'; - printf("%s\n", data); + putchar('\n'); + col = 0; + } + putchar(tmp); + col++; + continue; + } + /* There's some duplicated effort in here, but I couldn't find a cleaner + * way to put tab stuff in with the spaces, where it belongs */ + if (c == '\t') { + if (col == 0) { continue; } + spaces = 1; + while ((tmp = getchar()) == '\t') { + spaces++; + } + ts = (spaces * 8) - (col % 8); + if (col + ts < LINEWIDTH) { + spaces = (spaces * 8) - (col % 8); + while (spaces > 0) { + putchar(' '); + spaces--; + col++; + } + } else { + putchar('\n'); + col = 0; + } + putchar(tmp); + col++; + continue; + } + putchar(c); + col++; + if (c == '\n') { + col = 0; } - printf("%s", data); } - + return 0; } |