【问题标题】:Explain this C code to reverse a string解释此 C 代码以反转字符串
【发布时间】:2011-07-01 15:55:18
【问题描述】:

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

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

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

有人可以帮我看一下“你好”这个例子吗?

【问题讨论】:

  • 你试过在纸上画出来吗?尝试在一张纸上写出h e l l o \0,然后遍历strend 指向的位置以及tmp 在代码的每一步中包含的内容。是否有一段特定的代码让您感到困惑?
  • 它从两端交换字符,向中间移动...
  • 很高兴看到不调用strlen()的解决方案
  • 如何在调试器中单步执行代码。

标签: c string algorithm reverse


【解决方案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);
 }

【讨论】:

    【解决方案2】:

    好的,它的作用就是这样。

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

    【讨论】:

      【解决方案3】:

      这段代码背后的基本思想是分两遍工作:

      1. 在第一遍中,我们最终得到一个指向字符串最后一个字符的指针。
      2. 在第二遍中,我们在知道字符串结束位置的帮助下翻转字符串。

      这第一遍由以下逻辑给出:

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

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

       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 在字符串开始前一步,则立即为假,因此没有任何反应。

      希望这会有所帮助!

      【讨论】:

        【解决方案4】:

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

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

        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
        

        【讨论】:

          【解决方案5】:

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

          以“你好”为例:

          v   v
          hello
           v v 
          oellh
            v
          olleh
          

          然后循环结束,str = end

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2014-07-12
            • 2012-04-30
            • 2011-07-20
            • 2015-10-11
            • 1970-01-01
            • 2018-09-20
            • 2019-05-18
            • 1970-01-01
            相关资源
            最近更新 更多