tags:

views:

1081

answers:

7

Hi, I had just written a programme which reverses a sentence whatever the user gives. for eg:If the user gives the sentence as "How are you",my programm generates "uoy era woH". The programme which i had written is shown below.I just have a wild intution that there can be a smarter programe than the one which i had written.So valuable inputs from your side is most appreciated or any better programme than this is also most welcome.

int ReverseString(char *);

main()
{
    char *Str;
    printf("enter any string\n");
    gets(Str);
    ReverseString(Str);
    getch();
}

int ReverseString(char *rev)
{
    int len = 0;
    char p;
    while(*rev!='\0')
    {
        len++;
        rev++;
    }
    rev--;
    while(len>0)
    {
        p = *rev;
        putchar(p);
        rev--;
        len--;
    }
}

Thanks a lot

A: 

This wont work. Should allocate memory for your sentence.

    char *Str;
   printf("enter any string\n");
   gets(Str);

should be>

char str[81]={0};
printf("Enter any string up to 80 characters\n");
scanf("%80s\n",str);
ReverseString(str)

Besides, you should avoid gets function. It leads to buffer overflows

Tom
Right about needing some memory for the buffer - wrong about how to read into the buffer.
anon
ooops, thanks you two
Tom
Tom,what about the memory wastage if for instance say we just enter the string of 20 bytes,so reamining 60 bytes get wasted.Can that me justified??Please correct me if i am wrong
While a legitimate question, at this point in your learning, you shouldn't really worry about 59 bytes of 'wasted' data. When you start using *alloc to allocate space, you can worry about extra space.
Nick Presta
@GNR :How can you expect to know how much is the user going to type in? If he typs 20, ok, too bad, 60 bytes gone to waste. Thats not a problem, because those will be freed once the stack unwinds (i.e main finishes)
Tom
But may be think of a scenario may be some real time systems,where each byte is valuable and too much wastages cost your time and speed.
@GNR >I think (anyone correct me if needed) that chances are that embedded systems are not going to ask user for input and reverse it. Even if they did, then you should ask for input byte by byte. Still, you are going to need memory to store that. The code you posted doesnt, and leads to undefined behaviour
Tom
Tom,Infact embedded systems may or may not use string reverse programes,but sometimes the implementation may be directly or indirectly related to the question i asked.So i think optimising in that point of view could make more sense
This is pointless. Choose a number you like, 1,2,3,10,20,80 and use it. The real issue, allocate memory.
Tom
GNR, you're not programming in an embedded systems environment. You're most likely programming on a machine with more than 536 870 912 bytes of memory. I don't think 60, or even 1000 extra bytes are of concern. You're asking how to reverse a string. You need to learn the fundamentals of how to reverse a string, not the details of storage.
Nick Presta
H nick,I wasjust thinking that wenever we write any programe we need to think abt the ways so that this programm can be portable anywhere rather than thinking that this is meant for embedded system or not.I hope u got my point.Its just not wasting of some 1000 bytes or so but making it efficient in all ways.
+8  A: 

You could use recursion.

         int ReverseString(char *rev)
         {
            if(*rev!='\0')
            {
               ReverseString(rev + 1);
               putchar(*rev);
            }

            return 1;
         }
devinb,Thats really a beautifull code.Thanks a lot
It's nice, and is the cleanest way I know to reverse a linked list - a common interview question, it seems. An iterative approach is probably better for strings, however.
anon
There are ways to change it so that you can reverse the string itself, rather than just outputting, but it's not quite as pretty =P
+2  A: 
void ReverseString( char* str, int len )
{
    if( len > 1 )
    {
        swap( &str[0], &str[len - 1] );
        ReverseString( ++str, len - 2 );
    }
}

Or, unrolling the tail-recursion:

void ReverseString( char* str, int len )
{
    while( len > 1 )
    {
        swap( &str[0], &str[len - 1] );
        ++str;
        len -= 2;
    }
}

Where swap is defined as:

void swap( char* a, char* b )
{
    *a ^= *b;
    *b ^= *a;
    *a ^= *b;
}

If you use this though, your TA's will definitely know you didn't figure this out yourself :)

Not Sure
that std::swap is probably much for a C begginer.
Tom
Not Sure/Tom,any idea about the std::swap.Just couldnt get any idea abt it..
Especially as it is C++, not C.
anon
There, defined swap :)
Not Sure
fine..thanks a lot sir.now got it fine
@NotSure Your swap functions is still not C, which does not have references.
anon
@neil, edited to use pointers instead...
Not Sure
@NotSure, that 3-step XOR is a fancy overkill. It would be better to keep a local (stack) variable and swap through it right in the ReverseString while() loop or if() block for the two schemes.
nik
Agreed - xor swap in C code is usually, as in this case, just being clever for the fun of it. The only excuse for it is in assembler code where you're swapping two registers and don't want to spill to stack in order to use another one. Also, a function called just "swap" should either have a massive warning comment, or should work with equal parameters. This xor-swap shouldn't be called with a == b...
Steve Jessop
A: 

Okay, here is my function. I wrote it a while ago, just for practice.

char* reverse(char *string){

    int length = 0;
    int half = 0;

    length = strlen(string);
    half = (length/2) - 1;
    --length;

    int i = 0;
    register char interim;
    for(; i<=half; ++i){
        interim = string[i];
        string[i] = string[length - i];
        string[length - i] = interim;
    }

    return string;

}

now that I look at it, I'm less proud of it than when I got it to work. I'm just posting it because you asked me to post it when I found it--and for completeness' sake.

After looking at some other answers I realize that the calculation of half the string is unnecessary and I could have just decremented length until i and length were equal. Oh well--here it is.

Also, please don't bash me for the use of the register keyword :P

Carson Myers
also 'strlen' is an 'O(n)' operation, so there's still two loops in your code, one of them is just hidden.
I originally had my own length calculation in there but changed it to strlen because the reversal was the point of the code. But really, the length has to be known anyway, whether it's calculated before or after the function is called.
Carson Myers
Thnaks a lot carson.
A: 

If you don't know the length of the string:

void reverse_string(char* str)
{
    char* p2 = str;
    while (*p2 != '\0')
    {
     /* assumes the string is null-terminated, will fail otherwise */
     ++p2;
    }
    --p2;
    char* p1 = str;
    while (p1 < p2)
    {
     char tmp = *p1;
     *p1 = *p2;
     *p2 = tmp;
     ++p1;
     --p2;
    } 
}

If you do:

void reverse_string(char* str, const size_t len)
{
    if (len <= 1)
    {
     return;
    } 
    char* p2 = str + len - 1; 
    char* p1 = str;
    while (p1 < p2)
    {
     char tmp = *p1;
     *p1 = *p2;
     *p2 = tmp;
     ++p1;
     --p2;
    } 
}
quant_dev
know what I love about while loops? That first one you have there, with the comment in it, can also be written as just while(*p2++);
Carson Myers
also, p1 and p2 both just point to str (you haven't copied the string to new locations, so you're just working on the same string with two variables). Really, you could replace every occurrence of *p1 and *p2 with *str.
Carson Myers
"That first one you have there, with the comment in it, can also be written as just while(*p2++);" -- too terse IMHO; I wouldn't put it in production code, neither in an example for a C beginner
quant_dev
"also, p1 and p2 both just point to str (you haven't copied the string to new locations, so you're just working on the same string with two variables). Really, you could replace every occurrence of *p1 and *p2 with *str." -- not true, they point to different places in the string.
quant_dev
A: 

The following program prints its arguments in reverse character order:

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

char * reverse(char * string)
{
    char * a = string;
    char * b = string + strlen(string) - 1;

    for(; a < b; ++a, --b)
        *a ^= *b, *b ^= *a, *a ^= *b; // swap *a <-> *b

    return string;
}

int main(int argc, char * argv[])
{
    for(int i = 1; i < argc; ++i)
        puts(reverse(argv[i]));
}

Nothing new here, but imo more readable than most other answers.

Christoph
A: 
void revstr(TCHAR *str)
{
    if( *str == '\0' )
    {
        return;
    }

    TCHAR *start = str;
    TCHAR *end = start + strlen(str) - 1;

    while(start < end)
    {
        *start ^= *end;
        *end ^= *start;
        *start ^= *end;
        *start++;
        *end-–;
        /*

        could also use *start ^= *end ^= *start++ ^= *end–-; if you want to get fancy
        */
    }
}

Stolen from the 2005 version of myself, but screw that guy, he slept with my wife.

Yes, I know I don't need some of the '*'s, but I wrote the one-liner first and just converted it, and the one-liner does require them.

Chris Doggett
Chris,Thanks a lot