Thread: Is my word-wrapping algorithm too complex?

  1. #1
    Registered User
    Join Date
    Feb 2011
    Posts
    144

    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. #2
    Stoned Witch Barney McGrew's Avatar
    Join Date
    Oct 2012
    Location
    astaylea
    Posts
    420
    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. #3
    Registered User
    Join Date
    Feb 2011
    Posts
    144

    Correct

    Quote Originally Posted by Barney McGrew View Post
    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. #4
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    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.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 6
    Last Post: 06-02-2011, 02:00 PM
  2. Replies: 16
    Last Post: 01-28-2010, 03:50 PM
  3. A basic Word Puzzle Algorithm
    By m0ntana in forum C Programming
    Replies: 5
    Last Post: 03-29-2007, 12:05 PM
  4. Number-to-Word Algorithm
    By byte in forum C Programming
    Replies: 4
    Last Post: 09-23-2005, 12:59 PM
  5. looking for good word count algorithm?
    By ccoder01 in forum C Programming
    Replies: 1
    Last Post: 05-29-2004, 12:16 AM