# Thread: Is my word-wrapping algorithm too complex?

1. ## Is my word-wrapping algorithm too complex?

Hi, everyone.

I am writing a word-wrapping program. The idea is that it will read in text, and ensure that no output line is longer than a given limit. Where a line of text contains at least one space, it will split the line at the rightmost space. If the line contains no spaces, it will hyphenate and split the line.

I'm doing this as an exercise, based on (but not identical to) exercise 1-22 of K&R.

This is my present effort. I wanted to implement it in such a way as never to waste storage space by buffering text that need not be buffered. Note that subsequent_word_handler() is still buggy. I simply want to know: Is this approach a good thing? Or should my code be much simpler?

Code:
```#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

#define LINE_MAX 10

char buffer[LINE_MAX];
unsigned int bufpos = 0;

struct update left_column_handler(char c, unsigned int column);
struct update blanks_handler(char c, unsigned int column);
struct update initial_word_handler(char c, unsigned int column);
struct update subsequent_word_handler(char c, unsigned int column);

struct update
{
struct update (*handler)(char c, unsigned int column);
unsigned int column;
};

void push_char(char c)
{
assert(bufpos < LINE_MAX);
assert((c != ' ') && (c != '\n'));

buffer[bufpos] = c;
++bufpos;
}

void print_buffer(void)
{
unsigned int i;

for (i = 0; i < bufpos; ++i)
putchar(buffer[i]);

bufpos = 0;  /* invalidate buffer data */
}

struct update left_column_handler(char c, unsigned int column)
{
struct update update;

putchar(c);

if (c == ' ')
{
update.handler = blanks_handler;
update.column = 1;
}
else if (c == '\n')
{
update.handler = left_column_handler;
update.column = 0;
}
else /* c != ' ' && c != '\n' */
{
update.handler = initial_word_handler;
update.column = 1;
}

return update;
}

struct update blanks_handler(char c, unsigned int column)
{
struct update update;

if (c == ' ')
{
putchar(c);
++column;

if (column < LINE_MAX)
{
update.handler = blanks_handler;
update.column = column;
}
else /* column == LINE_MAX */
{
putchar('\n');

update.handler = left_column_handler;
update.column = 0;
}
}
else if (c == '\n')
{
putchar(c);

update.handler = left_column_handler;
update.column = 0;
}
else  /* c != ' ' && c != '\n' */
{
push_char(c);

update.handler = subsequent_word_handler;
update.column = column; /* has not been incremented */
}

return update;
}

struct update initial_word_handler(char c, unsigned int column)
{
struct update update;

if (c == ' ')
{
putchar(c);
++column;

if (column == LINE_MAX)
{
putchar('\n');

update.handler = left_column_handler;
update.column = 0;
}
else
{
update.handler = blanks_handler;
update.column = column;
}
}
else if (c == '\n')
{
putchar(c);

update.handler = left_column_handler;
update.column = 0;
}
else /* c != ' ' && c != '\n' */
{
if (column == LINE_MAX - 1)
{
int d = getchar();  /* lookahead */
ungetc(d, stdin);

if ((d != ' ') && (d != '\n'))
{
printf("-\n%c", c);

update.handler = initial_word_handler;
update.column = 1;
}
else
{
printf("%c\n", c);

if ((d == '\n') || (d == ' '))
(void) getchar();  /* dispose of extra whitespace */

update.handler = left_column_handler;
update.column = 0;
}
}
else /* column < LINE_MAX - 1 */
{
putchar(c);
++column;

update.handler = initial_word_handler;
update.column = column;
}
}

return update;
}

struct update subsequent_word_handler(char c, unsigned int column)
{
struct update update;
unsigned int room = LINE_MAX - column;

if (c == ' ')
{
if (bufpos > room) /* change to >= to include trailing spaces */
{
putchar('\n');
column = 0;
}

column += bufpos;
print_buffer();

if (column < LINE_MAX)
{
putchar(c);
++column;

update.handler = blanks_handler;
update.column = column;
}
else
{
putchar('\n');

update.handler = left_column_handler;
update.column = 0;
}
}
else if (c == '\n')
{
if (bufpos > room) /* change to >= to include trailing spaces */
{
putchar('\n');
column = 0;
}

column += bufpos;
print_buffer();

putchar(c);

update.handler = left_column_handler;
update.column = 0;
}
else /* c != ' ' && c != '\n' */
{
push_char(c);

if (bufpos == room)
{
int d = getchar();  /* lookahead */
ungetc(d, stdin);

if ((d != ' ') && (d != '\n'))
{
putchar('\n');
column = 0;
}

column += bufpos;
print_buffer();

if (column == LINE_MAX)
{
putchar('\n');
column = 0;
}
}

update.handler = subsequent_word_handler;
update.column = column;
}

return update;
}

int main(void)
{
char c;
unsigned int column = 0;
struct update (*handler)(char c, unsigned int column)
= left_column_handler;

while (c = getchar(), c != EOF)
{
struct update update = handler(c, column);

handler = update.handler;
column = update.column;
}

return EXIT_SUCCESS;
}```
Richard

2. Well, this isn't really an answer to your question, but just a note. You ought to define c with the type int since char can't represent EOF when it's unsigned (and it will usually clash with another character when it is signed.)

3. ## Correct

Originally Posted by Barney McGrew
Well, this isn't really an answer to your question, but just a note. You ought to define c with the type int since char can't represent EOF when it's unsigned (and it will usually clash with another character when it is signed.)
Yes, on line 254. Well spotted.

4. Your intuition is spot on. It's way over the top.

About all you need is the length of the next word, and the distance to the right margin. If the length of the next word is > the distance to the right margin, then it won't fit. Otherwise, it will fit.