Nangs
Nangs

Reputation: 33

Reversing the order of words backwards in a string

Sorry for such a mediocre question, but I ran into what seems to be a tiny problem, but simply can't get over it. For my task I have to take a line of string from a file, and put it into another file backwards, for example:

one two three
four five six

would be

three two one
six five four

My problem is, is that I'm getting

 three two one
 si five four

So basically the flaw is that there is a space character at the beginning of each line and the last letter of the last word is always missing. Here's my reverse function:

void reverse(char input[], int length, char output[]) {
    char space = 32;
    input[length - 1] = space;
    int value = 0;
    int i, k = 0, j;
    for (i = 0; i <= length; i++) {
        if (input[i] == space) {
            for (j = i - 1; j >= k; j--, value++) {
                output[value] = input[j];
            }
            if (j == -1) {
                output[value] = space;
                value++;
            }
            k = i;
        }
    }

    char c = 0;
    for (int i = 0, j = length - 1; i <= j; i++, j--) {
        c = output[i];
        output[i] = output[j];
        output[j] = c;
    }
}

What I'm doing is first reversing each word by character, and then the whole line. If someone could help me find the last bits that I've missed I would greatly appreciate it.

Upvotes: 1

Views: 111

Answers (2)

chqrlie
chqrlie

Reputation: 144715

The flaws come from your approach:

  • why do you force a space at offset length - 1? If you read the line with fgets(), there is probably a newline ('\n') at the end of the line, but it might be missing at the end of the input, which would explain the x getting overwritten on the last line.
  • you should not modify the input buffer.

Here is a simplified version, along with a simple main function:

#include <stdio.h>
#include <string.h>

void reverse(const char *input, int length, char *output) {
    int i, j, k, v;
    for (i = k = v = 0;; i++) {
        if (i == length || input[i] == ' ') {
            for (j = i; j-- > k; v++) {
                output[v] = input[j];
            }
            for (; i < length && input[i] == ' '; i++) {
                output[v++] = ' ';
            }
            if (i == length) {
                output[v] = '\0';
                break;
            }
            k = i;
        }
    }
    for (i = 0, j = length - 1; i < j; i++, j--) {
        char c = output[i];
        output[i] = output[j];
        output[j] = c;
    }
}

int main() {
    char input[256];
    char output[256];

    while (fgets(input, sizeof input, stdin)) {
        reverse(input, strcspn(input, "\n"), output);
        puts(output);
    }
    return 0;
}

Output:

three two one
six five four

Here is a simpler reverse function that operates in one pass:

#include <string.h>

void reverse(const char *input, int length, char *output) {
    int i, j, k, v;
    for (i = k = 0, v = length;; i++) {
        if (i == length || input[i] == ' ') {
            for (j = i; j-- > k;) {
                output[--v] = input[j];
            for (; i < length && input[i] == ' '; i++) {
                output[--v] = ' ';
            }
            if (v == 0) {
                output[length] = '\0';
                break;
            }
            k = i;
        }
    }
}

Upvotes: 4

Replace input[length - 1] = space; with input[length] = space;

Upvotes: 0

Related Questions