Zamiana liczby na string i znaku na liczbę – prośba o ocenę kodu

0

Piszę właśnie artykuł dla maturzystów, nie chciałbym więc napisać brzydkiego kodu, a z C++ nie jestem orłem. Czy ktoś może ocenić jakość tego kodu:

#include <iostream>
#include <sstream>

using namespace std;

int main()
{
    int liczba = 1234567890;
    stringstream ss;
    ss << liczba;
	string napis = ss.str();
    int suma = 0;
    int ileCyfr = napis.length();
    for (int i = 0; i<ileCyfr; i++) {
			char znak = napis[i];
			int cyfra = int(znak - '0');
			suma = suma + cyfra;
		}
    cout << "Suma wszystkich cyfr to: " << suma<< endl;
    return 0;
}
2

Jest ok, ale:

  • możesz po prostu użyć std::to_string (C++11)
  • znak - '0' nie musisz castować na int, to wyrażenie już ma taki typ
  • jeśli już castujesz, to C-style casty są źle widziane. Tutaj - static_cast
  • using namespace std jest złą praktyką
  • osobiście dałbym spacje wokół <
  • brak #include <string> (to raczej drobnostka, skoro jest <sstream>)

Przy czym, skoro to dla maturzystów, to w kontekście samej matury (t.j. dla osób, które nie wiążą dalszej przyszłości z C++) wydaje się ok dla mnie.

1

Wg tytułu wątku jest źle, to nie jest konwersja.
Nie podajesz założeń w treści.

W treści nagle strzelasz nam przed oczy oczy sumą cyfr.

0
kq napisał(a):

Jest ok, ale:

  • możesz po prostu użyć std::to_string (C++11)
  • znak - '0' nie musisz castować na int, to wyrażenie już ma taki typ
  • jeśli już castujesz, to C-style casty są źle widziane. Tutaj - static_cast
  • using namespace std jest złą praktyką
  • osobiście dałbym spacje wokół <
  • brak #include <string> (to raczej drobnostka, skoro jest <sstream>)

Przy czym, skoro to dla maturzystów, to w kontekście samej matury (t.j. dla osób, które nie wiążą dalszej przyszłości z C++) wydaje się ok dla mnie.

  1. A czy wszystkie kompilatory maturalne to rozumieją? Niestety dla mnie C++ to dość odległy temat i nie chciałbym maturzysty wpuścić na minę.
  2. OK, usunę rzutowanie. A możesz wyjaśnić czemu takie są źle widziane? Czym static_cast będzie lepsze?
  3. Właśnie kilka razy już widziałem jak krytykujesz using namespace, ale przed chwilą bingałem sobie ten temat i znalazłem właśnie same zalety tego, a nie umiem dojść czemu to źle, zwłaszcza że Code::Blocks to automatycznie sam wstawia.
  4. Racja, dodam spacje
  5. A co daje zaincludowanie <string>? Bo bez tego działa. Jak usunąłem sstream to też działa :)

t.j. dla osób, które nie wiążą dalszej przyszłości z C++

Nie wiem, może wiążą :) po prostu piszę cykl artykułów na mojego bloga :) i ja z moimi uczniami pracuję w Jawie, ale wolę wrzucić też kod w C++ i Pythonie, żeby był komplet języków maturalnych.

#include <iostream>
using namespace std;
int main()
{
    int liczba = 1234567890;
	string napis = to_string(liczba);
    int suma = 0;
    int ileCyfr = napis.length();
    for (int i = 0; i < ileCyfr; i++) {
			char znak = napis[i];
			int cyfra = znak - '0';
			suma = suma + cyfra;
		}
    cout << "Suma wszystkich cyfr to: " << suma<< endl;
    return 0;
}
1
  1. Nie wiem. Ale C++11 został wprowadzony 9 lat temu, więc zakładam, że tak.
  2. rzutowanie w stylu C jest narzędziem do wszystkiego, niepozwalającym na dokładną kontrolę tego co robisz - jeśli się pomylisz to możesz zrobić znacznie mniej bezpieczny cast, albo jakiś kompletnie błędny i kompilator nie ostrzeże - bo użyłeś opcji atomowej. static_cast pozwala tylko na "sensowne" casty, tj nie psujące systemu typów. Poza tym jest jeszcze const_cast - pozwalający na zdjęcie const, oraz reinterpret_cast - pozwalający na prawie dowolną reinterpretację danych. C-cast to kombinacja wszystkich trzech, a Ty tu chcesz zrobić tylko ten bezpieczny i sensowny. Tylko, że nawet static_cast jest tu zbędny, bo to wyrażenie jest intem, a nawet gdyby nie było, to konwersja do większego typu może odbyć się niejawnie.
  3. https://stackoverflow.com/q/1452721/2456565 - to zła praktyka dla jakichkolwiek projektów ponad 50 linii w jednym pliku. Nie powinno się jej uczyć w ogóle nowicjuszy.
  4. u Ciebie działa, na innym kompilatorze nie musi. Każdy nagłówek standardowy może inkludować inne (tu tak się dzieje dla <iostream>), ale nie musi (poza kilkoma przypadkami, gdzie jest to explicite wymuszone).
0
kq napisał(a):
  1. https://stackoverflow.com/q/1452721/2456565 - to zła praktyka dla jakichkolwiek projektów ponad 50 linii w jednym pliku. Nie powinno się jej uczyć w ogóle nowicjuszy.

A dlaczego Code::Blocks ma to domyślnie ustawione?

0

To by trzeba pytać autorów Code::Blocksa. IMO to absolutnie zły default.

0

Formatowanie to bym zostawił IDE albo innemu narzędziu. Przy instalacji Clang oprócz kompilatora C++ mamy narzędzie clang-format, a używamy go tak:

  • clang-format --dump-config -style=microsoft > .clang-format - robimy zrzut configa do pliku
  • modyfikujemy .clang-config wedle własnych potrzeb, niektórzy plik ten dodają do również do repozytorium
  • clang-format -i main.cpp formatuje kod w pliku, bez -i sformatowany kod wyświetlany jest na standardowym wyjściu

W Vim :map <F8> :%!clang-format<CR> przypisuje formatowanie kodu do klawisza F8, do VSCode jest rozszerzenie Clang-Format, które pozwala włączyć automatyczne formatowanie przed zapisem. CodeBlocks chyba za bardzo jest zintegrowany z AStyle, żeby to przestawić.

0

Kod można uprościć, usuwając zbędne zmienne i używając stylu C++ 11 ( auto , const_cast , range for )

#include <iostream>

int main()
{
    auto napis { std::to_string(1234567890) };
    auto suma {0};

    for( const auto& znak : napis )
    {
        suma += static_cast<int>( znak - '0' );
    }

    std::cout << "Suma wszystkich cyfr to: " << suma << std::endl;

    return 0;
}

Można jeszcze bardziej uprościć kod, sięgając do komponentów biblioteki STL ( accumulate ).

#include <iostream>
#include <numeric>

int main()
{
    auto napis { std::to_string(5528551) };
    std::cout << "Suma wszystkich cyfr to: " << std::accumulate(napis.cbegin(),napis.cend(),-48*napis.size()) << std::endl;

    return 0;
}
0
TomaszLiMoon napisał(a):

Kod można uprościć, usuwając zbędne zmienne

Wiem, ale specjalnie rozbijam na etapy, o czym będzie w artykule. Żeby każdy etap zrobić osobno i omówić osobno.

Można jeszcze bardziej uprościć kod, sięgając do komponentów biblioteki STL ( accumulate ).

Nie, dlatego że zadaniem nie jest wykonanie sumy, a stworzenie szkieletu pod różne zadania maturalne operujące na pojedynczych cyfrach liczby. Trzeba umieć się dobrać do dowolnych cyfr liczby, a nie dokonać sumy jako takiej, suma tam jest tylko jako przykład, żeby sprawdzić czy metoda działa i na jakimś jednym przykładzie ją omówić.

Zresztą, w 2 części artykułu będzie wyłuskiwanie cyfr wzorem matematycznym.

1

Alternatywa dla to_string to to_chars: Konwersje int na string i string na int

0

może się wtrącę ?
Mam jedno pytanie do autora posta ?

Czy chcesz pokazać maturzystom na czym W RZECZYWISTOŚCI polega konwersja liczby na string i odwrotnie aby zrozumieli ideę SKĄD taka konwersja się wzięła i jak to działa ?

Jeżeli tak, to czy nie lepiej byłoby to pokazać na przykładzie kodu działającego na tablicy ASCII jak przebiega konwersja ?

Znaki które widzimy na ekranie monitora to tylko reprezentacja graficzna, natomiast to co dzieje się "pod maską" to już jest żonglowanie kodami ASCII.

Czy o taką ideę chodzi ? Bo wydaje mi się, że na przykładzie ASCII taki artykuł miałby większą wartość merytoryczną i każdy by zrozumiał to, co dzieje się "pod maską". U ciebie w kodzie tego nie widać - "działa i już" ale co tam tak naprawdę się dzieje, to nowicjusz już tego się nie dowie...

3

Strzelam że to art nakierowany na rozwiązanie zadania na maturze, a więc pokazanie wygodnych i prostych w użyciu narzędzi biblioteki standardowej, a nie detali implementacyjnych. Szczególnie, że ASCII nie jest gwarantowane.

1

Doczytałem że przy okazji skracamy ten kod, więc moja propozycja:

#include <iostream>
#include <numeric>

int main() {
    int liczba = 5528551;
    auto napis{std::to_string(liczba)};
    int suma = [napis](int r) { for (char c:napis) r += c - '0'; return r;}(0);
    std::cout << "Suma wszystkich cyfr to: " << suma << std::endl;

    return 0;
}

https://ideone.com/ZvlXzh

0
zkubinski napisał(a):

Czy chcesz pokazać maturzystom na czym W RZECZYWISTOŚCI polega konwersja liczby na string i odwrotnie aby zrozumieli ideę SKĄD taka konwersja się wzięła i jak to działa ?

Nie. Chcę pokazać szkielet algorytmu wyodrębniania cyfr z liczby.
Na razie artykuł wygląda tak: https://lobo.guru/?p=1239&preview=1&_ppp=3ff2017542
To jest publicznie dostępny draft. Więc możecie popatrzeć czy nie ma jakiś totalnych błędów, aczkolwiek drobne poprawki jeszcze wiem, że pewnie są konieczne, bi jest 2 w nocy za chwilę, więc muszę rano to przeczytać na spokojnie całe. Na razie jest napisane :)

@kq w tym drafcie dałem jeszcze inne kody C++, jak masz ochotę, to zobacz czy nie ma tam błędów w podejściu.

2

Code::Blocks nie jest konieczne i bez tego program działa

To jest zależne od kompilatora (i biblioteki standardowej), a nie IDE (Code::Blocks na OSX, Windowsie i Linuksie będzie na pewno korzystać z różnych kompilatorów i różnych ich wersji). Uważam że to dość niegroźny (w kontekście maturalnym) błąd merytoryczny

zmienna typu char to tak naprawdę jest po prostu liczba zawierająca kod ASCII przedstawianego znaku

Zdanie od wielkiej litery :​P C++ nie gwarantuje użycia ASCII. Owszem, chyba wszędzie się z tym spotkasz (może poza IBM utrzymującym EBCDIC na mainframe'ach), ale formalnie rzecz biorąc - gwarancji nie ma. Natomiast C++ gwarantuje, że wartości od '0' do '9' będą kolejnymi wartościami liczbowymi, dlatego zawsze możesz uzyskać wartość cyfry poprzez odjęcie wartości znaku zero.

Wcześniej też ktoś powiedział, że mogłeś się pokusić o range for - też tak uważam, ale w tym przypadku to jeszcze za bardzo nie boli. Jest tak natomiast w C++ z gwiazdką:

for (std::list<int>::iterator it = cyfryLiczbowo.begin(); it != cyfryLiczbowo.end(); it++)

Tego kodu nie przepuściłbym przez code review:

  1. używasz std::list nadaremno. Zasada jest prosta: używaj std::vector, chyba że masz twarde dowody na to, że std::list jest lepsze. Spotkałem się z takim przypadkiem raz w życiu, było to w zadaniu na Advent of Code 2019 (taki konkurs)
  2. jeśli już chcesz używać iteratorów zamiast ranged for - koniecznie użyj auto zamiast precyzować typ iteratora.
  3. nie modyfikujesz nic, użyj cbegin() i cend()

warto zauważyć, że jest tam operator *, gdyż samo it jako takie jest wskaźnikiem na element i operator * pozwoli wyłuskać wskazywany w pamięci element.

it nie jest wskaźnikiem, jest iteratorem, czyli klasą spełniającą kontrakt wskaźnika, ale implementacyjnie absolutnie nim nie jest (nie musi być). Ma po prostu przeładowany operator* (ciekawostka: dla klas takich jak std::array czy std::vector iterator faktycznie może być po prostu wskaźnikiem - ale nie musi)

0
kq napisał(a):

warto zauważyć, że jest tam operator *, gdyż samo it jako takie jest wskaźnikiem na element i operator * pozwoli wyłuskać wskazywany w pamięci element.

it nie jest wskaźnikiem, jest iteratorem, czyli klasą spełniającą kontrakt wskaźnika, ale implementacyjnie absolutnie nim nie jest (nie musi być). Ma po prostu przeładowany operator* (ciekawostka: dla klas takich jak std::array czy std::vector iterator faktycznie może być po prostu wskaźnikiem - ale nie musi)

Pisałem to o 1 w nocy i czułem, że to jest do bani. Tylko nie wiem jak to opisać, żeby nie było do bani i żeby osoba początkująca miała szansę zrozumieć. Twoje wyjaśnienie ja rozumiem jak przez mgłę, a co dopiero newbe :( Dlatego ja uważam, że C++ nie nadaje się na język maturalny. Niestety bardzo duży odsetek w ten język idzie, jest masa materiałów itp. Teraz to się zmienia pomału, bo od paru lat jest Python dopuszczony ci pomału zaczyna on się wkradać w łaski materiałów maturalnych.

Niestety ta hardcorowa skomplikowaność C++ sprawia, że całkiem sporo maturalnych materiałów jest potem właśnie C-like, żeby nie wchodzić w te tematy. No nie wiem, po prostu nie wiem jak opisać tą część z iteratorem, skoro ja ją czuję jedynie powierzchownie, a wiem, że ludzie których uczę, są słabsi ode mnie, bo nieraz dużo mniej skomplikowanych rzeczy nie łapią.

W przestrzeni szkolnej nie ma za bardzo miejsca na klasy, obiekty, wskaźniki, a co dopiero na „klasę spełniającą kontrakt wskaźnika z przeładowanym operatorem” Ja miałem trochę na studiach tematyki związanej z operatorami i ich przeładowaniami, więc to mi pobieżnie gdzieś się kolibie w głowie, ale uczeń szkolny w żadnym momencie nie ma szans do tego dotrzeć :(

0
kq napisał(a):
for (std::list<int>::iterator it = cyfryLiczbowo.begin(); it != cyfryLiczbowo.end(); it++)

Tego kodu nie przepuściłbym przez code review:

  1. używasz std::list nadaremno. Zasada jest prosta: używaj std::vector, chyba że masz twarde dowody na to, że std::list jest lepsze. Spotkałem się z takim przypadkiem raz w życiu, było to w zadaniu na Advent of Code 2019 (taki konkurs)

A możesz mnie poduczyć czemu tak jest gorzej? Bo np. Pythonowcy dla odmiany kochają listy. Wystarczy, że zamienię słówko list na vector i będzie dobrze? Bo sprawdziłem w kodzie, że działa, ale żeby znów nie było, że coś przeoczyłem, co wynika ze niezdefiniowanego zachowania

  1. jeśli już chcesz używać iteratorów zamiast ranged for - koniecznie użyj auto zamiast precyzować typ iteratora.

A jak by to miało wyglądać? Bo taki zapis znów znalazłem na stacoverflow.
Tak by to miało być?

for (auto it = cyfryLiczbowo.cbegin(); it != cyfryLiczbowo.cend(); it++)

Pozmieniałem w artykule, możesz rzucić okiem?

1

Tylko nie wiem jak to opisać, żeby nie było do bani i żeby osoba początkująca miała szansę zrozumieć.

Napisz, że zachowuje się jak wskaźnik, a nie że nim jest.

A możesz mnie poduczyć czemu tak jest gorzej? Bo np. Pythonowcy dla odmiany kochają listy. Wystarczy, że zamienię słówko list na vector i będzie dobrze?

Będzie dobrze. list w C++ to linked lista, a w Pythonie to struktura o czasie dostępu do elementu O(1) - podobnie do vectora. Python linked listy nawet nie dostarcza ze swoją biblioteką standardową. Niestety problematyczne jest tutaj nazewnictwo, różne w różnych językach. Nazwa vector też mi się za bardzo nie podoba, ale co zrobić.

for (auto it = cyfryLiczbowo.cbegin(); it != cyfryLiczbowo.cend(); it++)

To wygląda dobrze, choć zawsze możesz for(char c : cyfryLicznowo)

Na art rzucę okiem później.

2

Żeby wyjaśnić rozbieżność, porównanie na przykładzie Javy:
Java: ArrayList = C++ std::vector = Python list
Java: LinkedList = C++ std::list = w Pythonie nawet nie ma tego

0

Od iteratorów w zasadzie nie da się uciec bo one są również dostępne w pythonie i warto by było poznać co to w ogóle jest, bo często się o nich mówi i stosuje

Tak w skrócie: "Wzorzec projektowy iteratora" to jest interfejs opisujący pomost łączący algorytm z kontenerem. Algorytm, czyli jakaś funkcja która dobiera się do poszczególnych elementów kontenera nie robi tego bezpośrednio, tylko przez pośrednika jakim jest obiekt iteratora. Bez niego trzeba by było napisać osobny algorytm foreach dla tablicy i listy, bo w tym pierwszym posługujemy się indeksem zwiększanym o 1 a w drugim trzeba przesuwać wskaźnik next = next->next. Jak algorytm pobiera elementy poprzez iterator to kontenerem może być cokolwiek, vector, lista, drzewo, etc. pod warunkiem że iterator udostępnia operacje przesunięcia o 1 "++it" oraz wyłuskania "*it" bo tak jest zdefiniowany interfejs i takiego zachowania spodziewa się np. algorytm foreach.

Gdybyś chciał przeglądać kontener w inny sposób np. 2 indeksy do przodu, 1 do tyłu to musiałbyś zmodyfikować funkcję algorytmu. Albo implementując własną wersję iteratora, czyli przeciążając operator++ a w nim dowolny sposób operacji na indeksie. Inny przykład: tworzysz iterator na podstawie dwóch tablic, tak że element zwracany poprzez *it pobierany jest na przemian z pierwszej i drugiej tablicy, operacja ++it wewnętrznie przełącza np. na zmianę tablice. Kolejny przykład: iterator zapętlania tablicy, który powiela tablicę dowolną ilość razy nawet nieskończoną.

Być może jakaś prosta prezentacja jak przeglądać kontener w dziwny sposób nie zmieniając funkcji algorytmu pomogła by uzmysłowić na czym polega koncepcja iteratora.

0
enedil napisał(a):

Żeby wyjaśnić rozbieżność, porównanie na przykładzie Javy:
Java: ArrayList = C++ std::vector = Python list
Java: LinkedList = C++ std::list = w Pythonie nawet nie ma tego

A mógłbyś to jakoś rozwinąć, jak to pod spodem działa? Bo zawsze używałem w Jawie ArrayList, ale w zasadzie to nie wiem jak to w środku jest realizowane. Bo vector w C++ to o ile dobrze kumam, jakaś nakładka na tablicę. Ale tablica nie jest rozciągliwa. Więc myślałem, że lista to jest powiedzmy coś w rodzaju takiej struktury, w której każdy element trzyma wskaźnik na następny. Dzięki czemu nie są one po kolei w pamięci, ale całościowo są związane jeden z drugim określoną kolejnością.

2

To o czym myślisz to są właśnie std::list, czy LinkedList. Element trzyma dowiązanie do kolejnego.

Z kolei, std::vector oraz ArrayList przechowują elementy obok siebie w pamięci. Jak sobie radzą ze zmiennym rozmiarem?
std::vector mógłby się składać z trzech elementów:

  1. wielkość wektora (zliczająca elementy, do których wolno się odnosić)
  2. wielkość zarezerwowanej pamięci
  3. wskaźnik na dane
    Nie jest to dokładnie zawsze realizowane, ale stanowi dosyć dobre przybliżenie.

Czym jest ten punkt 2? Otóż zawsze trzymasz w pamięci "tablicę", z której używasz tylko część. Jak ktoś chce dodać nowy element, to jeśli wciąż mamy miejsce, to wkładamy ten element do kolejnej komórki tablicy po ostatnim i aktualizujemy informacje o liczbie trzymanych elementów. Jeśli przypadkiem już się miejsce skończyło, prosimy o nowe miejsce w pamięci, zazwyczaj dwa razy większe niż poprzednio (w ten sposób gwarantujemy, że ilość straconej pamięci to maksymalnie połowa (pomijając sytuacje gdy później taki wektor staje się mniejszy)). Jak już dostaniemy nowy kawałek, wszystkie elementy ze starego kawałka pamięci są kopiowane do nowego, a następnie pozbywamy się starego kawałka. Przez tę heurystykę podwajania zarezerwowanej pamięci, gwarantujemy, że przy ciągłym wstawianiu, narzut czasowy który wynika z tego jest logarytmiczny, a więc dostatecznie niewielki.

0
enedil napisał(a):

To o czym myślisz to są właśnie std::list, czy LinkedList. Element trzyma dowiązanie do kolejnego.

Z kolei, std::vector oraz ArrayList przechowują elementy obok siebie w pamięci. Jak sobie radzą ze zmiennym rozmiarem?
std::vector mógłby się składać z trzech elementów:

  1. wielkość wektora (zliczająca elementy, do których wolno się odnosić)
  2. wielkość zarezerwowanej pamięci
  3. wskaźnik na dane
    Nie jest to dokładnie zawsze realizowane, ale stanowi dosyć dobre przybliżenie.

Czym jest ten punkt 2? Otóż zawsze trzymasz w pamięci "tablicę", z której używasz tylko część. Jak ktoś chce dodać nowy element, to jeśli wciąż mamy miejsce, to wkładamy ten element do kolejnej komórki tablicy po ostatnim i aktualizujemy informacje o liczbie trzymanych elementów. Jeśli przypadkiem już się miejsce skończyło, prosimy o nowe miejsce w pamięci, zazwyczaj dwa razy większe niż poprzednio (w ten sposób gwarantujemy, że ilość straconej pamięci to maksymalnie połowa (pomijając sytuacje gdy później taki wektor staje się mniejszy)). Jak już dostaniemy nowy kawałek, wszystkie elementy ze starego kawałka pamięci są kopiowane do nowego, a następnie pozbywamy się starego kawałka. Przez tę heurystykę podwajania zarezerwowanej pamięci, gwarantujemy, że przy ciągłym wstawianiu, narzut czasowy który wynika z tego jest logarytmiczny, a więc dostatecznie niewielki.

No tak, tylko że zjadasz nadmiernie pamięci, bo np. przy 10 tysiącach elementów, trzymasz już 20 tysięcy miejsca.
Do tego każde podwajanie kosztuje, bo pamięć jest kopiowana.
Poza tym, jeżeli to jest tablica, to wymaga ciągłego obszaru pamięci, więc przy wspomnianych 20 tysiącach elementów masz już 20 tysięcy zajętego ciągłego miejsca.

Czy nie lepiej mieć listę, w której właśnie każdy nowy element podpina się pod poprzedni? Wtedy zajętość pamięci jest taka sama jak rozmiar danych i nie ma narzutów z kopiowaniem. A do tego pamięć może być poszatkowana, bo każdy nowy element się dopnie z miejsca, w którym akurat leży.

3

Nie, zdecydowanie nie lepiej - serio, jest na to pełno benchmarków. Dlatego pisałem, ze listy używasz wyłącznie gdy masz twardy dowód (benchmark na zoptymalizowanym kodzie na danych zbliżonych do docelowych, na docelowej architekturze), że jest lepsza. Bo prawie nigdy nie jest lepsza, poza naprawdę akademickimi dywagacjami.

Co do vectora - w C++ masz funkcje reserve() i shrink_to_fit() które pozwalają uniknąć tego typu problemów, ale osobiście nigdy nie było to dla mnie rzeczywistym problemme.

3

Jeszcze dodam, że z punktu widzenia alokatora, prościej mieć jeden obszar długości 20000 niż 5000 obszarów długości 4 do zarządzania. Nie wspominając o

  1. braku swobodnego dostępu do elementów (ile czasu zajmie dostanie się do elementu nr 3000 w std::liście?)
  2. braku lokalności danych (jeśli czytasz z pamięci która jest w różnych miejscach, to cache procesora jest bez przerwy opróżniane)

A co do użycia pamięci, to miej na uwadze, że wskaźniki też swoje kosztują. Jeśli masz mieć std::list<int>, to zajmujesz automatycznie 5 tyle pamięci co tablica intów, bo int ma 4 bajty, a dwa wskaźniki, na element poprzedni i następny zajmują każdy po 8.

0
kq napisał(a):

[o namespace std]
To by trzeba pytać autorów Code::Blocksa. IMO to absolutnie zły default.

Właśnie czytam książkę do C++ Grębosza, która jest chwalona od lat i tam też jest namespace std. W sumie skoro w języku to się pojawiło, to i autorzy języka chyba nie są temu jakoś mocno przeciwni.

Tak sobie rozkminiam, jeśli błędnie, popraw mnie proszę, że dla uczących się języka może to być pomocne, a jeśli ktoś będzie pisał coś profesjonalnego i nie ogarnie ewentualnych zagrożeń, to w sumie nie powinien chyba pisać niczego profesjonalnego? Bo np. ja tych zagrożeń nie rozumiem i dlatego niczego profesjonalnego nie piszę :)

0

Grębosza też nie polecamy - przynajmniej Symfonii, Opus Magnum jeszcze nie miałem czasu ruszyć, ale po spisie treści też wydaje się uczyć w ten sam błędny sposób.

2

Pytania nie do mnie, ale nie znam się więc się wypowiem... ;-)

heillos napisał(a):
kq napisał(a):

[o namespace std]
To by trzeba pytać autorów Code::Blocksa. IMO to absolutnie zły default.

Właśnie czytam książkę do C++ Grębosza, która jest chwalona od lat i tam też jest namespace std. W sumie skoro w języku to się pojawiło, to i autorzy języka chyba nie są temu jakoś mocno przeciwni.

Ostatnio jak się w tym rozeznawałem to:

  1. using namespace std było zabronione w nagłówkach (*.h)
  2. dozwolone w plikach źródłowych (*.cpp)

Możliwe że moduły zmieniają tę zasadę jakoś.

Tak sobie rozkminiam, jeśli błędnie, popraw mnie proszę, że dla uczących się języka może to być pomocne, a jeśli ktoś będzie pisał coś profesjonalnego i nie ogarnie ewentualnych zagrożeń, to w sumie nie powinien chyba pisać niczego profesjonalnego? Bo np. ja tych zagrożeń nie rozumiem i dlatego niczego profesjonalnego nie piszę :)

Programistą można być przy braku znajomości zagrożeń i języka. Ważne żebyś znał domenę. Smutno się patrzy na taki kod, ale przynajmniej działa.
Gorzej jak ogarniasz super język, ale nie wiesz co masz tworzyć.

Natomiast tworzenie kursów wymaga znajomości idiomów, standardów i styli pisania w danym języku (i ogólnie styli programowania).

Wybrałeś C++, które do prowadzenia kursów jest jednym z najtrudniejszych języków, ponieważ:

  • ma kilka dopuszczalnych paradygmatów (OOP, proceduralny, para-funkcyjny, STL)
  • ma kilka różnych standardów (C z klasami, C++98, C++11, c++2x...)
  • ma kilka sposobów na robienie tego samego

Dlatego każdy na tym forum może Ci inaczej odpowiedzieć w zależności od bagażu doświadczeń.

0

Grębosza też nie polecamy - przynajmniej Symfonii

Ta książka ma już 27 lat (pierwsze wydanie w 1993), więc trudno jest w niej szukać nowości. Czytając ją, można poczuć klimat lat z początków programowania. Jednakże w swoim czasie była to całkiem dobra pozycja, która w przystępny i łatwy sposób tłumaczyła podstawy C++.

1 użytkowników online, w tym zalogowanych: 0, gości: 1