Question

Exercise 1-22 of The C Programming Language is as follow:

Write a program to "fold" long input lines into two or more shorter lines after the last non-blank character that occurs before the n-th column of input. Make sure your program does something intelligent with very long lines, and if there are no blanks or tabs before the specified column.

This is the code:

#include <ctype.h>
#include <stdio.h>

#define MAXLINE 500
#define FOLD_LENGTH 15

/* _getline:  read a line into s, return length  */ 
size_t _getline(char s[], int lim) 
{ 
    int c; 
    size_t i;

    for (i=0; i < lim-1 && (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;
    char line[MAXLINE];
    char temp;
    unsigned last_space_idx = 0, i, offset = 0;

    while (_getline(line, MAXLINE) != 0) {
        for (i = 0; line[offset+i] != '\0'; i++) {
            if (i == FOLD_LENGTH) {
                temp = line[offset+last_space_idx];
                line[offset+last_space_idx] = '\0';
                printf("%s\n", line+offset);
                line[offset+last_space_idx] = temp;
                offset = last_space_idx;
                i = 0;
                continue;
            }
            if (isspace(line[offset+i])) {
                last_space_idx = offset+i;
            }
        }
        printf("%s\n", line+offset);
    }
    return 0;
}

This is the sample input I'm using:

Penny Lane is in my ears and in my eyes
There beneath
the blue suburban skies

And this is the output I get:

Penny Lane is
 in my ears and in my ey
 and in my eyes

 eyes

 eyes

 eyes

What's the bug here? I really have no clue.

Was it helpful?

Solution

Lots of errors. You do this:

last_space_idx = offset+i;

But you also do this:

temp = line[offset+last_space_idx];

Which means that temp = line[(2 * offset) + last_observed_space_relative_to_offset].

You also do this:

offset = last_space_idx;

That means the offset becomes equal to the last observed space, so you'll have a preceding space on every line after the first, like this:

Penny lane is
 in my ears
 and in my eyes

Your _getline() method does this:

if (c == '\n') { 
    s[i] = c; 
    ++i; 
}

That means any line returns are preserved, so if you have There beneath\nthe blue suburban skies as the input you'll get this output:

There beneath

the blue suburban skies

Lastly, each new line you read uses the last space index and offset from the previous line. You need to reset them before the for loop starts.

Here's a fixed version. I've tidied up the style a little and replaced the printf() bodge with a string format that will print a substring.

#include <stdio.h>

#include <ctype.h>
#include <stdio.h>

#define MAXLINE 500
#define FOLD_LENGTH 15

size_t _getline(char s[], int lim);

/* _getline:  read a line into s, return length  */ 
size_t _getline(char s[], int lim) {

    char c; 
    size_t i;

    for (i = 0; i < lim - 1 && (c = getchar()) != EOF && c != '\n'; ++i) {
        s[i] = c;
    }

    s[i] = '\0'; 
    return i; 
}

int main() {

    char line[MAXLINE];
    unsigned last_space_idx = 0;
    unsigned i;
    unsigned offset = 0;

    while (_getline(line, MAXLINE) != 0) {

        last_space_idx = 0;
        offset = 0;

        for (i = 0; line[offset+i] != '\0'; ++i) {
            if (i == FOLD_LENGTH) {
                printf("%.*s\n", last_space_idx, line + offset);
                offset += last_space_idx + 1;
                i = 0;
            } else if (isspace(line[offset + i])) {
                last_space_idx = i;
            }
        }

        printf("%s\n", line + offset);
    }
    return 0;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top