Member 14076805 Ответов: 3

Реверс строки рекурсивный и с использованием циклов


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

Второй способ должен быть рекурсивным .
моя функция putBack использует malloc для динамического выделения памяти для результата .
где я могу освободить память?Я думаю, что именно тогда, когда данные из Указателя, возвращенного putBack (), уже были скопированы в новый буфер на один символ больше.Но я не знаю, как это сделать.

Что я уже пробовал:

#include <stdio.h>
#include <stdlib.h>

//1
  char *reverse(char *s){
		int lengths = length(s);
	char *reverse = (char *) malloc(sizeof(char) * lengths);
	if(lengths>0){
		int k = lengths-1;
		for(int i=0; i<lengths; i++, k--){
			reverse[i] = s[k];
		}
	}else{
		reverse = "";
	}
	return reverse;;
}

int length(char *s) {
  int n = 0;
  while(*s != '\0') {
    n++;
    s++;
  }

  return n;
}


void copy(char* s, int n, char* t) {
  int i = 0;
  while(i < n) {
    t[i] = s[i];
    i++;
  }
}


char* putBack(char* s, char c) {
  const int n =  length(s);
 
 char* r = malloc(sizeof(char) * (n+2));
  copy(s, n, r);
  r[n] = c;
  r[n+1] = '\0';
 return r;
}


char* reverseRec(char *input){
     static int i =0; 
     static char ReverseStr[10];

     char* R[length(input)];

     if(*input){
        reverseRec(input+1);
        ReverseStr[i++]= *input;

        *R =putBack(ReverseStr,*input); //hängt ein Zeichen hinten  String an

     }
     printf("%c", *input);

     return *R;
   }

3 Ответов

Рейтинг:
5

Patrice T

Цитата:
Я попытался написать программу на языке Си, которая перевернет строку в двух направлениях .
Второй способ должен быть рекурсивным .

Сама идея использования рекурсии для реверса строки плоха. Это делает вещи медленными, сложными, и это будет злоупотреблять вызовом стека просто для удовольствия.
Чтобы использовать рекурсию, лучше иметь вескую причину:
- Данные рекурсивны по своей природе: двоичное дерево, синтаксический анализ языка.
- Использование рекурсивного определения легкости написания кода: функция GCD, набор Фибоначчи.

В противном случае вы вольны делать все так сложно, как вам хочется, но не ждите, что мы последуем за вами по этому пути.


CPallini

Третья веская причина может быть домашнее задание. У меня 5.

Patrice T

Лучший из них :)
Спасибо

Рейтинг:
22

OriginalGriff

Зачем вообще пытаться реверсировать строку рекурсивно? Это очень неэффективный способ сделать это...
Но... все очень просто.
Это очень сильно пахнет "домашним заданием", поэтому я не собираюсь давать вам никакого "настоящего" кода.
напишите функцию, которая принимает два параметра, оба указателя на символ:

void Reverse(char* in, char* out)

Внутри функции сравните вход и выход:
in < out      swap characters between in and out, call Reverse with in + 1 and out - 1.
in == out     )
               --- do nothing.
in > out      )
Понимаете, что я имею в виду? Простой. Но очень, очень неэффективно - цикл гораздо проще и легче работать.


Member 14076805

Я думал, что это проще, когда я использую free или delete, чтобы освободить память

OriginalGriff

Почему? Во-первых, как это проще? А во-вторых, сколько памяти вы собираетесь создать, чтобы перевернуть строку размером 1 МБ?

В-третьих, когда вы собираетесь освободить память? Вы не можете освободить его в конце функции, потому что это рекурсивно и потребуется, чтобы они вернулись на "более низкие уровни".

Рейтинг:
16

John R. Shaw

Считайте это обзором кода.
Сначала сделайте нам одолжение; перед публикацией, пожалуйста, убедитесь, что код может компилироваться. Если только речь не идет о невозможности компиляции.

обратный() функция:
1. Изменение char *reverse(char *s) к char *reverse(const char *s).
2. The длина() функция не определена (вызовет ошибку компиляции). Либо объявите прототип, либо переместите определение над прототипом. обратный() функция.
3. The длина() эквивалентна стандартной C-функции функция strlen(). Эта функция не включает в себя '\0' в результате. Поэтому размер буфера, который вы выделяете, должен быть длина + 1 символы в размере - не длины.
4. Проверьте отсек возврата указателя функция malloc(). Если функция malloc() если произойдет сбой, то программа взорвется, если длины > 0.
5. Выйти из привычку писать с шагом как у меня++, ++используют вместо меня. Да, я знаю, что сейчас все так делают, но есть законные причины для того, чтобы это была плохая привычка.
6. Либо возвращать указатель на выделенную память или null. Не назначайте обратный указатель на статическую строку at (reverse = "") или ваша программа просто взорвется в какой-то момент.

копировать функция:
1. технически было бы безопаснее, если бы вы предоставили длины обоих строковых буферов, которые передаются в копировать() или снова у вас могут возникнуть проблемы.

добивания функция:
1. при этом выделяется произвольный буфер, который может никогда не освободиться. Я рекомендую вам переосмыслить это, или вы будете утекать память повсюду.

реверсерек функция:
Эта функция показывает, что вы не понимаете, как работает рекурсия. Боюсь, у меня нет времени рассказывать вам все, что не так с этой функцией.
1. статических переменных можно избежать. Плюс у вас будет переполнение буфера Реверсестр в определенный момент.
2. R[длина(вход)] является недопустимым синтаксисом и не будет компилироваться.
3. *R = putBack(ReverseStr, *input); будет постоянно протекать память (см. добивания)
4. Если требуются статические значения, то в какой-то момент они должны быть возвращены к своим исходным значениям. я он просто будет увеличиваться при каждом вызове, пока программа не взорвется из-за переполнения буфера.

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