Перевернуть строку С++

Я новичок в программировании. Сегодня я научился переворачивать строку. Я пытался использовать строку вместо char, но терминал выдает ошибку.

string name = { "george" };
int nChar = sizeof(name) - 1;
string *pName = &name;
string *pNameLast = &name + nChar - 1;

while(pName < pNameLast) {
    string save = *pName;
    *pName = *pNameLast;
    *pNameLast = save;
    
    pName++;
    pNameLast--;
}

cout << name << endl;

введите здесь описание изображения


person Community    schedule 18.12.2020    source источник
comment
пожалуйста, укажите ошибку в вопросе. Обратите внимание, что есть алгоритм std::reverse, я думаю, вы хотите использовать рукописный текст, верно?   -  person 463035818_is_not_a_number    schedule 18.12.2020
comment
Чего вы хотите добиться с помощью string *pNameLast = &name + nChar - 1;? Вы знаете, что это делает? Похоже, вы только что заменили каждый экземпляр char на string.   -  person churill    schedule 18.12.2020
comment
Подсказка: вы не можете просто заменить char* на std::string и ожидать, что ваш код будет работать.   -  person Yksisarvinen    schedule 18.12.2020
comment
я понимаю. но как я могу изменить его с помощью строки? я не очень понимаю как это работает :\   -  person    schedule 18.12.2020
comment
sizeof(name) даст вам размер объекта std::string, который не совпадает с длиной строки, которую он обертывает.   -  person Some programmer dude    schedule 18.12.2020
comment
Проверьте значение на nChar. Кроме того, вместо того, чтобы пытаться использовать указатели, просто используйте name[i]...   -  person Damien    schedule 18.12.2020
comment
Я предлагаю вам инвестировать в несколько хороших книг, чтобы правильно изучить C++. Возможно, даже взять несколько занятий.   -  person Some programmer dude    schedule 18.12.2020
comment
хорошо, спасибо всем. :)   -  person    schedule 18.12.2020
comment
Чтобы добраться до указателя начала массива, содержащегося в строке, &name нужно заменить на reinterpret_cast<void*>(name.data()) с помощью c++11 (разница в 2 байта).   -  person Soleil    schedule 18.12.2020
comment
@Soleil-MathieuPrévot в коде вообще не должно быть &name   -  person 463035818_is_not_a_number    schedule 18.12.2020
comment
Отвечает ли это на ваш вопрос? Как перевернуть строку на месте на C или C++?   -  person JHBonarius    schedule 18.12.2020


Ответы (3)


Вот пример использования std::reverse_interator. Это лучший способ сделать это. Вместо того, чтобы делать это самостоятельно.

#include <iostream>
#include <string>
#include <iterator>
 
int main()
{
    std::string s = "George";
    std::reverse_iterator<std::string::iterator> r = s.rbegin();
    std::string rev(r, s.rend());
    std::cout << rev << endl;
}
person Bybit360    schedule 18.12.2020
comment
Вероятно, вы захотите использовать rbegin и rend, так как прямо сейчас вы разыменовываете end. - person Stephen Newell; 18.12.2020
comment
Стивен Ньюэлл прав, это дает мне дополнительное пространство в начале, которое, как я полагаю, связано с Undefined Поведение, вызванное разыменованием std::string::end(). - person GaryNLOL; 18.12.2020
comment
@GaryNLOL Ты прав. Позвольте мне исправить это. - person Bybit360; 18.12.2020

Проблема:

Когда вы пытаетесь выполнить такие операции, как string *pName = &name и string *pNameLast = &name + nChar - 1;, вы обрабатываете std::string как char*. Вы не можете сделать это и ожидать, что код будет работать.

Решение:

Рассматривайте std::string как std::string. Вместо string *pName = &name объявите pName как int и используйте оператор [] из std::string для доступа к значениям. Аналогично с pNameLast. Вы также должны объявить string save как char или, как я предпочитаю, использовать функцию std::swap.

Дополнительная информация:

  1. Насколько я вижу, вы, вероятно, используете using namespace std;, поскольку объявляете std::string как string. Если это так, считайте, что using namespace std; считается плохой практикой (дополнительная информация здесь).

Полный код:

#include <iostream>

int main() {
    std::string name = "george";
    int length = name.size();
    int pNameFirst = 0;
    int pNameLast = length - 1;

    while(pNameFirst < pNameLast)
    {
        std::swap(name[pNameFirst],name[pNameLast]);

        pNameFirst++;
        pNameLast--;
    }
    std::cout << name << std::endl;
}
person GaryNLOL    schedule 18.12.2020
comment
это самая точная версия. благодарю вас :) - person ; 21.12.2020

Если вы хотите инвертировать строковый объект, просто сделайте следующее (обратите внимание, что это один из многих способов, сделанных вручную:

#include <iostream>
#include <string>

int main() {

    std::string my_string{"hello"};

    // Similar to your way:
    int index{static_cast<int>(my_string.length() - 1)};
    for (; index >= 0; --index) {
        std::cout << my_string.at(index) << std::endl;
    }
}
person Krapnix    schedule 18.12.2020
comment
лучше не называть его length, когда это не длина, а индекс - person 463035818_is_not_a_number; 18.12.2020
comment
@largest_prime_is_463035818 правда - person Krapnix; 18.12.2020
comment
Разве ваше условие цикла не всегда будет истинным, поскольку size_t не имеет знака, а это означает, что оно будет переполнено, когда index==0? - person Stephen Newell; 18.12.2020
comment
Стивен Ньюэлл прав, это недостаточно. terminate called after throwing an instance of 'std::out_of_range' what(): basic_string::at:: __n (which is 18446744073709551615) >= this->size() (which is 5). - person GaryNLOL; 18.12.2020
comment
@StephenNewell, это правда! Я перейду на правильную петлю - person Krapnix; 19.12.2020