1

I am trying to reverse the string using pointers but it seems that it does not work, what's the problem? the output is olllo but should be olleh.

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


void reverse(char *cadena){

    size_t len = strlen(cadena);
    char *end= cadena;
    char *aux = cadena;
    while(*++end){}
    --end; //end points to a

    for(;len;--len){
        *aux++ = *end--;

    }

}

int main()
{

    char buffer[] = "hello";
    reverse(buffer);
    printf("%s",buffer);


    return 0;
}
3
  • Your for-loop is broken; you should swap each character pair and run only up to the half of the string. Commented Jun 24, 2018 at 22:38
  • And you don't really need two loops for this task Commented Jun 24, 2018 at 22:41
  • @SHG is correct, you can simply calculate end using the length directly. char *end= cadena + (len - 1); Commented Jun 24, 2018 at 22:43

3 Answers 3

3

The line:

*aux++ = *end--;

Does not swap anything. It just assigns the left side the value of the right side. You'll always end up with a palindrome, made from the right half of the string. For swap logic, you should do:

char tmp = *aux;
*aux = *end;
*end = tmp;

Also, you shouldn't really iterate through the whole string. Actually, it'd mean reversing the string and then reversing it back again. Just apply the swapping logic while iterating through just half of the string, and you're good to go:

void reverse(char *cadena) {
    if(cadena != NULL){                                 // add some checks...    
        size_t len = strlen(cadena);
        char *end = cadena + (len > 1 ? len - 1 : 0);   // ...for safety    
        char *aux = cadena;

        for (len /= 2; len; --len) {
            char tmp = *aux;
            *aux++ = *end;
            *end-- = tmp;
        }
    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

Well, I don't know why you decided to define NULL as nop, I would generally prefer a fast abort to make debugging easier. But it's not actually wrong. I would also try to reduce branching...
Im sorry but this isn't code review. Here the main goal was to demonstrate the idea, not to provide the optimal solution
1

Addressing your fault

The problem with your loop is that while you try to reverse the characters in place you end up swap already swapped characters.

I'll try to explain by showing what happens in each iteration. You can see the initial contents of cadena and the final (res) after each swap in each iteration. The | are where the pointers aux and end are currently pointing:

len = 5
aux  |  
     h e l l o
end          |
res: o e l l o

len = 4
aux    |  
     h e l l o
end        |
res: o l l l o

len = 3
aux      |  
     h e l l o
end      |
res: o l l l o

len = 2
aux        |  
     h e l l o
end    |
res: o l l l o

len = 1
aux          |  
     h e l l o
end  |
res: o l l l o

len = 0
=> break the loop

On a solution..

My inplace reverse would be this one:

void reverse(char *str)
{
    if (!str || !(*str)) return;

    char *end = str + strlen(str) - 1;

    while (str < end) {
        char tmp = *str;
        *str++ = *end;
        *end-- = tmp;
    }
}

Some key points:

  • notice the use of strlen to find the last character of the string
  • you should iterate until the starting and ending pointers meet. Otherwise you re-reverse the string

2 Comments

You also suffer from UB when handed the empty string. Fix that by reconsidering where to decrement.
@Deduplicator Thanks for the remark. Had it in mind but never written it.
0

There are three important errors in your code:

  1. You are mishandling the empty string when advancing to the end in this snippet:

    char *end= cadena;
    // Irrelevant: char *aux = cadena;
    while(*++end){}
    --end; //end points to a
    

    Anyway, you already have the string-length, so just add it.

    When fixing this error, make sure you only create valid pointers, meaning to or just behind objects.

  2. You are going over the length of the whole string, instead of just half of it. If you actually swapped the elements, you would thus swap everything twice, a quite expensive nop:

    for(;len;--len){
    
  3. You are copying instead of swapping. You didn't save the value you overwrote, and you didn't store it back where it belongs.

        *aux++ = *end--;
    }
    

Fixed code:

void reverse_string(char* s) {
    char* e = s + strlen(s);
    while (s < e) {
        char t = *s;
        *s++ = *--e;
        *e = t;
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.