First transformation : d
can only be 0
or 1
. It's only read in the while
loop's condition. In fact, it is the loop condition, the function's body can be rewritten as :
int a = 0;
int b = strlen(p) - 1;
while(a != b)
{
char t = *(p + a);
*(p + a) = *(p + b);
*(p + b) = t;
a += 1;
b -= 1;
}
The three-lines block is definitely a swap. In C++ you'd use the actual std::swap
function, but in the absence of generic functions and overloading I guess doing it by hand is fine. Let's comment it and use the indexing notation though :
// Swap p[a] and p[b]
char t = p[a];
p[a] = p[b];
p[b] = t;
a += 1
and b -= 1
can also be rewritten as ++a
and --b
.
It's now clear that this function uses two indices, a
and b
, that start at the ends and meet in the center, swapping the indexed characters on the way. It's an in-place string reversal function, so let's rename it (and p
). a
and b
could also be renamed, but it's clear enough IMO.
void reverse(char *str)
(Swiped from Lundin's answer) as a
and b
are indices inside an array, their type of choice should be size_t
.
size_t a = 0u;
size_t b = strlen(str) - 1u;
Now, the bug you spotted : indeed, if strlen(str)
is even, a
and b
will run past each other in the middle, and never be equal. Let's change the condition to account for this :
while(a < b)
Finally, handling str == NULL
: this function is quite low-level. There's nothing useful you can do to react to a null pointer, so just add an intelligible fail condition if that happens :
assert(str && "Please provide a non-null pointer.");
The end product :
void reverse(char *str)
{
assert(str && "Please provide a non-null pointer.");
size_t a = 0u;
size_t b = strlen(str) - 1u;
while(a < b)
{
// Swap str[a] and str[b]
char t = str[a];
str[a] = str[b];
str[b] = t;
++a;
--b;
}
}
Live on Coliru