C. for循环与字符

时间:2019-03-21 14:40:09

标签: c pointers char

您能解释这些输出吗?

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

输出:夏季

2 个答案:

答案 0 :(得分: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=&s[5]指针p指向s[5]的地址,即0x105。接下来是p>=s,即0x105 >= 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 >= 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 >= 0x100:此

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

是三元运算符,即首先执行((--*p)<'a'),如果结果为true,则(*p+=('a'-'A'))将是输出,否则为(*p)。因此,这里看起来像((--*p)<'a'),即'r' < '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 >= 0x100:这个

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

'E' < 'a'70 < 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 >= 0x100

答案 1 :(得分:0)

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

只需从字符串末尾递减每个字符代码: p &s[5],因此s+5然后s+4 ...然后s在执行--*p时,'T'-1为'S,'v'-1为'u'等,因此 TvNnFs 的结果为 SuMmEr < / p>

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

执行相同的操作,然后查看字符是否为大写(< 'a',因为AZ的ASCII码小于az的ascii码)),然后添加'a' - 'A',以便将其转换为小写,所以结果是 SuMmEr 小写,所以 summer

请注意< 'a'仅适用于字母a..z A..Z