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

[Lekcja 21] Zadanie domowe - wyloswanie iczb podanych z klawiatury bez powtórzeń

Ostatnio zmodyfikowano 2015-01-29 19:14
Autor Wiadomość
bladegd
Temat założony przez niniejszego użytkownika
[Lekcja 21] Zadanie domowe - wyloswanie iczb podanych z klawiatury bez powtórzeń
» 2014-12-04 15:58:50
Treść:
1. Napisz program, który wczyta 3 liczby podane przez użytkownika do tablicy, a następnie wylosuje 2 z nich bez powtórzeń. Wynik wypisz na ekran. Postaraj się napisać ten program w oparciu o funkcje.

Od wczoraj głowie się co mam źle zrobione i nie mogę do tego dojść, proszę o rady.

Przykładowe wyjście:
Podaj 3 liczby:

2
4
5

Wylosowane liczby:
4197776 ,4197776 ,
Process returned 0 (0x0)   execution time : 10.691 s
Press ENTER to continue.

C/C++
#include<iostream>
#include<ctime>
#include<cstdlib>

using namespace std;

void wczytywanieLiczb( int t[], int index )
{
    int a, i = 0;
    cout << "Podaj " << index << " liczby:" << endl;
    do {
        cin.clear();
        cin.ignore( 1000, '\n' );
        cin >> a;
        t[ i ] = a;
        i++;
    } while( cin.fail() || i < index );
   
}
bool losDoTabl( int los, int wysw[], int ileWyl )
{
    int i = 0;
    do {
        los;
        if( wysw[ i ] != los )
             wysw[ i ] = los;
       
        i++;
    } while( i < ileWyl );
   
}
void wypisanie( int wysw[], int ileWyl )
{
    int i = 0;
    cout << "Wylosowane liczby:" << endl;
    do {
        cout << wysw[ i ] << " ,";
        i++;
    } while( i < ileWyl );
   
}
int main()
{
    srand( time( NULL ) );
    int zapis[ 3 ];
    int index = 3;
   
    int wysw[ 2 ];
    int ileWyl = 2;
    int los = zapis[ rand() % index ];
   
    wczytywanieLiczb( zapis, index );
    losDoTabl( los, wysw, ileWyl );
    cout << endl;
    wypisanie( wysw, ileWyl );
    return 0;
}
P-122184
Rashmistrz
» 2014-12-04 16:18:02
Zbudowałeś źle szkielet programu. :F

C/C++
int zapis[ 3 ];
int index = 3;

int wysw[ 2 ];
int ileWyl = 2;
int los = zapis[ rand() % index ];
// ...
Deklarujesz trójelementową tablicę "zapis" bez inicjalizacji,
więc zawiera "buraki" czyli przypadkowe wartości które
znajdowały się w przydzielonym tej tablicy miejscu.
(np. pozostałości po działaniu innych programów)
Z tablicą "wysw" dzieje się to samo.

Później przypisujesz jeden z buraków
z tablicy zapis do zmiennej "los".

Dopiero teraz pobierasz liczby od użytkownika...
(i nie wiem dlaczego dopiero teraz)

Przez
cin.ignore( 1000, '\n' );
 trzeba
wcisnąć przed wpisywaniem "enter" inaczej będzie
ignorował wszystkie znaki wpisane przed nim :F

Teraz wywołujesz funkcję "losDoTabl" z argumentami:
"los" (w której są jakieś buraki), tablicę
"wysw" i zmienną "ileWyl" o wartości 2...
(Prawie zawsze buraki są różne od buraków,
więc
if
 prawie zawsze jest spełniony :F )
a w niej przypisujesz elementom tablicy "wysw" buraki,
które otrzymujesz w argumencie "los".
(dlaczego akurat funkcja jest typu "bool", jak nic nie zwraca?)

Później wypisujesz dwa razy (pośrednio)
to co przypisało się do zmiennej "los".
_______________________________________________________

Nie chodzi mi o to byś je zainicjalizował,
a poprawił ten szkielet programu.

Polecam Ci ułożyć schemat działania,
a jak jakieś działanie jest zbyt
złożone to rozbij je na części.

// i jeszcze zapomniałeś że inkrementowanie "i" powinieneś
// wykonywać tylko wtedy gdy wczytanie się powiodło...
P-122186
bladegd
Temat założony przez niniejszego użytkownika
» 2014-12-05 12:35:47
Dopiero teraz pobierasz liczby od użytkownika...
(i nie wiem dlaczego dopiero teraz)

hmmm... nie miałem pojęcia, że po deklaracji tablicy trzeba ją wywołać zanim się zadeklaruje kolejna tablice, bo powstają "buraki" :)

(dlaczego akurat funkcja jest typu "bool", jak nic nie zwraca?)
Przez niedopatrzenie, po moim kombinowaniu zostało zamiast void, nie zauważyłem tego.

Przez
cin.ignore( 1000, '\n' );
 trzeba
wcisnąć przed wpisywaniem "enter" inaczej będzie
ignorował wszystkie znaki wpisane przed nim :F
Siedzę na linuxie i
cin.sync()
 nie chce mi działać poprawnie.

Mam taki sajgon na wyjściu, że się gubię. Parę przykładowych wyjść:

Przykładowe wyjście u mnie dla
cin.sync()
 z wprowadzonymi złymi danymi
Podaj 3 liczby:
a
s
^[OR
4
3
1   
2
3
4
12
41
2
i tak w nieskończoność...


Przykładowe wyjście u mnie dla
cin.ignore( numeric_limits < streamsize >::max(), '\n' )
 z wprowadzonymi złymi danymi
Podaj 3 liczby:
asd
asd
as
^[OP
1
2
3
Wpprowadz co najmiej 1 rozne liczby.
Podaj 3 liczby:
we
qwe
qq

5
6

Wylosowane liczby:
2 ,4 ,
Process returned 0 (0x0)   execution time : 20.401 s
Press ENTER to continue.


Tutaj z kolei raz pojawia się część 2, czyli tak jak powinno, a innym razem warunek nie jest niby spełniony i pojawia się to w takiej formie(cz.1 i cz.2):
Podaj 3 liczby:                 //
                                      //
5                                     //  część
5                                     //    1
6                                     //
Wpprowadz co najmiej 1 rozne liczby.  //
Podaj 3 liczby:                            //
                                           //
5                                          //
5                                          //  część
6                                          //    2
                                           //
Wylosowane liczby:                         //
6 ,5 ,                                     //
Process returned 0 (0x0)   execution time : 9.859 s
Press ENTER to continue.

I ostatni wariant, kiedy to po wpisaniu 3 liczb takich samych, każe mi podać jeszcze raz liczby, ale i tak 1 liczbę bierze z wcześniejszego wprowadzania danych.

Podaj 3 liczby:

2
2
2
Wpprowadz co najmiej 1 rozne liczby.
Podaj 3 liczby:
 
3
4
5

Wylosowane liczby:
2 ,3 ,
Process returned 0 (0x0)   execution time : 16.544 s
Press ENTER to continue.

Mój kod.
C/C++
#include<iostream>
#include<ctime>
#include<cstdlib>
#include<limits>

using namespace std;

int losowanie( int zapis[], int index )
{
    return zapis[ rand() % index ];
}
void wczytywanieLiczb( int t[], int index )
{
    int a, i = 0;
    cout << "Podaj " << index << " liczby:" << endl;
    do {
        cin.clear();
        cin.ignore( numeric_limits < streamsize >::max(), '\n' );
        cin.sync();
        cin >> a;
        if( cin.good() )
        {
            t[ i ] = a;
            i++;
        }
    } while( i < index );
   
}
bool czyJuzWylosowano( int los, int wysw[], int ileWyl )
{
    if( ileWyl == 0 )
         return 0;
   
    int i = 0;
    do {
        if( wysw[ i ] == los )
             return 1;
       
        i++;
    } while( i < ileWyl );
   
    return 0;
}
void losDoTabl( int wysw[], int ileWyl, int zapis[], int index )
{
    int los, i = 0;
    do {
        los = losowanie( zapis, index );
        if( czyJuzWylosowano( los, wysw, ileWyl ) == 0 )
        {
            wysw[ i ] = los;
            i++;
        }
        else
        {
            cout << "Wpprowadz co najmiej " << index - ileWyl << " rozne liczby." << endl; // tu to ja się głowiłem co
            wczytywanieLiczb( zapis, index ); // sie powinno dziać w takim wypadku
        }
    } while( i < ileWyl );
   
}
void wypisanie( int wysw[], int ileWyl )
{
    int i = 0;
    cout << "Wylosowane liczby:" << endl;
    do {
        cout << wysw[ i ] << " ,";
        i++;
    } while( i < ileWyl );
   
}
int main()
{
    srand( time( NULL ) );
    int zapis[ 3 ];
    int index = 3;
    wczytywanieLiczb( zapis, index );
   
    int wysw[ 2 ];
    int ileWyl = 2;
    losDoTabl( wysw, ileWyl, zapis, index );
   
    cout << endl;
    wypisanie( wysw, ileWyl );
    return 0;
}
P-122254
Rashmistrz
» 2014-12-05 15:47:52
hmmm... nie miałem pojęcia, że po
deklaracji tablicy trzeba ją wywołać
zanim się zadeklaruje kolejna tablice,
 bo powstają "buraki" :)

Źle mnie zrozumiałeś.
Jak deklarujesz dowolną zmienną to przydzielane
jest jej miejsce w pamięci, jednak nie wiemy
co zostawiły poprzednie programy po przestaniu
używania tego miejsca.

Mi chodziło o to że użyłeś tych buraków
które tam zostały zamiast liczb
wprowadzonych przez użytkownika...

//Burakami nazywam błędy graficzne,
//uszkodzenia tekstu i inne niepożądane efekty.
//np.: Pac Man i  zdanie "Za┼╝├│┼é─ç g─Ö┼Ťl─ů ja┼║┼ä!" ("Zażółć gęślą jaźń")
____________________________________________________________________

Dziękuję Ci za podanie informacji co nie działa,
znacznie mi to ułatwia rozwiązanie tej sprawy...

C/C++
int losowanie( int zapis[], int index )
{
    return zapis[ rand() % index ];
}
Poco zrobiłeś z tego funkcję?
Starczy:
los = zapis[ rand() % index ];
.



I ostatni wariant, kiedy to po
wpisaniu 3 liczb takich samych,
każe mi podać jeszcze raz liczby,
ale i tak 1 liczbę bierze z
wcześniejszego wprowadzania danych.
W funkcji "losDoTabl" działasz na samym
początku z danymi tablicy które nie są pożądane.
Pierwsza liczba ze "złej" tablicy jest zawsze
dopisywana do tablicy wyników, bo funkcja
"czyJuzWylosowano" zwraca prawdę przy
pierwszym losowaniu...

Jest też szansa że jak podasz 1, 1, 2 zaczniesz losować:
to wylosuje 1 i 2, następnie wypisze wyniki,
bądź wylosuje 1 (zapisze do wyników)
i natrafi na drugą 1, więc poprosi o ponowne podanie liczb...

Powinieneś sprawdzać czy liczby są
różne przed rozpoczęciem losowania,
bądź losować indeksy liczb i je
zapisywać do tablicy zamiast zapisywać
do wyników wartości liczb użytkownika.


Podaj 3 liczby:

1
1
1
Wpprowadz co najmiej 1 rozne liczby.
Podaj 3 liczby:
2
2
2

Wylosowane liczby:
1 ,2 ,
Process returned 0 (0x0)   execution time : 11.032 s
Press any key to continue.
P-122259
bladegd
Temat założony przez niniejszego użytkownika
» 2014-12-06 16:04:37
Dziękuję Ci za podanie informacji co nie działa,
znacznie mi to ułatwia rozwiązanie tej sprawy...
Nie jestem pewien czy to ironia, czy nie przez te kropki na końcu ;)

W funkcji "losDoTabl" działasz na samym
początku z danymi tablicy które nie są pożądane.
tzn. chodzi o tablice wysw?

Pierwsza liczba ze "złej" tablicy jest zawsze
dopisywana do tablicy wyników, bo funkcja
"czyJuzWylosowano" zwraca prawdę przy
pierwszym losowaniu...
Rozumiem, że chodzi o ten kawałek kodu
C/C++
if( ileWyl == 0 )
     return 0;


Powinieneś sprawdzać czy liczby są
różne przed rozpoczęciem losowania,
bądź losować indeksy liczb i je
zapisywać do tablicy zamiast zapisywać
do wyników wartości liczb użytkownika.
Średnio rozumiem, a właściwie mało :/
P-122356
Rashmistrz
» 2014-12-06 18:10:30
W funkcji "losDoTabl" działasz na samym
początku z danymi tablicy które nie są pożądane.
tzn. chodzi o tablice wysw?
O tablicę "zapis". Nie sprawdzasz jej przed
losowaniem pod kątem różności liczb w niej,
co jest przyczyną wcześniej omawianych efektów.

Powinieneś sprawdzać czy liczby są
różne przed rozpoczęciem losowania,
bądź losować indeksy liczb i je
zapisywać do tablicy zamiast zapisywać
do wyników wartości liczb użytkownika.
Średnio rozumiem, a właściwie mało :/

Sprawdzić tablicę:
C/C++
while( !zawieraRozneLiczby( zapis, index ) )
     wczytywanieLiczb( zapis, index );


albo

Losować indeksy:
C/C++
los = rand() % indeks;
if( czyJuzWylosowano( los, wysw, ileWyl ) == 0 )
     wysw[ i++ ] = los;
else
     continue;

// wypisanie:
cout << zapis[ wysw[ i ] ];


(Możesz użyć tablicy typu
bool
 do
zaznaczania wylosowanych indeksów.
Lepiej poświęcić trochę pamięci zamiast
czasu przy porównywaniu dużej ilości liczb)
C/C++
bool zapis_niewylosowano[ indeks ];
for( int i = 0; i < index; ++i )
     zapis_niewylosowano[ i ] = true;

// a potem sprawdzac tak:
if( zapis_niewylosowano[ los ] )
{
    zapis_niewylosowano[ los ] = false;
    wysw[ i ] = los;
}
else
     continue;

// i wyswietlac tak:
cout << zapis[ wysw[ i ] ];
P-122371
bladegd
Temat założony przez niniejszego użytkownika
» 2014-12-16 20:19:25
Ja dalej nie wiem jak to zrobić, poleciałem przez ten czas kolejne lekcje kursu i dojechałem do lekcji o pętli [code src="C++"]while[/code]. Po czym wróciłem do Twojego ostatniego postu i nic... na nic nie wpadłem.

Powinieneś sprawdzać czy liczby są
różne przed rozpoczęciem losowania
Czy dobrze rozumiem, że ma być taka kolejność wykonywanych zadań:
1. wczytanie liczby do tablicy [code src="C++"]int zapis[/code] x3;
2. sprawdzenie czy przynajmniej 1 z wczytanych liczb jest różna od pozostałych, jeżeli nie, powtórz, jeżeli tak, pkt. 3;
3. zacznij losowanie liczby bez powtórzeń do tablicy [code src="C++"]int wysw[/code];

Nawet jeżeli tak ma to przebiegać, to nie wiem jak zrobić sprawdzanie tych wpisanych liczb opierając się na tym(działanie tego kodu w pełni rozumiem):
[code src="C++"]
while( !zawieraRozneLiczby( zapis, index ) )
     wczytywanieLiczb( zapis, index );
/code]

Natomiast, jeżeli chodzi i o losowanie wg. indeksów to sam do końca nie wiem czy rozumiem o co chodzi czy nie :/...

Czy mogę prosić o jakąś pomoc w wytłumaczeniu jak zrobić to sprawdzanie różności liczb wypisanych z klawiatury.
P-122957
darko202
» 2014-12-16 21:29:31
1.
Jeśli losujesz liczby to wylosowane zapisujesz do jakiegoś kontenera
np. tablicy

2.
przy wylosowaniu nowej - jak można określić czy liczba jest inna od wcześniejszych
- musisz porównać ją z wszystkimi w kontenerze  (pętla)
i w niej podjąć decyzję jest różna (if)
  albo nie jest różna (else)

P-122966
« 1 » 2
  Strona 1 z 2 Następna strona