Hi All,

I've just started to learn C from "The C Programming Language" (Kernighan). One of the exercises asks you to write function that folds a line of text into newlines after x number of characters without splitting a word.

This is my attempt so far:

// fold: folds the line into newlines
void fold(char s[], int l) {
    int i, j, foldHere;

    i = j = 0;

    foldHere = FOLDLENGTH;

    while (i < l) {
        if (i != ' ') {
            j = i;
            while (j != ' ' && j < l) {
                ++j;
                if (j == foldHere)
                    putchar('\n');
            }
            while (i < j) {
                putchar(s[i]);
                ++i;
            }
        } else {
            if (i == foldHere)
                putchar('\n');
            else
                putchar(s[i]);
            ++i;
        }
    }
}

s[] is holding the string.
l is the size of s[].
I've defined (#define) FOLDLENGTH to be 10.

I've been testing with the string "This is malfunctioning".

The output I get is: a newline, the string.
Instead of having the newline placed in the sting before "malfunctioning" is output.

I feel that the problem is perhaps my misunderstanding of putchar().

Where am I going wrong?

Thank in advance for any help offered.

You are comparing indexes to string values. In addition there seemed to be some logic mistakes. Here's an attempt to fix them for you:

void fold(char s[], int l)
{
    int i, j, foldHere;
    i = j = 0;

    foldHere = FOLDLENGTH;

    while (i < l)
    {
        // We are currently on a non-space symbol.
        if (s[i] != ' ')
        {
            // Copy our index to 'j'.
            j = i;

            // Go to the next space-symbol (or to the end of the string)
            while (s[j] != ' ' && j < l) {
                putchar(s[j]);
                ++j;
            }

            // We're not at the end of the string and the fold marker was passed.
            // This means there are words following, print the newline now.
            // Future improvement: check if the following characters are non-whitespace characters.
            if (j < l)
            {
                if (j >= foldHere) {
                    putchar('\n');
                } else {
                    putchar(s[j]);
                }
            }

            // Continue after the marker.
            i = j + 1;
        }
        else
        {
            if (i == foldHere)
                putchar('\n');
            else
                putchar(s[i]);
            ++i;
        }
    }
}

I wasn't fully sure what you were trying to do however. Here's another approach that might be easier to read:

void fold(char str[], int length, int fold_index)
{
    // Assuming the parameters are "correct".
    int i;

    // Everything up until fold_index can 'safely' be printed.
    for (i = 0; i < fold_index; i++)
        putchar(str[i]);

    // Would you want to check for other whitespace characters too?
    while(str[i] != ' ' && i < length) {
        putchar(str[i]);
        ++i;
    }

    // There is more.
    if (i < length)
        putchar('\n');

    // Print the remains.
    for (i = i + 1; i < length; i++) {
        putchar(str[i]);
    }
}

Like your version there's some things things that might be undesired. (mainly whitespace related. Like when there's only whitespaces after the fold index. In order to not make things more complex I didn't really check for things like this)

I also wasn't sure if the cut-off point should come before are after the desired point if the desired point is placed inside a word. The code above puts it after the word.

Thanks Gonbe.

I just noticed that too. It must be Friday. I really hate making stupid mistakes like that.

// fold: folds the line into newlines
void fold(char s[], int l) {
    int i, j, foldHere;

    i = j = 0;

    foldHere = FOLDLENGTH;

    while (i < l) {
        if (s[i] != ' ') {
            j = i;
            while (s[j] != ' ' && j < l) {
                ++j;
                if (j == foldHere)
                    putchar('\n');
            }
            while (i < j) {
                putchar(s[i]);
                ++i;
            }
        } else {
            if (i == foldHere)
                putchar('\n');
            else
                putchar(s[i]);
            ++i;
        }
    }
}

I don't think the new code gives the desired output. Mainly:

while (s[j] != ' ' && j < l) {
    ++j;
    if (j == foldHere)
        putchar('\n');
}

You may print a newline here before having print anything that comes before it. For example, take a FOLDLENGTH of 1 with the string you posted in the first post.

Yeah, it's far from perfect. It's a work-in-progress. Thanks for the advice though :)

This question has already been answered. Start a new discussion instead.