Подсчитайте конкретные цифры и замените четные цифры на 0, используя рекурсию - PullRequest
0 голосов
/ 16 ноября 2018

Я новичок в C ++, это мое первое трудное задание, и у меня возникают проблемы с пониманием рекурсии.Мне нужно запрограммировать рекурсивную функцию, чтобы подсчитать, сколько раз пользователь вводит 5 и 8. А также заменить четные цифры на 0. Пример:

Ввод пользователя: 4585

Количество 5 &8: 3

Заменить даже на 0: 0505

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

#include <iostream> 
using namespace std; 

int countThreeFives(int num) {
    static int count=0;

    int digit = num % 10; 
    if (n == 5 || n == 8)
    {
        count++;
        countThreeFives(num/10);
    }
    else
    {
        return count;
    }
}

int replaceEven(int num){ 
    int digit = num % 10;
    if (digit % 2 != 0) {
    // Confused here (incomplete)
    } 
int main() { 
    int x; 
    cout << "Enter a positive number: "; 
    cin >> x;

    cout << "The count of 8 & 5 is: " << countThreeFives(x); 
    cout << "Replacing even with 0: " << replaceEven(x);
}

Ответы [ 5 ]

0 голосов
/ 17 ноября 2018

Другие люди ответили на ваш вопрос с решениями, которые используют подписи, отличные от вашего кода:

int countThreeFives(int num);
int replaceEven(int num);

и / или просто отбросили требование рекурсии. Кроме того, вы указали int, но попросили пользователя ввести положительное число - если ваш код действительно работает только с положительными числами, вам следует рассмотреть unsigned int вместо int. Или просто иметь дело с отрицательными числами. Обращаясь ко всему этому и сохраняя дух вашего оригинального кода:

#include <iostream> 
using namespace std;

int countThreeFives(int number) {

    if (number != 0) {

        int count = 0, digit = abs(number % 10);

        if (digit == 5 || digit == 8) {
            count++;
        }

        return count + countThreeFives(number / 10);
    }

    return 0;
}

int replaceEven(int number) {

    if (number != 0) {
        int digit = (number % 10) * (number % 2);

        return ((number > 0) ? 1 : -1) * (replaceEven(abs(number) / 10) * 10 + digit);
        }

    return number;
}

int main() { 
    int number;

    cout << "Enter a number: "; 
    cin >> number;

    cout << "The count of 8 & 5 is: " << countThreeFives(number) << endl;
    cout << "Replacing even with 0: " << replaceEven(number) << endl;
}

Пример использования, показывающий поддержку отрицательного числа:

> ./a.out
Enter a number: -382135
The count of 8 & 5 is: 2
Replacing even with 0: -300135
>

Однако есть пара других проблем, когда ваша функция принимает аргументы int и возвращает int. Например, ваш пример:

User enter: 4585
Count of 5 & 8: 3
Replace even with 0: 0505

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

> ./a.out
Enter a number: 4585
The count of 8 & 5 is: 3
Replacing even with 0: 505
Mac-mini>

т.е. нет ведущих нулей. Вы получаете только ведущий ноль с нечисловым подходом. Другая проблема с использованием целых чисел заключается в том, что длина ввода числа ограничена. Обычно максимальная длина ввода будет:

> ./a.out
Enter a number: 356756453
The count of 8 & 5 is: 3
Replacing even with 0: 350750053
>

Больше, и вам нужно будет использовать больший целочисленный тип (например, unsigned long long) или снова использовать нечисловой подход.

0 голосов
/ 17 ноября 2018

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

Ключ к рекурсии состоит из 3 частей:

  1. Определить базовый регистр, который не обрабатывает никаких совпадающих символов
  2. Определить рекурсивный регистр, который обрабатывает первое вхождение совпадающего символа
  3. Определить рекурсивный регистр, который продолжает поискостаток строки после выполнения части 2.

Работает для ввода любой длины.

#include <iostream>
#include <string>

int numChars(char, std::string, int);

std::string replaceEvenWithZero(std::string);

int main()
{
    std::string str;

    std::cout << "User Enter: ";
    std::cin >> str;

    // Display the number of times the '5' or '8' appear in the string.
    std::cout << "Count of 5 & 8: " << numChars('5', str, 0) + numChars('8', str, 0) << " times.\n";

    std::cout << "Replace even with 0: " << replaceEvenWithZero(str) << std::endl;

    return 0;
}

int numChars(char search, std::string str, int subscript)
{
    if (subscript >= str.length())
    {
        // Base case: end of the string was reached.
        return 0;
    }
    else if (str[subscript] == search)
    {
        // Recursive case: A matching character was found. Return
        // 1 plus the number of times the search character appears
        // in the string.

        return 1 + numChars(search, str, subscript + 1);
    }
    else
    {
        // Recursive case: A character that does not match the search
        // character was found. Return the number of times the search
        // character appears in the rest of the string.

        return numChars(search, str, subscript + 1);
    }
}

std::string replaceEvenWithZero(std::string str) 
{
    // check the index (position) of each character in the string
    for (int i=0; i < str.length(); i++){
        // if the index even number position
        // (divides by 2 with no remainder, then true)
        // replace character with `0` at this index
        if (i % 2 != 0){
           str = str.substr(0,i-1) + "0" + str.substr(i, str.length());
        }
    }
    return str; // return our newly created string with `0`s
} 

Демонстрация:

User Enter: 4585
Count of 5 & 8: 3 times.
Replace even with 0: 0505

User Enter: 6856756453
Count of 5 & 8: 4 times.
Replace even with 0: 0806050403
0 голосов
/ 16 ноября 2018

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

#include <iostream>
#include <string>

int main()
{
    std::string input;

    std::cout << "User Enter: ";
    std::cin >> input;

    int num8 = 0;
    int num5 = 0;

    for (std::string::size_type i = 0; i < input.size(); ++i) 
    {
        if (input[i] == '8') 
        {
            num8++;
        }

        if (input[i] == '5') 
        {
            num5++;
        }

        if (input[i] == '2' || input[i] == '4' || input[i] == '6' || input[i] == '8')
        {
            input[i] = '0';
        }
    }

    std::cout << "Count of 5 & 8: " << num5 + num8 << std::endl;
    std::cout << "Replace Even  : " << input << std::endl;
}

Что это делает и получает ввод от пользователя, затем перебирает каждый символ в строке. Если дело доходит до 8 или 5, это увеличивает счетчик. В то же время он проверяет символ на наличие четного числа (2, 4, 6 или 8) и, если так, заменяет его на 0. Наконец, он печатает вывод.

0 голосов
/ 16 ноября 2018

Я предполагаю, что это школьное задание, поэтому здесь необходимо использовать рекурсию.В любом случае, вот рекурсивное решение:

Обозначим через f (d, n) число 5 и 8 в первых n цифрах строки цифр d.Тогда мы можем сформировать следующее рекурсивное отношение:

f (d, n) = 1 + f (d, n - 1), если n-ая цифра равна 5 или 8

f (d, n) = f (d, n - 1), если n-ая цифра не является ни 5, ни 8

, а наш базовый случай равен f (d, 0) = 0, поскольку строка размера 0 будетне имеют ни 5, ни 8с

#include <iostream>
#include <string>

int countAndReplace(std::string& digits, int n)
{
    if(n == 0)
    {
        return 0;
    }
    bool addOne = (digits[n - 1] == '5' || digits[n - 1] == '8');
    if(digits[n - 1] % 2 == 0)
    {
        digits[n - 1] = '0';
    }
    return addOne + countAndReplace(digits, n - 1);
}

int main()
{

    std::string digits;

    std::cin >> digits;

    std::cout << countAndReplace(digits, digits.size()) << '\n';

    std::cout << digits << '\n';

    return 0;
}

Сначала нам нужно прочитать цифры из стандартного ввода, для которого лучше всего использовать std :: string, так как мы не знаем количество цифр заранее.Затем мы вызываем нашу рекурсивную функцию, которая принимает два аргумента - ссылку на строку цифр (используется для изменения цифр на месте, для второй части задачи) и длину указанной строки.В функции для каждой цифры мы также проверяем, нужно ли ее заменять в соответствии с опубликованными вами правилами, и если она это делает, мы делаем замену на месте, поэтому в качестве аргумента используется ссылка на строку.

Это очень простая проблема.Пожалуйста, в следующий раз, попробуйте решить свои задачи самостоятельно, прежде чем обращаться за помощью.В противном случае у вас будут проблемы с прогрессом.

0 голосов
/ 16 ноября 2018

Вы можете просто использовать std :: unordered_map , чтобы отслеживать количество уникальных целых чисел.Вот пример реализации:

#include <iostream>
#include <unordered_map>

int main() {
  std::unordered_map<int, int> numbs;
  int numb;
  while (std::cin >> numb) {
    if (numb % 2 == 0) {
      ++numbs[0];
    }
    else {
      ++numbs[numb];
    }
  }
  for (const auto p : numbs) {
    std::cout << p.first << " was seen " << p.second  << " time(s) " << std::endl;
  }
  return 0;
}

Ввод:

1 2 3 4 6 5 7 4 2 5 7 5

Выход:

5 was seen 3 time(s)
3 was seen 1 time(s)
1 was seen 1 time(s)
7 was seen 2 time(s)
0 was seen 5 time(s)

Обратите внимание на часть ++numbs[0].Как видите, в этом примере мы не проверяем, существует ли ключ в numbs, мы просто увеличиваем его на единицу.Это потому, что когда мы используем [numb], объект с этим ключом создается, если он еще не существует, и мы можем просто увеличить его на единицу, поскольку int по умолчанию инициализируется как 0.

...