[C++][Podstawy] Program liczący silnię

Witam,

Dopiero uczę się C++ i mam kilka pytań.

Napisałem program liczący silnię i wcześniej sprawdzający czy podano poprawną liczbę (całkowitą i nieujemną).

Kod programu:

http://wklej.org/id/72842/

Kompilator wyświetla ostrzeżenie dla wiersza [13]:

Wiem co to znaczy i skąd się wzięło, ale tylko taki miałem pomysł żeby sprawdzić czy liczba jest całkowita.

Pytanie 1.

Czy można w jakiś inny sposób sprawdzić czy podana liczba jest całkowita? Tak żeby nie pojawiało się ostrzeżenie.

Lub czy można wyłączyć to konkretne ostrzeżenie.

Pytanie 2.

Program fajnie liczy dla liczb od 0 do 12, ale już większe wyświetla błędnie. wiem że to się wiąże z wartością maksymalną dla funkcji int, ale czy można coś zrobić żeby liczyło więcej?

P.S. Kompilator Dev-C++

Nic dziwnego że kompilator wyświetla ostrzeżenie skoro dla:

float a;

int b;

wykonujesz a=b;

A tak nawiasem mówiąc to poczytaj trochę o niesławnej instrukcji goto.

Spróbuj napisać : b=static_cast(a);

Aby powiększyć zakres ustaw typ zmiennej ‘c’ na unsigned long.

A tak swoją drogą słowo silnia aż każe użyć rekurencji. :slight_smile:

Np.

int silnia(int n)

{

    if (n==0) return 1;

    else return n*silnia(n-1);

}

masosz"b=static_cast(a);" zadziałało, ale

“unsigned long int c=1;” nie zadziałało

Odnośnie goto ostatnio gdzieś przeczytałem że nie jest dobrze widziany. Jednak uczę się c++ od 3 dni więc nie wymagaj ode mnie za dużo :slight_smile:

Ad. 1 Rzutuj jawnie, operatorem rzutowania.

Ad. 2 Zmień typ na pojemniejszy, obecnie najpojemniejszy w C++ to unsigned long (w C++0x będzie unsigned long long).

Poza tym raczej nie używa się goto w kodzie wysokopoziomowym. Za Wikipedią:

To, że liczenie silni jest świetnym akademickim przykładem tłumaczenie rekurencji, nie oznacza, że należy tak robić. Nie sądzę, aby miało to jakikolwiek większy sens. Co prawda przepełnienie stosu w tym przypadku raczej nie grozi, ale lepiej nabierać dobrych nawyków.

Użyłeś kiedyś goto? ;>

Jedyny sensowny przypadek używania goto jest w C# w celu przechodzenia między case’ami w switch’u. Poza tym, to praktycznie zawsze da się obejść w bezpieczniejszy i czytelniejszy sposób. Moim zdaniem powinni pominąć goto we wszelkich kursach i podręcznikach podstaw programowania.

Może mi ktoś wyjaśnić po co tu ten float i to całe rzutowanie, skoro operujemy wyłącznie na liczbach całkowitych?

I nie ma sensu używać conio.h tylko dla tego jednego getch(), które można zastąpić czymkolwiek innym.

dzięki za rady :slight_smile:

postaram się poczytać trochę więcej i omijać goto.

Pozdrawiam,

Ciekawe czemu nikt nie wspomniał o if(a=0) warunek który będzie zawsze nie prawdą a na dodatek zmieni wartość zmiennej a na zero.

Za pomocą konstrukcji while/break/continue można całkiem zastąpić goto , użycie w C/C++ tego operatora jest oznaką barbarzyństwa :lol:

somekind mądrze powiedział lepiej nabierać dobrych nawyków, ja z nim w kilku kwestiach się nie zgadzam w kwestii co jest dobrym nawykiem a co złym ale akurat w tym przypadku zgadzamy się jak widać :smiley:

Przykład kontroli kodu bez goto , nawet na literach się nie wywali

#include using namespace std;

Pytanie: jak ładnie wyjść z zagnieżdżonych pętli? :wink:

Ale macie racje, goto nie jest ładne i do tego bezpieczne, a jak się źle użyje to i mało wydajne.

Odpowiedzi:

  1. [*:20540py2]za pomocą return;[*:20540py2]za pomocą throw;

:wink:

@up: return rzadko kiedy jest dobrym wyjściem, bo np. musisz wykonać coś jeszcze poza pętlą. throw nie do tego służy. Do tego dochodzą inne problemy(więcej kodu, mniej przejrzystości, kolejne zakresy, etc.). Akurat w C++ wyjście z zagnieżdżonych pętli najlepiej wykonywać przez goto.

Przestałem analizować kod autora, gdy zobaczyłem pierwsze goto.

Nie chcę się czepiać, ale Twój kod jakoś tak nie bardzo działa pod VC++ przy podaniu liczby ujemnej. Wpada w nieskończoną pętlę i zużywa procesor.

Fiołek - nie załamuj mnie :stuck_out_tongue_winking_eye:

Można użyć flag i break’ów, można zagnieżdżoną pętlę wrzucić do funkcji i w razie czego wyskoczyć returnem. Tak czy siak każde rozwiązanie inne niż goto będzie ładniejsze.

Tez miałem taką chęć, ale jakoś się przemogłem :slight_smile:

Nie każdej tylko -1 nie chciało mi się stawić w warunku: i<=N&&i - aby potem nie pisać posta wyjaśniającego jak ta i może okazać się zerem. :lol:

Fiołek - widzisz tez wśród propozycji return, byle nie goto.

A tu mnie zaskoczyłeś a dla czego wg ciebie służy throw, to właśnie jest takie super goto dla wychodzenia nie tylko z zagnieżdżonych pętli ale tez zagnieżdżonych funkcji.

Niedokładnie wczoraj sprawdziłem - nie zawiesza się totalnie, tylko pracuje dłuższą chwilę, aż zwróci wynik.

Sam zobacz:

silniavc.th.png

Całą nagonka na goto ma zaszłości historyczne - pochodzi z czasów przesiadki Basica na nowsze. Miało być pewną wskazówką dla osób które nie lubiły zmian i praktykowały " W każdym języku można programować w Basicu*". Goto jest często używany w kernelu linuksowym do skakania do sekcji funkcji, która zwalnia pamięć i tym podobne, zamiast bezpośredniego użycia returna. Pewnie jakby poszukać można by znaleźć jeszcze parę takich konstrukcji. Wydaje mi się, że throw zamiast goto to odrobinkę hipokryzja ale co komu pasuje :slight_smile:

* Zamiast Basic można wstawić dowolnym innym językiem, a fragmenty dzieł ludzi, którzy nie zważają na to co oferuje/ułatwia język, którego “używają”, można znaleźć na thedailywtf.com

Tak, piętnaście zagnieżdżonych pętli i piętnaście flag, podziękuje :wink:

Dodatkowa funkcja to też kłopot, jeśli zagnieżdżenie jest kilkupoziomowe to rozrasta się na kilka funkcji, a tak to mamy wszystko w jednym miejscu(nie jestem fanem rozdrabniania kodu na setki funkcji, która każda robi tylko kilka czynności i jest używana w jednym miejscu).

Throw służy do rzucania wyjątków których używa się w sytuacjach wyjątkowych a wyjście z zagnieżdżonych pętli takie być nie musi.

Nie jestem wielkim fanem goto ale do zagnieżdżonych pętli jest ono najlepsze(najbardziej przejrzyste).