解释此C代码以反转字符串

时间:2011-02-22 00:24:25

标签: c string algorithm reverse

我真的不明白最后一个循环正在做什么,有人可以解释一下吗?

void reverse(char *str) { 
    char * end = str; 
    char tmp; 

    if (str) {
        while (*end) { 
            ++end;
        }
        --end; 
        while (str < end) {
            tmp = *str; 
            *str++ = *end;
            *end-- = tmp;
        }
    }
}

有人可以通过示例“你好”吗?

5 个答案:

答案 0 :(得分:11)

此代码背后的基本思想是两次通过:

  1. 在第一遍中,我们最终得到一个指向字符串最后一个字符的指针。
  2. 在第二遍中,我们在字符串结束处的知识的帮助下转动字符串。
  3. 第一遍由以下逻辑给出:

    char *end = str;
    while (*end) { 
        ++end;
    }
    --end; 
    

    while循环以指向字符串开头的end指针开始。然后它继续向前推进end指针一步,直到循环条件*end不再评估为真。因为C字符串是以空值终止的,所以只要end指针指向字符串中间的某处而不是字符串末尾的空终止符,循环条件就会计算为true。因此,当此循环结束时,end指针将一直走到字符串的末尾并停在空终止符处。然后我们执行--end以将指针备份一步。此时,end指针指向字符串中的最后一个字符。以下是“Hello:”

    的示例
     H e l l o
     ^       ^
     |       |
    str     end
    

    现在我们有了这个end指针,我们实际上运行逻辑来反转字符串。这由以下代码给出:

    while (str < end) {
        tmp = *str; 
        *str++ = *end;
        *end-- = tmp;
    }
    

    这段代码背后的想法是,直到字符串的开始和结束指针相互交叉,我们交换它们指向的值,然后将两个指针向内推向另一个。如果我们通过略微更详细的

    重写这个等价物
    while (str < end) {
        tmp = *str; 
        *str = *end;
        *end = tmp;
    
        ++str;
        --end;
    }
    

    然后可能会更容易看出它是如何工作的。此修改循环的前三行交换起始和结束指针指向的值,接下来的两行将指针向内移动。这是一个例子:

     H e l l o
     ^       ^
     |       |
    str     end
    
     o e l l H
       ^   ^
       |   |
      str end
    
     o l l e H
         ^
         |
      str end
    

    此时,两个指针相遇,我们正确地反转了字符串。

    请注意,我们必须在这里考虑一个不寻常的边缘情况,这就是当字符串是空字符串时会发生什么。如果发生这种情况,那么第一个循环将表现得有些奇怪。特别是,这段代码:

    char *end = str;
    while (*end) { 
        ++end;
    }
    --end; 
    

    永远不会执行循环体,因为end指针将从指向空终止符开始。因此循环不执行任何操作,我们最终在字符串开始之前备份end 一步!这是一个无效指针,取消引用它将有未定义的结果。但幸运的是,在这种情况下,没有任何反应,因为反转字符串的循环具有以下条件:

    while (str < end)
    

    如果end在字符串开始之前是一步,则立即返回false,因此没有任何反应。

    希望这有帮助!

答案 1 :(得分:4)

在最里面的while循环中基本上发生的是,在每次迭代中,strend指向的字符交换,str递增以指向下一个字符,并且end递减以指向前一个。

以“你好”为例:

v   v
hello
 v v 
oellh
  v
olleh

然后循环结束,str = end

答案 2 :(得分:0)

第一个找到最后一个字符;所以,在它之后,end将指向它。

第二个时间将str指向的字符与end指向的字符交换,并将str向前移动1个字符,向end向后移动1个字符。这样,字符就会从字符串的extern转换到内部。

end开始指向str之前的字符时,外观结束,这意味着我们到达字符串的中心并且所有字符都已经被交换。

“你好”的例子:

S   E            S   E
V   V            V   V
Hello  >>swap>>  oellH

>>pointer increment/decrement>>

 S E              S E
 V V              V V
oellH  >>swap>>  olleH

>>pointer increment/decrement>>
it would result in

  E                
  S                
  V                
olleH

but now str is no longer before end, so the loop terminates

答案 3 :(得分:0)

好的,它的作用是什么。

void reverse(char *str) { 
    char * end = str;  // copy the pointer 
    char tmp; 

    if (str) {
        // Now step through the string until you get to the last character.
        // which will be the null terminator \0
        while (*end) { 
            ++end;
        }
        // One step back, and we're pointing at the last actual character.
        --end; 
        // Now.  Move the start at either end and work your way inwards until
        // they meet in the middle.
        while (str < end) {
            // take copy of left character into tmp
            tmp = *str; 
            // copy right character into left position and move left pointer right
            *str++ = *end;
            // copy tmp character into right position and move right pointer left
            *end-- = tmp;
        }
    }
}

答案 4 :(得分:-1)

#include<stdio.h>
#include<string.h>
main()
{
  int i=0,lenght,j;
  char str[100],st[100];
  printf("\nEnter a string");
  scanf("%s",str);
  lenght=strlen(str);
  for(i=0,j=(lenght-1);str[i]!='\0',j>=0;i++,j--)
   {
      st[j]=str[i];
   }
  st[i]='\0';
  printf("\nThe reversed string is %s\n",st);
 }