Learning C: K&R 1-22: 'fold'. Is this solution very unwieldy? This exercise gave me some trouble, but I think I have a solution here that fulfils the spec. However it's very long compared to what I'm looking at on the solutions page at clc-wiki.net. 

In the course of solving the problem I loop over my buffered line three or four times. This seems like quite a lot, and the various edge cases I have to account for means my prog is over 100 lines long (including spacing). 

If anyone is kind enough to have patience to read it, I'd really appreciate your thoughts. Could it be shorter? Are there any glaring redundancies? 

#include &lt;stdio.h&gt;

#define FOLD 20

int getline( char s[], int max );
int does_line_have_blanks( char line[], int len );
int locate_last_space ( char line[], int len );
int find_split( char line[], int len, int offset);
int mark_split_and_clean_trailing_spaces( char line[], int len, int spacecount );
int print_with_split( char s[], int split_pos );

int main()
{
  int len, i, split_pos, offset;
  char line[FOLD+1];

  len = split_pos = 0;
  for ( i = 0; i &lt; FOLD+1; ++i )
    line[i] = 0;
  offset = 0; /*keeps track of characters that overflow the split so next buffer may be shortened accordingly*/

  while ( ( len = getline(line, (FOLD+1) - offset) ) &gt; 0 ) {

    split_pos = find_split ( line, len, offset );

    offset = print_with_split( line, split_pos );

    /* clean out buffer*/
    for ( i = 0; i &lt; FOLD+1; ++i )
      line[i] = '\0';
  }
  return 0;
}

int getline ( char s[], int max ) /* doesn't add newlines as K&amp;R's does */
{
  int i, c;

  for (i = 0 ; i &lt; max-1 &amp;&amp; (c = getchar()) != EOF &amp;&amp; c != '\n'; i++ )
    s[i] = c;
  s[i] = '\0';

  return i;
}

int find_split( char line[], int len, int offset ) {

    int i, split_pos, blanks;

    i = split_pos = 0;

    /*make sure there are blanks - if not the line will be printed as-is*/ 
    blanks = does_line_have_blanks( line, len );

    if ( len &lt; FOLD-offset || blanks != 1 ) {
      split_pos = len; /* hit a newline or EOF - split at end of input */
    } else {
      split_pos = locate_last_space( line, len );
    }
    return split_pos;
}

int does_line_have_blanks( char line[], int len ) {

  int i, blanks;

  i = blanks = 0;

  for ( i = 0; i &lt; len; ++i )  { /*len is at null char in line*/
    if (line[i] == ' ' )
      blanks= 1;
  }
  return blanks;
}

int locate_last_space ( char line[], int len ) {

  int i, inspace, spacecount, split_pos;

  inspace = spacecount = split_pos = 0;

  for ( i = 0; i &lt; len; ++i ) {
    if ( line[i] == ' ' ) {
      inspace = 1;
      ++spacecount;
    } else {
      inspace = 0;
      if ( spacecount &gt; 0 ) { /*if we leave inspace state, split on the preceding char */
        spacecount = 0;
        split_pos = i -1;
      }
    }
  }

  if ( inspace == 1 ) { /* and if we left in a space... */
    split_pos = mark_split_and_clean_trailing_spaces( line, len, spacecount );
  }

  return split_pos;
}

int mark_split_and_clean_trailing_spaces( char line[], int len, int spacecount ) {

  int split_pos, i;

  split_pos = i = 0;

  split_pos = len - spacecount; /*... split where it started */
  for ( i = split_pos + 1; i &lt; len; ++i ) { /*nullify trailing spaces as per instructions*/
    line[i] = '\0';
  } 

  return split_pos;
}

int print_with_split( char line[], int split_pos ) {

   int i, offset;

   offset = 0;

   for ( i = 0; i &lt; split_pos; ++i ) {
      putchar(line[i]);
    }
    putchar('\n');
    for ( i = (split_pos + 1 ); line[i] != '\0'; ++i) /*miss out the space we split on*/ {
      ++offset; /* extra chars on next line, so buffer will be smaller */
      putchar(line[i]);
    }

    return offset;
}


EDIT Added a return type for main()
Instead of reading an entire line, then finding where to break the line, I think I'd read one word, and depending on the length of the line up to that point and the length of the word, decide whether or not to write a new-line before writing that word.

That way, the main loop would come out something like this:

while (getword(buffer, max_len)!=EOF) {
    if (current_length + strlen(buffer) &gt; max_len) {
       print("\n");
       current_length = 0;
    }
    print(buffer);
    current_length += strlen(buffer);
}