• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Obliczanie silni- rekurencja

Object Storage Arubacloud
0 głosów
382 wizyt
pytanie zadane 19 grudnia 2022 w C i C++ przez Zuzan Początkujący (390 p.)
zmienione kategorie 19 grudnia 2022 przez adrian17

Hej, jestem początkującą w programowaniu. Mam do wykonania następujące zadanie: 

Napisz program, który dla n z zakresu <0, 20> podanego przez użytkownika wyznaczy i wyświetli wartość silnii n!.

  • W przypadku podania niewłaściwej wartości n przez użytkownika, program powinien wyświetlić komunikat Incorrect input data i zwrócić kod błędu 2.
  • W przypadku wprowadzenia błędnych danych powinien wyświetlić komunikat Incorrect input i zakończyć działanie z kodem błędu 1.

W tym celu napisz funkcję do obliczania wartość wyrażenia n! metodą rekurencyjną. Funkcja powinna mieć następujący prototyp:

unsigned long factorial_rec(int n);

Przykład interakcji z programem:

Podaj n: 5⏎
Wynik: 120⏎

Uwagi

  • W programie nie wolno używać zmiennych globalnych.
  • W programie nie wolno używać słowa kluczowego static.
  • W programie nie wolno używać pętli.

Program napisany przeze mnie wygląda następująco: 

#include <stdio.h>
unsigned long factorial_rec(int n)
{
    if (n==0) { return 1; }
    else { return (unsigned long) n * factorial_rec(n - 1); }
}

int main(void) {
    int n;
    printf("Podaj n: ");
    int t=scanf("%d", &n);
    if (t!=1)
    {
        printf("incorrect input");
        return 1;
    }
    else if(n<0||n>20)
    {
        printf("Incorrect input data");
        return 2;
    }
    printf("%lu", factorial_rec(n));

    return 0;
}

Wydaje się, że program działa prawidłowo natomiast podczas testów przez dante wyskakuje taki komunikat: ,,Test został przerwany; Program PRZERWANY; miał zwrócić wartość 0 a zakończył się sygnałem SIGSEGV". Nie wiem co mogłabym tu zmienić, aby dante przyjął mój program. Będę wdzięczna za pomoc :).

komentarz 19 grudnia 2022 przez Dawid Kuraś Nowicjusz (150 p.)
edycja 19 grudnia 2022 przez Dawid Kuraś
Przyjrzyj się if’om
komentarz 19 grudnia 2022 przez TOWaD Mądrala (6,000 p.)
edycja 19 grudnia 2022 przez TOWaD

A właściwe to else. Brakuje jednego.[online]

edit::

Może tak, choć to nie zgodne z teścia zadania.

Podaj n: 20
20!=2 432 902 008 176 640 000

unsigned long     4     unsigned long int     Od 0 do 4294 967 295

 

2 odpowiedzi

+1 głos
odpowiedź 19 grudnia 2022 przez Oscar Nałogowiec (29,320 p.)
edycja 19 grudnia 2022 przez Oscar

Wszystko wygląda OK poza jednym szczegółem - nie wypisujesz słówka "Wynik" i znaku nowej linii - te automatyczne testery mogą być dość skrupulatne, przekierowują wyjście do pliku i tam sprawdzają być może nawet znak po znaku. Oczywiście zakładam, że kompilujesz 64 bitowo. Na wszelki wypadek użyłbym typu uint64_t, jednak skoro nagłówek funkcji (a zatem typu zmiennych) masz narzucone w treści zadania to pozostaje zabawa opcjami kompilacji. U mnie usigned long jest 64-bitowy  (printf("%lu \n", sizeof(unsigned long)); - daje 8), więc powinno wystarczyć, ale standard języka C nie narzuca konkretnych wymagań na poszczególne typy.

 

Natomiast SIGSEGV praktycznie może mieć dwie przyczyny (na tym poziomie kodu) - wyjście poza tablicę lub zamazanie stosu, jednak tablic ani wskaźników nie używasz, podejrzana pozostaje rekurencja - na 20-krotne zagłębienie to każdy stos powinien wystarczyć ale jeśli coś jest źle to tam.

Jeśli nastąpi wywołanie funkcji z ujemnym parametrem to rekurencja nigdy się nie skończy (no, po przewinięciu się n, ale to za dużo razy).  Dodałbym w linijce z if else nawiasy by wymusić taką kolejność działań jak wszyscy myślą, że być powinna. Zawsze dodaje nawiasy w złożonych wyrażeniach (a dokładnie to nigdy nie chce mi się pamiętąć tych wszystkich priorytetów i wiązań operatorów).

komentarz 19 grudnia 2022 przez mokrowski Mędrzec (155,460 p.)

ale standard języka C nie narzuca konkretnych wymagań na poszczególne typy.

Oczywiście że narzuca: https://en.wikipedia.org/wiki/C_data_types

Zawsze dodaje nawiasy w złożonych wyrażeniach (a dokładnie to nigdy nie chce mi się pamiętąć tych wszystkich priorytetów i wiązań operatorów).

I bardzo dobrze robisz. Są standardy bezpiecznego kodowania tak dla C i C++ i twierdzą że należy otaczać wyrażenia nawiasami. 

 

komentarz 20 grudnia 2022 przez Zuzan Początkujący (390 p.)
Tak, rzeczywiście musiałam dodać w funkcji warunek if dotyczący ujemnego parametru i program przeszedł. Dziękuję bardzo.
0 głosów
odpowiedź 19 grudnia 2022 przez Kuba_w Nowicjusz (140 p.)
Brakuje ci else Zamiast : printf("%lu", factorial_rec(n)); Powinno być: else printf("%lu", factorial_rec(n));

Podobne pytania

0 głosów
0 odpowiedzi 352 wizyt
0 głosów
1 odpowiedź 2,439 wizyt
pytanie zadane 18 marca 2019 w Java przez Paweł123 Nałogowiec (33,500 p.)
0 głosów
2 odpowiedzi 419 wizyt
pytanie zadane 20 stycznia 2020 w SPOJ przez enpikku Nowicjusz (120 p.)

92,576 zapytań

141,426 odpowiedzi

319,652 komentarzy

61,961 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...