Как я могу поменять местами n символов в строке, когда значением по умолчанию для n является длина строки?

#c

#c

Вопрос:

Мне нужно создать функцию reverse (), которая меняет количество символов в str на обратное. Вот это прототип:

 void reverse(char **str, int count = ???);
  

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

Я попытался назначить это следующим образом:

   void reverse(char **str, int count = strlen(*str))
  

Но компилятор выдал следующую ошибку:

 error: local variable ‘str’ may not appear in this context
 void reverse(char **str, int count = (int) strlen(*str)) {
  

Вот мой код:

 
    #include <iostream>
    #include <cstring>

    using namespace std;

    void reverse(char **str, int count = (int) strlen(*str)) {
        int i;
        char temp;
        for (i = 0; i < count / 2; i  ) {
            temp = (*str)[i];
            (*str)[i] = (*str)[count - i];
            (*str)[count - i] = temp;
        }
    }

    int main() {
        char buf[100];
        cout << "Enter your string:n" << endl;
        cin >> buf;
        char *str;
        str = new char(strlen(buf) 1);
        strcpy(str, buf);

        reverse(amp;str);
        cout << "Reversed string:n" << str << endl;

        return 0;
    }

  

Как я могу с этим справиться?

Комментарии:

1. void reverse(char **str, int count = strlen(*str)) — Честно говоря, это одно из самых неортодоксальных объявлений функции для изменения строки, которое я когда-либо видел. Это имеет больше смысла: void reverse(char *str, int count = -1) а -1 указывает на обратное изменение всей строки. В чем причина того, что char ** когда char * этого достаточно?

Ответ №1:

Исходя из того, что сказал Пол Маккензи. Вам не нужен указатель на указатель, чтобы поменять местами строку. Указатель на указатель потребуется только в том случае, если вы пытаетесь изменить указатель. Но вы этого не делаете, вы пытаетесь изменить то, на что указывается, поэтому требуется простой указатель.

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

И вы отклоняетесь на единицу в своем алгоритме, str[count - i] когда i равно нулю, вы индексируете str[count] то, что находится за концом строки.

Попробуйте это

 void reverse(char *str, int count = -1)
{
    if (count < 0)
        count = strlen(str);
    for (int i = 0; i < count / 2; i  )
    {
        char temp = str[i];
        str[i] = str[count - i - 1];
        str[count - i - 1] = temp;
    }
}
  

Ответ №2:

Поскольку вы используете C , если вы используете std::string вместо char * обратного значения по умолчанию для всей строки (или первых count символов, если они указаны), становится так просто, как:

 std::string reverse (const std::stringamp; s, size_t count = 0)
{
    if (count > s.length())
        count = 0;
    if (count)
        count = s.length() - count;
    return std::string (s.rbegin()   count, s.rend());
}
  

Коротким примером может быть:

 #include <iostream>
#include <string>

std::string reverse (const std::stringamp; s, size_t count = 0)
{
    if (count > s.length())
        count = 0;
    if (count)
        count = s.length() - count;
    return std::string (s.rbegin()   count, s.rend());
}

int main (void)
{
    std::string s("123456789");
    std::string r = reverse(s);
    std::cout << "sn" << s << "nnreverse(s)n" << r 
                << "nnreverse(s, 2)n";
    r = reverse(s, 2);
    std::cout << r << "nnreverse(s, s.length() - 1)n";
    r = reverse(s, s.length() - 1);
    std::cout << r << 'n';
}
  

(смотрите: std::basic_string::rend, std::basic_string::crend и std::basic_string::rbegin, std ::basic_string::crbegin)

Пример использования / вывода

 $ ./bin/strrev
s
123456789

reverse(s)
987654321

reverse(s, 2)
21

reverse(s, s.length() - 1)
87654321
  

Всегда печатайте символы полной длины

Если вы хотите поменять местами только count символы, но напечатать полную длину результирующей строки только с теми, которые перевернуты, вы можете сделать что-то похожее на:

 std::string reverse (const std::stringamp; s, size_t count = 0)
{
    if (count > s.length())
        count = 0;
    if (count) {
        count = s.length() - count;
        return std::string (s.rbegin()   count, s.rend())   suffix;
    }
    return std::string (s.rbegin()   count, s.rend());
}
  

Все символы

 $ ./bin/strrev
s
123456789

reverse(s)
987654321

reverse(s, 2)
213456789

reverse(s, s.length() - 1)
876543219
  

Библиотека контейнеров предоставляет ряд преимуществ по сравнению с использованием основных типов.

Ответ №3:

итак, это должно работать таким образом:

 #include <iostream>
#include <cstring>

using namespace std;

void reverse(char *str) {
    int count = (int)strlen(str);
    char temp;
    for (int i = 0; i < count / 2; i  ) {
        temp = str[i];
        str[i] = str[count - i-1];
        str[count - i-1] = temp;
    }
}

int main() {
    char buf[100];
    cout << "Enter your string:n" << endl;
    cin >> buf;
    char *str;
    str = new char(strlen(buf) 1);
    strcpy(str, buf);

    reverse(str);
    cout << "Reversed string:n" << str << endl;

    return 0;
}
  

Вам просто нужно передать функции строку, а не указатель на строку. Символ ** — это слишком много, вы можете изменить символы, потому что у вас уже есть указатель на символ *. Если вы не задаете длину строки функции, вы не сможете выполнять какие-либо исправления. Я вызываю функцию strlen в обратном порядке, это увеличивает временную сложность на один O (n), что не так уж проблематично, потому что ваша функция уже выполняется в O (n). Если вам интересно, почему я использовал str[count -i-1], то, поскольку CString завершаются 0, что означает, что строка «hallo» на самом деле является «»hallo 0» с литералом -1, убедитесь, что не меняете это ‘ 0’, которое необходимо для завершения CString.