Forum Coders' city Strona Główna Coders' city
Nasza pasja to programowanie!
 

 PomocPomoc   SzukajSzukaj   UżytkownicyUżytkownicy   GrupyGrupy  RejestracjaRejestracja 
Archiwum starego forum + teoria    RSS & Panel/SideBar
 ProfilProfil   Zaloguj się, by sprawdzić wiadomościZaloguj się, by sprawdzić wiadomości   ZalogujZaloguj 

Potrzebuję szybkiej odpowiedzi na moje pytanie... Zasady

Cz?sto udzielane odpowiedzi

Idź do strony 1, 2  Następny

 
Odpowiedz do tematu    Forum Coders' city Strona Główna -> C i C++
Zobacz poprzedni temat :: Zobacz następny temat  
Autor Wiadomość
marcin_an



Dołączył: 26 Maj 2005
Posty: 18822

PostWysłany: Sro Gru 24, 2008 11:51 pm  OP    Temat postu: Cz?sto udzielane odpowiedzi Odpowiedz z cytatem Pisownia

Kiedy? mikmas stworzy? w?tek zatytu?owany "nie!", w którym podawa? informacje, co powinno by? opisane w po?cie, ?eby nie trzeba by?o wzywa? wró?ki. Robi? w?a?nie podobn? rzecz, ale w celu u?atwienia sobie odpowiedzi. S? odpowiedzi, których udzielam cz??ciej ni? innych. Nie ma wtedy czasu na opisanie problemu dok?adnie. Czasami te? celowo pomijam pewne kwestie lub przedstawiam je w troch? innym ?wietle. S?dz?, ?e w?tek, w którym mo?na rozwin?c te odpowiedzi mo?e si? przyda?. Oto i on.

Zasady:
  1. W?tek b?dzie przyklejony, ?eby nie spada?.
  2. Ka?dy mo?e tuaj dopisywa? swoje odpowiedzi, je?li uzna, ?e udziela ich na tyle cz?sto, ?e opisanie ich w oddzielnym, wi?kszym po?cie mo?e by? potrzebne.
  3. To nie jest FAQ (przynajmniej nie wprost)! Chc?, by trafia?y tutaj tylko odpowiedzi, które faktycznie si? powtarzaj? (niezale?nie od ilo?ci pyta?) i których pog??bienie mo?e by? potrzebne, a mo?liwo?? odes?ania do takiego wyja?nienia b?dzie przydatna.
  4. To nie jest oficjalne CC-FAQ. Jest to co? w rodzaju magazynu tekstów do dawania do nich odno?ników. Tym samym ka?dy mo?e sobie tutaj umie?ci? "paczk?" wg w?asnego uznania i jej zawarto?? nie b?dzie weryfikowana w tym w?tku pod k?tem merytorycznym. Mo?esz napisa?, ?e S?o?ce kr??y wokó? Ziemi* i je?li tak napiszesz, to tak b?dzie w twoim po?cie. Oczywi?cie poza tym posty s? moderowane, wi?c nie oznacza to, ?e mo?na wstawi? go?? panienk? i post b?dzie wisia? na forum.
  5. ?adnych pyta? i dyskusji w tym w?tku. Ka?de pytanie lub prób? prowadzenia rozmowy usun? bez ostrze?enia. Mo?na w tym celu za?o?y? oddzielny w?tek i tam dyskutowa?. Tutaj umieszczamy tylko rzeczy do robienia do nich linków.
  6. Poniewa? osoby spoza zespo?u moderatorów i administracji nie maj? mo?liwo?ci usuni?cia swoich postów, mo?na da? zna? komu? z tych zespo?ów, by to zrobi?. Jest to do zrobienia poprzez prywatn? wiadomo?? lub dopisanie posta z tak? pro?b?. Prosz? jednak o to, by pro?by by?y wyra?ne i dobrze opisywa?y, co ma by? usuni?te. Moderator mo?e odmówi? usuni?cia wpisu, je?li uzna, ?e naruszy?oby to tre?? postów do niego si? odnosz?cych.
  7. Jeden post - jednen temat. Nie publikujemy tutaj artyku?ów o wszystkim i niczym. Poruszany temat -> odpowied?/wyja?nienie.
  8. Tym samym dozwolone jest umieszczanie kilku postów jeden pod drugim i je?eli s? to oddzielne tematy (tj. nie s? to dopiski "bo zapomnia?em napisa?"), to moderatorzy nie b?d? zwracali na to uwagi.
  9. Nie jest to miejsce na publikacj? swoich artyku?ów, rozpraw etc. To mo?na zrobi? w serwisach do tego przeznaczonych.
  10. Je?eli moderator stwierdzi, ?e wpis nie jest wykorzystywany lub te? u?ytkownik wcale nie umie?ci? w nim niczego, na co musia? cz?sto odpowiada?, post mo?e zosta? usuni?ty.
  11. Go?cie nie mog? si? tutaj wypowiada?. Przepraszam, kwestie organizacyjne ;).
____
* Co akurat jest prawd?...

_________________
Nieaktywny od 2017-04-01


Ostatnio zmieniony przez marcin_an dnia Czw Gru 25, 2008 12:02 am, w całości zmieniany 1 raz
Powrót do góry
Zobacz profil autora Wyślij prywatną wiadomość
marcin_an



Dołączył: 26 Maj 2005
Posty: 18822

PostWysłany: Sro Gru 24, 2008 11:51 pm  OP    Temat postu: [] Zwracanie warto?ci z main Odpowiedz z cytatem Pisownia

Zwracanie warto?ci z main
Tagi: C++
Q
Czy main musi zwraca? warto??? Czy prawid?owy jest kod:
Kod:
int main() {}


A
Z punktu widzenia j?zyka: tak, prawid?owy. Tak w sensie sk?adni, jak i zwracanych warto?ci. C++ wymaga, by w przypadku braku istnienia jawnego zwracania warto?ci z main zosta?a zwrócona warto?? 0. Powy?szy kod jest zatem równowa?ny:
Kod:
int main()
{
    return 0;
}

W czym wi?c problem?
  • main nie zawsze b?dzie g?ówn? funkcj? programu lub te? to, co zdefiniujemy jako main, niekoniecznie musi by? widziane przez kompiltor jako main. Przyk?ady: WinMain w Windowsie lub SDL_main podstawiany zamiast main w SDL.
  • Zasada o automatycznym zwróceniu 0 dzia?a tylko, je?li w main nie ma ?adnego jawnego zwrócenia.
    Kod:
    int main()
    {
        if (warunek)
        {
            return 1;
        }
    }

    Powy?szy kod nie zwróci automatycznie 0 w przypadku, gdy warunek da false, poniewa? gdzie? w kodzie main ju? co? jest zwracane (nie ma znaczenia, czy jest to osi?galne, czy nie). Problem? Wbrew pozorom przy wielu edycjach funkcji okazuje si?, ?e nietrudno zgubi? to return na ko?cu, je?li od pocz?tku go tam nie by?o (nawet je?li teraz wydaje si? to niedorzeczne).
  • Pocz?tkuj?cy: jeden z cz?stych b??dów osób zaczynaj?cych przygod? z programowaniem jest nie?wiadome pomijanie warto?ci zwracanych przez funkcj? np. przy wyst?pieniu sytuacji alternatywnych. Uczenie, ?e mo?na od tak sobie co? pomin??, chyba nie wp?ywa pozytywnie na zmian? tego - lepiej niech ucz?cy si? my?li, co ma zwróci? i niech to zwraca.


--- edit 27.12.2009 22:20 ---
Pojawi?y si? pewne niejasno?ci, zatem wyja?niam. Interpretacja z punktu 2 jest jedn? z dwóch interpretacji. Druga mówi, ?e automatyczne zwrócenie zadzia?a zawsze. Problem z ni? polega na tym, ?e przy takim uj?ciu warunek "without encountering a return statement" jest co najmniej g?upi. Mo?liwe, ?e jest to defekt standardu, ale narazie nie by? jako taki zg?aszany, w najnowszym szkicu nadal wyst?puje, a sama interpretacja jest bezpieczniejsza - w t? stron? nie zepsuje si? ?adnego programu, a w przeciwn? ju? mo?na. Z tych powodów oraz dlatego, ?e cz??ciej si? z ni? spotyka?em, podaj? t?.

Bo profesor tak wymaga: je?li profesor b?dzie wymaga?, ?eby podczas pisania kodu chodzi? po ?cianach, to student ma obowi?zek chodzi? po ?cianach, bo inaczej nie zaliczy. Podane informacje dotycz? normalnych sytuacji. Profesorowi pisz jak profesor chce.

_________________
Nieaktywny od 2017-04-01


Ostatnio zmieniony przez marcin_an dnia Nie Gru 27, 2009 10:26 pm, w całości zmieniany 3 razy
Powrót do góry
Zobacz profil autora Wyślij prywatną wiadomość
marcin_an



Dołączył: 26 Maj 2005
Posty: 18822

PostWysłany: Sro Gru 24, 2008 11:53 pm  OP    Temat postu: Wypychanie danych ze strumieni Odpowiedz z cytatem Pisownia

Wypychanie danych ze strumieni
Tagi: C++
Q
Co robi std::endl i dlaczego jego stosowanie jest z?e?
A
std::endl nie jest z?y i jego stosowanie równie? z?e nie jest. Jest wr?cz bardzo przydatne. Jest jednak jeden istotny warunek: jest stosowane do tego, do czego s?u?y. Dosta?e? informacj?, ?e niepotrzebnie wypychasz dane ze strumienia lub w twoim programie pojawiaj? si? konstrukcje podobne do tych?
Kod:
cout << "ala ma kota" << endl;
Kod:
cout << "x = " << x << endl;
cout << endl << endl << endl;
Je?eli tak, to prawdopodobnie pad?e? ofiar? nauczania, ?e endl s?u?y do robienia znaków nowej linii w "stylu C++" (czymkolwiek to jest...). Nie b?d? si? tutaj rozpisywa? o ?ród?ach takiego przekonania, ale jedno mog? powiedzie? natychmiast: jest to bzdura. Nie wierzysz? Zajrzyj do dobrej dokumentacji i sprawd?, jakie jest znaczenie tego manipulatora. Jest nim wypychanie danych ze strumienia, podobnie jak manipulatora std::flush. Ró?nica pomi?dzy nimi polega na tym, ?e std::endl dodatkowo wyprowadza przed wypchni?ciem danych znak nowej linii. Co powoduje wypchni?cie danych ze strumienia? 1001 rzeczy w zale?no?ci od rodzaju strumienia - generalnie zapewnia, ?e dane b?d?ce w wewn?trznych buforach implementacji zostan? w tym w?a?nie momencie wypchni?te z nich do miejsca, do którego prowadzi strumie?. Np. do pliku na dysku, na terminal lub do sieci. Co robi w przypadku cout? Teoretycznie zapewnia, ?e... <blablabla>. Szczerze? W praktyce absolutnie nic. Na systemach uniksowych znak nowej linii i tak powoduje opró?nienie tych buforów, na Windowsie wyj?cie jest niebuforowane. Mo?e istniej? inne implementacje, dla których to dzia?a - nie mog? zaprzeczy?. Ch?tnie si? dowiem jakie.
Zatem stosujesz konstrukcj?, która:
  1. Jest u?yta niezgodnie ze swoim przeznaczeniem i wykonuje inn? czynno??, ni? ta, któr? chcesz uzyska?.
  2. Wyd?u?a i komplikuje niepotrzebnie kod.
  3. Prawdopodobnie nic nie robi.
Równowa?ne kody b?d?ce nie mniej w "stylu C++":
Kod:
cout << "Hello world\n";
Kod:
cout << "x = " << x << "\n\n\n\n";
Je?li chcesz co?, co bardziej pasuje do czego? daj?cego si? nazwa? stylem C++, to taki kod b?dzie tego lepszym przyk?adem:
Kod:
cout << format("X = %1%\n") % x;
Tak, co? jak printf, ale daj?ce si? u?ywa?. Dost?pne w pakiecie Boost.
Kiedy u?ywa? endl? Wtedy, kiedy jest potrzebne ;). Mo?esz u?y? prostej zasady: je?eli napisa?by? jeden z poni?szych, wykonuj?cych w zasadzie to samo, kodów...
Kod:
output.put('\n').flush();
output << '\n' << flush;
..., to nale?y u?y? endl. W innych przypadkach nie nale?y.
Dlaczego widzia?e? te endl w 9 na 10 ksi??ek, dlaczego u?ywa? ich sam Stroustrup i wiele innych znanych w ?rodowisku C++ osób etc.? Moja teoria jest taka: kto? kiedy? co? takiego naklepa? w ksi??ce (mo?e nawet faktycznie mia? ku temu powód). Osoby ucz?ce si? nie maj? zwyczaju stara? si? dog??bnie zrozumie? tematu, wi?c tego typu konstrukcje (np. static_const w srand+time) maj? w swej naturze rozprzestrzenianie si? gorzej ni? wirusy komputerowe przez powtarzanie zaobserwowanego wzorca. U?ycie takiej konstrukcji nie oznacza, ?e kto? nie ma bladego poj?cia o C++. Najprawdopodobniej po prostu nigdy nie zastanawia? si? nad tym, co pisze.
Bo profesor tak wymaga: je?li profesor b?dzie wymaga?, ?eby podczas pisania kodu chodzi? po ?cianach, to student ma obowi?zek chodzi? po ?cianach, bo inaczej nie zaliczy. Podane informacje dotycz? normalnych sytuacji. Profesorowi pisz jak profesor chce.

_________________
Nieaktywny od 2017-04-01


Ostatnio zmieniony przez marcin_an dnia Czw Cze 25, 2009 6:37 am, w całości zmieniany 3 razy
Powrót do góry
Zobacz profil autora Wyślij prywatną wiadomość
marcin_an



Dołączył: 26 Maj 2005
Posty: 18822

PostWysłany: Sro Gru 24, 2008 11:59 pm  OP    Temat postu: Odpowiedz z cytatem Pisownia

Interfejsy konsolowe w C++
Tagi: C++, C

Uwaga: po zamianie IOStreams na stdio, a cin/cout na odpowiednie funkcje stdio, poni?sze jest prawdziwe tak?e dla C.

Q
U?ywam IOStreams. Jak wyczy?ci? konsol?? Jak przenie?? kursor na wybran? pozycj?? Jak pokolorowa? litery? Jak pobiera? klawisze bez naciskania entera? Jak sprawdzi? dane i poprosi? o ponowne ich wprowadzenie? Program mi pomija polecenia.
A
Nijak. Pradopodobnie kto? powiedzia? ci, ?e cin i cout s?u?? do pisania po ekranie i czytania z klawiatury. Nie jest to jednak prawda. IOStreams s?u?y do operowania na strumieniach i jest to ca?kiem dobra biblioteka do budowania aplikacji strumieniowych. Aplikacja strumieniowa to pude?ko z dwoma (lub wi?cej) rurami. Przez jedn? wpada ci?g danych, przed drug? wypada ci?g danych (wi?cej). Koniec. Nie ma miejsca na jak?kolwiek interakcj? z u?ytkownikiem, kolorowe interfejsy i klawiatury/ekrany. C++ nawet nie wie, co to klawiatura: sterownik konsoli, pod który prawdopodobnie zosta? podpi?ty strumie? danych, interpretuje dane z klawiatury i wysy?a je w postaci tekstu do strumienia. Aplikacja strumieniowa tekst ten odbiera. Sam strumie? nie ma zatem ?adnego zwi?zku z klawiatur? b?d? ekranem. Mo?e nawet nie mie? ze sterownikiem konsoli, bo strumienie mo?na zwykle przekierowa? z poziomu systemu (typowe przyk?ady: przekierowanie do pliku lub sieci). Owszem, mo?na zrobi? bardzo prosty interfejs na zasadzie "pytanie-odpowied?". Taki, ?eby wystarczy? do pokazów dzia?ania kodu albo jego debugowania w czasie laboratoriów na studiach. Nie licz jednak na to, ?e zbudujesz cokolwiek wi?cej. Nie dlatego, ?e IoStreams jest z?e, tylko dlatego, ?e to nie jest narz?dzie do robienia tego typu rzeczy. Mo?esz oczywi?cie próbowa? i przy odpowiednim nak?adzie pracy, wspó?pracy sterownika konsoli (sterowanego odpowiednimi kodami) i ew. pomocy funkcji systemowych mo?e nawet cz??? z wymienionych wcze?niej rzeczy uda ci si? uzyska?. B?dzie to jednak próba wkr?cania ?ruby m?otkiem i podobnie si? natrudzisz. Zamiast tego we? po prostu bibliotek? do obs?ugi konsoli, która wi?kszo?? tego za?atwi ci w jednej linijce kodu. Przyk?adem takiej biblioteki s? ró?ne implementacje curses: np. pdcurses pod Windowsa lub ncurses. Je?eli korzystasz curses, to przeczytaj dobrze najpierw manual, ?eby? za chwil? nie pyta?, dlaczego je?li wyprowadzasz co? przez cout, to to potem nagle znika albo jest wyprowadzane nie tam, gdzie ustawi?e? kursor. Wskazówka: dlatego, ?e u?ywasz cout zamiast funkcji z biblioteki. W manualu s? one opisane.
Dlaczego zosta?e? ok?amany? Po raz kolejny nie chc? si? zag??bia? w histori?. W skrócie: dawno, dawno temu ?wiat wygl?da? zupe?nie inaczej, systemy by?y ubo?sze, ich API robione zupe?nie inaczej itd. Sterowanie konsol? by?o realizowane w?a?nie przez wysy?anie danych na strumie?* pomieszane z wywo?aniami funkcji systemowych. Dzisiaj mamy do tego proste biblioteki i nie ma powodu, by robi? dziwaczne konstrukcje, których efekty cz?sto s? zupe?nie inne, ni? ich autor sobie wyobra?a (cz?sto wystarczy troch? inna konfiguracja nawet tego samego systemu). Nie wszyscy nauczaj?cy maj? jednak w zwyczaju aktualizowa? swoj? wiedzi? i nie dociera do nich, ?e informacje sprzed 20 lat mog? by? z lekka nie?wie?e.
Bo profesor tak wymaga: je?li profesor b?dzie wymaga?, ?eby podczas pisania kodu chodzi? po ?cianach, to student ma obowi?zek chodzi? po ?cianach, bo inaczej nie zaliczy. Podane informacje dotycz? normalnych sytuacji. Profesorowi pisz jak profesor chce.

--- edit: uzupe?nienie o uwagi dla C
--- edit: link do posta o aplikacjach strumieniowych
____
* Z technicznego punktu widzenia gdzie? na samym dole nadal cz??? funkcjonalno?ci jest tak realizowana. Jest to jednak poziom daleko poza tym, co le?y w polu zainteresowa? osoby, która chcia?aby po prostu napisa? u?yteczn? aplikacj?.

_________________
Nieaktywny od 2017-04-01


Ostatnio zmieniony przez marcin_an dnia Nie Lut 20, 2011 9:16 am, w całości zmieniany 2 razy
Powrót do góry
Zobacz profil autora Wyślij prywatną wiadomość
hobson



Dołączył: 13 Sie 2007
Posty: 439
Skąd: Trójmiasto

PostWysłany: Pią Mar 06, 2009 9:24 pm      Temat postu: Znikaj?ca konsola Odpowiedz z cytatem Pisownia

Q: Napisa?em swój pierwszy program typu "Hello World", ale on nie dzia?a! Jedyne, co widz?, to migaj?ce przez chwil? czarne okienko konsoli. Co jest ?le?

Najprawdopodobniej, nic nie jest ?le. Po prostu twój program wykonuje si? tak szybko, ?e zanim zd??ysz cokolwiek zobaczy? na konsoli, funkcja main ko?czy swe dzia?anie, a konsola znika. Problem ten mo?na rozwi?za? na kilka sposobów:

  • Je?li uruchamiasz program pod kontrol? debuggera (a tak powinno by? w przypadku 99% uruchomie? podczas pisania programu), mo?esz ustawi? breakpoint na ostatniej linijce funkcji main, lub na nawiasie klamrowym zamykaj?cym t? funkcj?. Gdy program dojdzie do tego miejsca zatrzyma si?, a ty mo?esz zobaczy? wynik jego dzia?ania na konsoli.
  • Niektóre ?rodowiska maj? opcj? uruchamiania programu i pozostawiania otwartej konsoli po zako?czeniu. Inne pozwalaj? na podgl?d wyj?cia programu, gdy zako?czy on swe dzia?anie. W ?rodowisku MS Visual Studio mo?na skorzysta? z opcji Run without debugging (skrót klawiszowy Ctrl + F5).
  • Gdy chcesz uruchomi? swój program poza kontrol? ?rodowiska, otwórz konsol? (np. nast?puj?cym poleceniem systemu Windows: Start/Uruchom.../cmd), przejd? do katalogu, w którym znajduje si? twój skompilowany program, i wpisz jego nazw? (oraz, w razie potrzeby, parametry). Gdy program zako?czy si?, konsola pozostanie otwarta, a ty b?dziesz móg? przeczyta? wszystko, co program wypisa?.
  • Je?li chcesz uruchamia? program przy pomocy dwukrotnego klikni?cia na ikonk?, mo?esz stworzy? plik wsadowy uruchamiaj?cy twój program, i zatrzymuj?cy si? przy pomocy polecenia specyficznego dla Twojej pow?oki. Albo mo?esz utworzy? skrót z ustawion? opcj? pozostawiania otwartego okna konsoli po zako?czeniu programu.


Q: Ale kto? powiedzia? mi, ?e mog? zatrzyma? program przy pomocy jakiej? linijki kodu. Czy jest to mo?liwe? Jak to zrobi??

Tak, jest to mo?liwe. Takich sposobów na zatrzymanie programu w celu powstrzymania konsoli przed znikaniem przy pomocy kodu jest kilka. Niestety, ?aden z nich nie jest idealny. Przede wszystkim, powstrzymywanie konsoli przed znikni?ciem jest w zdecydowanej wi?kszo?ci przypadków zupe?nie bez sensu, poniewa? nie jest to sposób, w jaki powinny dzia?a? aplikacje strumieniowe (a tego typu aplikacji zazwyczaj dotyczy ten problem). Popatrz sam: czy program ipconfig zatrzymuje si? po wy?wietleniu wszystkich informacji? A polecenie dir? Je?li jednak powy?sze argumenty nie przekona?y ci?, i nadal upierasz si? przy tym, ?e powstrzymywanie konsoli przed znikaniem jest dobrym pomys?em, masz ca?kiem sporo sposobów do wyboru:


  • getch() z biblioteki conio.h - najgorszy chyba mo?liwy sposób. Wymaga do??czenia niestandardowej, przestarza?ej biblioteki. Pochodzi z czasów DOSa, dost?pna jest na przestarza?ych kompilatorach Borlanda, jej obecno?? nie jest gwarantowana w ?adnej wspó?cze?nie dostarczanej platformie.

  • system("PAUSE") - sposób jeszcze gorszy od poprzedniego. Jest ma?o efektywny, wymaga uruchomienia przez ?rodowisko dodatkowych programów, dzia?a tylko na systemach Windows (i to nie jest gwarantowane, ?e na ka?dym).

  • cin.get() z iostream oraz getchar() z stdio.h - troch? lepsze ni? poprzednie, ale nie dzia?aj? do ko?ca tak, jak by?my sobie tego ?yczyli. Przede wszystkim, s? to funkcje do obs?ugi strumieni, nie maj? zielonego poj?cia o istnieniu klawiatury i o wciskaniu klawiszy. Program, je?li jest uruchomiony w konsoli, co prawda si? zatrzyma, ale wcale nie ruszy dalej po wci?ni?ciu dowolnego przycisku. Najcz??ciej (ale nie zawsze, kolejny niepewny punkt!) dane z konsoli przesy?ane s? do strumienia dopiero po wci?ni?ciu klawisza ENTER, wi?c u?ytkownik mo?e wpisa? ca?kiem d?ugi elaborat, zanim jego program ruszy dalej. Co gorsza, wszystko, co wpisa? (nie tylko pierwszy znak), zostanie przes?ane do strumienia wej?ciowego programu, wi?c przy kolejnych próbach komunikacji z u?ytkownikiem mo?e on nie mie? mo?liwo?ci wpisania czegokolwiek, bo w strumieniu ju? b?d? dane.

  • funkcje do obs?ugi konsoli, np. z biblioteki curses - chyba najlepszy sposób na wybrni?cie z problemu, bo operuje na konsoli, czyli robi dok?adnie to, o co nam chodzi. Ale i tu tkwi haczyk: je?li zainicjalizujemy bibliotek? curses, nie mamy pewno?ci, co stanie si? ze standardowymi strumieniami podpi?tymi do konsoli. Mo?e nie stanie si? nic, a mo?e przestan? dzia?a?. Mo?e na twoim komputerze nie stanie si? nic, a na komputerze profesora przestan? dzia?a?. Najlepiej, je?li zdecydujesz si? na u?ycie funkcji do obs?ugi konsoli, zrezygnowa? ze strumieni standardowych (iostream w C++ lub stdio.h w C).

  • Sposób jedyny s?uszny: zrezygnowa? z aplikacji strumieniowej, i zast?pi? j? aplikacj? konsolow?, korzystaj?c? z odpowiednich funkcji w ka?dym miejscu programu.


Najwa?niejsz? rzecz? jest jednak przyj?cie do wiadomo?ci, ?e zatrzymanie aplikacji strumieniowej po jej wykonaniu to NIE JEST sposób, w jaki powinna ona dzia?a?.
Powrót do góry
Zobacz profil autora Wyślij prywatną wiadomość Numer GG
marcin_an



Dołączył: 26 Maj 2005
Posty: 18822

PostWysłany: Wto Kwi 14, 2009 6:44 pm  OP    Temat postu: Odpowiedz z cytatem Pisownia

Aplikacje strumieniowe
Tagi: C++
Q
Co to jest aplikacja strumieniowa?
A
Najkrócej, ?opatologicznie i obrazowo: m?ynek z dwoma rurami. Jedn? rur? znaki wpadaj? do m?ynka, drug? wypadaj?:
  .
.
.

A

C
,--------.
| |
X -----------| M?YNEK |-----------
Q R T D > > R T A G
-----------| |----------- B
| |
`--------' U

S

.
.
.
Mówi?c bardziej formalnie: aplikacja ma na wej?ciu (rura po lewej na obrazku) ci?g znaków i wyprowadza na wyj?cie (rura po prawej na obrazku) równie? ci?g znaków. Aplikacja mo?e pobiera? kolejno znaki z wej?cia i kolejno wyprowadza? je na wyj?cie. W mi?dzyczasie mo?e je sobie mieli?. Na tym, dok?adnie na tym, ko?czy si? dzia?anie tej aplikacji. Nie ma praktycznie ?adnego wp?ywu ani na ?ród?o danych, ani na odbiorc? danych. Do rur mog? by? pod??czane najró?niejsze rzeczy i aplikacji nie interesuje, co tam b?dzie. Przyk?adowo mo?e to by? plik, inny program, po??czenie TCP/IP, port komputera z pod??czonym pod niego czujnikiem, mikrofon/g?o?nik, sterownik jakiego? urz?dzenia, drukarka lub nawet "nic". To tylko proste przyk?ady, nie pe?na lista! Co by jednak nie by?o, jest to zwykle poza zainteresowaniami aplikacji. Aplikacja normalnie nie ma te? wi?kszego wp?ywu na to, sk?d si? dane bior? i jak s? wysy?ane. Akceptuje po prostu to, co dostaje. Gdy uruchamiasz w shellu polecenia takie jak ls, netstat czy cat, programów tych nie interesuje, co si? dzieje z danymi, które wyprowadza na wyj?cie. Mo?e trafiaj? do pliku? Mo?e zosta?y wywo?ane ze skryptu, który przechwytuje ich wynik? Mo?e wynik trafia do grepa lub seda, które przetwarzaj? i filtruj? dane? Mo?e, co jest dosy? prawdopodobne do sterownika konsoli, dzi?ki czemu u?ytkownik mo?e je zobaczy?. Nie wiadomo. I to s? w?a?nie aplikacje strumieniowe: dwie rury do m?ynka. Proste, ale w odpowiednich r?kach pot??ne narz?dzie.

Praktycznie wszyscy programi?ci C++ zaczynali przygod? z tym j?zykiem w?a?nie od aplikacji strumieniowych. Niestety nikt im wcze?niej o tym nie powiedzia?, a domy?lne dzia?anie wielu systemów polegaj?ce na pod??czeniu strumieni pod sterownik konsoli nie u?atwia wcale zauwa?enia tego prostego faktu. Na dodatek niejeden ich nauczyciel nagada? bzdur, które tylko zaciemni?y obraz wszystkiego. Potem pojawiaj? si? pytania takie, jak trzy posty wy?ej - o konsol?. Pomimo, ?e aplikacja nie jest aplikacj? konsolow?, lecz strumieniow?.
Je?eli padnie pytanie, jak to si? zatem dzieje, ?e wpisywany w konsoli tekst trafia do programu i tekst wyprowadzany jest na ekranie, to wcale si? nie zdziwi?. Sprzeczno?ci jednak nie ma. Po prostu rury zosta?y pod??czone pod sterownik konsoli. Kolejny wielki m?ynek. Odbiera od systemu wiadomo?ci o wci?ni?ciu klawiszy, przetwarza je na znaki, które to znaki sobie zbiera i co jaki? czas wysy?a do rury wej?ciowej pod??czonej pod niego aplikacji. Co ile? Ró?nie, ale najbardziej typowe rozwi?zanie to po ka?dym napotkaniu znaku nowej linii, co jest cz?sto równoznaczne naci?ni?ciu entera. Czyli je?li naci?niesz kolejno klawisze: A, L, A, <spacja>, M, A, <spacja>, K, O, T, A, <enter>, 1, 2, 4, 8, 1, 2, <enter>, Q, W, E... taki sterownik konsoli wykona nast?puj?ce rzeczy:
Klawisz     Bufor sterownika        Rura wej?ciowa
---------------------------------------------------------------
"" ""
A "A" ""
L "AL" ""
A "ALA" ""
<spacja> "ALA " ""
M "ALA M" ""
A "ALA MA" ""
<spacja> "ALA MA " ""
K "ALA MA K" ""
O "ALA MA KO" ""
T "ALA MA KOT" ""
A "ALA MA KOTA" ""
<enter> -- wys?anie ------> "ALA MA KOTA\n"
1 "1" "ALA MA KOTA\n"
2 "12" "ALA MA KOTA\n"
4 "124" "ALA MA KOTA\n"
8 "1248" "ALA MA KOTA\n"
1 "12481" "ALA MA KOTA\n"
2 "124812" "ALA MA KOTA\n"
<enter> -- wys?anie -------> "ALA MA KOTA\n124812\n"
Q "Q" "ALA MA KOTA\n124812\n"
W "QW" "ALA MA KOTA\n124812\n"
E "QWE" "ALA MA KOTA\n124812\n"
Je?eli przed pierwszym naci?ni?ciem entera program b?dzie próbowa? czyta? z wej?cia, to implementacja zobaczy, ?e rura jest pusta i b?dzie czeka?a, a? co? si? w rurze pojawi. Gdy wreszcie po naci?ni?ciu entera co? si? pojawi, b?dzie to czyta?a. Potem znowu si? zablokuje, gdy rura si? opró?ni i znowu b?dzie czeka?a, a? b?dzie co? nadaj?cego si? do "zjedzenia". Z tego wynika "czekanie" aplikacji na wpisanie czego? od u?ytkownika. To nie operator >> powoduje, ?e aplikacja zatrzymuje si?, a ty mo?esz co? wpisa? i potwierdzi? to enterem. Aplikcja blokuje si?, bo czeka na dane. Dane te otrzymuje od sterownika konsoli, który sam je sobie zbiera. Aplikacja nie ma wi?kszego wp?ywu ani na to, sk?d te dane tak naprawd? b?d?, ani na to, jak b?d? wpisywane. Teraz rozumiesz, czemu pytanie o to, jak uniemo?liwi? wpisanie jakiego? znaku jest bez sensu? Dlatego, ?e to nie twoja aplikacja robi to czarne okienko, nie ona odczytuje wci?ni?te klawisze, nie ona wy?wietla odpowiadaj?ce im znaki przy kursorze i nie on przesuwa kursor - to wszystko robi zupe?nie inny program, który dopiero w pewnym momencie ju? skompletowane dane wysy?a do twojej aplikacji. Przenosz?c si? do strony, ?e si? tak wyra??, tylnej - dlaczego dane wy?wietlaj? si? na ekranie? Bo sterownik konsoli odczytuje dane z rury wylotowej. Sprawdza co to za dane, interpretuje je w razie konieczno?ci i wy?wietla. Po raz kolejny: to nie twoja aplikacja cokolwiek wy?wietla. Ona nawet nie wydaje polecenia wy?wietlenia. Jedyne co robi, to w rur? wyj?ciow? pakuje dane, które trafiaj? dopiero do urz?dzenia, które po ich analizie przeprowadza operacj? ich wy?wietlenia. Poniewa? nie twoja aplikacja cokolwiek rysuje i nie ona wy?wietla to okienko, to równie? pytanie o to, jak zmieni? twoj? aplikacj?, by sterowa?a tym okienkiem, s? nieporozumieniem. Twoja aplikacja nie mo?e tego zrobi? bezpo?rednio, bo to nie ona tym wszystkim zarz?dza.
W najlepszym przypadku mo?e wykorzysta? fakt, ?e sterowniki konsoli mog? u?ywa? protoko?u zawieraj?cego jakie? polecenia. Np. terminale ANSI mia?y zbiór polece? pozwalaj?cy powiedzie? im (bo to nadal one wszystko kontrolowa?y), ?e maj? zmieni? kolor czcionki, przenie?? kursor czy wyczy?ci? ekran. Stosowanie takich technik ma jednak dwie istotne wady. Po pierwsze s? nieprzeno?ne. Po drugie w dzisiejszych czasach istniej? gotowe biblioteki do sterowania konsol?, w których mo?na wszystko zrobi? kilkoma prostymi funkcjami zamiast zapychania kodu programu mas? brzydkich krzaczków.

Pos?uguj?c si? jeszcze jedn? analogi?: twój program jest krow? na pastwisku. Pytanie o zmian? sposobu wprowadzania danych do programu jest równie sensowne, co pytanie, jak przerobi? krow?, ?eby trawa szybciej ros?a. Pytanie o zmian? sposobu wy?wietlania danych z programu jest równie sensowne, co pytanie, jak przerobi? krow?, ?eby pan Józio przyje?d?a? po jej odchody w poniedzia?ki, a nie ?rody. Oczywi?cie mu?ki nie zmienisz. Krowa zawsze b?dzie jedn? stron? pobiera?a zielone dane wej?ciowe, a drug? stron? wyrzuca?a plackowate dane wyj?ciowe, bo taki jest jej ?ywot (jak zreszt? ka?dego wi?kszego ?ywego stworzenia).

_________________
Nieaktywny od 2017-04-01
Powrót do góry
Zobacz profil autora Wyślij prywatną wiadomość
hobson



Dołączył: 13 Sie 2007
Posty: 439
Skąd: Trójmiasto

PostWysłany: Sro Kwi 15, 2009 11:55 am      Temat postu: Tablice dwuwymiarowe Odpowiedz z cytatem Pisownia

Q: Jak zrobi? dynamiczn? tablic? dwuwymiarow? (macierz)?

W C++ nie istniej? gotowe klasy reprezentuj?ce dwuwymiarowe dynamiczne tablice, lub macierze w sensie matematycznym. Biblioteka standardowa zawiera jednak kilka elementów, które wspomagaj? utworzenie tego typu rzeczy. Je?li musisz zrobi? tak? tablic?, mo?esz pos?u?y? si? kilkoma sposobami

Za?o?enia:
  • Przyk?ady poni?ej u?ywaj? kodu C++, aby ich u?y? w C niezb?dne s? pewne przeróbki.
  • Obs?uga b??dów w poni?szych próbkach kodu to jedynie przyk?ady, mo?na je dostosowa? do w?asnych okoliczno?ci.
  • Terminy 'macierz' i 'tablica dwuwymiarowa' u?ywane s? przemiennie, nie oznaczaj? one 'macierzy liczb' czy te? 'tablic obiektów'.


1. U?ycie kontenerów dostarczanych przez bibliotek? standardow?.

Jest to w wi?kszo?ci przy padków najlepszy sposób na realizacj? tego zadania. Do jego g?ównych zalet nale?y fakt, ?e kontenery automatycznie zarz?dzaj? pami?ci?, i nie trzeba po nich sprz?ta?. Ilo?? potrzebnego do napisania kodu spada, trudniej pope?ni? b??d, i nie trzeba si? przejmowa? zwalnianiem pami?ci. W bibliotece standardowej istnieje spora gama kontenerów do wyboru, w razie potrzeby prac? ka?dego z nich mo?na sterowa? przy pomocy w?asnego alokatora. W wi?kszo?ci zastosowa? dobrym wyborem b?dzie szablon std::vector. Ale je?li np. spodziewasz si?, ?e twoje macierze b?d? wykorzystywane w operacjach arytmetycznych, jako kontenera mo?esz u?y? klasy std::valarray, która implementuje kilka podstawowych operacji na tablicach liczb:

Kod:

    //z uzyciem std::valarray
    {
        typedef std::valarray<int> Wiersz;
        typedef std::valarray<Wiersz> Macierz;

        Macierz macierz(Wiersz(kolumny), wiersze);
        
        for(size_t i=0; i < wiersze; ++i) {
            for(size_t j=0; j < kolumny; ++j) {
                macierz[i][j] = i;
            }
        }
    }

    //z uzyciem std::vector

    {
        typedef std::vector<int> Wiersz;
        typedef std::vector<Wiersz> Macierz;

        Macierz macierz(wiersze, Wiersz(kolumny));
        
        for(size_t i=0; i < wiersze; ++i) {
            for(size_t j=0; j < kolumny; ++j) {
                macierz[i][j] = i;
            }
        }
    }



W razie potrzeby, po niewielkich modyfikacjach, mo?liwe jest przekszta?cenie powy?szego kodu w taki sposób, aby u?ywa? wierszy o niejednakowej d?ugo?ci (tzw. jagged arrays). Jako dwuwymiarowej tablicy znaków do przechowywania linijek tekstu mo?esz u?y? std::vector<std::string> >.


Nie zawsze u?ycie kontenerów jest jednak mo?liwe. W j?zyku C trzeba alokowa? pami?? r?cznie. Czasami, w ramach zaj?? na uczelni, nie mo?emy korzysta? z kontenerów, poniewa? profesorowi wydaje si?, ?e C++ to takie troch? bogatsze C. W ka?dym razie, jakie by nie by?y powody, trzeba u?y? innych ?rodków.


2. R?czna alokacja jednego du?ego fragmentu pami?ci.

W tej metodzie alokowana jest od razu pami?? na ca?? macierz, a potem wska?niki na fragmenty tego obszaru zapisywane s? do tablicy wierszy:

Kod:

    {
        int* dane = NULL;
        int** macierz = NULL;

        try {
            //alokacja
            dane = new int[wiersze * kolumny];        
            macierz = new int* [wiersze];

            for(size_t i =0; i < wiersze; ++i) {
                macierz[i] = dane + i * kolumny;
            }

            //operacje na macierzy...
            for(size_t i=0; i < wiersze; ++i) {
                for(size_t j=0; j < kolumny; ++j) {
                    macierz[i][j] = i;
                }
            }

            //zwolnienie pamieci
            delete[] macierz;
            delete[] dane;

        } catch(const bad_alloc& ) {

            //gdyby nastapil blad alokacji
            delete[] macierz;
            macierz = NULL;

            delete[] dane;
            dane = NULL;
        }
    }



U?ycie tej metody poci?ga za sob? wszystkie uci??liwe aspekty r?cznego zarz?dzania pami?ci?. Trzeba pami?ta? o zwolnieniu zaalokowanych tablic, zarówno w sytuacji, gdy wszystko idzie dobrze, jak i w chwili wyst?pienia b??dów.

Metoda ta u?ywa tylko dwóch dynamicznych alokacji pami?ci, co sprawia, ?e powinna by? nieco wydajniejsza od trywialnego alokowania ka?dego wiersza z osobna, a sprz?tanie jest wiele ?atwiejsze, poniewa? nie trzeba ?ledzi?, które tablice ju? zosta?y zaalokowane, a które jeszcze nie. Jednak w przypadku bardzo du?ych tablic mo?e si? ona okaza? zawodna, poniewa? w systemie mo?e nie by? mo?liwe odnalezienie dostatecznie du?ego obszaru pami?ci (jest podatna na fragmentacj? pami?ci). W wi?kszo?ci zastosowa? jest to jednak ma?o prawdopodobne. U?ywaj?c tego sposobu nieco trudniejsze jest utworzenie tablicy o niejednakowej d?ugo?ci wierszy.


3. Alokacja wiersz po wierszu

W tej metodzie najpierw alokowana jest tablica wska?ników na ka?dy z wierszy macierzy, a potem ka?dy wiersz jest alokowany z osobna:

Kod:

    {
        int** macierz = NULL;
        try {
            //alokacja
            macierz = new int* [wiersze];
            for(size_t i=0; i<wiersze; ++i) {
                macierz[i] = NULL;
            }        

            for(size_t i=0; i < wiersze; ++i) {
                macierz[i] = new int[kolumny];
            }

            //operacje na macierzy...
            for(size_t i=0; i < wiersze; ++i) {
                for(size_t j=0; j < kolumny; ++j) {
                    macierz[i][j] = i;
                }
            }

            //zwolnienie pamieci
            for(size_t i=0; i < wiersze; ++i) {
                delete[] macierz[i];
            }
            delete[] macierz;
            
        } catch(const bad_alloc& ) {

            //gdyby nastapil blad alokacji, trzeba
            //zwolnic zaalokowane do tej pory wiersze
            if(macierz) {
                for(size_t i=0; i < wiersze; ++i) {
                    delete[] macierz[i];
                    macierz[i] = NULL;
                }
                delete[] macierz;
                macierz = NULL;
            }
        }
    }



Generalnie nie jest to zbyt dobry sposób: wprowadza nadmiarow? fragmentacj? pami?ci, bardzo uci??liwe w nim jest obs?ugiwanie b??dów, a du?a ilo?? alokacji dynamicznych spowalnia prac? programu. Jego chyba jedyn? zalet? jest fakt, ?e w miar? ?atwo pozwala na tworzenie tablic o niejednorodnej d?ugo?ci wierszy.


Je?li to mo?liwe, bardzo dobrym pomys?em by by?o opakowanie którego? z powy?szych sposobów w klas?, i udost?pnienie przez ni? interfejsu pozwalaj?cego na dost?p do danych i wykonywanie wymaganych przez nas operacji. W przypadku r?cznej alokacji pami?ci trzeba pami?ta? oczywi?cie o konstruktorze kopiuj?cym, operatorze przypisania, i destruktorze. Jeszcze lepiej, mo?na t? klas? uczyni? szablonem, i sprawi?, aby ten sam kod nadawa? si? do tworzenia tablic dwuwymiarowych przechowuj?cych obiekty niemal dowolnego typu.

Komentarz
Powrót do góry
Zobacz profil autora Wyślij prywatną wiadomość Numer GG
Quentin



Dołączył: 10 Lip 2009
Posty: 193
Skąd: Warszawa

PostWysłany: Sro Sie 12, 2009 8:37 pm      Temat postu: Odpowiedz z cytatem Pisownia

Deklarowanie przyja?ni z szablonami

Q1: Dlaczego przy pisaniu deklaracji przyja?ni z funkcj? szablonow? musz? pisa? ostre nawiasy <> po jej nazwie ? Co by si? sta?o jakbym ich tam nie wymieni? ?

Q2: Jak mog? zaprzyja?ni? moj? klas? z ca?ym szablonem klas/funkcji ?


---------------------------------------------------------------------------------------------------------------------------------------------------------

Ad. 1

Na pocz?tek trzeba u?wiadomi? sobie, ?e nazwa funkcji wygenerowanej przez szablon to tak na prawd? nazwa + parametry w <>. Przyk?adowo takie oto wywo?anie:

Kod:
template <class typ1, class typ2>
void funkcja(typ1 arg1, typ2 arg2)
{    /* ... */    }

int main()
{
    funkcja(34, 3.0);
}


Powoduje powstanie funkcji funkcja<int, double>. Czyli jak wida? nawiasy <> przy deklaracji przyja?ni s? potrzebne - inaczej zadeklarujemy przyja?? ze zwyk?a funkcj? o takich argumentach (która niekoniecznie istnieje).

Jednak mo?na si? spotka? z dwoma ich wersjami:

~ friend void funkcja<>(int, double);
~ friend void funkcja<int, double>(int, double);

Formu?k? - aby to lepiej zapami?ta? - mo?na sformu?owa? sobie nast?puj?co:

Cytat:
Nazwy typów, które wyst?puj? w okr?g?ych nawiasach, kompilator automatycznie umie?ci w nawiasach ostrych (chyba, ?e sami je tam wymienimy)


Mo?na wi?c zapyta? - po co wi?c wymy?lono tak? d?u?sz? wersj? deklaracji przyja?ni jak przy "w??yku" drugim ?

Od czasu mo?liwo?ci pisania przy wywo?aniu funkcji szablonowej ostrych nawiasów (wcze?niej nie by?o to mo?liwe) - parametr szablonu funkcji mo?e zawiera? równie? takie sta?e wyra?enia, które wcze?niej mog?y pojawi? si? jedynie przy szablonach klas. S? to:

- warto?? ca?kowita
- adres obiektu globalnego
- adres funkcji globalnej
- adres sk?adnika statycznego klasy

Mo?na wi?c napisa? taki szablon:

Kod:
template <int nr, class typ1, class typ2>
void funkcja(typ1 arg1, typ2 arg2)
{    /* ... */    }


I zadeklarowa? z nim przyja?? w taki oto sposób:

Kod:
friend void funkcja<32>(int, double);
//LUB te?:
friend void funkcja<32, int, double>(int, double);    //(ALE - patrz regu?ka wy?ej)


Bo jak wida? parametr 1-szy nie wyst?puje na li?cie argumentów.

Mam nadziej?, ?e teraz jasne jest, jak wa?ne jest u?ycie ostrych nawiasów w deklaracji przyja?ni.

----------------------------------------------------------------------------------------------------------------------------------------

Ad. 2

1. Przyja?? z ca?ym szablonem funkcji:

~ W zwyk?ej klasie:

Kod:
class klasa
{
    //...
    template <class typ>
    friend void fun(typ cos);
};


~ W klasie szablonowej:

Kod:
template <class X, class Y>
class klasa
{
    //...
    template <class XX, class YY>
    //Wa?ne, ?eby nie by?y to takie same
    //parametry jak tej klasy 'klasa' !!!
    friend void fun(XX cos1, YY cos2);
};


O ró?nicy parametrów trzeba zapami?ta? - w tym miejscu najwi?cej pocz?tkuj?cych robi zazwyczaj b??dy.

2. Przyja?? z ca?ym szablonem klas:

~ W zwyk?ej klasie:

Kod:
class klasa
{
    //...
    template <class typ>
    friend class klasa_zaprzyjaz;
};


~ W klasie szablonowej:

Kod:
template <class X, class Y>
class klasa
{
    //...
    template <class XX, class YY>
    //Wa?ne, ?eby nie by?y to takie same
    //parametry jak tej klasy 'klasa' !!!
    friend class klasa_zaprzyjaz;
};



---------------------------------------------------------------------------------------------------------------------------------------------------------

W za??czniku znajduje si? plik PDF, który podsumowuje ca?y mój post - mo?e si? przyda :-)

Je?eli masz jakie? pytania, sugestie - napisz PW.



Deklaracje przyja?ni z szablonami.pdf
 Opis:
Plik PDF, który zawiera wskazówki co do deklaracji przyja?ni z szablonami.

Pobierz
 Nazwa pliku:  Deklaracje przyja?ni z szablonami.pdf
 Wielkość pliku:  686.92 KB
 Pobierano:  679 raz(y)

Powrót do góry
Zobacz profil autora Wyślij prywatną wiadomość Wyślij email
marcin_an



Dołączył: 26 Maj 2005
Posty: 18822

PostWysłany: Sro Wrz 16, 2009 2:41 am  OP    Temat postu: Odpowiedz z cytatem Pisownia

U?ywanie using w nag?ówkach
Tagi: C++
Q
Czy prawid?owy jest kod z nag?ówka:
Kod:
#ifndef FUN_INCLUDED__
#define FUN_INCLUDED__

#include <iostream>

namespace x
{
    using namespace std;
    
    inline void fun()
    {
        cout << "Ala ma kota\n";
    }
}

#endif


A
Sam plik - w oddzieleniu od innych plików, jego u?ycia oraz utrzymania - tak, nie zawiera b??dów sk?adniowych. W praktyce jednak linia 8 jest proszeniem si? o k?opoty i nigdy nie powinna by?a si? pojawi?.

Proste pytanie: co definiuje/deklaruje ten nag?ówek w przestrzeni nazw x? Wbrew pozorom nie tylko x::fun. Wprowadza on tak?e co najmniej osiem deklaracji obiektów: x::cin, x::cout, x::cerr, x::clog itd., a znaj?c faktyczny sposób implementacji nag?ówków: tak?e dziesi?tki innych deklaracji, cz?sto nawet nieudokumentowanych "wewn?trznych ?mieci" implementacji biblioteki. Czy faktycznie chcia?e?, aby to wszystko znalaz?o si? w x? Nie s?dz?. using u?yty w ten sposób w celu skrócenia sobie pisania jest z?y g?ównie dlatego, ?e powoduje za?miecenie przestrzeni nazw rzeczami, które nigdy nie mia?y si? tam znale??.

Nale?y te? pami?ta? o tym, ?e dyrektywa include powoduje do??czenie zawarto?ci (tekstu) wskazanego pliku. Je?eli do??czymy nag?ówek z nieodpowiednio u?ytym using, to w efekcie nasze using mo?e trafi? przed inne nag?ówki do??czane po tym. To jest samo w sobie b??dem, a w szczególnych sytuacjach mo?e spowodowa? b??dn? interpretacj? kolejnych nag?ówków.

Skutkiem mog? by? te? trudne do zlokalizowania b??dy. Przeanalizuj sobie taki kod:
Kod:
namespace ns
{
    class X;
}

using namespace ns;

class X;

void test()
{
    X* x; // B??d, kompilator nie wie, o któr? klas? `X` chodzi!
}

X* x; // To samo...

O sytuacj? tak? wbrew pozorom nietrudno, a ?eby by?o zabawniej, np. g++ w drugim przypadku daje komunikat, z którego trudno wywnioskowa?, co si? sta?o.

Gdzie zatem mo?na stosowa? using w nag?ówkach? We wszystkich zakresach, których zawarto?? nigdy nie b?dzie osi?galna przez u?ytkownika. S? nimi oczywi?cie implementacje funkcji:
Kod:
inline void fun()
{
    using namespace std;
    cout << "Ala ma kota\n";
}
Tak, ten kod jest prawie (patrz ni?ej) poprawny. Ponadto mo?na sobie stworzy? "prywatn?" przestrze? nazw, która zgodnie z dokumentacj? b?dzie zastrze?ona dla implementacji biblioteki. W niej mo?na robi? w zasadzie co si? chce. Je?eli kto? si? do niej odwo?a, to sam sobie robi problemy - nie s? one wynikiem zaniedbania autora nag?ówka.

Wcze?niej napisa?em, ?e ostatni kod jest "prawie poprawny". Nadal jest jednak podatny na ostatni z wymienionych problemów. Cz?sto niezalecane jest w ogóle u?ywanie konstrukcji using namespace, je?li nie jest to dok?adnie to, co chcemy zrobi?. Lepszym rozwi?zaniem jest zwykle importowanie poszczególnych nazw, czyli w tym przypadku lepszym by?oby: using std::cout;. W ten sposób wiemy, co dok?adnie ?ci?gamy do swojego kodu.

Kiedy using poza wymienionymi wy?ej przypadkami mo?e wyst?pi? w nag?ówku? Wtedy, gdy faktycznie chcemy, by dane deklaracje znalaz?y si? we wskazanym miejscu. Nie jest to cz?ste, czasami jest problemotwórcze, ale samo w sobie nie jest jeszcze b??dem.

Bo profesor tak wymaga: je?li profesor b?dzie wymaga?, ?eby podczas pisania kodu chodzi? po ?cianach, to student ma obowi?zek chodzi? po ?cianach, bo inaczej nie zaliczy. Podane informacje dotycz? normalnych sytuacji. Profesorowi pisz jak profesor chce.

_________________
Nieaktywny od 2017-04-01
Powrót do góry
Zobacz profil autora Wyślij prywatną wiadomość
hobson



Dołączył: 13 Sie 2007
Posty: 439
Skąd: Trójmiasto

PostWysłany: Pon Gru 07, 2009 3:12 pm      Temat postu: Odpowiedz z cytatem Pisownia

Q: Gdy u?ytkownik poda nieprawid?owe dane wej?ciowe, na przyk?ad litery zamiast liczby, program wpada w niesko?czon? p?tl?. Jak temu zapobiec?
http://www.parashift.com/c++-faq-lite/input-output.html#faq-15.2
http://www.parashift.com/c++-faq-lite/input-output.html#faq-15.3

Q: Czemu mój program ignoruje wywo?ania getline lub inne ??dania pobrania danych z wej?cia?
http://www.parashift.com/c++-faq-lite/input-output.html#faq-15.6

Q: Czemu mój program dwa razy przetwarza ostatni? porcj? danych wej?ciowych?
http://www.parashift.com/c++-faq-lite/input-output.html#faq-15.5
Powrót do góry
Zobacz profil autora Wyślij prywatną wiadomość Numer GG
Wyświetl posty z ostatnich:   
Odpowiedz do tematu    Forum Coders' city Strona Główna -> C i C++ Wszystkie czasy w strefie CET (Europa)
Idź do strony 1, 2  Następny
Strona 1 z 2

 
Skocz do:  
Możesz pisać nowe tematy
Możesz odpowiadać w tematach
Nie możesz zmieniać swoich postów
Nie możesz usuwać swoich postów
Nie możesz głosować w ankietach
Możesz dodawać załączniki na tym forum
Możesz pobierać pliki z tego forum




Debug: strone wygenerowano w 0.20956 sekund, zapytan = 13
contact

| Darmowe programy i porady Jelcyna | Tansze zakupy w Helionie | MS Office Blog |