Переместить оригинальный указатель на следующий символ в созданной функции - PullRequest
1 голос
/ 26 марта 2019

У меня было задание, в котором мне приходилось удалять пробелы в начале слова с помощью указателей, изменять исходное слово и возвращать измененное слово. Единственное, что мне дают, это то, что имя / аргументы функции должны выглядеть так:

char* trim(char *str)

и что в основной функции должно быть что-то вроде этого: (комментарии показывают ожидаемый результат)

char str[] = "   Hello cpp", *newstr;
cout << "start" << str << "end" << endl;    // start   Hello cppend
newstr = trim(str);
cout << "start" << str << "end" << endl;    // startHello cppend
cout << "start" << newstr << "end" << endl;    // startHello cppend

Функция, которую я создал, выглядит следующим образом:

char* trim(char *str){
    while(*str<33){
        str++;
    }
    cout<<str<<endl;
    return str;
}

Идея заключалась в том, что когда значением текущего указателя является пробел (* str <33), я хочу переместить адрес указателя на следующий символ. Я использовал «while», поэтому он перемещается в следующее место, пока не укажет на значение, которое не является пробелом. </p>

Когда дело доходит до возвращения, все работает хорошо. «newstr» возвращается без пробелов, и вывод «startHello cppend», и когда я вывожу str в функции , он показывает текст без пробелов. Но первоначальная стоимость остается нетронутой. Выход в основном все еще start Hello cppend

Почему при перемещении указателя в функции с использованием str ++ исходный указатель не изменяется, а в основной функции он по-прежнему с пробелами, но str в функции отображается без пробелов?

Ответы [ 4 ]

2 голосов
/ 26 марта 2019

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

как psuedocode:

char * trim(char * str)
{
    var ptrFirstNonSpace=str, ptrCurr=str
    while ptrFirstNonSpace points to a space and not to end of string
        increment ptrFirstNonSpace
    while ptrFirstNonSpace does not point to end of string
        copy char from pFNS to ptrCurr
        increment both ptrCurr and pFNS
    set terminating char at ptrCurr
    return str
}
0 голосов
/ 26 марта 2019

В вашей функции вам нужно переместить строку вперед.Это делается путем нахождения первого индекса с непробельным символом, вычисления количества символов, которое необходимо переместить (включая терминатор строки \ 0), и вызова memmove () для смещения данных на месте.

Или ... вы можете просто

char* trim(char *str)
{
  while (*str == ' ' && *str != '\0')
  {
    for (unsigned i = 0; str[i] != '\0'; ++i)
    {
      str[i] = str[i+1];
    }
  }
  std::cout << str << std::endl;
  return str;
}

Это редактирует входную строку, изменяет оригинал и дает ожидаемый результат из комментариев в вашем фрагменте кода.

Согласнок проблеме, как указано,

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

вынеобходимо вернуть новую строку (это делает это для функции с потенциальной утечкой, хотя вам нужно иметь дело с возвращенной памятью после ее использования)

char* trim(char *str)
{
  char* rv = new char[std::strlen(str)+1];

  std::strcpy(rv, str);
  while (*rv == ' ' && *rv != '\0')
  {
    for (unsigned i = 0; rv[i] != '\0'; ++i)
    {
      rv[i] = rv[i+1];
    }
  }

  std::cout << rv << std::endl;
  return rv;
}
0 голосов
/ 26 марта 2019

"str" ​​в функции обрезки является локальной копией этой функции. Это отличается от "ул" в основном. Поэтому любые изменения, внесенные в str в отделке, не влияют на основную функцию.

Фактически char str[] = " Hello" это объявит str как массив символов. В этом случае мы не можем изменить массив str для исключения пробелов (str ++ или str = str + 1 и т. Д.,). Если вы объявите char *str = " Hello", это объявит указатель str для указания символа. В этом случае мы можем изменить str так, чтобы он указывал на первый символ в строке.

И еще одна вещь, изменив код на while (*str == 32), чтобы пропустить пробелы в функции обрезки.

0 голосов
/ 26 марта 2019

Я бы сказал, что текущее поведение является правильным. Таким образом, если вы не хотите менять исходный указатель, вы можете. Хороший пример для этого - когда он указывает на выделенную память и ему все еще нужно иметь исходное значение, чтобы освободить блок памяти.

И если вы хотите изменить его, вы можете просто использовать: str = trim(str);

При этом C ++ передает параметры по значению, поэтому вам нужно явно объявить ссылку, если вы хотите изменить переменную вызывающей стороны:

char* trim(char *&str)

Но я настоятельно советую вам не делать этого.

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