{"id":1632,"date":"2019-05-04T11:10:56","date_gmt":"2019-05-04T09:10:56","guid":{"rendered":"https:\/\/www.kompikownia.pl\/?p=1632"},"modified":"2019-05-07T12:08:04","modified_gmt":"2019-05-07T10:08:04","slug":"piec-sztuczek-c-o-ktorych-nie-miales-pojecia","status":"publish","type":"post","link":"https:\/\/www.kompikownia.pl\/index.php\/2019\/05\/04\/piec-sztuczek-c-o-ktorych-nie-miales-pojecia\/","title":{"rendered":"Pi\u0119\u0107 sztuczek C++, o kt\u00f3rych nie mia\u0142e\u015b poj\u0119cia"},"content":{"rendered":"<span class=\"rt-reading-time\" style=\"display: block;\"><span class=\"rt-label rt-prefix\">Czas czytania:<\/span> <span class=\"rt-time\">2<\/span> <span class=\"rt-label rt-postfix\">minut<\/span><\/span>\n<p>Chcia\u0142by\u015b pozna\u0107 kilka sztuczek, kt\u00f3rymi mo\u017cesz zaskoczy\u0107 swoich znajomych? Bierzesz udzia\u0142 w konkursach programistycznych, w kt\u00f3rych wymagane jest szybkie rozwi\u0105zanie problemu, a nast\u0119pnie szybkie zakodowanie rozwi\u0105zania? J\u0119zyk C++ kryje wiele ciekawych i intryguj\u0105cych ciekawostek, o kt\u00f3rych wiedz\u0105 tylko do\u015bwiadczeni programi\u015bci. Sztuczki te polegaj\u0105 na wykorzystaniu ma\u0142o znanych cech j\u0119zyka. Optymalizacyjne natomiast &#8211; cech procesora. Chcesz je pozna\u0107? Przeczytaj ten wpis i poszerz swoje horyzonty wiedzy. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Iteracja przez ci\u0105g znak\u00f3w (C style array)<\/h2>\n\n\n\n<p>Na ka\u017cdym punkcie podkre\u015blam, aby do minimum ograniczy\u0107 u\u017cywanie starych tablic w stylu j\u0119zyka C. <a href=\"https:\/\/www.kompikownia.pl\/index.php\/2019\/04\/18\/poznaj-nowoczesna-tablice-vector-w-c\/\">O wiele lepsze s\u0105 vectory<\/a>. Programowanie z u\u017cyciem zwyk\u0142ych tablic pr\u0119dzej czy p\u00f3\u017aniej mo\u017ce doprowadzi\u0107 do pewnych problem\u00f3w, (takich jak <a href=\"https:\/\/www.kompikownia.pl\/index.php\/2019\/03\/27\/czym-jest-undefined-behavior-w-c-c\/\">undefined behavior<\/a>) kt\u00f3rych rozwi\u0105zanie z pewno\u015bci\u0105 poch\u0142onie pewn\u0105 ilo\u015b\u0107 cennego czasu. Niestety, zdarzaj\u0105 si\u0119 sytuacje kiedy musisz ich u\u017cy\u0107. Przypu\u015b\u0107my, \u017ce tworzysz aplikacj\u0119 na urz\u0105dzenie wbudowane (np.: na procesorek archirektury AVR). Ilo\u015b\u0107 pami\u0119ci kt\u00f3r\u0105 masz do dyspozycji jest bardzo ograniczona. Natomiast zadanie, kt\u00f3re wykonuje tw\u00f3j uk\u0142ad wymaga od ciebie iteracji przez ca\u0142y ci\u0105g znak\u00f3w i dla ka\u017cdego znaku wykonania jakiej\u015b operacji. <\/p>\n\n\n\n<p>95% programist\u00f3w rozwi\u0105za\u0142oby ten problem w nast\u0119puj\u0105cy spos\u00f3b:<\/p>\n\n\n\n\n<div class=\"codecolorer-container cpp default\" style=\"overflow:auto;white-space:nowrap;width:90%;\"><div class=\"cpp codecolorer\"><span class=\"kw4\">char<\/span> array<span class=\"br0\">&#91;<\/span><span class=\"nu0\">60<\/span><span class=\"br0\">&#93;<\/span><span class=\"sy4\">;<\/span><br \/>\n<span class=\"co1\">\/\/ wype\u0142niamy tablic\u0119 array czym\u015b<\/span><br \/>\n<span class=\"kw4\">int<\/span> length <span class=\"sy1\">=<\/span> <span class=\"kw3\">strlen<\/span><span class=\"br0\">&#40;<\/span>array<span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n<span class=\"kw1\">for<\/span><span class=\"br0\">&#40;<\/span><span class=\"kw4\">int<\/span> i <span class=\"sy1\">=<\/span> <span class=\"nu0\">0<\/span><span class=\"sy4\">;<\/span>i<span class=\"sy1\">&lt;<\/span>length<span class=\"sy4\">;<\/span><span class=\"sy2\">++<\/span>i<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp;<span class=\"co1\">\/\/ wykonujemy jak\u0105\u015b operacj\u0119 <\/span><br \/>\n<span class=\"br0\">&#125;<\/span><\/div><\/div>\n\n\n\n\n<p class=\"example_code\">Rozwi\u0105zanie jest dobre i dzia\u0142a. Ale zauwa\u017c, \u017ce marnujemy co nieco czasu na wywo\u0142anie funkcji <em>strlen(). <\/em>Czy to jest naprawd\u0119 konieczne? Wydaje si\u0119, \u017ce tak. Sk\u0105d w innym wypadku b\u0119dziemy wiedzieli jak d\u0142ugo przegl\u0105da\u0107 tablic\u0119 oraz gdzie znajduje si\u0119 jej koniec? Ten tok rozumowania nie jest do ko\u0144ca optymalny. Aby znale\u017a\u0107 najlepsze rozwi\u0105zanie, musimy najpierw przeanalizowa\u0107 jak ci\u0105gi znak\u00f3w przechowywane s\u0105 w pami\u0119ci komputera. <\/p>\n\n\n\n<p>&#8222;Tablica&#8221; to po prostu wska\u017anik na kom\u00f3rk\u0119 zawieraj\u0105c\u0105 pierwszy jej element. Ten wska\u017anik nie wie nic o tym, jak du\u017c\u0105 ilo\u015b\u0107 danych przechowujemy. Ale nie wszystko stracone! Posiadamy informacj\u0119 o tym, gdzie dany ci\u0105g znak\u00f3w si\u0119 ko\u0144czy, gdy\u017c ka\u017cdy z nich w j\u0119zyku C\/C++ jest zako\u0144czony specjalnym tzw. null termination: \/0. Czym jest null termination? To po prostu kom\u00f3rka pami\u0119ci wype\u0142niona zerami. <\/p>\n\n\n\n<p class=\"example_code\">Czy musimy zna\u0107 d\u0142ugo\u015b\u0107 ci\u0105gu znak\u00f3w je\u015bli i tak chcemy przejrze\u0107 go ca\u0142ego, znak po znaku? NIE!. Co w takim wypadku musimy zrobi\u0107? Zamiast u\u017cywa\u0107 niewydajnej funkcji <em>strlen()<\/em>, wystarczy odpowiednio zmodyfikowa\u0107 warunek p\u0119tli for. <\/p>\n\n\n\n\n<div class=\"codecolorer-container cpp default\" style=\"overflow:auto;white-space:nowrap;width:90%;\"><div class=\"cpp codecolorer\"><span class=\"kw4\">char<\/span> array<span class=\"br0\">&#91;<\/span><span class=\"nu0\">60<\/span><span class=\"br0\">&#93;<\/span><span class=\"sy4\">;<\/span><br \/>\n<span class=\"co1\">\/\/ wype\u0142niamy tablic\u0119&amp;nbsp;array czym\u015b;<\/span><br \/>\n<span class=\"kw1\">for<\/span><span class=\"br0\">&#40;<\/span><span class=\"kw4\">int<\/span> i <span class=\"sy1\">=<\/span> <span class=\"nu0\">0<\/span><span class=\"sy4\">;<\/span>array<span class=\"br0\">&#91;<\/span>i<span class=\"br0\">&#93;<\/span><span class=\"sy4\">;<\/span><span class=\"sy2\">++<\/span>i<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n<span class=\"co1\">\/\/ wykonujemy jak\u0105\u015b operacj\u0119<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><\/div><\/div>\n\n\n\n\n<p class=\"example_code\">Warunkiem zako\u0144czenia p\u0119tli jest array[i]. Nie przyr\u00f3wnujemy tego do niczego, wi\u0119c jak to w\u0142a\u015bciwie dzia\u0142a? W C++ zero jest fa\u0142szem. Pozosta\u0142e warto\u015bci s\u0105 prawd\u0105. A wi\u0119c warunek b\u0119dzie spe\u0142niony i p\u0119tla b\u0119dzie dzia\u0142a\u0142a dop\u00f3ty, dop\u00f3ki <em>array[i]<\/em> b\u0119dzie r\u00f3\u017cne od zera. W momencie, gdy<em> array[i]<\/em> b\u0119dzie r\u00f3wne zero (a wi\u0119c wtedy gdy dojdziemy do null terminated) p\u0119tla zostanie przerwana.<\/p>\n\n\n\n<p class=\"example_code\">Oszcz\u0119dzamy czas &#8211; pisz\u0105c mniej kodu. Teoretycznie oszcz\u0119dzamy moc obliczeniow\u0105 &#8211; nie wywo\u0142uj\u0105c nadaremno funkcji <em>strlen(). <\/em>Wad\u0105 jest nieco wi\u0119ksze zaciemnienie kodu &#8211; warunek kt\u00f3ry umie\u015bcili\u015bmy w p\u0119tli nie musi by\u0107 zrozumia\u0142y dla osobnika czytaj\u0105cego nasz kod na pierwszy rzut oka. Ale to nie wszystko, co kryje C++.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Kr\u00f3tszy zapis dla x!=-1<\/h2>\n\n\n\n<p>Nast\u0119pna sztuczka ma charakter typowo &#8222;zabawowy&#8221; i raczej nie powinna by\u0107 u\u017cywana w praktyce, gdy\u017c nieco zaciemnia kod :).<\/p>\n\n\n\n<p>Programuj\u0105c, tworz\u0105c jak\u0105\u015b wi\u0119ksz\u0105 aplikacj\u0119 na pewno korzystasz z funkcji API udost\u0119pnianych przez system operacyjny lub inne biblioteki. Niestety, C++ ma nieco &#8222;upo\u015bledzony&#8221; system obs\u0142ugi sytuacji wyj\u0105tkowych. Wi\u0119kszo\u015b\u0107 funkcji API np.: systemu Linux nie korzysta z systemu wyj\u0105tk\u00f3w wbudowanego w j\u0119zyk. Zamiast tego zwraca -1 w przypadku niepowodzenia. Zawsze powinni\u015bmy obs\u0142u\u017cy\u0107 takie sytuacje, nawet je\u015bli prawdopodobie\u0144stwo ich zaistnienia jest bardzo niskie. Przecie\u017c nigdy nie wiadomo, jakie informacje na wej\u015bcie programu poda jego u\u017cytkownik \ud83d\ude42 <\/p>\n\n\n\n<p>A jak obs\u0142u\u017cy\u0107 je w najprostszy spos\u00f3b? Oczywi\u015bcie zapisa\u0107 wynik zwracany przez funkcj\u0119 i sprawdzi\u0107 czy nie jest on r\u00f3wny -1. <\/p>\n\n\n\n<p>Logika podpowiada, \u017ce najprostszy spos\u00f3b wykonania tej operacji jest nast\u0119puj\u0105cy: <\/p>\n\n\n<div class=\"codecolorer-container cpp default\" style=\"overflow:auto;white-space:nowrap;width:90%;\"><div class=\"cpp codecolorer\">pid_t x<span class=\"sy1\">=<\/span> fork<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span> <span class=\"co1\">\/\/ przyk\u0142adowa funkcja mog\u0105ca si\u0119 nie powie\u015b\u0107 - utworzenie nowego procesu<\/span><br \/>\n<span class=\"kw1\">if<\/span><span class=\"br0\">&#40;<\/span>x<span class=\"sy3\">!<\/span><span class=\"sy1\">=<\/span><span class=\"sy2\">-<\/span><span class=\"nu0\">1<\/span><span class=\"br0\">&#41;<\/span> <br \/>\n&nbsp; &nbsp; &nbsp;<span class=\"kw3\">cout<\/span><span class=\"sy1\">&lt;&lt;<\/span><span class=\"st0\">&quot;Nowy proces zosta\u0142 utworzony!!!. Yupi :)&quot;<\/span><span class=\"sy1\">&lt;&lt;<\/span>endl<span class=\"sy4\">;<\/span><\/div><\/div>\n\n\n\n<p>Obecnie zapis instrukcji warunkowej sprawdzaj\u0105cej czy uda\u0142o si\u0119 utworzy\u0107 proces liczy a\u017c 5 znak\u00f3w! Mo\u017cemy go skr\u00f3ci\u0107 a\u017c o 3 znaki. W jaki spos\u00f3b? <\/p>\n\n\n\n<p>Przypomnij sobie, jak wygl\u0105da zapis liczby -1 w systemie liczbowym U2. Spokojnie, je\u015bli nie pami\u0119tasz to ci przypomn\u0119 \ud83d\ude42 <\/p>\n\n\n\n<p>-1 w systemie dziesi\u0119tnym to 11111111 w U2. <\/p>\n\n\n\n<p>Co si\u0119 stanie je\u015bli zastosujemy negacj\u0119 bitow\u0105? Wszystkie jedynki zamieni\u0105 si\u0119 na zero. A wi\u0119c w systemie dziesi\u0119tnym zmienna tak\u017ce b\u0119dzie mia\u0142a warto\u015b\u0107 r\u00f3wn\u0105 zero. Pami\u0119tamy, \u017ce warunek w C\/C++ jest niespe\u0142niony wtedy kiedy warto\u015b\u0107 zmiennej wynosi 0. W ka\u017cdym innym wypadku jest spe\u0142niony. <\/p>\n\n\n\n<p>Tym samym wiemy ju\u017c, jak mo\u017cemy skr\u00f3ci\u0107 zapis:<\/p>\n\n\n<div class=\"codecolorer-container cpp default\" style=\"overflow:auto;white-space:nowrap;width:90%;\"><div class=\"cpp codecolorer\">pid_t x <span class=\"sy1\">=<\/span> fork<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span> <span class=\"co1\">\/\/ przyk\u0142adowa funkcja mog\u0105ca si\u0119 nie powie\u015b\u0107 - utworzenie nowego procesu<\/span><br \/>\n<span class=\"kw1\">if<\/span><span class=\"br0\">&#40;<\/span>~x<span class=\"br0\">&#41;<\/span> <br \/>\n&nbsp; &nbsp; &nbsp;<span class=\"kw3\">cout<\/span><span class=\"sy1\">&lt;&lt;<\/span><span class=\"st0\">&quot;Nowy proces zosta\u0142 utworzony!!!. Yupi :)&quot;<\/span><span class=\"sy1\">&lt;&lt;<\/span>endl<span class=\"sy4\">;<\/span><\/div><\/div>\n\n\n\n<p>Je\u015bli chcemy sprawdzi\u0107, czy co\u015b <strong>jest r\u00f3wne -1,<\/strong> mo\u017cemy skorzysta\u0107 z takiego, tym razem trzy znakowego zapisu:<\/p>\n\n\n<div class=\"codecolorer-container cpp default\" style=\"overflow:auto;white-space:nowrap;width:90%;\"><div class=\"cpp codecolorer\">pid_t x <span class=\"sy1\">=<\/span> fork<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span> <span class=\"co1\">\/\/ przyk\u0142adowa funkcja mog\u0105ca si\u0119 nie powie\u015b\u0107 - utworzenie nowego procesu<\/span><br \/>\n<span class=\"kw1\">if<\/span><span class=\"br0\">&#40;<\/span><span class=\"sy3\">!<\/span>~x<span class=\"br0\">&#41;<\/span> <br \/>\n&nbsp; &nbsp; &nbsp;<span class=\"kw3\">cout<\/span><span class=\"sy1\">&lt;&lt;<\/span><span class=\"st0\">&quot;Utworzenie nowego procesu nie powiod\u0142o si\u0119&quot;<\/span><span class=\"sy1\">&lt;&lt;<\/span>endl<span class=\"sy4\">;<\/span><\/div><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Szybkie sprawdzanie parzysto\u015bci<\/h2>\n\n\n\n<p> Sprawdzenie parzysto\u015bci liczby jest osi\u0105 wielu algorytm\u00f3w. Jest to zatem bardzo cz\u0119sto wykonywana operacja. Skutki jej &#8222;powolno\u015bci&#8221; odczuwamy tym bardziej, im wi\u0119ksze s\u0105 dane wej\u015bciowe napisanego programu. Co zatem mo\u017cemy zrobi\u0107, jako dobrzy programi\u015bci aby rozwi\u0105za\u0107 ten niecierpi\u0105cy zw\u0142oki optymalizacyjny k\u0142opot? <\/p>\n\n\n\n<p>W szkole ucz\u0105 nas aby sprawdza\u0107 parzysto\u015b\u0107 liczby w nast\u0119puj\u0105cy spos\u00f3b:<\/p>\n\n\n\n\n<div class=\"codecolorer-container cpp default\" style=\"overflow:auto;white-space:nowrap;width:90%;\"><div class=\"cpp codecolorer\"><span class=\"kw4\">int<\/span> toCheck <span class=\"sy1\">=<\/span> <span class=\"nu0\">43<\/span><span class=\"sy4\">;<\/span><br \/>\n<span class=\"kw1\">if<\/span><span class=\"br0\">&#40;<\/span>toCheck<span class=\"sy2\">%<\/span><span class=\"nu19\">2<\/span><span class=\"br0\">&#41;<\/span> <span class=\"kw3\">cout<\/span><span class=\"sy1\">&lt;&lt;<\/span><span class=\"st0\">&quot;Liczba nieparzysta&quot;<\/span><span class=\"sy1\">&lt;&lt;<\/span>endl<span class=\"sy4\">;<\/span><\/div><\/div>\n\n\n\n\n<p>Powy\u017cszy spos\u00f3b dzia\u0142a i to wy\u015bmienicie. Problem w tym \u017ce jest niesamowicie wolny. Operator modulo opiera si\u0119 na dzieleniu. A procesory <strong>strasznie nie lubi\u0105<\/strong> dzieli\u0107. Najlepiej i najszybciej im wychodzi dodawanie, odejmowanie liczb ca\u0142kowitych oraz wykonywanie <strong>operacji logicznych &#8230;<\/strong><\/p>\n\n\n\n<p>I to w\u0142a\u015bnie jest klucz do sukcesu!<\/p>\n\n\n\n<p>Zastan\u00f3w si\u0119, czym r\u00f3\u017cni si\u0119 parzysta liczba od nieparzystej w systemie binarnym? Por\u00f3wnajmy kilka:<br>1100 = 6(dec)<br>11110 = 30(dec)<br>111 = 7(dec)<br>100001 = 33(dec)<\/p>\n\n\n\n<p>Zauwa\u017cy\u0142e\u015b jak\u0105\u015b ciekaw\u0105 w\u0142asno\u015b\u0107? Liczby parzyste na pozycji LSB (najmniej znacz\u0105cego bitu) maj\u0105 warto\u015b\u0107 0, a liczby nieparzyste 1. Oczywi\u015bcie, por\u00f3wnanie kilku liczb ze sob\u0105 nie stanowi matematycznego dowodu, ale ten \u0142atwo znajdziesz sobie w Internecie \ud83d\ude42 Jak mo\u017cemy to wykorzysta\u0107? <\/p>\n\n\n\n<p>Po prostu sprawdzajmy za pomoc\u0105 operatora sumy logicznej, czy na pozycji LSB jest 0 czy 1. <\/p>\n\n\n\n\n<div class=\"codecolorer-container cpp default\" style=\"overflow:auto;white-space:nowrap;width:90%;\"><div class=\"cpp codecolorer\"><span class=\"kw4\">int<\/span> toCheck <span class=\"sy1\">=<\/span> <span class=\"nu0\">43<\/span><span class=\"sy4\">;<\/span><br \/>\n<span class=\"kw1\">if<\/span><span class=\"br0\">&#40;<\/span>toCheck<span class=\"sy3\">&amp;<\/span><span class=\"nu0\">1<\/span><span class=\"br0\">&#41;<\/span> <span class=\"kw3\">cout<\/span><span class=\"sy1\">&lt;&lt;<\/span><span class=\"st0\">&quot;Liczba nieparzysta&quot;<\/span><span class=\"sy1\">&lt;&lt;<\/span>endl<span class=\"sy4\">;<\/span><\/div><\/div>\n\n\n\n\n<p>O ile powy\u017cszy kod jest szybszy od &#8222;szkolnego&#8221;? Nie przeprowadza\u0142em osobi\u015bcie test\u00f3w, ale <a href=\"http:\/\/mziccard.me\/2015\/05\/08\/modulo-and-division-vs-bitwise-operations\/\">wiarygodne \u017ar\u00f3d\u0142a<\/a> m\u00f3wi\u0105 \u017ce r\u00f3\u017cnica du\u017ca &#8211; rz\u0119du 50% (w j\u0119zyku C). Warto zastanowi\u0107 si\u0119 nad stosowaniem tej regu\u0142y. R\u00f3\u017cnica w czytelno\u015bci kodu oraz w jego d\u0142ugo\u015bci jest \u017cadna. Nie jeste\u015bmy natomiast zale\u017cni od jako\u015bci kompilatora, kt\u00f3ry mo\u017ce &#8211; ale nie musi &#8211; optymalizowa\u0107 operatora modulo. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Jednolinijkowy IF<\/h2>\n\n\n\n<p>Jest wiele styli formatowania kodu. Niekt\u00f3rzy umieszczaj\u0105 klamr\u0119 w tym samym wierszu w kt\u00f3rym znajduje si\u0119 sygnatura funkcji. Inni robi\u0105 enter i umieszczaj\u0105 klamr\u0119 w kolejnym wierszu. Niekt\u00f3rzy kr\u00f3tkie ify pisz\u0105 w jednej linijce (warunek+reakcja), inni rozbijaj\u0105 to na dwie linijki (w jednej warunek, w drugiej reakcja). <\/p>\n\n\n\n<p>Osobi\u015bcie jestem zwolennikiem jak najbardziej zwi\u0119z\u0142ego kodu. Uwa\u017cam, \u017ce nie warto bez powodu &#8222;rozwija\u0107 kodu wzd\u0142u\u017c&#8221;. Rezultat zadzia\u0142ania instrukcji warunkowej &#8211; je\u015bli jest on kr\u00f3tki &#8211; umieszczam w tej samej linijce w kt\u00f3rej znajduje si\u0119 instrukcja warunkowa.<\/p>\n\n\n\n<p>Wydaje si\u0119, \u017ce C++ stawia nam pewne ograniczenie. Sp\u00f3jrz na poni\u017cszy kod:<\/p>\n\n\n<div class=\"codecolorer-container cpp default\" style=\"overflow:auto;white-space:nowrap;width:90%;\"><table cellspacing=\"0\" cellpadding=\"0\"><tbody><tr><td class=\"line-numbers\"><div>1<br \/>2<br \/>3<br \/>4<br \/><\/div><\/td><td><div class=\"cpp codecolorer\"><span class=\"kw4\">int<\/span> a <span class=\"sy1\">=<\/span> <span class=\"nu0\">5<\/span><span class=\"sy4\">;<\/span><br \/>\n<span class=\"kw4\">int<\/span> b <span class=\"sy1\">=<\/span> <span class=\"nu0\">0<\/span><span class=\"sy4\">;<\/span><br \/>\n<span class=\"kw4\">int<\/span> c <span class=\"sy1\">=<\/span> <span class=\"nu0\">0<\/span><span class=\"sy4\">;<\/span><br \/>\n<span class=\"kw1\">if<\/span><span class=\"br0\">&#40;<\/span>a<span class=\"sy1\">==<\/span><span class=\"nu0\">6<\/span><span class=\"br0\">&#41;<\/span> b<span class=\"sy2\">++<\/span><span class=\"sy4\">;<\/span> c<span class=\"sy2\">++<\/span><span class=\"sy4\">;<\/span><\/div><\/td><\/tr><\/tbody><\/table><\/div>\n\n\n\n<p>Zwr\u00f3\u0107 uwag\u0119 na linijk\u0119 czwart\u0105, w kt\u00f3rej znajduje si\u0119 nasza instrukcja warunkowa. Je\u015bli warunek b\u0119dzie prawdziwy, obie instrukcje si\u0119 wykonaj\u0105: b++ oraz c++. W przypadku, gdy warunek nie b\u0119dzie prawdziwy b++ si\u0119 nie wykona. <strong>Niestety inkrementacja zmiennej c dojdzie do skutku,<\/strong> gdy\u017c jest to &#8222;kolejna&#8221; instrukcja po instrukcji warunkowej i formalnie od niej nie zale\u017cy. Nie ma znaczenia, \u017ce umieszczona jest w tym samym wierszu co instrukcja warunkowa.<\/p>\n\n\n\n<p>Najprostszym rozwi\u0105zaniem wydaje si\u0119 u\u017cycie klamer. Ale za\u0142o\u017cyli\u015bmy, \u017ce nie chcemy ich u\u017cywa\u0107. Jest inne rozwi\u0105zanie, o kt\u00f3rym by\u0107 mo\u017ce nie masz poj\u0119cia. Instrukcje j\u0119zyka c++ mo\u017cemy rozdziela\u0107 za pomoc\u0105 przecinka. <\/p>\n\n\n<div class=\"codecolorer-container cpp default\" style=\"overflow:auto;white-space:nowrap;width:90%;\"><table cellspacing=\"0\" cellpadding=\"0\"><tbody><tr><td class=\"line-numbers\"><div>1<br \/>2<br \/><\/div><\/td><td><div class=\"cpp codecolorer\"><span class=\"kw4\">int<\/span> a<span class=\"sy1\">=<\/span><span class=\"nu0\">5<\/span>,b<span class=\"sy1\">=<\/span><span class=\"nu0\">0<\/span>,c<span class=\"sy1\">=<\/span><span class=\"nu0\">0<\/span><span class=\"sy4\">;<\/span><br \/>\n<span class=\"kw1\">if<\/span><span class=\"br0\">&#40;<\/span>a<span class=\"sy1\">==<\/span><span class=\"nu0\">6<\/span><span class=\"br0\">&#41;<\/span> b<span class=\"sy2\">++<\/span>,c<span class=\"sy2\">++<\/span><span class=\"sy4\">;<\/span><\/div><\/td><\/tr><\/tbody><\/table><\/div>\n\n\n\n<p>Dzi\u0119ki poznaniu tej, pozornie nic nieznacz\u0105cej, mo\u017cliwo\u015bci j\u0119zyka C\/C++ uda\u0142o nam si\u0119 zmniejszy\u0107 obj\u0119to\u015b\u0107 naszego kodu do dw\u00f3ch linijek. Niebywale! Co najwa\u017cniejsze, kod teraz dzia\u0142a prawid\u0142owo. <\/p>\n\n\n\n<p>Wad\u0105 tego sposobu jest nast\u0119puj\u0105ca. W tak skonstruowanej instrukcji warunkowej nie mo\u017cemy umieszcza\u0107 s\u0142\u00f3w kluczowych zmieniaj\u0105cych przep\u0142yw sterowania programu, takich jak return, break czy continue. W takim wypadku niestety jeste\u015bmy skazani na dodanie nawias\u00f3w klamrowych oraz \u015brednik\u00f3w. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">(C) Niestandardowe wype\u0142nienie tablicy za pomoc\u0105 scanf<\/h2>\n\n\n\n<p class=\"example_code\"><em>scanf()<\/em>, podobnie jak wielu innych funkcji j\u0119zyka C <strong>nie powinni\u015bmy u\u017cywa\u0107 gdy programujemy w C++<\/strong>. Mo\u017cemy z\u0142ama\u0107 t\u0119 zasad\u0119 tylko wtedy, gdy nast\u0105pi taka konieczno\u015b\u0107, co zdarza si\u0119 bardzo rzadko. Jednak\u017ce je\u015bli piszemy w j\u0119zyku C, nie mamy innej mo\u017cliwo\u015bci pobrania danych od u\u017cytkownika jak stary dobry scanf. <\/p>\n\n\n\n<p>Jak w najprostszy spos\u00f3b wype\u0142ni\u0107 tablic\u0119? <\/p>\n\n\n<div class=\"codecolorer-container cpp default\" style=\"overflow:auto;white-space:nowrap;width:90%;\"><div class=\"cpp codecolorer\"><span class=\"kw4\">int<\/span> a<span class=\"br0\">&#91;<\/span><span class=\"nu0\">100<\/span><span class=\"br0\">&#93;<\/span><span class=\"sy4\">;<\/span><br \/>\n<span class=\"kw1\">for<\/span><span class=\"br0\">&#40;<\/span><span class=\"kw4\">int<\/span> i <span class=\"sy1\">=<\/span> <span class=\"nu0\">0<\/span><span class=\"sy4\">;<\/span>i<span class=\"sy1\">&lt;<\/span><span class=\"nu0\">100<\/span><span class=\"sy4\">;<\/span><span class=\"sy2\">++<\/span>i<span class=\"br0\">&#41;<\/span> <span class=\"kw3\">scanf<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;%d&quot;<\/span>,<span class=\"sy3\">&amp;<\/span>a<span class=\"br0\">&#91;<\/span>i<span class=\"br0\">&#93;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><\/div><\/div>\n\n\n\n<p class=\"example_code\">Takiego sposobu pewnie uczyli ci\u0119 w szkole lub na studiach. Nie jest on z\u0142y &#8211; prosty i dzia\u0142a.W tym wypadku musimy u\u017cy\u0107 operacji &#8222;pobrania&#8221; adresu (symbol &amp;). Ten sam kod mo\u017cemy zapisa\u0107 w nieco inny spos\u00f3b, kt\u00f3ry zniweluje konieczno\u015b\u0107 u\u017cycia tego operatora. <\/p>\n\n\n<div class=\"codecolorer-container cpp default\" style=\"overflow:auto;white-space:nowrap;width:90%;\"><div class=\"cpp codecolorer\"><span class=\"kw4\">int<\/span> a<span class=\"br0\">&#91;<\/span><span class=\"nu0\">100<\/span><span class=\"br0\">&#93;<\/span><span class=\"sy4\">;<\/span><br \/>\n<span class=\"kw1\">for<\/span><span class=\"br0\">&#40;<\/span><span class=\"kw4\">int<\/span> i <span class=\"sy1\">=<\/span> <span class=\"nu0\">0<\/span><span class=\"sy4\">;<\/span>i<span class=\"sy1\">&lt;<\/span><span class=\"nu0\">100<\/span><span class=\"sy4\">;<\/span><span class=\"sy2\">++<\/span>i<span class=\"br0\">&#41;<\/span> <span class=\"kw3\">scanf<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;%d&quot;<\/span>,a<span class=\"sy2\">+<\/span>i<span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><\/div><\/div>\n\n\n\n<p>Korzystamy tu z wielokrotnie wspominanej cechy tablic j\u0119zyka C\/C++. Mo\u017cemy przyj\u0105\u0107, \u017ce tablica jest tak naprawd\u0119 wska\u017anikiem na jej pierwszy element. Je\u015bli do tego wska\u017anika dodamy warto\u015b\u0107 indeksu, otrzymamy adres elementu znajduj\u0105cego pod danym indeksem. Dzi\u0119ki temu scanf mo\u017ce szybko i bezproblemowo zapisa\u0107 tam wynik swoich operacji. <\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Dodatkowy spos\u00f3b na okre\u015blenie konkretnego elementu tablicy<\/h3>\n\n\n\n<p class=\"example_code\">Warto przy tej okazji wspomnie\u0107 o kolejnej ma\u0142o znanej w\u0142a\u015bciwo\u015bci j\u0119zyka C\/C++. W poprzednim rozdziale udowodnili\u015bmy, \u017ce zapis  <em>a[i]<\/em> mo\u017cemy w niekt\u00f3rych wypadkach zamieni\u0107 na <em> a+i <\/em>. Istnieje jeszcze jedna mo\u017cliwo\u015b\u0107 zapisu elementu tablicy. <\/p>\n\n\n\n<p class=\"example_code\">Dodawanie i mno\u017cenie, jak zapewne wiemy jeszcze ze szko\u0142y podstawowej, s\u0105 dzia\u0142aniami przemiennymi. Czy to oznacza, \u017ce np.: zapis <em> a[5] <\/em>mo\u017cemy zamieni\u0107 na <em>5[a] <\/em>? Oczywi\u015bcie \ud83d\ude42 <\/p>\n\n\n\n<p>Poni\u017cszy listing prezentuje wszystkie trzy mo\u017cliwo\u015bci zapisywania i odczytywania element\u00f3w znajduj\u0105cych si\u0119 pod konkretnymi indeksami. <\/p>\n\n\n\n\n<div class=\"codecolorer-container cpp default\" style=\"overflow:auto;white-space:nowrap;width:90%;\"><div class=\"cpp codecolorer\"><span class=\"kw4\">int<\/span> a<span class=\"br0\">&#91;<\/span><span class=\"nu0\">4<\/span><span class=\"br0\">&#93;<\/span><span class=\"sy4\">;<\/span><br \/>\n<span class=\"kw3\">scanf<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;%d&quot;<\/span>,a<span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span> <span class=\"co1\">\/\/ element pod indeksem 0 w tablicy<\/span><br \/>\n<span class=\"kw3\">scanf<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;%d&quot;<\/span>,<span class=\"sy3\">&amp;<\/span>a<span class=\"br0\">&#91;<\/span><span class=\"nu0\">1<\/span><span class=\"br0\">&#93;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n<span class=\"kw3\">scanf<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;%d&quot;<\/span>,<span class=\"sy3\">&amp;<\/span><span class=\"nu0\">2<\/span><span class=\"br0\">&#91;<\/span>a<span class=\"br0\">&#93;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n<span class=\"kw3\">scanf<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;%d&quot;<\/span>,a<span class=\"sy2\">+<\/span><span class=\"nu0\">3<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n<span class=\"kw1\">for<\/span><span class=\"br0\">&#40;<\/span><span class=\"kw4\">int<\/span> i <span class=\"sy1\">=<\/span> <span class=\"nu0\">0<\/span><span class=\"sy4\">;<\/span>i<span class=\"sy1\">&lt;<\/span><span class=\"nu0\">4<\/span><span class=\"sy4\">;<\/span>i<span class=\"sy2\">++<\/span><span class=\"br0\">&#41;<\/span> <span class=\"kw3\">printf<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;%d &quot;<\/span>,<span class=\"sy2\">*<\/span><span class=\"br0\">&#40;<\/span>a<span class=\"sy2\">+<\/span>i<span class=\"br0\">&#41;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span> <span class=\"co1\">\/\/ korzystamy z dereferencji gdy\u017c printf potrzebuje warto\u015bci elementu, a nie adresu<\/span><\/div><\/div>\n\n\n\n\n<h2 class=\"wp-block-heading\">DLC: Zamiana warto\u015bci zmiennych bez zmiennej tymczasowej<\/h2>\n\n\n\n<p>Wiem, \u017ce mia\u0142o by\u0107 5 sztuczek, wi\u0119c potraktujmy ten ostatni punkt jako darmowy &#8222;DLC&#8221; \ud83d\ude42 <\/p>\n\n\n\n<p>W wielu algorytmach, a szczeg\u00f3lnie w algorytmach sortowania musimy zamieni\u0107 ze sob\u0105 warto\u015bci dw\u00f3ch zmiennych. Najpro\u015bciej wykona\u0107 t\u0119 czynno\u015b\u0107 za pomoc\u0105 zmiennej tymczasowej:<\/p>\n\n\n<div class=\"codecolorer-container cpp default\" style=\"overflow:auto;white-space:nowrap;width:90%;\"><div class=\"cpp codecolorer\"><span class=\"kw4\">int<\/span> a <span class=\"sy1\">=<\/span> <span class=\"nu0\">24<\/span><span class=\"sy4\">;<\/span><br \/>\n<span class=\"kw4\">int<\/span> b <span class=\"sy1\">=<\/span> <span class=\"nu0\">48<\/span><span class=\"sy4\">;<\/span><br \/>\n<span class=\"kw4\">int<\/span> temp <span class=\"sy1\">=<\/span> a<span class=\"sy4\">;<\/span><br \/>\na <span class=\"sy1\">=<\/span> b<span class=\"sy4\">;<\/span><br \/>\nb <span class=\"sy1\">=<\/span> temp<span class=\"sy4\">;<\/span><\/div><\/div>\n\n\n\n<p>Zamieniaj\u0105c warto\u015b\u0107 zmiennych ze sob\u0105, w pewnym momencie musimy nadpisa\u0107 zawarto\u015b\u0107 jednej z nich warto\u015bci\u0105 drugiej. Aby\u015bmy nie utracili informacji, nadpisywane dane musimy przechowa\u0107 w zmiennej tymczasowej. <\/p>\n\n\n\n<p>Wydaje si\u0119, \u017ce nie ma \u017cadnej mo\u017cliwo\u015bci omini\u0119cia potrzeby u\u017cycia zmiennej tymczasowej. A mo\u017ce jednak? Kilka razy udowodnili\u015bmy ju\u017c, jak przydatne w informatyce s\u0105 operacje bitowe. Okazuje si\u0119, \u017ce przy czynno\u015bci takiej jak zamiana liczb one tak\u017ce mog\u0105 nam bardzo pom\u00f3c.<\/p>\n\n\n<div class=\"codecolorer-container cpp default\" style=\"overflow:auto;white-space:nowrap;width:90%;\"><div class=\"cpp codecolorer\"><span class=\"kw4\">int<\/span> a <span class=\"sy1\">=<\/span> <span class=\"nu0\">24<\/span>, b <span class=\"sy1\">=<\/span> <span class=\"nu0\">48<\/span><span class=\"sy4\">;<\/span><br \/>\na <span class=\"sy1\">=<\/span> a <span class=\"sy3\">^<\/span> b<span class=\"sy4\">;<\/span><br \/>\nb <span class=\"sy1\">=<\/span> a <span class=\"sy3\">^<\/span> b<span class=\"sy4\">;<\/span><br \/>\na <span class=\"sy1\">=<\/span> a <span class=\"sy3\">^<\/span> b<span class=\"sy4\">;<\/span><\/div><\/div>\n\n\n\n<p>Wykonujemy trzy razy operacj\u0119 XOR (alternatywy wykluczaj\u0105cej). Jak to dzia\u0142a? <\/p>\n\n\n\n<p>Alternatywa wykluczaj\u0105ca, jak pami\u0119tamy, daje warto\u015b\u0107 jeden tylko wtedy gdy jeden z argument\u00f3w jest r\u00f3wny jeden a drugi zero. Operacja ta daje na wyj\u015bciu warto\u015b\u0107 zero w ka\u017cdym pozosta\u0142ym wypadku. Przeanalizujmy wi\u0119c algorytm:<\/p>\n\n\n\n<table class=\"wp-block-table aligncenter is-style-regular\"><tbody><tr><td>a<\/td><td>0<\/td><td>0<\/td><td>0<\/td><td>1<\/td><td>1<\/td><td>0<\/td><td>0<\/td><td>0<\/td><td>24<\/td><\/tr><tr><td>b<\/td><td>0<\/td><td>0<\/td><td>1<\/td><td>1<\/td><td>0<\/td><td>0<\/td><td>0<\/td><td>0<\/td><td>48<\/td><\/tr><tr><td><strong>a=a^b<\/strong><\/td><td>0<\/td><td>0<\/td><td>1<\/td><td>0<\/td><td>1<\/td><td>0<\/td><td>0<\/td><td>0<\/td><td><strong>40<\/strong><\/td><\/tr><\/tbody><\/table>\n\n\n\n<p>Tak\u0105 warto\u015b\u0107 przyjmie zmienna a w drugiej linijce. Hmmm &#8211; jeste\u015bmy nieco daleko od prawid\u0142owego wyniku. Zobaczmy jednak co b\u0119dzie si\u0119 dzia\u0142o dalej!<\/p>\n\n\n\n<table class=\"wp-block-table aligncenter\"><tbody><tr><td>a<\/td><td>0<\/td><td>0<\/td><td>1<\/td><td>0<\/td><td>1<\/td><td>0<\/td><td>0<\/td><td>0<\/td><td>40<\/td><\/tr><tr><td>b<\/td><td>0<\/td><td>0<\/td><td>1<\/td><td>1<\/td><td>0<\/td><td>0<\/td><td>0<\/td><td>0<\/td><td>48<\/td><\/tr><tr><td><strong>b=a^b<\/strong><\/td><td>0<\/td><td>0<\/td><td>0<\/td><td>1<\/td><td>1<\/td><td>0<\/td><td>0<\/td><td>0<\/td><td><strong>24<\/strong><\/td><\/tr><\/tbody><\/table>\n\n\n\n<p>Wow! Otrzymali\u015bmy ju\u017c prawid\u0142owy wynik dla zmiennej b!. <\/p>\n\n\n\n<table class=\"wp-block-table aligncenter\"><tbody><tr><td>a<\/td><td>0<\/td><td>0<\/td><td>1<\/td><td>0<\/td><td>1<\/td><td>0<\/td><td>0<\/td><td>0<\/td><td>40<\/td><\/tr><tr><td>b<\/td><td>0<\/td><td>0<\/td><td>0<\/td><td>1<\/td><td>1<\/td><td>0<\/td><td>0<\/td><td>0<\/td><td>24<\/td><\/tr><tr><td><strong>a=a^b<\/strong><\/td><td>0<\/td><td>0<\/td><td>1<\/td><td>1<\/td><td>0<\/td><td>0<\/td><td>0<\/td><td>0<\/td><td><strong>48<\/strong><\/td><\/tr><\/tbody><\/table>\n\n\n\n<p>Do zmiennej a r\u00f3wnie\u017c trafi\u0142o to co powinno trafi\u0107. <\/p>\n\n\n\n<p>U\u017cycie operatora XOR jest nieco szybsze i bardziej oszcz\u0119dne je\u015bli chodzi o pami\u0119\u0107 od u\u017cywania zmiennej tymczasowej. Dlatego polecam poeksperymentowa\u0107 \ud83d\ude42 <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">To by by\u0142o na tyle \ud83d\ude42 <\/h2>\n\n\n\n<p>To wszystko, co chcia\u0142em wam przekaza\u0107 w dzisiejszym artykule. Mam nadziej\u0119, \u017ce nauczyli\u015bcie si\u0119 wielu ciekawych i interesuj\u0105cych \u017cycie, a wasze programowanie stanie si\u0119 szybsze i przyjemniejsze \ud83d\ude42<\/p>\n\n\n\n<p>Je\u015bli chcesz by\u0107 na bie\u017c\u0105co informowany o nowych wpisach, kliknij ikonk\u0119 &#8222;dzwoneczka&#8221; w lewym dolnym rogu. Dzi\u0119ki temu dostaniesz powiadomienie natychmiast po tym, jak nowy artyku\u0142 zostanie tutaj opublikowany \ud83d\ude42 <\/p>\n\n\n\n<p>Polub tak\u017ce mojego <a href=\"https:\/\/www.facebook.com\/kompikownia\/\">fanpage&#8217;a<\/a> na kt\u00f3rym cz\u0119sto umieszczam r\u00f3\u017cne ciekawostki \ud83d\ude42 <\/p>\n\n\n\n<p>Dzi\u0119ki za lektur\u0119 i powodzenia \ud83d\ude42 <\/p>\n","protected":false},"excerpt":{"rendered":"<p><span class=\"rt-reading-time\" style=\"display: block;\"><span class=\"rt-label rt-prefix\">Czas czytania:<\/span> <span class=\"rt-time\">2<\/span> <span class=\"rt-label rt-postfix\">minut<\/span><\/span> Chcia\u0142by\u015b pozna\u0107 kilka sztuczek, kt\u00f3rymi mo\u017cesz zaskoczy\u0107 swoich znajomych? Bierzesz udzia\u0142 w konkursach programistycznych, w kt\u00f3rych wymagane jest szybkie rozwi\u0105zanie problemu, a nast\u0119pnie szybkie zakodowanie rozwi\u0105zania? J\u0119zyk C++ kryje wiele &#8230;<\/p>\n","protected":false},"author":1,"featured_media":1674,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[31],"tags":[],"_links":{"self":[{"href":"https:\/\/www.kompikownia.pl\/index.php\/wp-json\/wp\/v2\/posts\/1632"}],"collection":[{"href":"https:\/\/www.kompikownia.pl\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.kompikownia.pl\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.kompikownia.pl\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.kompikownia.pl\/index.php\/wp-json\/wp\/v2\/comments?post=1632"}],"version-history":[{"count":56,"href":"https:\/\/www.kompikownia.pl\/index.php\/wp-json\/wp\/v2\/posts\/1632\/revisions"}],"predecessor-version":[{"id":1710,"href":"https:\/\/www.kompikownia.pl\/index.php\/wp-json\/wp\/v2\/posts\/1632\/revisions\/1710"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.kompikownia.pl\/index.php\/wp-json\/wp\/v2\/media\/1674"}],"wp:attachment":[{"href":"https:\/\/www.kompikownia.pl\/index.php\/wp-json\/wp\/v2\/media?parent=1632"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.kompikownia.pl\/index.php\/wp-json\/wp\/v2\/categories?post=1632"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.kompikownia.pl\/index.php\/wp-json\/wp\/v2\/tags?post=1632"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}