You have quite a few issues there.
1/ First, you do not allocate any storage for your string. This could be fixed with a simple char str[128];
depending on your size requirements. This will also mean that the NULL check is unnecessary and you don't have to worry about later printing (or trying to print) a NULL pointer - change the function contract so that this is explicitly forbidden.
2/ Next, don't ever use scanf("%s")
(ie., with an unbounded string format specifier) - it's an easy pathway to buffer overflow problems. If you want a robust input function with overflow checking see this answer.
In any case, %s
scans a word rather than a line so, if you enter "Hello Pax"
(with a space), it will see Hello
.
3/ Thirdly, if str
is a char*
, then *str
is a character, not a C string. You should be passing str
to strrev
, not *str
. This is true even with the fix in point 1 above.
4/ The __LINE__
macro expands to an integral type so won't take kindly to being treated as a character pointer as per the %s
format specifier. You may want to use %d
instead.
5/ The ISO standard reserves all names starting with str
and a lowercase letter for its own uses, as per 7.31.13 Future library directions
in C11. So strrev
is not actually a good idea.
6/ Lastly, the XOR-swap trick is an anachronism that has no place in today's modern environments. It's both unnecessary and may well be slower, given the calculations rather than simple moves of a temporary-variable solution. The correct way to swap to variables is:
int t = a;
a = b;
b = t;
Do yourself a favour and ditch that trick. It belongs in the same bucket as Duff's Device :-)
Some other issues, though this are more stylistic than anything else (as in I prefer this style), based on quite a few years of teaching programming.
7/ Most people I've encountered find it easier to understand array indexes rather than pointers since it's easier to think about a character in a string rather than an arbitrary memory location. Seasoned C programmers know there's no difference (both in terms of functionality and, with today's compilers, performance). Hence I tend to use indexes rather than pointers, such as with:
char *reverseStr (char *str) {
char tmpchar;
int front = 0;
int back = strlen (str) - 1;
while (front < back) {
tmpchar = str[front];
str[front++] = str[back];
str[back--] = tmpchar;
}
return str;
}
8/ You'll also notice another thing there, the use of more verbose variables like front
, back
and tmpchar
. The compiler doesn't care how big your identifiers are (within reason) and this makes code much more readable.