1

I am trying to create a non-recursive method to swap a c-style string. It throws an exception in the Swap method. Could not figure out the problem.

void Swap(char *a, char* b)
{
    char temp;
    temp = *a;
    *a = *b;
    *b = temp;
}
void Reverse_String(char * str, int length)
{
    for(int i=0 ; i <= length/2; i++)  //do till the middle
    {
        Swap(str+i, str+length - i);

    }

}

EDIT: I know there are fancier ways to do this. But since I'm learning, would like to know the problem with the code.

csharper
  • 77
  • 1
  • 5
  • What is the "exception"? Do you mean it crashes? Did you use a debugger? What input did you use that caused it to crash? – SoapBox Sep 24 '11 at 20:59
  • Can you provide a complete example (I suggest using ideone.com) that compiles correctly and fails when run? – Ben Voigt Sep 24 '11 at 21:00
  • It crashes. EXC_BAD_ACCESS in swap – csharper Sep 24 '11 at 21:01
  • what string do you reverse? where do you call your function – Andrew Sep 24 '11 at 21:03
  • 2
    Sounds like you are feeding it a constant string laying in a memory part you are not allowed to modify...or you have a off by one error (`str+length` should perhaps be `str+length-1`) – epatel Sep 24 '11 at 21:07

2 Answers2

7

It throws an exception in the Swap method. Could not figure out the problem.

No it doesn't. Creating a temporary character and assigning characters can not possibly throw an exception. You might have an access violation, though, if your pointers don't point to blocks of memory you own.

The Reverse_String() function looks OK, assuming str points to at least length bytes of writable memory. There's not enough context in your question to extrapolate past that. I suspect you are passing invalid parameters. You'll need to show how you call Reverse_String() for us to determine if the call is valid or not.

If you are writing something like this:

char * str = "Foo";
Reverse_String(str, 3);
printf("Reversed: '%s'.\n", str);

Then you will definitely get an access violation, because str points to read-only memory. Try the following syntax instead:

char str[] = "Foo";
Reverse_String(str, 3);
printf("Reversed: '%s'.\n", str);

This will actually make a copy of the "Foo" string into a local buffer you can overwrite.

André Caron
  • 44,541
  • 12
  • 67
  • 125
  • oh! I was doing the former. What exactly is the difference between `char str[] = "Foo";` and `char* str = "Foo"` ? – csharper Sep 24 '11 at 21:17
  • Where can i read more on this. Differences between char* char[] string and std::string? – csharper Sep 24 '11 at 21:20
  • 1
    You can read more in these related questions: [Why does simple C code receive segmentation fault?](http://stackoverflow.com/questions/164194/why-does-simple-c-code-receive-segmentation-fault) [Is it possible to modify a string of char in C?](http://stackoverflow.com/questions/1011455/is-it-possible-to-modify-a-string-of-char-in-c) – Greg Hewgill Sep 24 '11 at 21:24
2

This answer refers to the comment by @user963018 made under @André Caron's answer (it's too long to be a comment).

char *str = "Foo";

The above declares a pointer to the first element of an array of char. The array is 4 characters long, 3 for F, o & o and 1 for a terminating NULL character. The array itself is stored in memory marked as read-only; which is why you were getting the access violation. In fact, in C++, your declaration is deprecated (it is allowed for backward compatibility to C) and your compiler should be warning you as such. If it isn't, try turning up the warning level. You should be using the following declaration:

const char *str = "Foo";

Now, the declaration indicates that str should not be used to modify whatever it is pointing to, and the compiler will complain if you attempt to do so.

char str[] = "Foo";

This declaration states that str is a array of 4 characters (including the NULL character). The difference here is that str is of type char[N] (where N == 4), not char *. However, str can decay to a pointer type if the context demands it, so you can pass it to the Swap function which expects a char *. Also, the memory containing Foo is no longer marked read-only, so you can modify it.

std::string str( "Foo" );

This declares an object of type std::string that contains the string "Foo". The memory that contains the string is dynamically allocated by the string object as required (some implementations may contain a small private buffer for small string optimization, but forget that for now). If you have string whose size may vary, or whose size you do not know at compile time, it is best to use std::string.

Community
  • 1
  • 1
Praetorian
  • 106,671
  • 19
  • 240
  • 328