aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzlg <zlg@zlg.space>2013-07-23 05:10:32 -0500
committerzlg <zlg@zlg.space>2013-07-23 05:10:32 -0500
commit4d373709427451e6a5523453812bb84e6c0be72d (patch)
treeeb2971e498ee28f65beb78cfdc0a79050c4fa1bf
parentSolve Exercise 4-13: Recursive reverse() (diff)
downloadknr-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.
-rw-r--r--ch1/1-22_wordwrap.c115
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;
}