我在网站上发现了这段代码,似乎作者早已不见了,无论如何,我很难理解实际的交换以及相反的情况:
void strrev2(char *str)
{
if( str == NULL )
return;
char *end_ptr = &str[strlen(str) - 1];
char temp;
while( end_ptr > str )
{
temp = *str;
*str++ = *end_ptr;
*end_ptr-- = temp;
}
}
让我们说你喂它“测试”这个词
第一次迭代:
*end_ptr = 'g';
temp = 't'
*str = 'g' // is it first assigned and then incremented to point to the next location?
*end_ptr = 't' // is it first assigned and then decremented to point to the previous location?
第二次迭代会发生什么?我很难过,因为我想到了这一点:
char *end_ptr = &str[strlen(str) - 1];
end_ptr
只会包含一个字母的地址,那么*end_ptr
如何运作?
无论如何,如果有人能以某种图形方式向我解释这个...... 感谢。
答案 0 :(得分:23)
str
和end_ptr
只是指向字符串开头和结尾的指针。每次循环时,它们的字符都会被交换,并且每个字符都朝着字符串的中间移动一步。当它们相遇(或交叉)时,循环终止。
这是一张图片......
1. testing s is str
^ ^ e is end_ptr
s e
2. gestint
^ ^
s e
3. gnitset
^
se
4. done!
(顺便说一句,这是一个常见的面试问题的开始,那些公司认为脑筋急转弯的人会有很好的面试问题。这个问题不可避免地会持续下去......所以现在,你怎么用同样的原则来扭转这些话在一个句子中,没有颠倒每个单词中的字母?)
答案 1 :(得分:8)
我喜欢亚历克斯的艺术,我想再详细说明一下,所以这是一个更为抽象的版本,其中包括其他人一直在发布的相同解释。
开始:
|'t'|'e'|'s'|'t'|'i'|'n'|'g'|'\0'| str | | |
^ | 0x00 | | |
str
然后行
char *end_ptr = &str[strlen(str) - 1];
因为strlen(str)返回7,
end_ptr = &str[6]
所以:
|'t'|'e'|'s'|'t'|'i'|'n'|'g'|'\0'| str | end | temp |
^ ^ | 0x00 | 0x06 | |
str end
一旦它进入循环,它检查结果是一个比str更大的地址,然后在地址str指向temp指向temp的值:
|'t'|'e'|'s'|'t'|'i'|'n'|'g'|'\0'| str | end | temp |
^ ^ | 0x00 | 0x06 | 't' |
str end
然后继续将结束时的值赋给str的地址:
|'g'|'e'|'s'|'t'|'i'|'n'|'g'|'\0'| str | end | temp |
^ ^ | 0x00 | 0x06 | 't' |
str end
然后将指针str前进到下一个地址
|'g'|'e'|'s'|'t'|'i'|'n'|'g'|'\0'| str | end | temp |
^ ^ | 0x01 | 0x06 | 't' |
str end
将temp的值分配给end的地址:
|'g'|'e'|'s'|'t'|'i'|'n'|'t'|'\0'| str | end | temp |
^ ^ | 0x01 | 0x06 | 't' |
str end
然后最终减量结束并循环回到while语句的顶部:
|'g'|'e'|'s'|'t'|'i'|'n'|'t'|'\0'| str | end | temp |
^ ^ | 0x01 | 0x05 | 't' |
str end
等等。
答案 2 :(得分:4)
指针在赋值后递增和递减,因此当结束指针向后运行时,启动指针会遍历单词。
在“测试”中,第一次迭代交换“t”和“g”,第二次迭代交换“e”和“n”,依此类推,直到指针在单词的中间相交。
答案 3 :(得分:2)
首先它交换第一个和最后一个,同时将指针递增到第一个元素,使它指向第二个并递减指针指向最后一个,使它指向最后但只有一个。只要“最后”字符出现在“第一个”之后,它就会继续这种方式。如果情况并非如此,那就完成了。
不,我不是ascii艺术家,所以没有图片适合你。
答案 4 :(得分:2)
旁注:这样做要容易得多:
#include <algorithm>
void strrev2(char *str)
{
std::reverse(str, str + strlen(str));
}