C. для петли с символами - PullRequest
0 голосов
/ 21 марта 2019

Можете ли вы объяснить эти выводы?

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 ]

1 голос
/ 21 марта 2019

Это

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 ,

Теперь массив символов 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 не достигнет s, т.е. 0x100 >= 0x100 Наконец, массив символов 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'), если это приводит к истине, тогда (*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.

0 голосов
/ 21 марта 2019
 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

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

делает то же самое, затем смотрит, находится ли символ в верхнем регистре (< 'a', потому что ASCII-код для AZ меньше, чем ASCII-код для AZ)), и в этом случае добавьте 'a' - 'A', поэтому преобразуйте егов нижнем регистре, поэтому результат равен SuMmEr в нижнем регистре, поэтому лето

обратите внимание, что < 'a' работает только с буквой a..z A..Z

...