OK, sorry about the bad pun :P
I've coded the old trick 开发者_开发百科of HAL => IBM
in C. I've just read the first few pages in K&R reguarding them, and I thought it would be a good first play with them.
char evil[] = "HAL";
char *ptr = evil;
for (int i = 0; i < strlen(evil); ++i, ++ptr) {
(*ptr)++;
}
printf("%s\n", evil); // IBM
My problem is, I have two variables incrementing, i
and ptr
, and something is telling me one of them is redundant (perhaps I'm still not thinking C well enough).
The only reason I use i
is to determine if we have read to the end of the string. Is there any way to check the pointer to see if it has arrived at the end of the string?
Update
Sorry for any confusion of the actual question. By have I missed the point I basically meant, why would I use a pointer when I needed an incrementing index to check the length as well. I could just use that index to subscript the right char from the array.
You could as well write
for (char *ptr = evil; *ptr != '\0' ; ++ptr)
I typed the question, re-read it, and then realised something very obvious I had overlooked!
char evil[] = "HAL"
char *ptr = evil;
for (; *ptr != '\0'; ++ptr) {
(*ptr)++;
}
printf("%s\n", evil);
That seemed to do the trick.
You've figured out the correct implementation, but I would still like to make one point about your original code, which may give you a different way to think about such problems.
Your original solution may be even worse than you think, because its complexity is actually O(n^2), where n is the length of the string. strlen()
has a complexity of O(n), because it has to iterate over all the characters in the string until it finds '\0'
. So you have a loop that performs n iterations, and calls strlen()
each time, resulting in the complexity of O(n^2).
At the very least you should call strlen()
once before the loop, and cache the length of the string. And, of course, you have the correct solution that does not call strlen()
at all.
In C
strings end with '\0'
. You can use that fact to stop the loop.
for (; *ptr != '\0' ; ++ptr) {
/* ... */
}
The character pointed to will be '\0'
. But be careful, misplacing the NUL byte can be a source of program crashes or security holes.
Calling strlen(evil)
is inefficient. Instead of relying on strlen
, use the same thing that makes strlen
stop: the null terminator:
for (char *ptr = evil; *ptr; ++ptr) {
(*ptr)++;
}
This would do the trick:
char evil[] = "HAL";
*(int*) evil += 65793;
printf("%s\n", evil);
Since we are talking about evil:
#include <stdio.h>
int main()
{
char evil[] = "HAL";
char *ptr;
// Increment the pointer and its content in the same expression
// Just to be really evil
for (ptr = evil; *ptr != '\0'; ++*(ptr++)) { }
printf("%s\n", evil);
}
精彩评论