обратная строка в C ++ - PullRequest
       21

обратная строка в C ++

4 голосов
/ 22 сентября 2009

Я нашел этот фрагмент кода на сайте, кажется, что автора давно уже нет, так или иначе, мне трудно понять фактический обмен и как происходит обратное:

void strrev2(char *str)
{
        if( str == NULL )
                return;

        char *end_ptr = &str[strlen(str) - 1];
        char temp;
        while( end_ptr > str )
        {
                temp = *str;
                *str++ = *end_ptr;
                *end_ptr-- = temp;
        }
}

допустим, вы кормите его словом "тестирование"

Первая итерация:

*end_ptr = 'g';

temp = 't'
*str = 'g' // is it first assigned and then incremented to point to the next location?
*end_ptr = 't' // is it first assigned and then decremented to point to the previous location?

Что происходит на второй итерации? У меня трудное время, потому что я думал, что в этой строке:

char *end_ptr = &str[strlen(str) - 1];

end_ptr будет содержать только адрес одной буквы, так как *end_ptr может работать?

Во всяком случае, если кто-то сможет объяснить мне это каким-то графическим способом ... Спасибо.

Ответы [ 5 ]

23 голосов
/ 22 сентября 2009

str и end_ptr - это просто указатели на начало и конец строки. Каждый раз вокруг цикла их символы меняются местами, и каждый из них перемещается на один шаг к середине строки. Когда они встречаются (или пересекаются), цикл прекращается.

Вот картинка ...

1. testing        s is str
   ^     ^        e is end_ptr
   s     e

2. gestint
    ^   ^
    s   e

3. gnitset
      ^
      se

4. done!

(Между прочим, это начало общего вопроса об интервью в компаниях, которые считают, что «дразнилки» задают хорошие вопросы для интервью. Вопрос неизбежно продолжается ... так что теперь, как бы вы использовали тот же принцип, чтобы изменить слова в предложении, не меняя букв в каждом слове?)

8 голосов
/ 22 сентября 2009

Мне понравилось искусство Алекса, и я хотел немного проработать, так что это немного более рисованная версия из того же объяснения, которое публиковали все остальные.

Для начала: |'t'|'e'|'s'|'t'|'i'|'n'|'g'|'\0'| str | | | ^ | 0x00 | | | str Затем после линии char *end_ptr = &str[strlen(str) - 1]; так как strlen (str) возвращает 7, end_ptr = &str[6] Так: |'t'|'e'|'s'|'t'|'i'|'n'|'g'|'\0'| str | end | temp | ^ ^ | 0x00 | 0x06 | | str end как только он входит в цикл, он проверяет, что адрес конца больше, чем str, а затем назначает значение по адресу, на который str указывает temp: |'t'|'e'|'s'|'t'|'i'|'n'|'g'|'\0'| str | end | temp | ^ ^ | 0x00 | 0x06 | 't' | str end Затем он продолжается, присваивая значение в конце адресу по адресу str: |'g'|'e'|'s'|'t'|'i'|'n'|'g'|'\0'| str | end | temp | ^ ^ | 0x00 | 0x06 | 't' | str end Затем перемещает указатель str на следующий адрес |'g'|'e'|'s'|'t'|'i'|'n'|'g'|'\0'| str | end | temp | ^ ^ | 0x01 | 0x06 | 't' | str end Назначает значение temp адресу в конце: |'g'|'e'|'s'|'t'|'i'|'n'|'t'|'\0'| str | end | temp | ^ ^ | 0x01 | 0x06 | 't' | str end Затем, наконец, декременты заканчиваются и возвращаются к началу оператора while: |'g'|'e'|'s'|'t'|'i'|'n'|'t'|'\0'| str | end | temp | ^ ^ | 0x01 | 0x05 | 't' | str end и т. д. и т. д.

4 голосов
/ 22 сентября 2009

Указатели увеличиваются и уменьшаются после присваивания, поэтому указатель начала проходит через слово, а указатель конца проходит назад.

в «тестировании» первая итерация обменивается «t» и «g», вторая итерация обменивается «e» и «n» и т. Д., Пока указатели не встретятся в середине слова.

2 голосов
/ 22 сентября 2009

Примечание: это гораздо проще сделать:

#include <algorithm>
void strrev2(char *str)
{
    std::reverse(str, str + strlen(str));
}
2 голосов
/ 22 сентября 2009

Сначала он меняет местами первый и последний, одновременно увеличивая указатель на первый элемент так, чтобы он указывал на второй, и уменьшая указатель на последний, чтобы он указывал на последний, кроме одного. Это продолжается до тех пор, пока «последний» символ идет после «первого». Когда дело не в этом, дело сделано.

И нет, я не очень хороший художник ascii, поэтому вам не нужна графика.

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