Open ksorokosz opened 8 years ago
Tak, tak samo jak JEŻELI (czyli IF). Tam też pasuje tylko TRUE albo FALSE.
Przy czym, w języku C/C++ tak naprawdę TRUE to 1 a FALSE to 0, więc możesz mieć też zapis:
while(1) {}
i on jest tożsamy z while(true). Zwłaszcza w języku C, gdzie nie ma (a może już jest, ale kiedyś nie było na pewno) TRUE/FALSE.
W dniu 12.03.2016 o 21:27, Seba pisze:
Dzięki za wyjasnienie :) Więc pętla WHILE działa tylko w trybie dwójkowym - prawda lub fałsz
— Reply to this email directly or view it on GitHub https://github.com/MistrzowieKodowania/cPlusPlusMaterials/issues/12#issuecomment-195804972.
Przemysław Adam Śmiejek Zespół Szkół Ogólnokształcących nr 5 w Zabrzu
zaktualizowałem kod
https://github.com/Tigersoftis/16.-kalkulator-3/blob/master/16.kalkulator.3.cpp
unsinged usunąłem i zamiast tego dałem warunek, jeżeli spróbujemy wpisać ujemną silnię wyskoczy komunikat, tak chyba lepiej niż problemowe w tym wypadku unsinged
EDIT: Chcę następną rzecz dodać do kalkulatora i proszę o wyjaśnienie początku takiego kodu :
int a, b, c; int cos_tam (int a, int b, int c) {return b_b-4_a*c;}
i teraz moje pytania: co to oznacza jeżeli int cos_tam zawiera w nawiasie poprzednie inty ? po co to? return cos zwraca ale co to znaczy? wypisuje to na ekranie czy trzyma sobie gdzieś w pamięci? jeszcze nie uzywałem return. i dlaczego jest w nawiasie klamrowym jak petla czy warunek?,
@Tigersoftis @heillos
W C++ FALSE to 0, ale TRUE - to pozostałe liczby. Nie musi to być "1" while(2) {
} byłoby równoważne z while(1) { }
co więcej tego typu konstrukcja (jak niżej) z punktu widzenia języka C++ jest prawidłowa (kompilator nie da żadnych błędów - kolejne miejsce na które trzeba uważać) int a = 1; while( a = 1 ) { cout << "Test" << endl; a = 0; }
co się stanie? czy pętla wyjdzie? czy jest nieskończona? bo taka pętla się skompiluje.
@Tigersoftis co do kalkulatora ;) fajnie że go tak rozwinęłeś :) to co teraz? spróbuj może rozwinąć kalkulator z ostatnich zajęć - ten z wyrażeniami, albo może szyfr Cezara ;)
moim zdaniem wyjdzie?
to spróbuj ;)
pojawił się bład, ale w takiej postaci zadziałało:
int main() {
int a = 5; while( a > 0 ) { cout << "Test" <<a<< endl; a--; } return 0; }
ale jaki błąd? działanie tego kodu, który wkleiłem powinno wyglądać tak, że pętla będzie nieskończona. Dlaczego ponieważ "a = 1" to jest przypisanie(!) a nie porównanie. Różnica bardzo subtelna zamiast "==", użyliśmy "=". Przypisanie jest operacją, która zawsze kończy się sukcesem, a więc z punktu widzenia logiki matematycznej sukces jest "1" - co daje pętlę nieskończoną. Podsumowując: pętle kończą się jeżeli operacja wewnątrz pętli da "0". Ta operacja to może być warunek (np. operacja porównania), ale może to być dowolna inna operacja np. funkcja ;) może to być również liczba. Ściślej: nie chodzi o warunki, tylko o operacje, które mogą się zakończyć sukcesem (liczby nie będące 0) lub porażką (0).
Cały kod, który powinien się skompilować, ale program będzie zapętlony.
using namespace std;
int main() { int a = 1; while( a = 1 ) { cout << "Test" << endl; a = 0; } }
Tak, widzę juz tą subtelną różnicę :)
ale mam kolejne pytanie: dlaczego w moim kodzie break ten:
if (rodzaj_dzialania == wyjscie) { break; }
konczy petle i program, a jakikolwiek inny, np ten:
case dodawanie:
cout << "Podaj 1 liczbe: ";
cin >> liczba1;
cout << endl;
cout << "Podaj 2 liczbe: ";
cin >> liczba2;
cout << endl << endl;
cout << "Suma liczb wynosi: " << liczba1 + liczba2 << endl; break;
już nie?
bo jest bezposrednio w petli a nie w swith ?
EDIT:
Dziś juz nie powalczę bo cały dzien budowałem altankę na ogrodzie i padam :) ale proszę o odpowiedz jeśli mogę na powyższe pytanie i na wcześniejsze: Chcę następną rzecz dodać do kalkulatora i proszę o wyjaśnienie początku takiego kodu :
int a, b, c; int cos_tam (int a, int b, int c) {return bb-4a*c;}
i teraz moje pytania: co to oznacza jeżeli int cos_tam zawiera w nawiasie poprzednie inty ? po co to? return cos zwraca ale co to znaczy? wypisuje to na ekranie czy trzyma sobie gdzieś w pamięci? jeszcze nie uzywałem return. i dlaczego jest w nawiasie klamrowym jak petla czy warunek?,
i jeszcze raz wielkie dzięki za tracenie czasu na moje głupie pytania :) Miłej nocy :)
@Tigersoftis ponieważ "break" to trochę bardziej uniwersalne słowo kluczowe. Jeśli użyjesz break to program opuści najbliższy "sensowny" blok. Ponieważ tego słowa używamy zarówno do pętli "while" jak i instrukcji "switch", a instrukcja "switch" w przypadku, o który pytasz jest tą "najbliższą sensowną" to break w "case" powoduje wyjście ze switcha...a switch jest zagnieżdżony w pętli (drugą w kolejności "sensowną" dla tego konkretnego break instrukcją - drugą bo bardziej na zewnątrz) ;)
No tak, za szybko myślałem, binarnie :)
W dniu 12.03.2016 o 22:00, Kamil Sorokosz pisze:
@Tigersoftis https://github.com/Tigersoftis @heillos https://github.com/heillos
W C++ FALSE to 0, ale TRUE - to pozostałe liczby. Nie musi to być "1"
Przemysław Adam Śmiejek Zespół Szkół Ogólnokształcących nr 5 w Zabrzu
Nie jestem zawodowym programistą i nie znam niuansów specyfikacji C++, ale mam wrażenie, że breakowanie main() czy innej funkcji nie jest zbyt korzystnym działaniem. Mylę się?
W dniu 12.03.2016 o 22:33, Kamil Sorokosz pisze:
@Tigersoftis https://github.com/Tigersoftis ponieważ "break" to trochę bardziej uniwersalne słowo kluczowe. Jeśli użyjesz break to program opuści najbliższy "możliwy" blok. Ponieważ tego słowa używamy zarówno do pętli "while" jak i instrukcji "switch", a instrukcja "switch" w przypadku, o który pytasz jest tą najbliższą to break w "case" powoduje wyjście ze switcha...a switch jest zagnieżdżony w pętli ;)
— Reply to this email directly or view it on GitHub https://github.com/MistrzowieKodowania/cPlusPlusMaterials/issues/12#issuecomment-195811431.
Przemysław Adam Śmiejek Zespół Szkół Ogólnokształcących nr 5 w Zabrzu
@heillos i nikt nie breakuje main tylko pętlę while albo switch. warunek, o którym pisał @Tigersoftis jest w pętli while, a ten program, o którym rozmawiamy jest tutaj: https://github.com/Tigersoftis/16.-kalkulator-3
@Tigersoftis Twoje pytanie dotyczy funkcji. Chciałbym żebyś najpierw przypomniał sobie webinarium o funkcjach to powinno wszystko się wyjaśnić. inty w nawiesie są argumentami funkcji, to są zupełnie inne inty niż te wcześniejsze.
czy void to tworzenie procedury jak np "oto" w jezyku LOGO ? czytam o tym i próbuję to złapać bo jeśli tak to bylo by przydatne :)
void to typ bez typu :) Tani NIEOKREŚLONY.
int kaczka() { return 100; }
double kaczka() { return 100.98; }
void kaczka() { return; }
void wciskasz tam, gdzie jest potrzebny typ, głównie przy typie funkcji, jaką zwraca wartość, jeżeli nie chcesz mieć zwracanej wartości. Nie znam logo, ale np. w Pascalu byłoby tak:
function kaczka : Integer; begin kaczka:=100; end;
procedure kaczka; begin (* ta procedura nic nie zwraca *) end;
W dniu 13.03.2016 o 19:28, Seba pisze:
czy void to tworzenie procedury jak np "oto" w jezyku LOGO ? czytam o tym i próbuję to złapać bo jeśli tak to bylo by przydatne :)
— Reply to this email directly or view it on GitHub https://github.com/MistrzowieKodowania/cPlusPlusMaterials/issues/12#issuecomment-196016231.
Przemysław Adam Śmiejek Zespół Szkół Ogólnokształcących nr 5 w Zabrzu
niestety nie rozumiem jeszcze returnów :(
co daje return 100 ?
EDIT:
zrpbiłem jeden programik i mniej więcej zrozumialem:
https://github.com/Tigersoftis/17.-funkcja-void-procedura-
tylko widzę, że void jest bardziej ograniczone niż oto w logo, albo ja nie umiem bo miałem problem że void jest przed main. chciałem zrobic aby uzytkownik mógł wpisać ile razy powtórzyc znak ale przez to że void jest przed main nie dałem rady
Funkcja to taka czarna skrzynka. Do niej coś wchodzi, ona to mieli, mieli i coś z niej wychodzi. Mogą być jeszcze efekty uboczne. To co mieli w środku, to ty programujesz. Albo ktoś inny.
Jeżeli używasz funkcji liczącej pierwiastek (sqrt()) to nie wiesz co siedzi w środku. To czarna skrzynka o nazwie SQRT. Do niej wchodzi to, co wpuszczasz przez nawiasy. np. sqrt(3) wysyła do wnętrza funkcji liczbę 3. sqrt(1987) wysyła 1987 do wnętrza. Ona COŚ robi. Nie wiesz co, ale zwraca pierwiastek. Czyli możesz napisać coś takiego
wynik = sqrt( 3 );
To spowoduje, że do jej wnętrza wpadnie 3, ona to przemieli i wypluje wynik pierwiastka. I do zmiennej wynik trafi wynik pierwiastka. Załóżmy, że napiszemy sobie sami funkcję, która liczy drugą potęgę liczby całkowitej.
int potega_wlasna( int liczba) { int obliczenia; // deklarujemy chwilowo zmienną całkowitą obliczenia obliczenia = liczba * liczba; // wyliczamy wartość drugiej potęgi liczby return obliczenia; // zwracamy do programu wywołującego wartość obliczeń }
return kończy funkcję i jednocześnie zwraca jakąś wartość na zewnątrz. Ta funkcja:
int potega_wlasna_ale_inaczej( int liczba) { int obliczenia; // deklarujemy chwilowo zmienną całkowitą obliczenia double kaczka; // deklarujemy zmienną kaczka obliczenia = liczba * liczba; // wyliczamy wartość drugiej potęgi liczby kaczka = liczba * liczba / 12; // obliczamy wzór na kaczkę return obliczenia; // zwracamy do programu wywołującego wartość obliczeń }
ma inny środek, ale działa dokładnie identycznie, bo nasza kaczka nie jest zwracana. Ona jest wykonana chwilowo we wnętrzu funkcji i do niczego mądrego nie użyta. Więc funkcja zadziała tak samo.
Każda funkcja w językach C/C++ powinna mieć return. Return definitywnie kończy funkcję. jeżeli napiszemy:
int potega_wlasna( int liczba) { int obliczenia; // deklarujemy chwilowo zmienną całkowitą obliczenia obliczenia = liczba * liczba; // wyliczamy wartość drugiej potęgi liczby return obliczenia; // zwracamy do programu wywołującego wartość obliczeń obliczenia = 1987654332; }
to to nic nie zmieni, bo po returnie ta część się nie wykona. Kończy działanie i już. I coś zwraca. No ale co? No to co po returnie. Ale przecie czasami nie chcemy nic zwracać. Wtedy typ funkcji ustawiamy jako VOID. a po returnie piszemy od razu średnik. To kończy funkcję, ale nie ma sensownej wartości powrotu.
Wyjaśnienia z *. Mówiłem o efektach ubocznych funkcji. Otóż ta funkcja np. nie ma efektów ubocznych, ale zmodyfikujmy ją tak:
int potega_wlasna( int liczba) { int obliczenia; // deklarujemy chwilowo zmienną całkowitą obliczenia obliczenia = liczba * liczba; // wyliczamy wartość drugiej potęgi liczby cout << "Uwielbiam kaczki, zwłaszcza tłuszczyk, w którym maczam chlebuś" << endl; return obliczenia; // zwracamy do programu wywołującego wartość obliczeń }
funkcja liczy to samo. Liczy potęgę liczby. Zwraca potęgę liczby. Ale efektem ubocznym jest wypisanie czegoś na standardowe wyjście (cout). Efektami ubocznymi funkcji zazwyczaj jest pisanie do strumienia (cout, cerr, fstream itp.), czytanie ze strumienia (cin, fstream), łączenie się z siecią czy inne takie.
W dniu 13.03.2016 o 20:47, Seba pisze:
niestety nie rozumiem jeszcze returnów :(
— Reply to this email directly or view it on GitHub https://github.com/MistrzowieKodowania/cPlusPlusMaterials/issues/12#issuecomment-196036210.
Przemysław Adam Śmiejek Zespół Szkół Ogólnokształcących nr 5 w Zabrzu
@Tigersoftis
Logo (nigdy nie napisałem żadnego programu w tym języku, ale może rozumiem): ----------------> oto kalkulator pisz :obliczenia już
można potem napisać: kalkulator 8 + 2 wywołując tą procedurę. Dostajemy wtedy wynik. -----------------> W C++ natomiast jest inaczej ;) pisząc:
void suma(int a2, int b2) { int c = a2 + b2; }
napisaliśmy funkcję, która nie daje żadnego efektu ;) w zasadzie nie będziemy w stanie z niej skorzystać ;) dlaczego?
jeśi napiszemy sobie program: int a1, b1; cin >> a1 >> b1; suma(a1,b1);
to program wykona się w taki sposób: wczytane zostaną liczby a i b następnie wywołana zostanie funkcja, a z pamięci przydzielonej do a1 i b2 skopiowane zostaną wartości do zmiennych a2 i b2 (patrz jak wygląda funkcja suma - trochę wyżej) - czyli do innego obszaru pamięci.
Tak naprawdę w głównym programie korzystamy z innego obszaru pamięci niż w funkcji. Dlatego właśnie aby dostać się do wyniku musimy go z tej funkcji zwrócić! W przyciwnym wypadku w zasadzie nic się nie stanie - oczywiście jeśli funkcja ma zwracać wynik.
Funkcje zwracające wynik to np. obliczenia matematyczne ale również wynikiem może być pole planszy naszej gry albo cały wiersz biblioteki lub też zaszyfrowany napis ;) wynikiem może też być wartość logiczna np. że coś się udało bądź nie udało. Jeśli nie zwrócimy z takich funkcji wyniku to nasz program tego w ogóle nie zobaczy - w logo efekt działania procedury jest widoczny od razu. W C++ nie - sami o tym decydujemy: jak i czy użyć wyniku funkcji... Przykład mniej związany z programowaniem:
natomiast funkcje nie zwracające żadnego wyniku to np. funkcje ustawiające różne rzeczy w klasach albo wyświetlające coś na ekranie np. menu.
spróbuj obejrzeć webinarium dot. funkcji, ponieważ znajdziesz tam odpowiedzi na pytania o return i void. Myślę, że znajdziesz też odpowiedz na inne pytania np. argumenty, zasada działania. O void przed main też mówiłem - nawet na pierwszych zajęciach.
main jest funkcją specjalną. Jest to funkcja, która komunikuje się z systemem operacyjnym i to system operacyjny oczekuje odpowiedzi czy program się zakończył. A tą odpowiedzią jest to co dajemy w return.
Tutaj też masz trochę wyjaśnień: https://github.com/MistrzowieKodowania/cPlusPlusMaterials/wiki/S%C5%82ownik-Poj%C4%99%C4%87
i tutaj o return w main: https://github.com/MistrzowieKodowania/cPlusPlusMaterials/wiki/Z-sali
No nie do końca :) Możesz też dać couta do voidowej funkcji o przez efekty uboczne dobrać się do obliczeń, dokładnie tak samo jak w przykładzie z PISZ obliczenia.
W dniu 13.03.2016 o 21:41, Kamil Sorokosz pisze:
W C++ natomiast jest inaczej ;)
Przemysław Adam Śmiejek Zespół Szkół Ogólnokształcących nr 5 w Zabrzu
@hellios
czyli mówisz, że: void suma(int a2, int b2) { int c = a2 + b2; cout << "Wynik: " << c << endl; }
spowoduje, że "main" będzie widział zmienną "c" i będziemy w stanie napisać w main taki kod: suma(2,3); int c = [coś co da mi wynik funkcji suma]; cout << c << endl; i w rezultacie dostać dwie linie na ekranie tj.:
Wynik: 5 5
jeśli tak jest to chętnie poznam w jaki sposób jest to możliwe bez return? zgadzam się natomiast z tym, że użytkownik dostanie odpowiedź bo zostanie ona wyświetlona na ekranie, ale program moim zdaniem tej odpowiedzi nie dostanie.
A gdzie to mówiłem?
Napisaleś:
void suma(int a2, int b2) { int c = a2 + b2; }
napisaliśmy funkcję, która nie daje żadnego efektu ;) w zasadzie nie
Więc uzupełniłem, że można efektu skorzystać, choć nie mechanizmem return. Może misunderstaning wynika z tego, że nie wiem jak działa logo i PISZ mi sugerowało COUTA.
Uzupełniam, bo twoje zabrzmiało MI jak „funkcja typu void jest bez sensu, bo nie można skorzystać z wnętrza. Można, przez efekty uboczne. Mona na strumień wypuścić albo można przez wpisanie w odpowiednie miejsce w pamięci, a wtedy i z wnętrza programu możemy skorzystać. No ale tym może nie mieszajmy Sebie :)
W dniu 13.03.2016 o 22:01, Kamil Sorokosz pisze:
@hellios https://github.com/hellios
czyli mówisz, że: void suma(int a2, int b2) { int c = a2 + b2; cout << "Wynik: " << c << endl; }
spowoduje, że "main" będzie widział zmienną "c" i będziemy w stanie napisać w main taki kod: suma(2,3); int c = ; cout << c << endl; i w rezultacie dostać dwie linie na ekranie tj.:
Wynik: 5 5
jeśli tak jest to chętnie poznam w jaki sposób jest to możliwe bez return? zgadzam się natomiast z tym, że użytkownik dostanie odpowiedź bo zostanie ona wyświetlona na ekranie, ale program moim zdaniem tej odpowiedzi nie dostanie.
— Reply to this email directly or view it on GitHub https://github.com/MistrzowieKodowania/cPlusPlusMaterials/issues/12#issuecomment-196053079.
Przemysław Adam Śmiejek Zespół Szkół Ogólnokształcących nr 5 w Zabrzu
@heillos
ale to był tylko fragment mojego postu oraz jak widzisz funkcja suma nie miała cout. Wiem, że można tam to dopisać, ale akurat pisząc słowa: "napisaliśmy funkcję, która nie daje żadnego efektu" mówiłem o tej właśnie funkcji suma - tym konkretnym egzemplarzu, bez możliwości jej modyfikacji....nie ma tam ani wskaźników, ani referencji, ani cout.
W logo: pisz: obliczenia podejrzewam, że zawiera w sobie kilka rzeczy: cin, cout ale również samo dodawanie.
W logo by było tak:
Procedura bez parametrów rysująca kwadrat:
Oto kwadrat np 100 pw 90 np 100 pw 90 np 100 pw 90 np 100 pw 90 // pw - kąt obrotu w prawo, np - ilość kroków naprzód już
wywołanie procedury: kwadrat // i już rysuje to co zadaliśmy
teraz ta sama procedura z parametrem (niech uzytkownik może podać bok kwadratu:
Oto kwadrat :bok // :bok to parametr powtórz 4[np :bok pw 90] // tu to samo z pętlą 4 razy zamiast kazdy bok osobno już
wywołanie procedury: kwadrat parametr // np kwadrat 100 lub kwadrat 200 wtedy wstawi ilość kroków (np 100 w miejsce :bok)
procedura narysuje kwadrat
____ |
No więc taka właśnie ,,procedura'' to funkcja, która ma tylko efekty uboczne (rysowanie kwadratu), a nie zwraca żadnych wartości. I wtedy właśnie w C++ zapisałbyś ją jako
void kwadrat( TU PARAMETRY) { // tu rysowanie }
W dniu 14.03.2016 o 10:34, Seba pisze:
W logo by było tak:
Procedura bez parametrów rysująca kwadrat:
Oto kwadrat np 100 pw 90 np 100 pw 90 np 100 pw 90 np 100 pw 90 // pw - kąt obrotu w prawo, np - ilość kroków naprzód już
wywołanie procedury: kwadrat // i już rysuje to co zadaliśmy
teraz ta sama procedura z parametrem (niech uzytkownik może podać bok kwadratu:
Oto kwadrat :bok // :bok to parametr powtórz 4[np :bok pw 90] // tu to samo z pętlą 4 razy zamiast kazdy bok osobno już
wywołanie procedury: kwadrat parametr // np kwadrat 100 lub kwadrat 200 wtedy wstawi ilość kroków (np 100 w miejsce :bok)
procedura narysuje kwadrat
| |
— Reply to this email directly or view it on GitHub https://github.com/MistrzowieKodowania/cPlusPlusMaterials/issues/12#issuecomment-196225678.
Przemysław Adam Śmiejek Zespół Szkół Ogólnokształcących nr 5 w Zabrzu
I właśnie o to pytałem :) nawet wywołanie tej funkcji jest podobne jak procedury w logo :)
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?