user11954200
user11954200

Reputation:

Reversing a string without two loops?

I came up with the following basic item to reverse a string in C:

void reverse(char in[], char out[]) {

    int string_length = 0;

    for(int i=0; in[i] != '\0'; i++) {
        string_length += 1;
    }

    for(int i=0; i < string_length ; i++) {
        out[string_length-i] = in[i];
    }
    out[string_length+1] = '\0';
}

Is there a way to do this in one for loop or is it necessary to first use a for length to get the string length, and then do a second one to reverse it? Are there other approaches to doing a reverse, or is this the basic one?

Upvotes: 6

Views: 163

Answers (3)

Mihir Luthra
Mihir Luthra

Reputation: 6759

void reverse(char *in, char *out) {

    static int index;
    index = 0;

    if (in == NULL || in[0] == '\0')
    {
        out[0] = '\0';
        return;
    }
    else
    {
        reverse(in + 1, out);
        out[index + 1] = '\0';
        out[index++] = in[0];
    }
}

With no loops.

This code is surely not efficient and robust and also won't work for multithreaded programs. Also the OP just asked for an alternative method and the stress was on methods with lesser loops.

Are there other approaches to doing a reverse, or is this the basic one

Also, there was no real need of using static int. This would cause it not to work with multithreaded programs. To get it working correct in those cases:

int reverse(char *in, char *out) {

    int index;

    if (in == NULL || in[0] == '\0')
    {
        out[0] = '\0';
        return 0;
    }
    else
    {
        index = reverse(in + 1, out);
        out[index + 1] = '\0';
        out[index++] = in[0];
        return index;
    }
}

Upvotes: 3

hyde
hyde

Reputation: 62787

You can always tweak two loops into one, more confusing version, by using some kind of condition to determine which phase in the algorithm you are in. Below code is untested, so most likely contains bugs, but you should get the idea...

void reverse(const char *in, char *out) {

    if (*in == '\0') {
        // handle special case
        *out = *in;
        return;
    }

    char *out_begin = out;
    char *out_end;
    do {
        if (out == out_begin) {
            // we are still looking for where to start copying from
            if (*in != '\0') {
                // end of input not reached, just go forward
                ++in;
                ++out_end;
                continue;
            }
            // else reached end of input, put terminating NUL to out
            *out_end = '\0';
        }
        // if below line seems confusing, write it out as 3 separate statements.
        *(out++) = *(--in);
    } while (out != out_end); // end loop when out reaches out_end (which has NUL already)
}

However, this is exactly as many loop iterations so it is not any faster, and it is much less clear code, so don't do this in real code...

Upvotes: 1

andresantacruz
andresantacruz

Reputation: 1724

Assuming you can't use functions to get the string length and you want to preserve the second loop I'm afraid this is the shortest way.

Just as a side-note though: this code is not very safe as at for(int i=0; in[i] != '\0'; i++) you are not considering cases where the argument passed to parameter in is not a valid C string where there isn't a single \0 in all elements of the array pointed by in and this code will end up manifesting a buffer over-read at the first for loop when it will read beyond in boundaries and a buffer overflow in the second for loop where you can write beyond the boundaries of out. In functions like this you should ask the caller for the length of both arrays in and out and use that as a max index when accessing them both.

As pointed by Rishikesh Raje in comments: you should also change the exit condition in the second for loop from i <= string_length to i < string_length as it will generate another buffer over-read when i == string_length as it will access out by a negative index.

Upvotes: 4

Related Questions