C ++中的字符串反转

时间:2009-09-22 17:12:55

标签: c++ c string

我在网站上发现了这段代码,似乎作者早已不见了,无论如何,我很难理解实际的交换以及相反的情况:

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如何运作?

无论如何,如果有人能以某种图形方式向我解释这个...... 感谢。

5 个答案:

答案 0 :(得分:23)

strend_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));
}