MistrzowieKodowania / cPlusPlusMaterials

Projekty
4 stars 9 forks source link

Podsumowanie zajęć 4. #12

Open ksorokosz opened 8 years ago

ksorokosz commented 8 years ago

Z kłopotami technicznymi ale chyba udało się przebrnąć. Kod i prezentację wrzuciłem - dodałem jeszcze kilka komentarzy, może pomogą. Zachęcam do ściągnięcia tego kodu, uruchomienia i eksperymentowania. Zrozumienie tych zajęć wymaga zrozumienia poprzednich zajęć ponieważ wykorzystuję tutaj wszystko o czym mówiłem wcześniej! Gdybym miał udzielać wskazówek jak podejść do C++ aby się nauczyć:

cóż wymaga to całkiem dużo pracy, ale tak to właśnie jest... a za jakiś czas stwierdzicie, że język programowania to tylko narzędzie, a liczy się to co potrafimy przy jego pomocy zrobić (a to już często wymaga większej wiedzy, ale daje niesamowitą satysfakcję). ponadto dużo łatwiej jest mi pomagać jeśli korzystacie z GitHuba tj. wrzucajcie swój kod na Wasze konta - wtedy ja sam mogę go ściągnać i zmierzyć się z problemami, które macie - spojrzeć na całość, a nie tylko mały wycinek, który akurat skopiujecie - wtedy żaden błąd Nam nie straszny ;) a i jestem pewny, że chętnych do pomocy znajdzie się tutaj więcej.

dlatego do zrozumienia 4 zajęć trzeba zrozumieć:

kolejne zajęcia za 2 tygodnie, więc mam nadzieję, że w ciągu tych 2 tygodniu zasypiecie to forum pytaniami ;) od Was też zależy co na następnych zajęciach zrobimy. Może to być kalkulator, może to być powtórka z innych zajęć, a może to być kolejny temat czyli wczytanie pliku np. obrazka. Jeśli chodzi o ten kurs, z którego część z Was korzysta: http://cpp0x.pl/kursy/Kurs-C++/1 nie przejmujcie się liczbami. Zobaczcie, że na 5 lekcji były tam komentarze, a "lekcja" to często krótka strona. Aktualnie zrobiliśmy: poziom 1, poziom 2 i próbowaliśmy z poziomem 3, ale zawsze możemy wrócić nawet do poziomu 1. Co więcej poziom X od poziomu "4" różni się tak jak poziom 4 od poziomu zerowego (może tego nie wiecie, ale tak właśnie jest). Gdybym na każdych zajęciach robił jedną lekcję z tego kursu, na następnych zajęciach dowiedzielibyście się czym są komentarze ;)

swoją drogą zaktualizowałem "słownik" https://github.com/MistrzowieKodowania/cPlusPlusMaterials/wiki/S%C5%82ownik-Poj%C4%99%C4%87 w tym przypadku również proszę Was o pomoc. Jeśli chcecie aby coś tam się pojawiło to dajcie znać! Ja niestety nie potrafię czytać w myślach - chociaż chciałbym bardzo ;) znajdą się tam nowe słowa, ale takie o które zapytacie albo poprosicie o wyjaśnienie.

Więc owocnej współpracy i programowania :) Każdy z Was może próbować się mierzyć z C++ sam, ale GitHub umożliwia Wam mierzyć się z C++ w grupie? Jak jest łatwiej?

Tigersoftis commented 8 years ago

https://github.com/Tigersoftis/tablica-jednowymiarowa-zdefiniowana

mam tu 3 pytania:

  1. skąd sie bierze taka dziwna liczba za tablicą (w tej komórce 6, której nie ma ? W kolejnych komorkach pokazywało by 0 (zero) tak jak mówiłes ale czemu w 6 pokazuje 2293504?
  2. dlaczego jak tu dodam system ("pause"); to nie chce mi się kompilować ?
  3. gdybym chciał stworzyc tablicę z tekstem to było by char tablica [5] na przykład, a co jeśli miała być tablica z mieszaną zawartością - liczbami i tekstem?

jak się tego dowiem to spróbuję zrobić podobną tablicę, ale zeby uzytkownik mógł sam wsadzać tam liczby :) a potem polecę dalej :)

ksorokosz commented 8 years ago

@Tigersoftis ad 1) wyszedłeś poza zakres tablicy - stąd ta dziwna liczba. pojawienie się zer to przypadek tak na prawdę. Każda zmienna umieszczana jest w pamięci. Pamięć może być uzupełniona np. przez inne programy, mogą znajdować się tam również śmieci (pozostałości po innych programach). Jedyne czego jesteś pewien to to, że jesli tablica zostanie utworzona to w ramach tej tablicy wartości będą takie jakie ustawisz. Poza tablicą wartości mogą być totalnie różnie, a czasami Ci się program wywali np. gdy spróbujesz odczytać komórkę pamięci zajętą przez inny program (np. system operacyjny) ;) Spróbuj w ramach eksperymentu utworzyć tablicę, ale nie wypełniać jej żadnymi wartościami. Następnie ją odczytać. Co dostaniesz?

natomiast 0, o którym mówiłem to wskaźnik NULL. Liczbowo jest to 0, ale gdybym miał to z czymś porównać to jest to adres mieszkania bezdomnego -> czyli tak na prawdę brak tego adresu. Rozumiesz? Gdyby do wskaźnika nie przypisać NULL wtedy znajduje się tam losowy adres. Poeksperymentuj ze zmiennymi np. spróbuj utworzyć dwie zmienne - nic do nich nie przypisać, a potem je odczytać (wyświetlić ich wartości). Co dostaniesz na ekranie? Dokładnie tak samo będzie ze wskaźnikiem.

Ad 2) czasami jest tak, że IDE samo potrafi znaleźć takie funkcje bez wskazywania bibliotek. Jeśli zmieniłeś IDE (albo zainstalowałes inną wersję) to być może musisz dodać bibliotekę: cstdlib. Spójrz tutaj: http://www.cplusplus.com/reference/cstdlib/ znajdziesz w niej polecenie "system" ;)

Ad 3) o widzisz mieszana zawartość ;) to jest bardzo dobre pytanie. W C++ nie możemy stworzyć takiej tablicy używając typów: char, int, double, string... po prostu jest to niemożliwe (język tego zabrania). Ale można to zrobić inaczej :) i tutaj właśnie dochodzimy do odpowiedzi na pytanie: po co nam są klasy w C++ :) Dalej nie będę nic mówił, bo dalej to już na zajęciach ;)

jeden z moich programów to właśnie wsadzanie do tablicy liczb podanych przez użytkownika i policzenie ich sumy (spójrz tutaj https://github.com/MistrzowieKodowania/cPlusPlusMaterials/blob/master/Kod/Arrays%26Functions/arrays_1D.cpp - linijka 65) różnica polega na tym, że jest to tablica dynamiczna.

Jeśli chodzi o postinkrementacje i preinkrementacje - masz rację :) ale nadal jest to inkrementacja. W zasadzie nigdy wcześniej nie używałem przedrostków post i pre - więc również czegoś się nauczyłem! dzięki :)

heillos commented 8 years ago

W dniu 24.02.2016 o 11:11, Seba pisze:

skąd sie bierze taka dziwna liczba za tablicą (w tej komórce 6, której nie ma ?

to proste. Jak Ci pisałem wcześniej, tablica to tak jakby zestaw komórek w arkuszu. Po prostu zestaw zmiennych. Na przykładzie trzech zmiennych, weźmy tak:

int kaczka = 1; int indyk = 9; int stonoga = 12;

na razie nie ma tablicy, w pamięci (czyli w tej duuuuużej siatce „arkusza kalkulacyjnego”) system przydzielił nam 3 komóreczki o jakimś tam adresie. Bazując na porównaniu do arkusza -- może przydzielił po prostu A1, A2, A3. Może inaczej, A7, A8, A9. Ale RACZEJ przydzielił po kolei, bo deklarowane jest to razem. Nie wiadomo czy po kolei.

Teraz zamiast tego zapiszemy

int zwierzaki[3] = {1, 9, 12}

teraz pamięć została przydzielona dokładnie tak samo. System znalazł dla nas miejsce w tym duuużym arkuszu komórek pamięci i dał np. B7, B8, B9 a może jak w przykładzie wyżej A7, A8, A9, o ile tylko były wolne. Tym razem mamy PEWNOŚĆ, że są one po kolei. Tworząc tablicę, język C pamięta jaki adres ma pierwsza komórka i tyle, nic więcej. Czyli jeżeli wrzucił do A7, A8, A9, to zapamięta A7 i zapamięta, że A8 i A9 są zajęte. Ale to już nie w tablicy. Język C jest bardzo prymitywnym językiem (a tablice pochodzą z C).

Gdy piszesz zwierzaki[0] program bierze i sprawdza gdzie są zwierzaki. „o w A7”. Następnie patrzy co jest w nawiasie [0]. „A, czyli 0 kroków od A7, więc trafiam w samo A7”

Gdy piszesz zwierzaki[2] program bierze i sprawdza gdzie są zwierzaki. „o w A7”. Następnie patrzy co jest w nawiasie [2]. „A, czyli 2 kroków od A7, więc trafiam w A9”

I teraz dochodzimy do wyjścia poza tablicę...

Gdy piszesz zwierzaki[14] program bierze i sprawdza gdzie są zwierzaki. „o w A7”. Następnie patrzy co jest w nawiasie [14]. „A, czyli 14 kroków od A7, więc trafiam w A21”.

No i co się dzieje? Z punktu widzenia C, nie stało się nic niewłaściwego. Chciałeś się odwołać do komórki pamięci nazwanej przez nas obrazowo A21 poprzez porównanie do arkusza kalkulacyjnego, a w praktyce o adresie jakimśtam. Tyle, że ten adres nie został przydzielony twojej tablicy. Co tam może być?

1) może go nie być w ogóle, jak mamy mało pamięci albo daleko sięgamy ;) Nie wiem co wtedy się stanie, nie testowałem ;)

2) może to być obszar dostępny dla twojego programu, który nie został przez twój program jeszcze użyty, więc dostaniesz jakąś nieokreśloną wartość, która była tam sobie z jakiegoś powodu, np. poprzez pozostanie po poprzednim programie czy czymś innym. Błędu działania nie będzie, choć będzie to duży błąd logiczny, bo nie wiadomo co czytasz i program jest źle napisany najpewniej. Zwłaszcza jeśli będziesz tam pisał, a nie tylko czytał, to takie pisane na oślep po pamięci dość słabym pomysłem jest, bo możesz trafić w przypadek (3)

3) może to być obszar dostępny dla twojego programu, który został użyty na inną zmienną. np. miałeś w programie

int zwierzaki[3] = {1, 9, 12} int agawa = 18; int wpuscic_do_sejfu = 0;

i trafiasz przypadkiem w miejsce, gdzie jest wpuscic_do_sejfu. Błędu działania nie będzie, choć będzie to duży błąd logiczny, a w szczególności jeżeli będziesz pisał do tej komórki, bo wtedy zepsujesz sobie zmienną wpuscic_do_sejfu. A ona może np. właśnie oznaczać czy user się zalogował już hasłem. Było, że wpuscic_do_sejfu=0, czyli NIE WPUSZCZAĆ. Ty tam wpisałeś np. 1, co oznacza np., żeby wpuścić. I włamanie gotowe ;) Na takich błędach programistów bazują tzw. błędy przepełnienia bufora.

W typowych systemach współczesnych (Windows, Linux, MacOS X) możesz tak psuć tylko swoje (patrz przypadek 3), ale w czasach np. Windows 3.11 często było tak, że jeden program potrafił zepsuć drugi. I ludzie psioczyli na program X, że się wywala, a on się wywalał z powodu programu Y. Bo program Y mu badźgał po pamięci.

4) możesz trafić w obszar, gdzie nie masz prawa pisać, bo system operacyjny tam ci nie pozwala. Wtedy pod Windows dostaniesz to znane okienko „łups program spowodował hakuna matata i zostanie zabity”. Pod Linuksem zrobi Core Dumped i też zdechnie.

Przemysław Adam Śmiejek Zespół Szkół Ogólnokształcących nr 5 w Zabrzu

Tigersoftis commented 8 years ago

Po pierwsze dzięki Kamil i Heillos za tak rzeczowe i konstruktywne odpowiedzi, chętnie czerpie garściami z Waszej wiedzy :)

poprawiłem już tamten program i wszystko działa jak należy :) Zaczynam i to ogarniać :)

Mimo wielu niepowodzeń i zniechęceń udało mi się w końcu stworzyć zupelnie samodzielnie bez zagladania do naszych lekcji program do którego wprowadzamy liczby całkowite do tablicy, potem on je wyświetla w tablicy a następnie podaje sumę i iloczyn wprowadzonych liczb :)

problem największy miałem w tym, że wyświetlał dziwne liczby na początku, nie te wprowadzone, ale doszedłem do tego, że linijka int tablica [WIELKOSC_TABLICY] = {liczba1, liczba2, liczba3, liczba4}; musi być dopiero po wprowadzeniu liczb przez użytkownika a nie na początku bo inaczej czytał komórki pamieci w których jeszcze nie bylo liczb wprowadzonych przez użytkownika :) Nie wiem czy dokonałem tego zgodnie ze sztuką dobrego kodu, ale działa :) Generelnie musiałem powalczyć z kolejnością linii kodu :)

https://github.com/Tigersoftis/tablica-jednowymiarowa-do-wprowadzenia-liczb

Jak masz jakieś sugestię lub uwagi to chętnie przyjmę konstruktywną krytykę :) Jedno pytanie - wspomniałeś coś o tablicy dynamicznej? Czy ta moja teraz jest dynamiczna? Jaka jest różnica między dynamiczną a statyczną?

Czy ułożenie tej tablicy zależy tylko od sposobu w jaki ustawię że się wyświetli? Chodzi mi o to czy jest taka np: |||||_|

czy np taka: |||||| |||||| |||||| ||||||

czy np pionowa? || || || ||

czy można może poprostu wyświetlić tablicę np tablica[5] zamiast podawać po kolei tablica[0], tablica[1] itd? Tak żeby po prostu całą taka jaka jest wyświetliło?

pobawiłem się też w ramach utrwalenia w ASCII ART :P

https://github.com/Tigersoftis/TIGER-ASCII-ART

spróbuję się zabrać za tablice dwuwymiarowe i zrozumieć cokolwiek :)

heillos commented 8 years ago

Twoja jest statyczna, bo ma wielkość 4 zadeklarowaną na stałe. Dynamicznie deklarowane zmienne, to zmienne o wielkościach określanych dopiero w czasie trwania programu. Potrzebujesz 100 liczb, to tworzysz tablicę o rozmiarze 100. Potrzebujesz 1000000 to o takim rozmiarze. Decydujesz w trakcie działania programu.

W dniu 26.02.2016 o 17:34, Seba pisze:

Jak masz jakieś sugestię lub uwagi to chętnie przyjmę konstruktywną krytykę :) Jedno pytanie - wspomniałeś coś o tablicy dynamicznej? Czy ta moja teraz jest dynamiczna? Jaka jest różnica między dynamiczną a statyczną?

Przemysław Adam Śmiejek Zespół Szkół Ogólnokształcących nr 5 w Zabrzu

Tigersoftis commented 8 years ago

czyli dynamiczne tworzy się np za pomocą pętli?

Tigersoftis commented 8 years ago

czy

include cstdio

int main() { printf( "Czy to to samo?", 3 + 4, "siedem" ); return 0; }

to to samo co:

include iostream

int main() { cout << "Czy to to samo? ", 3 + 4, "siedem" ; return 0; }

czy to poprostu inna komenda bo z innej biblioteki na to samo?

pominąłem dziubki bo wtedy nie widać tu bibliotek.

ksorokosz commented 8 years ago

na poczatek gratulacje :) super ze ci sie udalo :) kod z tablica jest w porzadku, ascii art tez ;)

Na poczatek prostsze pytania ;) printf i cout daja podobny efekt ale inaczej dzialaja. Printf jest funkcja z jezyka C. Ten kod, ktory napisales nie zadziala ;) w printf wygladaloby to tak: printf("suma 3 i 4 to %d. I dalej... %.3f", 3 +4, 2.5555) Roznic jest kilka: magiczne %d oznacza ze w tym miejscu wyswietli sie liczba calkowita (d od decimal). Poniewaz to pierwszy znak specjalny to wyswietli sie to co jest pierwsze po "" czyli 7 (bo 3+4 sie obliczy). Potem jak widzisz jest napis i magiczne %.3f to oznacza ze kolejna wyswietlona liczba bedzie float (dlatego f) ale zaokraglony do 3 miejsc po przecinku bo (.3f), więc wyświetli się 2.555 (kolejna wartość) gdyby tam bylo %d wyswietlilo by sie 2, to co po przecinku w floacie zostaloby uciete. Jak widzisz uzywajac printf musisz podawac wprost jakiego typu jest zmienna ktora chcesz wyswietlic. to co wyswietlasz umieszczasz w jednej czesci, ale mozesz tez to sformatowac np. zaokraglajac liczby. Stad w nazwie komendy printf jest "f", bo to print formatted.

Co do tablicy odpowiem za jakas godzinke ;) A film niestety musze nagrac jeszcze raz bo sie nie zachowal, ale mam pomysl jak lepiej wytlumaczyc klasy. Sprobuje to zrobic jeszcze w ten weekend :)

ksorokosz commented 8 years ago

@Tigersoftis Jeśli chodzi o pozostałe pytania:

w c++ nie możesz po prostu wyświetlić całej tablicy w sposób cout << tablica. Musisz ją wyświetlać po kolei (element po elemencie albo dowolnie wybrany element/y), ale nie musisz tego robić w 4 komendach (przy 4 elementach). Jak coś się powtarza to używamy pętli ;) Sposób wyświetlenia tablicy zależy tylko i wyłącznie od Ciebie. Sposób ułożenia w pamięci zależy od systemu operacyjnego i nie masz na to większego wpływu.

Co do tablic dynamicznych jest tak jak @heillos napisał. tablice takie tworzymy w momencie ich wykorzystania. Wyobraź sobie taką sytuację: chcesz napisać program, który wyznaczy sumę pewnego ciągu liczb. Nie wiesz jak dużo liczb poda użytkownik, ale zawsze wynikiem ma być ich suma. Co robisz? Nie jesteś w stanie wtedy z góry założyć jak dużo miejsca potrzebujesz na tablicę. Możesz próbować zgadywać, że więcej niż 1000000 liczb nikt nie poda, ale:

Czyli jak rozwiązać problem sumowania dowolnie długiego ciągu liczb? Tutaj rozwiązaniem jest tablica dynamiczna. W kodzie jaki wrzuciłem znajdziesz dokładnie taki przykład :) spróbuj go przeanalizować.

I jeszcze jedno :) świetna obserwacja z tymi zmiennymi i tablicą. Jeśli najpierw zapiszesz: int tablica [WIELKOSC_TABLICY] = {liczba1, liczba2, liczba3, liczba4}; potem wczytasz te liczby to tablica nie będzie o tym wiedzieć. Przyczyna jest taka jaką podałeś. Zastanówmy się jednak z czego to wynika? Tablica to inny obszar pamięci niż zmienne. Więc: jeśli kolejność będzie taka: int liczba1; int liczba2; int tablica [WIELKOSC_TABLICY] = {liczba1, liczba2...} cin >> liczba1 cin >> liczba2

wtedy wartości liczba1 i liczba2 w tablicy będą równe tym wartościom powyżej tej linijki w której wstawiasz je do tablicy - zostaną skopiowane z pamięci ;) co zostanie skopiowane, ano nie wiadomo :) w odwrotnej kolejności wszystko będzie w porządku.

Teraz mam do Ciebie pytanie: a czy kojarzysz może sposób na to aby tablicę wypełnić czymś przed podaniem liczb przez użytkownika, tak aby po podaniu tych liczb, tablica widziała to co podał użytkownik? czyli X liczba1; X liczba2; X tablica[WIELKOSC_TABLICY] = {liczba1, liczba2} .... użytkownik podaje liczby..... .... wyświetlasz tablice w odpowiedni sposób i wszystko działa.... Podpowiem, że mówiliśmy o tym na zajęciach :)

heillos commented 8 years ago

Pętla to instrukcja sterująca przepływem sterowania. Może sterować także statycznymi tablicami.

int tablica[100000]; // tablica statyczna

for(int i=0, i< 100000; i++) cin >> tablica[i];

wczytujesz 100000 liczb do tablicy statycznej.

a tu dla odmiany masz tablicę o dynamicznym rozmiarze:

 int *tablica;
 int rozmiar;

 cout << "Jak duża ma być tablica? " ;
 cin >> rozmiar;

 tablica = new int[rozmiar];

 tablica[rozmiar] = 100;

 delete tablica;

i zero pętli ;) Choć sensu to użytkowego nie ma.

W dniu 26.02.2016 o 17:47, Seba pisze:

czyli dynamiczne tworzy się np za pomocą pętli?

— Reply to this email directly or view it on GitHub https://github.com/MistrzowieKodowania/cPlusPlusMaterials/issues/12#issuecomment-189366356.

Przemysław Adam Śmiejek Zespół Szkół Ogólnokształcących nr 5 w Zabrzu

ksorokosz commented 8 years ago

@heillos ale nie: tablica[rozmiar] = 100; - to jest poza tablicą tablica[rozmiar - 1] = 100.

heillos commented 8 years ago

Nie, to nie to samo

cout to obiekt z języka C++ Obiekt z przeciążonym operatorem << który odwołuje się do odpowiedniej metody obiektu. Ale tak naprawdę obiekt cout zawiera więcej metod. To jest element programowania obiektowego, z całym bagażem obiektowości i z jej zaletami.

printf() to funkcja z języka C. Ponieważ C++ powstał jako rozszerzenie C, więc funkcja ta dalej jest dostępna jako element standardowej biblioteki C. W przeciwieństwie do cout nie jest ona obiektem.

W dniu 26.02.2016 o 17:54, Seba pisze:

to to samo co:

Przemysław Adam Śmiejek Zespół Szkół Ogólnokształcących nr 5 w Zabrzu

heillos commented 8 years ago

A, sorry, tak oczywiście... Skupiłem się na czymś innym...

W dniu 27.02.2016 o 13:45, Kamil Sorokosz pisze:

@heillos https://github.com/heillos ale nie: tablica[rozmiar] = 100; - to jest poza tablicą tablica[rozmiar - 1] = 100.

— Reply to this email directly or view it on GitHub https://github.com/MistrzowieKodowania/cPlusPlusMaterials/issues/12#issuecomment-189631970.

Przemysław Adam Śmiejek Zespół Szkół Ogólnokształcących nr 5 w Zabrzu

ksorokosz commented 8 years ago

Nagrałem drugi raz zajęcia 4 (w związku z problemami z zapisem poprzednich). Zostały już wrzucone :) Postanowiłem, że w trochę inny sposób wytłumaczę klasy i obiekty, zapraszam do oglądania :)

na początku filmu mówiąc o projektach zapomniałem udostępnić ekranu, ale za chwilę będę to powtarzał, bo zorientowałem się że prawodopodobnie nie będzie nic widać :P przepraszam za ten błąd, ale nie chciałem drugi raz tego nagrywać ;)

Tigersoftis commented 8 years ago

Zassane, w wolnej chwili przenalizuję - wielkie dzięki Kamil :)

Tigersoftis commented 8 years ago

https://github.com/Tigersoftis/14.-kalkulator-1

udało mi się zrobić taki prymitywny kalkulator, bez biblioteki math.h (jesli się nie mylę co do biblioteki matematycznej)

ksorokosz commented 8 years ago

@Tigersoftis świetnie :) spróbuj teraz użyć biblioteki math.h i zaimplementować np. pierwiastek kwadratowy (sqrt) albo funkcje trygonometryczne. Opis biblioteki jest tutaj: http://www.cplusplus.com/reference/cmath/ zobaczysz, że będzie to bardzo proste :) a potem pomyślmy o użytkowniku tego kalkulatora ;) biedny człowiek musi za każdym razem włączać program od początku, ale możemy coś zrobić prawda?

EMCsoftware commented 8 years ago

Mam pytanie co do projektu biblioteki, muszę ją dzielić na kilka plików, czy mogę wszystko zrobić w jednym źródłowym?

ksorokosz commented 8 years ago

@EMCsoftware to nie jest kwestia przymusu, ale wygody i profesjonalizmu ;) dobry programista podzieliłby projekt na moduły, na kilka plików źródłowych i nagłówkowych aby to co zrobił było czytelne, zrozumiałe, aby mógł do tego wrócić po roku i nie tylko wiedzieć jak projekt działa, ale również użyć go gdzieś indziej.

Nie chcę Ciebie do niczego zmuszać - program napisany w jednym pliku będzie działał - chciałbym natomiast Ciebie przekonać przykładami ;) Wyobrażasz sobie grę Wiedźmin napisaną w jednym pliku? Ile linii miałby taki plik? Jak dużo czasu zajęłoby znalezienie błędu w takim kodzie? Spróbuj podzielić swój program na kilka plików, zmierzysz się z problemami, które w tej chwili będą być może skomplikowane, a za kilka lat może będziesz tworzył nowego Wiedźmina lub system operacyjny - wtedy dzisiejsze doświadczenie z biblioteką zaprocentuje i okaże się czymś niezwykle ważnym ;)

EMCsoftware commented 8 years ago

No więc, długo dłubałem w kodzie :dart:, ale to mnie przerosło :disappointed: Problem ze 169 linią, coś jest nie tak z przekazaniem vectora jako argument do funkcji, nie wiem, co zrobić :neutral_face: 169 cannot convertstd::vector<std::string, std::allocator >' to std::vector<std::string, std::allocator<std::string> >*' for argument1' to void sort(std::vector<std::string, std::allocator<std::string> >*, std::vector<int, std::allocator<int> >*, std::vector<int, std::allocator<int> >*, std::vector<int, std::allocator<int> >*, std::vector<int, std::allocator<int> >*, std::vector<std::string, std::allocator<std::string> >*, std::vector<std::string, std::allocator<std::string> >*, std::vector<int, std::allocator<int> >*, long long unsigned int)' Dodaję link do programu: https://github.com/EMCsoftware/ProgramyMistrzowieKodowania/blob/master/LU.cpp

kasianw commented 8 years ago

Kamil, pracowałeś nad Wiedźminem?

ksorokosz commented 8 years ago

@EMCsoftware

jeśli chodzi o ten błąd ;) wektor to szablon - czyli coś o czym chciałem mówić na ostatnich zajęciach - szablony zwykle generują takie skomplikowane błędy ;)

najważniejsza część tego komunikatu to: cannot convert std::vector to std::vector* a więc o co chodzi?

Domyślasz się bardzo dobrze :) Chodzi o sposób przekazania wektora do funkcji. Twoja funkcja sort dostaje jako argument tablicę wektorów (bo dodałeś [])! Nie pojedynczy wektor a jego tablicę ;) A wywołujesz ją dla pojedynczych wektorów. Czyli zamiast sort( std::vector taba[] ....) spróbuj sort ( std::vector& taba ... )

ale zachęcam też do przeanalizowania ostatniego webinarium - nagrałem go drugi raz i tym razem wyjaśniłem wszystko na przykładzie biblioteki właśnie ;) a kod znajdziesz oczywiście tutaj, jest tam również sortowanie: https://github.com/MistrzowieKodowania/cPlusPlusMaterials/tree/master/Kod/Classes/Library Oczywiście warto też powalczyć z Twoim kodem, bo na pewno dużo się dzięki temu nauczysz ;)

Dalej w tej funkcji używasz funkcji swap. Tutaj znajdziesz jej opis: http://www.cplusplus.com/reference/vector/vector/swap/ Ta funkcja nie zamienia elementów wektora tylko zgodnie z jej opisem: "After the call to this member function, the elements in this container are those which were in x before the call" ta funkcja zamienia elementy pomiędzy dwoma wektorami! Czyli jeśli jeden wektor zawiera: 2, 3, 1 a drugi: 4, 5, 6 to po użyciu funkcji swap będzie odwrotnie ;) Pierwszy wektor zawierałby: 4, 5, 6; drugi 2, 3, 1. Więc nie jest to funkcja, której należałoby użyć do sortowania. Potrzebujesz zamiany elementów ;) czyli z wektora 2, 3, 1 powinien powstać 1, 2, 3

Super, że poprawiłeś też kod! Widzę tam jeszcze jeden błąd z dostępem do pamięci, ale jak poradzisz sobie z tym błędem kompilacji na pewno go zauważysz ;) Także powodzenia! Dasz radę, wierzę w Ciebie :)

@kasianw Nie pracowałem, ale CDProject właśnie rekrutuje do kolejnej części Wiedźmina ;) http://pl.cdprojektred.com/jobs/sr-software-engineer-desktop-c/ próbowano mnie zrekrutować, ale musiałem odmówić, bo nie jestem specjalistą od gier, którego tam potrzebują - przynajmniej na razie nie jestem na to stanowisko gotowy ;) Pracuję przy przetwarzaniu sygnału mowy, dźwięku, wideo, powiedzmy sztuczna inteligencja ;)

EMCsoftware commented 8 years ago

Wooow, sztuczna inteligencja? Czyli to, co tygryski lubią najbardziej :wink: a co dokładnie Pan robi, jaki to typ inteligencji, tylko rozpoznawanie mowy czy elementów obrazu, czy może też chatboty? Ma Pan styczność z robotami lub chociażby samodzielnymi urządzeniami typu inteligentne domy lub RTV /AGD, czy siedzi w sofcie dla komputerów (ew. urządzeń mobilnych) ? Bardzo ciekawi mnie to zagadnienie, szczególnie robotyka. A co do poprawek - zaraz spróbuję to wszystko naprawić :smiley: P. S. często używa Pan Assemblera, o ile w ogóle? Warto się go uczyć? :smiley:

ksorokosz commented 8 years ago

@EMCsoftware spójrz na GitHuba w zakładkę pull request - zobaczysz tam poprawki, które wychwyciłem oprócz jednej, którą pozostawiam Tobie ;) Będziesz miał trochę łatwiej, a i tak możesz sprawdzić gdzie i co poprawiłem, więc nic Ci nie umknie. A na nagraniu webinarium GitHuba znajdziesz wyjaśnienie czym są pull requests i jak z tego korzystać ;)

Dokładnie to synteza mowy, rozpoznawanie mowy, być może w niedalekiej przyszłości tzw. sieci neuronowe (czyli coś co używane jest do tworzenia chatbotów właśnie). A urządzenia to np. inteligentne telewizory ;) chociaż w tej chwili rzadko pracuję przy sprzęcie (ale w przeszłości zdarzało się, hobbystycznie również tym się zajmuję). Jak interesujesz się robotyką to po kursie opowiem Wam dokładnie co można dalej robić z tą wiedzą ;) Teraz powiem, że możesz zainteresować się Arduino, programowaniem ARM albo Raspberry PI ;) A na studiach technicznych być może usłyszysz o FPGA albo GPU - dosyć niszowe, ale również sprzęt, na którym próbuje łamać się szyfry lub implementować algorytmy wizyjne, dzięki którym robot potrafi znaleźć bombę ;)

Jeśli chodzi o Assembler - w tej chwili jest to język, którego używa się bardzo rzadko - nawet programując w sprzęcie. Najczęściej używamy języków: C/C++ właśnie ;) W sztucznej inteligencji te języki też są najczęściej spotykane ;) Inne języki, którymi możemy ożywić sprzęt to np. VHDL, Verilog. Są one jednak dużo mniej intuicyjne niż C/C++.

Jeśli interesujesz się sztuczną inteligencją to C++ jest na pewno dobrym językiem na start, ale nie tylko! Będziesz mógł dzięki niemu zrobić dużo fajnych rzeczy. Musisz też wiedzieć, że w sztucznej inteligencji język programowania to tylko niewielki fragment całości ;) Matematyka i te wszystkie równania w końcu nabierają znaczenia ;)

@All W dalszej części naszej zabawy z programowaniem będę starał się również pomagać Wam poprzez patche tzw. pull-requests - kod, który sam napiszę np. trudniejsze poprawki. Dzięki temu będziecie mogli poczuć się jak programiści, którzy na codzień korzystają z takich rozwiązań jak GitHub i nie musicie obawiać się, że zostajecie sami z całym materiałem! A może znajdę naśladowców ;) Zachęcam więc jeszcze raz abyście dzielili się kodem nawet jeśli z czymś sobie nie radzicie! Ania mówiła o tym podczas webinarium z GitHuba, do którego link znajdziecie w naszym README.

EMCsoftware commented 8 years ago

OK, poprawiłem kod (n-ty raz): https://github.com/EMCsoftware/ProgramyMistrzowieKodowania/blob/master/LU.cpp Czy chodziło o miejsce, w którym sortuję listę? Haha, jak mogłem to przeoczyć? :laughing: Sortować w pętli... Miałoby to może swój sens, gdyby w trakcie pętli coś w liście się zmieniało, ale nie tutaj :smiley:

Tigersoftis commented 8 years ago

użyłem już w kalkulatorze math.h i mam już potęgi, liczbę Pi, liczbę e (eulera) w wolnym czasie ulepsze menu i dodam jeszcze jakieś obliczenia :) Coraz rzadziej borykam się z błędami :)

EMCsoftware commented 8 years ago

Cieszę się twoim szczęściem, ja się jeszcze borykam, często, oj często... :laughing:

Tigersoftis commented 8 years ago

Bo Ty inny Level, ja w Twoim kodzie niewiele rozumiem :(

A przed szkoleniem przygotowałem kalkulatro z biblioteką math,h i 3 kolejnymi działaniami: potęgowaniem, mnożeniem * Pi i mnożeniem * e , moze komus sie przyda :)

https://github.com/Tigersoftis/15.-kalkulator-2

Przy okazji pytanie - chciałem osiągnąć dokładność większą i zamiast float dałem double, ale to nic nie zmieniło :( wyniki wychodzą takie same. Zmienia się jakoś typ liczby wyniku ?

Co oznacza e, jeżeli zadam duże mnożenie i jest duzo liczb i to e pojawia się w wyniku? np: 2.05666e+007 jak to czytac?

ksorokosz commented 8 years ago

@Tigersoftis

zamieniając float na double zwiększasz precyzję. Czym jest ta precyzja? Spójrz na przykład:

float a = 1.f / 81;
float b = 0;
for (int i = 0; i < 729; ++ i)
        b += a;
cout << b << endl;   // prints 9.00002

double a2 = 1.0 / 81;
double b2 = 0;
for (int i = 0; i < 729; ++ i)
        b2 += a2;
cout << b2 << endl;   // prints 9

liczba b i b2 powstają poprzez dodawanie ułamka (raz zapisanego jako float, raz jako double). Wyświetlając wynik dostaniemy dwie różne wartości - ponieważ liczba float to 7 cyfr po przecinku, natomiast double to już 15.

Taka liczba: 2.05666e+007 oznacza liczbę zapisaną w tzw. notacji naukowej. Jest to 2.05666 * 10 ^ 7 zobacz, że precyzja tej liczby to 5 cyfr po przecinku (więc nie dziwne, że float i double są równe). Problem pojawi się gdy odczytamy kolejne cyfry np. 8 (której float nie ma) albo 7 na której już będzie widać zaokrąglenie ;)

@EMCsoftware spójrz na komentarz w pull request ;)

Tigersoftis commented 8 years ago

menu się powiększa o kolejne działania matematyczne :)

[0] - DODAWANIE [1] - ODEJMOWANIE [2] - MNOZENIE [3] - DZIELENIE [4] - KWADRAT LICZB [5] - SZESCIAN LICZB [6] - LICZBA 1 PODNIESIONA DO POTEGI LICZBY 2 [7] - LICZBY POMNOZONE PRZEZ LICZBE Pi [8] - LICZBY POMNOZONE PRZEZ LICZBE e (EULERA) [9] - exp OBU LICZB (EXPONENTA - exp(x)=e^x) [10] - LOGARYTM NATURALNY OBU LICZB

https://github.com/Tigersoftis/15.-kalkulator-2

zahaczyłem juz o funkcje wykladniczą exp, która o ile pamiętam jest czynnikiem całkującym bo exp(x) = e^x= pochodna d(e^x)/dx = całka (e^x) dx, ale poprawcie jeśli się mylę :)

dodam jeszcze przynajmniej pierwiastkowanie i wymysle jeszcze jakies działania :)

EDIT:

Funkcję exp zauważylem że można zrobić na 2 sposoby:

  1. exp (zmienna) - ale skoro to jest poprostu potęga stałej e to:
  2. pow (M_E, zmienna) i wynik bedzie taki sam, więc w sumie niepotrzebne jest samo exp w bibliotece :)

Już pierwiastkowanie dodane, jest więc już 11 działań - moze sprobuję silnię, ale do silni wydaje mi się, ze musi być pętla z dekrementacją do zera a potem pomnozone wszystkie liczby, tylko nie wiem czy nie było by dobrze to wsadzić w tablicę ? postdekrementacja czy predekrementacja to obojętne? czy tu nie musiała by być zmienna int jednak? czy źle kombinuję? a może wyważam otwarte drzwi i jest gotowa formuła na silnie w bibliotece (nie znalazłem)?

pytanie: doczytałem, że jest jeszcze zmienna long double, myślałem, że będzie dokładniej, ale wychodzą wtedy jakieś bzdury - dlaczego? Nie ma tej zmiennej w spisie, który dałeś więc niewiele o niej wiem :(

EDIT:

Znalazem w sieci kod na silnię:

http://www.algorytm.edu.pl/instrukcja-iteracyjna-ptle/34-silnia.html

wydaje się prostsze niz myslałem :) nawet matematycznej biblioteki nie trzeba. Tylko proszę o wyjaśnienie:

i chyba musiał bym jednak tak jak byslałem zrobić to na liczbach całkowitych, moze zaokrąglac jakos jesli ktos wprowadzi liczbe z przecinkiem ?

Edit:

Jak patrze na kod kalkulatora mojego, który poprawiłeś to jak na to patrzeć? zielone to zmiany wprowadzone przez Ciebie, czerwone to jak było moje a białe są bez zmian?

EDIT:

mam już pomysł do silni oprócz double liczba1 double liczba2 dodam int liczba3 i ją wsadze do silni zamiast powielac znowu z double , wtedy nikt nie uzyje innej niz całkowita liczba :) potem przetestuje :)

EMCsoftware commented 8 years ago

Co do unsigned int, to unsigned to zmienna bez "minusów", tzn. masz int, który ma jakiś tam zakres od "- iluś" do "iluś" , a słowo unsigned sprawia, że zmienna ma zakres od 0 (chyba) do 2*ta liczba, która by była pułapem zwykłego inta. Oczywiście możesz zrobić też unsigned short, long, long long (chyba to jest największa liczba, jaką możesz przechować), nie jestem natomiast pewien co do float. Rozumiesz teraz? Jak byś miał zakres od - 255 do 255 na przykład, to unsigned zrobi ci z niego 0 - 510.

Tigersoftis commented 8 years ago

Poddaję się... Wszystko działało puki nie uparłem się na siłę. 3 wersja kalkulatora:

https://github.com/Tigersoftis/16.-kalkulator-3

bede wdzięczny za wskazanie co zle z silnią zrobiłem :(

unsigned int n; //z tej liczby będziemy liczyć silnię (unsigned - liczby tylko dodatnie)
long long silnia = 1; //ta zmienna będzie przechowywać wynik silni

te wiersze próbowałem nawet w case silnia: dać a i tak jakis błąd zawsze :/ błędy i tak są tak opisane w kompilatorze, ze nigdy i tak nie wiem co zle robie :(

poprosze o wszelnie wskazówki co do tej wersji programu :) Teraz każde działanie spersonalizowałem bo nie do każdego trzeba bylo 2 liczb :)

ksorokosz commented 8 years ago

@Tigersoftis czerwone to linie, które usunąłem, a zastąpiłem je zielonymi. Masz tam takie znaczki "-" i "+" przy każdej linii.Białe są bez zmian.

z unsigned @EMCsoftware pozamiatał więc nie mam nic do dodania ;)

a jeśli chodzi o silnię. pomysł dobry tylko brakuje mściwego średnika ;) w tej linii: silnia = silnia * i //lub silnia*=i dokładnie 170.

i jeszcze jedna uwaga: zobacz, że Twój switch jest bardzo rozległy. To jest odpowiedni moment do tego aby wprowadzić tam funkcje i np. dodać plik nagłówkowy ;) a uparcie się to właściwy odruch :P jeszcze kilkadziesiąt godzin z programowaniem to cierpliwość wytrenujesz jak nigdy :P

Tigersoftis commented 8 years ago

Dodałem srednik i tak nic :(

taki błąd mi wywala:

http://zapodaj.net/4305352457143.jpg.html

ksorokosz commented 8 years ago

zamiast: cin << powinno być cin >>

linia 168

EDIT

a błąd mówi tyle: nie mogę znaleźć operator<< (czyli właśnie "<<") w obiekcie klasy istream (bo cin jest takim właśnie obiektem). a nie może znaleźć, bo on nie istnieje (co innego w cout) ;)

i możesz dwa razy kliknąć na ten błąd (opis) to przeniesie Cię do linijki w której on jest (zwykle będzie się zgadzać, ewentualnie błąd będzie linijkę wyżej/niżej... albo w trudniejszych przypadkach będzie gdzieś indziej - zdecydowanie rzadziej). poza tym w opisie błędu masz też numer linijki i kolumny ;) czyli w linii 168 i kolumnie (czyli pozycji kursora) 10 jest ten błąd.

jest jeszcze jeden błąd: silnia cannot appear in constant expression ;) zobacz, że "silnia" jest w enum ale również użyłeś tego jako nazwa zmiennej ;) pamiętasz jak mówiłem, że stałe w enum powinno się nazywać dużymi literami czyli np. SILNIA? Właśnie dlatego, żeby nie było konfliktu z nazwą zmiennych ;) a więc stałe (enum, #define) nazywamy wielkimi literami, chociaż oczywiście nie jest to przymus (bo małymi też działa) tylko pewien programistyczny standard zapobiegający takim błędom (ciężko zauważalnym - jak sam to zaobserwowałeś - opis błędu jest mylący bo patrząc na "case" widzisz że tam jest prawidłowa nazwa stałej, ale nie zwracasz uwagi, że kompilator nie ma pojęcia o tym, bo dla niego silnia to już zmienna zadeklarowana tutaj: long long silnia = 1; //ta zmienna będzie przechowywać wynik silni).

Tigersoftis commented 8 years ago

Ten drugi bład własnie sam zauwazyłem, zmieniłem nazwe z silnia na siln i juz wszystko działa :)

te znaczniki w cin >> zamiast wchodzic w strone cin to wychodza i w cout << wchodzą w out zamiast outowac się z niego mnie strasznie zawsze mylą muszę pamiętac ze jest odwrotnie niz pokazują

wielkie dzieki :)

spróbuję jeszcze opracować np ciąg fibonnaciego i moze jeszcze cos co mi sie podobalo w matematyce :) tak sie chyba najlepiej naucze :)

EDIT:

działa, ale cokolwiek wpisze wyskakuje 12 :(

ksorokosz commented 8 years ago

@Tigersoftis cin i cout możesz spróbować inaczej interpretować: jeśli cin|cout to terminal albo użytkownik to cin >> zmienna oznacza, że terminal/użytkownik wpisuje do zmiennej natomiast: cout << "jakis napis" oznacza, że "jakis napis" pojawia się w terminalu (bo jest to niego wrzucany). operacja "in" jest zwykle operacją w stronę komputera - czyli cin operacja "out" jest zwykle operacją w stronę użytkownika - czyli cout

ale silnia Ci tak działa, że dostajesz 12 czy ciąg fibonacciego?

Tigersoftis commented 8 years ago

silnia, ciągu jeszcze nie zacząlem bo stanąłem na silni :(

juz działa, pogłówkowałem i w petli zamiast na dekrementacji oparłem się na inkrementacji i policzyłem w drugą stronę, ale wszystko działa:

for(int i=1;i<=n;i++)

a pokazywało 12 bo w linijce niżej zapomniałem ze nazwe silnia zmieniłem na siln: zostawilem: siln = silnia * i; a powinno byc siln = siln * i; i juz działa :)

Ciężko mi jeszcze załapać pętle :( pewnie złapię jak użyję ich n razy do tej pory nie rozumiałem dlaczego nie działa, a teraz po raz pierwszy nie rozumiem dlaczego dziala :( nie rozumiem np dlaczego działa przerwanie pętli w miejscu i<=n skoro n to wprowadzona liczba dla której obliczam silnie a i zaczynam od 1 - w moim rozumowaniu już na starcie i jest <= n :( bp wpisze np ze n to 6 a i przeciez startuje od 1 więc już jest mniejsze... czemu więc od razu nie przerywa pętli ?

skąd pętla wie, kiedy konczy się to co ma byc w pętli, po średniku?

EDIT:

kolejne pytanie wpisuje 10 - silnia działa wpisuje 50 - silnia działa wpisuje 100 - i pokazuje wynik 0 (zero) i od tego momentu nawet jak wpisze 6 to juz zawsze pokazuje zero :( dlaczego? moze rozwiązaniem bylo by ograniczenie wpisywanej silni do momentu kiedy daje radę? Podejrzewam ze tak wielkiej liczby juz poprostu nie obsluguje?

ksorokosz commented 8 years ago

pętla for jest pętlą "dopóki" czyli powtarzaj dopóki jakiś warunek JEST spełniony. Jak przestanie być spełniony wtedy zakończ. pętla while też jest taką pętlą.

a odpowiedź na drugie pytanie sam podałeś ;) 100 już jest bardzo dużą liczbą dla tak obliczanej silni więc nie mieści się to w zakresie long long. Tego typu silnie oblicza się w trochę inny sposób - zapisując liczby na części np. w tablicy. Bo przecież każdą liczbę da się zapisać na kilka sposobów. Zobacz: 11 = 1 + 10 100 = 0 + 0 + 100.... a więc gdyby liczbę 11 zapisać w tablicy moglibyśmy to zrobić tak: [1,1] a liczbę 100 tak: [0,0,1] w ogólności: [ cyfry jedności, ile dziesiątek, ile setek, ile tysiecy,...., ile milionów, ....] wtedy działania mnożenia trzeba byłoby zaimplemenotwać zupełnie inaczej ;) Od takiej reprezentacji liczb już blisko do poważnej kryptografii (tam używa się liczb dużo większych niż long long) albo programowania w sprzęcie :) Gdybyś chciał więcej o tym poszukać jest to tak zwane kodowanie BCD (binary coded decimal). Sposobów zapisu liczb jest jeszcze więcej :)

a dlaczego potem jest zero? tutaj jest inna odpowiedź. Zrób taki eksperyment: najpierw wprowadź 2 a potem wprowadź znowu 2

co dostaniesz za drugim razem? ja zgaduję, że 4, ale na pewno nie 2. Zgadłem? Jeśli tak to spróbuj znaleźć sam odpowiedź dlaczego tak jest, bo błąd leży gdzieś indziej ;)

Tigersoftis commented 8 years ago

Miałeś rację, że tak jest, gdybys nie powiedział nawet bym sie nie zorientował najpierw 2! to 2 potem 4 potem 8.... ale od razu sie domysliłem ze chodzi o to ze long long siln = 1; jest przed tym jak wybierałem rodzaj zadania, a on jest zapętlony więc pętla juz nie łapie tego ze przy drugim wprowadzeniu danych long long ma powrócic do wartosci wyjsciowej i zapamietala ostatnia wartosc, wystarczylo w case dodac przed petla: siln = 1; i problem zniknal :P

EDIT:

skąd petla wie kiedy się zakonczy ( w kodzie ze do tej linijki a nie dalej)? do srednika? nie...

ksorokosz commented 8 years ago

z każdym krokiem zwieksza się "i" i za każdym razem następuje porównanie z n o to dba już kompilator ;) gratuluje :) o to chodziło. na następnych zajęciach pokaże Wam debugger bo widzę że może dużo wyjaśnić ;)

Tigersoftis commented 8 years ago

ale wie, że trzeba zlapać siln = siln * i; a nie łapie już cout << n << "! = " << siln << endl...

i nie rozumiem też poprzedniej pętli, głównej - while (true){ skąd wie do kiedy jest true? dalej nic na to nie wskazuje czy poprostu dalismy jakis warunek, który zawsze bedzie spełniony aby pętla zawsze chodzila a za wyjscie jest odpowiedzialne if (rodzaj_dzialania == wyjscie) { break; } a nie niedotrzymanie warunków pętli? Jeśli tak to zamiast powyzszego mogłbym dac np w case wyjscie np ze bool = false i petle tez bym przerwał? Tylko wtedy musiał bym w while (true){ tez jakos boola zawrzec?

ksorokosz commented 8 years ago

@Tigersoftis jeśli nie użyjesz {} to pętle, warunki widzą kod do pierwszego średnika. co do pętli while - jest tak jak piszesz. pętle wychodzą jak warunek nie jest spełniony (równy false). A więc while(true) oznacza, że pętla jest nieskończona, a z pętli wychodzimy dzięki "break" w warunku który wskazałeś. spróbuj zrobić eksperyment, który zaproponowałeś z tym "case" ;) jeśli dobrze Cię zrozumiałem to powinno zadziałać (wtedy zamiast while(true) powinno być while(jakiś warunek) )

EDIT: @Tigersoftis

spróbuj zaimplementować szyfr Cezara ;) będziesz miał już część projektu. Dorzucisz menu - już wiesz jak ;) i będzie to już bardzo dużo :)

Tigersoftis commented 8 years ago

while (bool == true) ? a w case wyjscie bool = false ?


czyli jeżeli nie dam {} petle działają do pierwszego ; to wiele wyjasnia :)


moja silnia przy duzych liczbach pokazywała głupoty, nawet liczby na minusie więc dałem:

if (siln <= 0) { cout << "\nNie moge obliczyc tak duzej silni! Podaj mniejsza liczbe." << endl; break; }
else { cout << endl << n << "! = " << siln << endl; break; }
i juz pokazuje tylko te dobre :)

EDIT:

ale jest w stanie obliczyc tylko do 25! :( trudno, tak zostawie

EDIT:

Jeszcze jeden problem, po wprowadzeniu liczby n ujemnej program stawał i nic nie szło zrobic, chciałem więc by po wprowadzeniu ujemnej wyrzuciło komunikat, ale mi nie działa, bede wdzieczny za wskazówki:

http://zapodaj.net/f537e5bd86a3d.jpg.html

próbowałem odwrócic petle ale dalej dziala tak samo:

http://zapodaj.net/432ac694cef76.jpg.html

ksorokosz commented 8 years ago

@Tigersoftis Spróbuj najpierw sprawdzić swoje pomysły. Jeśli pojawi się błąd to nic nie szkodzi :) to nie jest strata czasu, bo dzięki temu np. nauczysz się widzieć te błędy i z czasem je naprawiać, a potem ich nie robić (przynajmniej ograniczyć - ja też jeszcze robię różne błędy). Kompilator i wynik działania programu pokaże Ci czy dobrze myślisz ;)

Świadomie nie chcę Ci mówić jak dokładnie masz zaimplementować wyjście z tej pętli, bo sposobów jest bardzo dużo - koncepcję masz dobrą :) Zobacz jak już dużo potrafisz! :) Swoją drogą niuansów C++ jest mnóstwo, sposobów na zrobienie różnych rzeczy również, nie zdążyłbym o nich wszystkich opowiedzieć w trakcie naszych zajęć: chociaż tutaj https://github.com/MistrzowieKodowania/cPlusPlusMaterials/blob/master/Kod/Basic/loops.cpp możesz znaleźć podpowiedź ;)

EDIT:

z tymi liczbami ujemnymi: zaktualizuj kod na GitHubie. Ściągnę go i zobaczę. Obrazki niekoniecznie pomagają ;)

problem z ujemnymi wynika prawdopodobnie z tego: unsigned int n; (zadeklarowałeś jako liczbę nieujemną) cin wtedy źle reaguje żeby temu zaradzić spróbuj przeanalizować kod: https://github.com/MistrzowieKodowania/cPlusPlusMaterials/blob/master/Kod/Additional/input_validation.cpp

EMCsoftware commented 8 years ago

À propos debuggera, w moim projekcie pokazuje, że wychodzę poza pamięć zaalokowaną dla tej aplikacji :smiley:

ksorokosz commented 8 years ago

jeśli nie poprawiles tego problemu o którym pisałem ci w komentarzu do pull request to debugger się nie myli :p w zasadzie nigdy się nie myli ;) tak to jest z pamięcią że może wszystko działać ale tylko na jednym komputerze bądź zupełnie losowo. dla 5 klientów i więcej twój program przekracza zakres tablicy optlist - zaznaczył ci gdzie.

Tigersoftis commented 8 years ago

To latwiej by było zrobić zwykłą liczbe, nie nieujemną i dla niej warunek co zrobiłem wywalający komunikat :) popróbuję w wolnej chwili.

heillos commented 8 years ago

Nie można pisać TYP = WARTOŚĆ.

Spróbuję to wyjaśnić po kawałku. Otóż wyobraź sobie dwa urządzenia elektryczne. Jedno to WARUNEK albo TESTER LOGICZNY i to urządzenie ma w obudowie dziurę. Coś w nią wpada (za chwilę zastanowimy się co), ono to mieli, mieli, mieli i zapala tylko 1 napis na obudowie. 1 z dwóch możliwych. Na obudowie zapali się TRUE albo zapali się FALSE. Nie ma trzeciej możliwości. Urządzenie ma dwa takie napisy.

Teraz mamy drugie urządzenie, ono ma dziurę, ale do tej dziury pasuje tylko TRUE albo FALSE. Nie da się tam wepchnąć niczego innego. To urządzenie nazywa się WHILE. W momencie, gdy to urządzenie dostanie do swojej dziury FALSE, umiera i przestaje działać. A póki dostaje TRUE, to żyje i coś robi. To, co zaprogramowałeś.

Jak można się domyślić obydwa urządzenia pasują do siebie, jak dwa klocki. To co wyświetla WARUNEK, jest przechwytywane przez WHILE.

I teraz tak, mamy typowe zastosowanie

while( wynik < 17 ) { dokonuj trudnych obliczeń na wyniku }

No wiec w linii while( wynik < 17 ) do dziury WHILE wpada wynik z WARUNEK, gdzie warunek brzmi wynik < 17. Więc do dziury urządzenia WARUNEK wpada wynik oraz mniejsze oraz 17. Urządzenie to mieli, mieli i wychodzi mu albo TRUE albo FALSE. Nie ma trzeciej opcji. I wyświetla TRUE

Jeżeli zapiszesz to tak

while ( true ) {

}

oznacza, że pomijasz urządzenie WARUNEK. Że wyświetlasz TRUE bezpośrednio do urządzenia WHILE, zbudowałeś na stałe świecącą lampkę. I tyle.

(pisownia WHILE, TRUE itp. dużymi ma cel zapewnienia czytelności, w C/C++ są to nazwy pisane małymi.

W dniu 10.03.2016 o 22:30, Seba pisze:

while (bool == true) ? a w case wyjscie

Przemysław Adam Śmiejek Zespół Szkół Ogólnokształcących nr 5 w Zabrzu

Tigersoftis commented 8 years ago

Dzięki za wyjasnienie :) Więc pętla WHILE działa tylko w trybie dwójkowym - prawda lub fałsz