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.
#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; }
|
|
Rashmistrz |
» 2014-12-04 16:18:02 Zbudowałeś źle szkielet programu. :F 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... |
|
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 4 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. #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; wczytywanieLiczb( zapis, index ); } } 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; }
|
|
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... 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.
|
|
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 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 :/ |
|
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ę: while( !zawieraRozneLiczby( zapis, index ) ) wczytywanieLiczb( zapis, index ); alboLosować indeksy: los = rand() % indeks; if( czyJuzWylosowano( los, wysw, ileWyl ) == 0 ) wysw[ i++ ] = los; else continue;
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) bool zapis_niewylosowano[ indeks ]; for( int i = 0; i < index; ++i ) zapis_niewylosowano[ i ] = true;
if( zapis_niewylosowano[ los ] ) { zapis_niewylosowano[ los ] = false; wysw[ i ] = los; } else continue;
cout << zapis[ wysw[ i ] ]; |
|
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. |
|
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)
|
|
« 1 » 2 |