【问题标题】:C. for loop with charsC. 带字符的 for 循环
【发布时间】:2019-08-12 11:00:11
【问题描述】:

你能解释一下这些输出吗?

1)

char s[]="TvNnFs",*p;
for(p=&s[5];p>=s;p--) 
    --*p;
puts(s);

输出:SuMmEr

2)

char s[]="TvNnFs",*p;
for(p=&s[5]; p>=s; p--) 
    ((--*p)<'a') ? (*p+=('a'-'A')) : (*p);
puts(s);

输出:夏天

【问题讨论】:

  • 让您困惑的是什么?你期待什么,为什么?或者具体哪一部分不清楚?
  • 第一个将每个字母在字母表中移动一个位置。第二个也使整个字符串小写。
  • 你不明白哪个符号或指令?
  • 我确实理解代码。它是 for 循环中的语句,我不明白它是如何工作的
  • @ThomasJager 你明白了,字符串的小写现在是大写并且与大写相同(谈论输出。代码(1))。我只是问它为什么这样做? (特别是在代码 2 上,因为我可以理解代码 1 上的 --*p )。

标签: c pointers char


【解决方案1】:

这个

char s[]="TvNnFs",*p;

其中s 是一个字符数组,p 是字符指针,如下所示

 s[0]  s[1]   s[2]  s[3]  s[4]  s[5]  s[6]
  ------------------------------------------
 |  T  |  v  |  N  |  n  |  F  |  s  |  \0  |
  ------------------------------------------
 s 0x100 0x101 0x102 0x103 0x104 0x105 0x106.. (assume 0x100 is base address of s)

接下来,for 循环

for(p=&s[5];p>=s;p--) 
    --*p;

这里p=&amp;s[5]指针p指向s[5]的地址,即0x105。接下来是p&gt;=s,即0x105 &gt;= 0x100,这是真的,然后--*p首先执行*p,这意味着0x105内存位置的值s和递减将使s[5]成为r .

现在 char 数组 s 看起来像

 s[0]  s[1]   s[2]  s[3]  s[4]  s[5]  s[6]
  ---------------------------------------------
 |  T  |  v  |  N  |  n  |  F  |  r(new)|  \0  |
  ---------------------------------------------
 s 0x100 0x101 0x102 0x103 0x104 0x105 0x106..

注意:您可能想知道--*p 是如何影响s 的?这是因为p 指向或持有s 的地址,即对*p 所做的任何更改都会间接影响s

p-- 发生之后,即p 现在指向比以前更早的一个位置,即0x104。在p 到达s0x100 &gt;= 0x100 之前,将进行相同的操作。最后 char 数组 s 看起来像

      s[0]  s[1]   s[2]  s[3]  s[4]  s[5]  s[6]
      -------------------------------------------
     |  S  |  u  |  M  |  m  |  E  |  r  |  \0  |
      -------------------------------------------
     s 0x100 0x101 0x102 0x103 0x104 0x105 0x106..

因此它打印SuMmEr

案例2:

char s[]="TvNnFs",*p;
for(p=&s[5]; p>=s; p--) 
((--*p)<'a')?(*p+=('a'-'A')):(*p);
puts(s);

这里

       s[0]  s[1]   s[2]  s[3]  s[4]  s[5]  s[6]
      ------------------------------------------
     |  T  |  v  |  N  |  n  |  F  |  s  |  \0  |
      ------------------------------------------
     s 0x100 0x101 0x102 0x103 0x104 0x105 0x106..
                                      |
                                      p points here

对于0x105 &gt;= 0x100:这个

((--*p)<'a')?(*p+=('a'-'A')):(*p);

是三元运算符,即首先执行((--*p)&lt;'a'),如果结果为真,则(*p+=('a'-'A')) 将是输出否则(*p)。所以这里看起来像((--*p)&lt;'a'),即'r' &lt; 'a',这是错误的,所以只是(*p),但s[5]在这之后由于--*p而发生了变化。

      s[0]  s[1]   s[2]  s[3]  s[4]  s[5]  s[6]
      ------------------------------------------
     |  T  |  v  |  N  |  n  |  F  |  r  |  \0  |
      ------------------------------------------
     s 0x100 0x101 0x102 0x103 0x104 0x105 0x106..
                                | 
                                p points here due to p--

接下来,对于0x104 &gt;= 0x100:这个

((--*p)<'a')?(*p+=('a'-'A')):(*p);

'E' &lt; 'a'70 &lt; 97 这是真的,所以这个(*p+=('a'-'A')) 被执行,即

*p = *p + ('a' - 'A')
   = 'E' + (97 - 65)
   = 'E' + 32
*p = 'e' /* now s[4] overwritten by e(previously F) */

现在数组看起来像

   s[0]  s[1]   s[2]  s[3]  s[4]  s[5]  s[6]
  ------------------------------------------
 |  T  |  v  |  N  |  n  |  e  |  r  |  \0  |
  ------------------------------------------
 s 0x100 0x101 0x102 0x103 0x104 0x105 0x106..
                      | 
                      p points here due to p--

同样的操作一直持续到0x100 &gt;= 0x100

【讨论】:

  • 我确实知道指针是如何工作的,我确实了解了有关理论的一切。我只是不明白 prev chars (s[0] s[1] e.t.c) 是如何更改为 SuMmEr 的。
  • 这很简单。清楚地遵循每次迭代。在第二种情况下,粗略地说,如果s[0]T,那么--*p 使s[0] 成为S,即T 之前的一个字符,然后减去32 使s。哪一部分你没有得到?
猜你喜欢
  • 2013-11-02
  • 2022-01-26
  • 2013-11-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-02
  • 2014-02-16
相关资源
最近更新 更多