C/C++

Переполнение стэка на языке Си

При вводе более 4-значного числа крашится :


#include <stdio.h>
#include <conio.h>
#include <locale.h>
#include <ctype.h>

unsigned int odd(unsigned int x);
unsigned int even(unsigned int x);


int main(void)
{
setlocale(LC_ALL, "Rus");
unsigned int n;
unsigned char c;
do {
printf("\n Введите положительное натуральное число: ");
if (scanf_s("%u%c", &n, &c, 1) != 2 || c != '\n' || n <= 0) {
printf("\n Неправильный ввод. Попробуйте ещё раз.\n");
while (getchar() != '\n') {} // очистить буфер ввода
}
else {
break;
}
} while (1);

unsigned int k = even(n);

unsigned char* answer;
if (k == 1)
{
answer = "чётное";
}
else
{
answer = "нечётное";
}
printf("\n Число %u — %s", n, answer);

printf_s("\n\n Нажмите любую клавишу для выхода из приложения");
_getch();
return 0;
}

unsigned int odd(unsigned int x) {
if (x == 0) {
return 0;
}
else {
return even(x - 1);
}
}

unsigned int even(unsigned int x) {
if (x == 0) {
return 1;
}
else {
return odd(x - 1);
}
}
"задача сделать с помощью косвенной рекурсии" - тогда запрети ввод более 3х знаков. Можешь, конечно, размер стека увеличить, но тогда будет падать при 5, 6 и т.д.
Либо измени сами функции:

 bool isOdd( unsigned int x ) 

{
if( x == 0 ) return true;
if( x == 1 ) return false;
return !isEven( x % 2 );
}

bool isEven( unsigned int x )
{
if( x == 0 ) return false;
if( x == 1 ) return true;
return !isOdd( x % 2 );
}
123 123
123 123
38 458
Лучший ответ
Мадамин Ташматов Мне ответили: "а я хочу большое число ввести"
рекурсивные функции очень сильно расходуют место на стеке. Перепишите odd, even без рекурсии.
Если проблема в стеке то путей решения возникшей проблемы тьма

  1. Можно увеличить шаг рекурсии например для n>10 первый шаг делать return(n-n/10*10);
  1. Можно рекурсивный алгоритм заменить на итеративный
 bool is_even = true;  
while(n--)
is_even =!is_even ;
if(is_even){...}
else {...}
  1. Можно вынести x в область глобальных переменных и не передавать ее значение функции, более того можно и не возвращать значение из функции а по завершении смотреть на значение глобальной переменной x, что может несколько увеличить количество доступных итераций рекурсии.

Ну и это все исключая очевидную проверку четности в лоб. n&1==1 или n%2==0

И еще, есть впечатление что проблема этого кода не только в рекурсии, но и в том что указатель на char -- answer указывает на константы в блоке, область видимости которого уже закончилась.
Мадамин Ташматов задача сделать с помощью косвенной рекурсии
Николай Чубуков Ну или чтобы убрать вызов себя непосредственно можно считать odd(x-(x/10)*10-1); при условии что x>=11;
Мадамин Ташматов Спасибо огромное за помощь
Он мне выдал еще одно задание в нем тоже получается нужно повысить шаг рекурсии:
Мадамин Ташматов #include <stdio.h>
#include <locale.h>
#include <conio.h>
#include <ctype.h>

unsigned int leibniz_formula(int n);
unsigned int leibniz_formula_rec(int n, unsigned int sum, unsigned int sign);


int main() {
setlocale(LC_ALL, "Rus");
char c;
int n;
do {
printf_s("\n Введите положительное натуральное число или 'Ctrl + Z' для завершения программы: ");
while (1) {
if (scanf_s("%d%c", &n, &c, 1) != 2 || c != '\n' || n < 0 ) {
printf_s("\n Неправильный ввод. Попробуйте ещё раз: ");
while (getchar() != '\n') {} // очистить буфер ввода
}
else {
break;
}
}
if (c == EOF) {
break;
}
Мадамин Ташматов printf_s("Сумма первых %d натуральных чисел по рекурсивной функцие: %d\n", n, leibniz_formula_rec(n, 0, 1));
printf_s("Сумма первых %d натуральных чисел по формуле Лейбница: %d\n", n, leibniz_formula(n));
} while (1);


return 0;
} // 0 1

unsigned int leibniz_formula_rec(int n, unsigned int sum , unsigned int sign ) {
if (n == 0) {
return sum;
}
/*else if (n >= 10) {
sum = (sign * (sign - 10)) / 2;
sum = (sum - (sum / 10)) * 10;
sign++;
sign = (sign - (sign / 10)) * 10;
n = n - (n / 10) * 10;
return leibniz_formula_rec(n, sum, sign);
}*/
sum = (sign * (sign - 1)) / 2;
sign++;
return leibniz_formula_rec(n - 1, sum, sign);

}