Может кто-нибудь сказать мне, как этот кусок кода работает? - PullRequest
0 голосов
/ 19 февраля 2019
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void print_reverse(char *s)
{
    size_t len=strlen(s);
    char *t=s+len-1;
    printf("%s %s\n",t,s);
    while(t>=s){
        printf("%c",*t);
        t=t-1;
    }
    puts("");
}
int main(){
    print_reverse("Hello");

}

Может кто-нибудь сказать, как работает char *t=s+len-1; и while(t>=s).Я не могу понять, как число может быть добавлено к указателю и как сравниваются указатели в цикле while.Эта программа предназначена для обращения строки в c.

Ответы [ 2 ]

0 голосов
/ 19 февраля 2019

Арифметика указателя

Когда указатель указывает на массив, добавление целых чисел к указателю или вычитание целых чисел из указателя перемещает указатель вперед и назад в массиве.

Эта функция должна бытьпередал char *s, который указывает на строку, которая является массивом символов, заканчивающихся нулевым символом ('\0').Затем size_t len = strlen(s); устанавливает len для размера этой строки, а char *t = s+len-1; устанавливает t для указания на последний символ перед нулевым символом.

Затем в цикле t=t-1; перемещается t назад.

К сожалению, этот цикл использует t>=s в качестве условия управления.Он предназначен для остановки, когда t был перемещен к персонажу до s, что означает, что он вернулся до начальной точки.Однако стандарт C определяет арифметику указателей только для элементов в массиве плюс специальную позицию в конце массива.Если этой функции передано значение s, которое указывает на начало массива, то цикл в конечном итоге сделает точку t перед массивом, и стандарт C не определяет результирующее поведение.

ДругоеЧто нужно знать об арифметике указателей

Любой объект можно рассматривать как массив из одного элемента.Если у вас есть какой-то тип T и какой-то объект T x;, вы можете установить указатель T *p = &x;, и тогда ему будет разрешено продвигать указатель на один элемент, p = p+1;.Разыменование этого указателя с помощью *p не определено, но вы можете сравнить его, как в &x == p, или вы можете вычесть один из него.

Если print_reverse передал указатель в массив за пределаминачало, то его цикл будет в порядке.Однако теперь это то, как это используется в примере кода;print_reverse("Hello"); не является хорошим кодом.

Любой объект может рассматриваться как массив символов.Вы можете преобразовать указатель на любой объект в указатель на unsigned char, а затем изучить байты, составляющие объект.Это используется для специальных целей.Вам не следует использовать его в общем коде, пока вы изучаете C, но вы должны знать, что он существует.

0 голосов
/ 19 февраля 2019

Позволяет делать эту строку построчно:

print_reverse("Hello");
void print_reverse(char *s)

Теперь s указывает на строку, содержащую:

- - ----+----+----+----+----+----+----+---- - -
        |  H |  e |  l |  l |  o | \0 |
- - ----+----+----+----+----+----+----+---- - -
           ^
           s

Этот последний символ называется терминатором строки «NUL»потому что «NUL» - это имя символа с нулевым значением ASCII (все значения ASCII, которые не могут быть напечатаны, имеют трехбуквенные имена).

    size_t len=strlen(s);

Теперь len имеет значение пять.Обратите внимание, что он не включает терминатор «NUL», поэтому даже если строка занимает 6 байтов, длина равна 5.

    char *t=s+len-1;

Теперь t имеет значение s + 4.Если вы посчитаете ячейки памяти, это то, что вы получите:

- - ----+----+----+----+----+----+----+---- - -
        |  H |  e |  l |  l |  o | \0 |
- - ----+----+----+----+----+----+----+---- - -
           ^                   ^
           s                   t

Обратите внимание, что s+strlen(s) будет указывать на терминатор "NUL".

    printf("%s %s\n",t,s);

Этот printf должен печатать Hello o

    while(t>=s)

Этот цикл while будет продолжаться до тех пор, пока t>=s означает, что он будет выполнять тело цикла для каждого символа, включая тот, на который указывает s.

        printf("%c",*t);

Печатает содержимое памяти, на которую указывает t.Он начинается с o и продолжается в обратном направлении к H.

        t=t-1;

Это та часть, которая движется t назад.В конце концов, t пройдет s, а затем цикл закончится.Когда цикл завершится, он будет выглядеть следующим образом:

- - ----+----+----+----+----+----+----+---- - -
        |  H |  e |  l |  l |  o | \0 |
- - ----+----+----+----+----+----+----+---- - -
      ^    ^
      t    s

Тогда есть одна последняя строка:

    puts("");

, которая печатает пустую строку и окончательный перевод строки - там не былоперевод строки в строке, но он нам нужен, так что это способ сделать это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...