Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[C++] Zakończenie programu po wpisaniu 3 różnych kolejnych liczb

Ostatnio zmodyfikowano 2013-11-22 00:09
Autor Wiadomość
Atexor
Temat założony przez niniejszego użytkownika
[C++] Zakończenie programu po wpisaniu 3 różnych kolejnych liczb
» 2013-11-04 21:21:52
Witam,
to mój pierwszy post tutaj więc pokrótce się przywitam :)
Jestem Kamil, mam 19 lat i zacząłem programować w C od początku października wraz z zaczęciem studiów. Na forum trafiłem, gdyż mam problem z częścią jednego zadania ćwiczeniowego - kompletnie nie rozumiem jak je ugryźć. Liczę na Waszą pomoc :)


Program wczytujący z klawiatury liczby całkowite do momentu pojawienia się żądanej sekwencji trzech różnych od siebie liczb?


Myślałem o warunku, że x1 != x2 != x3 ale on chyba raczej jest błędny. Posiadam "gotowca" programu, niestety go także nie potrafię zrozumieć. Poza tym on chyba raz zczytuje 3 liczby "trójkami", czyli wprowadzając "1 2 1 2 3" przy ostatnich 3 liczbach nie przerywa lub pisząc "1 2 1 2 1 3 1" dopiero wtedy przerywa (pokazując 7 liczb mimo że 3 ostatnie nie były całkowicie od siebie różne - 2 razy było 1)...

Wygląda tak:
C/C++
#include <stdio.h>

int main()
{
    int i, x = 0, a, b, ilosc = 0, c;
    for( i = 0; i == i; i++ )
    {
        printf( "Podaj liczbe: " );
        scanf( "%d", & a );
        if( i == 0 )
        {
            b = a;
            c = b;
            x++;
        }
        else
        {
            if( a != b && a != c ) //if(a-b) bedzie 0 (te same liczby) to sie nie wykona, ale jesli rozne to jest ok
            {
                x++;
                c = b;
                b = a;
            }
            else
                 x = 1;
           
        }
        ilosc++;
       
        if( x == 3 )
             break;
       
    }
    printf( "Wczytano %d liczb.\n", ilosc );
    system( "pause" );
    return 0;
}


I tu mam dwa pytania:
1. W programie przy i==0 jest:
b=a;
c=b;
Czyli w takim przypadku pod b przypisujemy a oraz pod c dajemy b... czyli c=a? Po co to? Ogólnie po co rozdzielać na tyle przypadków program, gdzie i==0, różne od 0 itp.? Mógłby mi ktoś kolejno wyjaśnić co i dlaczego skąd się bierze i czy można jakoś prościej napisać taki program (używając podstawowych operatorów/instrukcji w C?
2. 1. W pętlach (np. for) czy jest różnica jeżeli wartość inicjująca pętlę to i=0 lub i==0 (same różnice z tym znam), bo dziwi mnie że większość programów z pętlami zawiera przypisanie nie równość. Mi w kilku przypadkach nie chciał tak program działać, mimo że wcześniej wartość wyrażenia nie została zadeklarowana.
3. Jak działa pętla do... while (a--), gdy a=5? Miałem to dzisiaj na wejściówce i wszyscy sądzili że zmierza do -inf. A tu się okazuje że do 0, ale jeszcze z uwagi na postdekrementację do -1.. Jak? A przy predekrementacji W TYM przypadku zachowa się identycznie?

Z góry dziękuję za pomoc i przepraszam za dość zawiły kłopot :)
P-95304
den93
» 2013-11-04 22:04:39
można jakoś prościej napisać taki program
Pewnie nie wiesz jeszcze co to tablice, ale obczaj to:
C/C++
int dane[ 3 ];
scanf( "%d%d%d", dane, dane + 1, dane + 2 );
for( unsigned i = 0; dane[ 0 ] == dane[ 1 ] || dane[ 0 ] == dane[ 2 ]
|| dane[ 1 ] == dane[ 2 ]; i++ )
     scanf( "%d", dane + i % 3 );
Wolałbym nie dawać gotowców, no ale 4 linijki...
P-95305
Buby
» 2013-11-04 22:23:59
Kolego den93, uważam, że twój sposób jest lepszy od mojego, ale kolega Kamil prosił o wytłumaczenie.
Dla niego wiele aspektów może być nowych, a ty dałeś mu sposób z tablicą, której definicji oraz zastosowania może nie znać.

Choć nie jestem specem od C [znacznie wolę C++], napisałem to o co prosiłeś.
Zamieszczam tutaj bardziej toporną wersję, z komentarzami.

KOD:

C/C++
#include <stdio.h>

int main() /* Funkcja glowna programu */
{
    int liczba1 = 0; /* Deklaracja zmiennych */
    int liczba2 = 0; /* -||- */
    int liczba3 = 0; /*  -||- */
    int iloscProb = 0; /* Deklaracja zmiennych */
   
    printf( "\tPodaj 3 rozne liczby. \n\n" ); /* Wiadomosc dla usera */
   
    while( liczba1 == liczba2 || liczba1 == liczba3 || liczba2 == liczba3 ) /* Warunek, ze petla bedzie sie wykonywac,dopoki liczby sa sobie rowne */
    {
        printf( "Podaj pierwsza liczbe: \n" ); /* Wiadomosc dla usera */
        scanf( "%i", & liczba1 ); /* Pobranie wprowadzonej liczby i zapis do zmiennej o adresie &liczba1 */
       
        printf( "Podaj druga liczbe: \n" ); /* Wiadomosc dla usera */
        scanf( "%i", & liczba2 ); /* Pobranie wprowadzonej liczby i zapis do zmiennej o adresie &liczba2 */
       
        printf( "Podaj trzecia liczbe: \n" ); /* Wiadomosc dla usera */
        scanf( "%i", & liczba3 ); /* Pobranie wprowadzonej liczby i zapis do zmiennej o adresie &liczba3 */
       
        iloscProb++; /* Postinkrementacja zmiennej ilosc prob - doslownie +1 */
    }
   
    printf( "\nWypisales 3 rozne liczby: %i %i %i \n", liczba1, liczba2, liczba3 ); /* Wiadomosc koncowa, wypisanie podanych liczb */
    printf( "Potrzebowales na to %i prob.", iloscProb ); /*  -||-, wypisanie ilosci prob */
   
    return 0; /* Wiadomocsc, ze program zakonczyl sie bez bledow */
}

Co do wskazówek w kodzie:
While
 to z angielskiego
dopóki
, warto znać to słowo, bo
pętla będzie się wykonywać
dopóki
 liczby będą równe.
P-95308
Atexor
Temat założony przez niniejszego użytkownika
» 2013-11-05 17:37:46
den93 - tak, jeszcze tablic nie miałem. Bodajże za 3 tygodnie będą  :)
Sprawdziłem jak on działa... i nie działał. Nie chciał kompilować mimo dodania biblioteki standardowej stdio.h(chyba taką nazwę nosi stdio.h czy math.h) itp. dopóki nie przestawiłem języka na C++. Tak z ciekawości - czy można do tych tablic dołożyć tekst typu "Wczytano liczbe"?


W c++ działa dokładnie tak jak chcę, tj. jeżeli podaję 1 2 1 2 1 2 1 2 i kiedyś się pojawił inna liczba to przerywa.

Buby - twój program rozumiem całkowicie. Nie rozumiem tylko jak mogłem sam na to nie wpaść :P, jednakże on uwzględnia liczby "trójkami", tzn. że nie zwróci uwagi na drugą liczbę, trzecią i pierwszą, ale z już następnej pętli.

Zasadę while poniekąd także znam, ale nie wiem dlaczego się w tamtym przykładzie 3. (na dole pierwszego postu) przy while (d--), gdzie zadeklarowano d=5 na końcu programu wychodziło d=-1...
Mógłbyś jeszcze wytłumaczyć pkt.2? Pierwszy już sobie daruję bo jak jeszcze teraz na niego patrzę to jest strasznie chaotyczny i "zbugowany".

Dzięki za szybkie odpowiedzi :)
Pozdrawiam
P-95359
den93
» 2013-11-05 18:34:00
2. To samo na 2 sposoby:
C/C++
for( i == 0; costam; costam );


C/C++
i == 0; // linijka nic nie robi
for(; costam; costam );

Warunki się wstawia po pierwszym średniku nie przed nim.

3. Dwie równoznaczne pętle:
C/C++
while( d-- ) // sprawdza czy różne od 0 i dekrementuje
{
    // dalsze instrukcje
}

while( d )
{
    d--;
    // dalsze instrukcje
}
d--;


dopóki nie przestawiłem języka na C++
Zamiast:
C/C++
for( unsigned i = 0;...;...)
     scanf(...);

może pomoże jeśli zrobisz to tak:
C/C++
unsigned i; // lub int, wedle uznania
for( i = 0;...;...)
     scanf(...);
P-95371
Buby
» 2013-11-05 18:36:28
Dobrze, spróbuje odpowiedzieć na twoje pytanie ;)

A). Przyjrzyjmy się teraz pętli
for
:


for( int iloscWykonan = 0; iloscWykonan < 5; ++iloscWykonan )


1.Czym właściwie jest iloscWykonan?
Odpowiedź - pierwszy argument pętli
for
 to deklaracja zmiennej - w tym przypadku,
typ int, czyli liczba całkowita o nazwie iloscWykonan.

2. Co oznacza
iloscWykonan < 5
?
Odpowiedź - drugim argumentem pętli
for
, jest warunek kończący pętlę.
W tym przypadku, pętla będzie się wykonywać dopóki warunek jest spełniony,
czyli iloscWykonan nie równa się 5.

3.
iloscWykonan++


Preinkrementacja zmiennej
iloscWykonan
 - dosłownie 
iloscWykonan = iloscWykonan + 1
.


B). Różne formy zapisu.

1.W języku C spotkamy się z takim zapisem.

C/C++
int iloscWykonan = 0;
for(; iloscWykonan < 5; ++iloscWykonan );

Wykonuje on te same czynności co kod z punktu B.
Różnica polega na tym, że definiujemy zmienną poza pętlą
for
.

I wtedy zmienna jest widoczna poza nią, w przeciwieństwie do przykładu, który opisałem w punkcie C.1 .


C). Ciekawostki:

1. Zmienna utworzona w pętli
for
 jest nie widoczna poza pętlą. Oznacza to, że
możemy utworzyć dowolną liczbę
równorzędnych
 pętli, ze zmienną o tej samej nazwie
i nie wpłynie to źle na działanie naszego programu. Przykład:

C/C++
for( int i = 0; i < 5; ++i )
     std::cout << "Ta pętla się wypisze.\n";

for( int i = 0; i < 5; ++i ) // Poprzednie "i" nie ma wplywu na ta petle.
     std::cout << "Ta też.\n";

for( int i; i < 5; ++i ) // Program kompiluje się, ale nie zna wartości i, więc nie wypisze nic.
     std::cout << "Ta nie.\n";

for( int i; i < 10; ++i ) /* A tutaj, aby pokazać, że zmienna i nie jest widoczna - zmieniony
                               Warunek a program nie wykona nic, gdybysmy zdefiniowali zmienna i
                               poza petla to zmienialaby sie za kazdym razem, gdy wywolamy ++i. */
     std::cout << "Ta też nie.";[ code ]


2.Jeszcze jedna ciekawostka z książki o C, dostępnej dla każdego na wikibooks.
Świetny materiał, dla początkujących i zaawansowanych:
W kodzie źródłowym spotyka się często inkrementację i++ . Jest to zły zwyczaj, biorący
się z wzorowania się na nazwie języka C++. Post-inkrementacja i++ powoduje, że tworzony
jest obiekt tymczasowy, który jest zwracany jako wynik operacji (choć wynik ten nie jest
nigdzie czytany). Jedno kopiowanie liczby do zmiennej tymczasowej nie jest drogie, ale w
pętli “for” takie kopiowanie odbywa się po każdym przebiegu pętli. Dodatkowo, w C++ po-
dobną konstrukcję stosuje się do obiektów — kopiowanie obiektu może być już czasochłonną
czynnością. Dlatego w pętli “for” należy stosować wyłącznie ++i


D). Twoje pytanie.
Gdybyśmy w pętli napisali:
[code src="C++"] int i;
for( i == 1; i < 5; i++);[/code]
To nie wykonałaby się ona, z racji tego, że porównujemy, czy i jest równe 1.
Wartość zwróci prawdę, czyli 1 jeśli to prawda - analogicznie 0 jeśli fałsz.


E). Komentarz ;)

Moim zdaniem, jeśli chciałbyś się podszkolić, to popracuje trochę z kursem C++ na tej stronie.
Pozdrawiam!
P-95372
pekfos
» 2013-11-05 18:44:59
Jedno kopiowanie liczby do zmiennej tymczasowej nie jest drogie, ale w pętli “for” takie kopiowanie odbywa się po każdym przebiegu pętli.
Tam nie musi być żadnego kopiowania i, w większości przypadków, go tam nie ma. Dla typów wbudowanych, w pętli for (i nie tylko) obie instrukcje są równie efektywne.
P-95375
Buby
» 2013-11-05 18:47:57
@UP:

Tak wyczytałem w książce i ja stosuje się do tego :)
Napisałem, że to tylko ciekawostka :P
P-95376
« 1 » 2 3
  Strona 1 z 3 Następna strona