Haskell Input and Output Źródło:

Wielkość: px
Rozpocząć pokaz od strony:

Download "Haskell Input and Output Źródło:"

Transkrypt

1 Haskell Input and Output Źródło: Brak stanu i czystość funkcji Wstęp - Wejście i Wyjście Wspomnieliśmy że Haskell jest czysto funkcyjnym językiem. W językach imperatywnych rzeczy są robione przez dawanie komputerowi serii kroków do wykonania, a w językach funkcyjnych programowanie w większości jest definiowaniem czym rzeczy są. W Haskell-u, niemożliwe jest zmienienie jakiegoś stanu przez funkcję, np. zmienienie wartości jakiejś zmiennej. (zmianę jakiegoś stanu przez funkcję nazywamy efektem-ubocznym; funkcję która ma efekt uboczny nazywamy funkcja nieczystą). Jedyną rzeczą jaką funkcja w Haskellu może zrobić to zwrócenie jakiejś wartości, być może wyliczonej na podstawie wartości parametru. Jeśli funkcja Haskell-a będzie wywołana dwa razy, z taką samą wartością parametru, to musi zwrócić taką samą wartość. Mimo że wydaje się to trochę ograniczające, jeśli zna się tylko imperatywne języki programowania, to my zauważyliśmy że to jest jednak całkiem fajne i przydatne. W językach imperatywnych, nie ma gwarancji, że prosta funkcja, która powinna tylko coś wyliczyć, nie zmieni wartości jakiejś zmiennej. Na przykład kiedy (w Haskell-u) tworzone jest drzewo binarne, element nie jest dokładany do drzewa przez modyfikacje drzewa w miejscu. Funkcja w Haskellu w rzeczywistości zwraca nowe drzewo z nowym elementem gdyż nie jest możliwa modyfikacja/zmiana początkowego drzewa. Niemożliwość zmiany stanu przez funkcję jest zaletą, ponieważ pomaga rozumować o działaniu programów, ale rodzi jeden problem. Jeśli niemożliwe jest zmienienie czegokolwiek przez funkcję to jak ma zakomunikować ludziom to co wyliczyła. Aby zakomunikować wynik obliczeń, trzeba zmienić stan urządzenia wyjścia (zazwyczaj stan ekranu), który emituje fotony, które podróżują do oczu, i zmieniają stan ludzkiego umysłu. Okazuje się że Haskell ma naprawdę mądry system do obchodzenia się z funkcjami mającymi efekty uboczne, który w czysty sposób oddziela część programu która jest czysta, od nieczystej i który wykonuje cała nieczystą pracę np. komunikacją z ekranem lub klawiaturą. Z tymi częściami oddzielonymi, można nadal łatwo rozumować o czystej części, i czerpać korzyści z braku efektów ubocznych, takich jak lenistwo, zwiększona niezawodność (odporność na błędy), modularność, a zarazem efektywnie komunikować się z światem zewnętrznym. 1

2 Program Hello, world! Wpisz w edytorze tekstowym: main = putstrln "hello, world" Właśnie zdefiniowaliśmy nazwę main, a w niej wywołujemy funkcję nazywaną putstrln z parametrem Witaj świecie!. Wygląda zupełnie standardowo, ale nie jest zobaczymy za chwilę. Zapisz plik jako helloworld.hs. A teraz skompilujemy nasz program! Otwórz terminal, przejdź do katalogu gdzie helloworld.hs się znajduje i wykonaj to co poniżej: $ ghc --make helloworld [1 of 1] Compiling Main ( helloworld.hs, helloworld.o ) Linking helloworld... Okay!. Jeśli mamy trochę szczęścia, to dostaliście coś podobnego i teraz możecie uruchomić program poprzez. 2$./helloworld hello, world Nasz pierwszy skompilowany program, który wyświetla coś w terminalu. Przyjrzyjmy się temu co napisaliśmy. Najpierw spójrzmy na typ funkcji putstrln ghci> :t putstrln putstrln :: String -> IO () ghci> :t putstrln "hello, world" putstrln "hello, world" :: IO () Możemy przeczytać typ putstrln tak: putstrln bierze string i zwraca I/O akcje która zawiera coś typu () (i.e. pusty, tuple (n-tkę) pustą, także nazywaną jednostką (po angielsku unit)). Akcja I/O, kiedy wywołana spowoduje powstanie efektu ubocznego (zazwyczaj wczytanie czegoś z urządzenia wejścia, lub wyświetlenie czegoś na ekranie) a także będzie zawierać (nie całkiem zwracać) jakąś wartość w sobie. Wyświetlanie na ekranie nie powoduje zwracania jakiejś wartości, toteż nic nieznacząca wartość () jest składowana w akcji (zwracana ale nie całkiem). Pusta tuple jest wartością () i ma też typ (). Kiedy akcja I/O będzie wykonana? W grę wkracza main. Akcja I/O będzie wykonana kiedy nazwiemy ją main i uruchomimy/wykonamy program. Wydaje się ograniczające aby cały program był tylko jedną akcją I/O. Dlatego też możemy użyć składni do do sklejenia razem pewnej liczby akcji I/O w jedną. Spójrzcie na następujący przykład. putstrln "Hello, what's your name?" name <- getline 2

3 putstrln ("Hey " ++ name ++ ", you rock!") Interesująca nowa składnia! I w dodatku wygląda całkiem jak program napisany w języku imperatywnym. Jeśli skompilujecie ten program i wypróbujecie, to będzie pewnie działał tak jak oczekujecie. Zauważcie że tam jest napisane do a potem wypisana seria kroków zupełnie jak w programie imperatywnym. Każdy z tych kroków jest akcją I/O. Poprzez składanie ich razem przez użycie składni do stworzyliśmy (skleiliśmy) je w jedną akcje I/O. Akcja, którą otrzymaliśmy ma typ IO (),ponieważ takiego typu jest ostania akcja. Z tego powodu, main zawsze ma sygnature typu main :: IO coś, gdzie coś jest jakimś konkretnym typem. Jest przyjęte że zazwyczaj nie piszemy deklaracji typu do main. Nową i interesującą rzeczą, której wcześniej nie napotkaliśmy znajduje się w linii trzeciej name <- getline. Wygląda jakby czytała linie z urządzenia wejścia i przypisywała do zmiennej nazwanej name. Ale czy naprawdę. Sprawdźmy typ getline. ghci> :t getline getline :: IO String Aha getline jest akcją I/O która zawiera we wnętrzu rezultat typu String. Ma to sens, gdyż ta akcja poczeka aż użytkownik wprowadzi jakieś dane przy użyciu klawiatury i te dane będą reprezentowane jako string. A co z name <- getline? Można ten kawałek programu interpertować(rozumieć) tak: wykonaj akcje I/O getline i potem powiąż(wyciągnis z wnętrza akcji) wczytaną wartość z nazwą name. getline ma typ IO String, więc name będzie miało typ String. Można myśleć o I/O akcji jako o pudełku/kontenerze z nogami, które wniosą pudełko (I/O akcje) w rzeczywisty świat i coś w nim zrobią (np. namalują jakiś rysunek na ścianie) i może powrócą z jakimiś danymi w pudełku. Jak już pudełko z danymi powróciło, to jedynym sposobem na otwarcie i wyciągnięcie danych z tego pudełka jest użycie konstrukcji <-. A jeśli już chcemy się dobierać do danych w I/O akcji, to musimy robić to we wnętrzu innej I/O akcji. W taki oto sposób Haskell-owi udaje się starannie oddzielić czyste i nieczyste kawałki naszego kodu (programu). getline jest nieczyste bo zwracana wartość może być inna za każdym wywołaniem. Dlatego getline jest skażonym konstruktorem typu IO i można dostać się do danych tylko w kodzie I/O. I dlatego że kod I/O też jest skażony, a wszelkie obliczenia które zależą od danych I/O które są skażone, będą miały skażone wyniki. Kiedy mówię skażone, nie mam na myśli że naznaczone w sensie że nigdy nie możemy użyć danych powstałych w wyniku użycia akcji IO w czystym kodzie. Wcale nie, tymczasowo odkażamy dane w środku akcji I/O kiedy powiązujemy je (dane) z nazwą, to jest kiedy wykonujemy name <- getline, name to zwykły string, reprezentuje on to co jest w środku pudełka. Możemy mieć naprawdę skomplikowaną funkcję, która np. Bierze imię (zwykły string) jako parametr i mówi ci twój horoskop, całą przyszłość twojego życia, bazując tylko na twoim imieniu. Możemy zrobić to tak: putstrln "Hello, what's your name?" name <- getline 3

4 putstrln $ "Read this carefully, because this is your future: " ++ tellfortune name i funkcja tellforune (lub każda inna funkcja do której przekażemy name ) nie musi nic wiedzieć o I/O, jest zwykłą funkcją typu String -> String! Spójrzmy na ten kawałek kodu? Czy jest poprawny? nametag = "Hello, my name is " ++ getline Jeśli powiedziałeś nie, idź w nagrodę zjeść ciasteczko, miałeś racje. Jeśli powiedziałeś tak,, napij się miski wypełnionej roztopioną lawą wulkaniczną żartuję nie pij! Przyczyną błędu jest to że ++ wymaga aby oba parametry (ten przed ++ oraz ten po ) były listami z tymi samymi typami w środku. Parametr po lewej ma typ String (czyli [Char]), a getline zwraca IO String. Nie można połączyć string-u i akcji I/O. Najpierw trzeba wyciągnąć dane z akcji I/O dostając wartość typu String, a mamy tylko jeden sposób na to. name <- getline we wnętrzu jakiejś akcji I/O. Jeśli posługujemy się nieczystymi danymi, musimy to zrobić w skażonym środowisku. Więc skażenie rozprzestrzenia się jak grupa zombi, i w naszym najlepszym interesie jest to aby część kodu z I/O była jak najmniejsza. Każda akcja I/O która jest wykonana, zawiera jakieś dane w środku. Dlatego poprzedni program może być zapisany tak: foo <- putstrln "Hello, what's your name?" name <- getline putstrln ("Hey " ++ name ++ ", you rock!") Można zauważyć że zmienna foo będzie miała przypisaną wartość (), więc przypisywanie do zmiennej wartości z putstrln jest zbędne. W kolejnym putstrln nie wyciągamy wartości z akcji I/O i nie powiązujemy z jakąś zmienną. Robimy tak gdyż w sekcji/bloku do, ostatnia akcja nie może być powiązana/przypisana z nazwą tak jak pierwsze dwie w powyższym przykładzie. Dowiemy się dlaczego tak jest trochę później, kiedy poznamy monad-y. Na razie, możecie myśleć o tym że sekcja/blok do automatycznie wyciąga wartość z ostatniej akcji i powiązuje/przypisuje do własnej zwracanej wartości. Poza pierwszą linią, każda linia w bloku/sekcji do,co do której nie ma potrzeby przypisywania/powiązywania może być zapisana tak: _ <- putstrl coś coś. Ale to jest zbędnie wiec nie piszemy <- dla akcji I/O która nie zawiera przydatnej wartości, tak jak putstrln jakis tekst Poczontkujący czasami myślą o zrobieniu czegoś takiego: name = getline czytają z wejścia i potem przypisują wartość z akcji do zmiennej name. To nie zadziała. To po prostu daje akcji I/O nową nazwę: name. Pamiętajcie, aby wydostać wartość z akcji I/O, trzeba to zrobić w środku/wewnątrz innej akcji I/O poprzez powiązanie z nazwą zmiennej operatorem <- 4

5 Akcje I/O są wykonywane tylko kiedy nazwie się je main albo kiedy one są w środku większej akcji I/O którą składamy poprzez użycie bloku/sekcji do. Używamy bloku/sekcji do w celu sklejenia razem kilku akcji I/O, w celu użycia w innym większym bloku/sekcji do i tak dalej. Mamy jeszcze jeden przypadek gdzie akcje I/O są wykonywane. Kiedy wypiszemy akcje I/O w interpreterze GHCI i naciśniemy Enter to akcja zostanie wykonana/ ghci> putstrln "HEEY" HEEY Nawet kiedy możemy wpisać liczbę lub wywołać funkcję w GHCI a potem nacisnąć return, obliczenia zostaną wykonane, na wynikach zostanie wywołane show, a na końcu wypisany tekst w terminalu przy niejawnym użyciu putstrln Pamiętacie komendę let? Przeczytajcie sekcje o niej. Ma formeę let bindings in expression, gdzie bindings są nazwami nadawanymi wyrażeniom a expression to wyrażenie które ma być wykonane. Powiedzieliśmy że w lsit comprehensions część in nie jest potrzebna,. Można ich używać w sekcjach do prawie tak samo jak w list comprehensions. Przeanalizujmy to: import Data.Char putstrln "What's your first name?" firstname <- getline putstrln "What's your last name?" lastname <- getline let bigfirstname = map toupper firstname biglastname = map toupper lastname putstrln $ "hey " ++ bigfirstname ++ " " ++ biglastname ++ ", how are you?" Widać jak akcje I/O w skecji do są ustawione. Można też zauważyć jak let są ustawione z akcjami I/O i nazwy w let są ustawione razem? To dobra praktyka, gdyż wcięcia są ważne w Haskell-u. Wykonaliśmy map toupper firstname, co np. zamienia John w JOHN. Powiązaliśmy ciągi znaków składające się z dużych liter do nazwy i użyliśmy w ciągach znaków wyświetlanych na ekranie. Zastanawiacie się kiedy używać a kiedy let? Pamiętajcie, jest między innymi do wykonywania akcji I/O i powiązywania ich wyników do nazw zmiennych. map toupper firstname, nie jest akcją I/O. Jest czystym wyrażeniem w Haskell-u. Używamy aby powiązać wynik akcji I/O do nazwy a wyrażenia let w celu powiązania czystych wyrażeń do nazw. Robiąc coś let firstname = getline nazwalibyśmy I/O akcje getline dodatkową nazwą firstname i nadal musielibyśmy użyć aby ją wykonać. Teraz zrobimy program który cały czas wczytuje linie i wypisuje ze słowami w których litery są odwrotnej kolejności. Program się zatrzymuje po wpisaniu pustej linii. Oto ten program: line <- getline if null line then return () 5

6 else do putstrln $ reversewords line main reversewords :: String -> String reversewords = unwords. map reverse. words Aby poczuć co program robi, możecie wykonać go przed omówieniem kodu. WSKAZOWKA: Aby uruchomić program, można go skompilować i wykonać plik wykonywalny ghc make helloworld i potem./hellowold lub można użyć komendy runhaskell tak: runhaskell helloworld.hs Najpierw spójrzmy na funkcje reversewords. To zwykła czysta funkcja biorąca string np. hey there man i potem wykonująca na nim words aby wyprodukować listę słów [ hey, there, man ] Potem używamy map reverse na litej liście otrzymując [ yeh, ereht, nam ] i na końcu z listy tworzymy jeden string przy użyciu unwords otrzymując yeh ereht nam Przyjrzyjcie jak użyliśmy składania funkcji. Bez kompozycji funkcji trebaby było napisać reversewords st = unwords(map reverse (words st)). A co z main? Najpierw wczytujemy linie z terminala poprzez wywołanie getline. Poniżej mamy wyrażenie warunkowe if. Pamiętajcie że w Haskell-u każde if musi mieć odpowiadające else gdyż każde wyrażenie musi zwracać jakąś wartość. Konstruujemy wyrażenie if tak że kiedy warunek jest prawdą (true) (w tym przypadku kiedy wpisana linia jest pusta) wykonujemy jedną akcje I/O a kiedy warunek nie jest spełniony akcja IO pod else jest wykonywana. Z tych powodów w I/O sekcji do if-y muszą mieć taką formę: if condition then I/O action else I/O action Popatrzmy co się dzieje w członie else Skoro musimy mieć dokładnie jedną akcje I/O po else używamy do do sklejenia dwóch akcji I/O w jedną. Można by było zapisać tą cześć tak: else (do putstrln $ reversewords line main) Co się dzieje kiedy null line jest prawdą? Co jest wykonywane po then? Widzimy że tam jest napisane then return (). Jeśli znacie języki imperatywne takie jak C, Java czy Python pewnie myślicie że wiecie co robi return. W Haskell-u return to coś innego niż w większości innych języków i dlatego nazwa return dezorientuje ludzi. W językach imperatywnych, return zazwyczaj kończy wykonywanie metody, lub podprogramu i zazwyczaj zwraca jakąś wartość do miejsca wywołania.. W Haskell-u return, (zwłaszcza w akcji I/O) tworzy akcje I/O z czystej wartości. Jeśli użyjemy analogii pudełka to return bierze wartość i opakowuje ją pudełkiem. Nowo powstała akcja nic nie robi,ma tylko jakąś wartość. Więc w kontekście I/O return haha będzie typu IO String. Poco zamieniać czystą wartość w akcje I/O która nic nie robi? Po co plamić program dodatkową akcją I/O - bo potrzeba jakiejś akcji I/O w przypadku pustej linii na wejściu. Dlatego tworzymy pustą akcje, która nic nie robi poprzez return (). Użycie return nie skutkuje w zakończeniu wykonywania I/O sekcji do. Następujący program wykona wszystkie linie aż do końca. 6

7 return () return "HAHAHA" line <- getline return "BLAH BLAH BLAH" return 4 putstrln line Te wszystkie return -y nic nie robią poza kapsułkowaiem wartości. Owe wartości nie są użyte, nie są powiązane z jakąś nazwą. Jest możliwe użycie return oraz do związania jakiejś wartości z nazwą. a <- return "hell" b <- return "yeah!" putstrln $ a ++ " " ++ b Jak widać return jest czymś w rodzaju odwrotności do. Wiadomo że return bierze wartość i opakowuje ją pudełkiem, a bierze pudełko (i wykonuje je (jakąś akcje)), wyjmuje wartość z pudełka i wiąże z nazwą. W powyższym przykładzie użycie return i zaraz potem jest zbędne. Można użyć let w środku sekcji do tak jak poniżej. let a = "hell" b = "yeah" putstrln $ a ++ " " ++ b Podczas używania I/O sekcji do najczęściej używamy return bo trzeba stworzyć akcję I/O która nic nie robi, albo nie chcemy aby akcja I/O tworzona przez sekcje do miała wartość ostatniej akcji zawartej w sekcji do, a chcemy inną wartość którą tworzymy przez return z potrzebną wartością w środku. Owe return umieszczamy jako ostatnią linie w sekcji do. Sekcja do może mieć tylko jedną akcję I/O, a wtedy można zastąpić sekcje do właśnie tą akcją I/O. Niektórzy preferują napisanie then do return () bo w jednym z powyższych przykładów po else było do. Przed rozpatrywaniem operacji na plikach, spójrzmy na kilka przydatnych funkcji przy pracy z I/O. PutStr jest prawie takie same jak putstrln, bo bierze string jako parametr a zwraca akcję I/O która wyświetla string na ekranie ale nie przechodzi do nowej linii.. putstr "Hey, " putstr "I'm " putstrln "Andy!" $ runhaskell putstr_test.hs Hey, I'm Andy! Ma sygnaturę typu putstr :: String -> IO () więc wartością opakowaną jest () (unit), wartość bezużyteczna więc nie potrzeba powiązywania jej a nazwą. 7

8 putchar bierze znak i zwraca I/O akcje która wyświetli go na ekranie putchar 't' putchar 'e' putchar 'h' $ runhaskell putchar_test.hs teh putstr jest definiowany rekurencyjnie przy użyciu putchar. Graniczny warunek putstr-a jest pusty string, więc kiedy wyświetlamy pusty string, akcja tworzona przez return () jest zwracana. Jeśli string nie jest pusty, wyświetl pierwszy znak przy użyciu putchar, a resztę przy użyciu putstr. putstr :: String -> IO () putstr [] = return () putstr (x:xs) = do putchar x putstr xs Widzimy że można używać rekurencji w I/O, tak jak w czystym kodzie. Tak jak w czystym kodzie definiujemy brzegowy przypadek i potem myślimy czym jest wynik. To akcja wyświetlająca pierwszy znak, a po nim wyświetlająca resztę string-u. print bierze wartość która jest instancją show (co znaczy że wiemy jak ją reprezentować w formie tekstowej), wywołuje show. W zasadzie jest to putstrln. show. i Najpierw jest uruchomiony show z daną wartością, a później putstrln, co zwraca I/O akcje która wyświetli wartość. print True print 2 print "haha" print 3.2 print [3,4,3] $ runhaskell print_test.hs True 2 "haha" 3.2 [3,4,3] Pamiętacie kiedy rozmawialiśmy o akcjach I/O wykonywanych tylko wtedy kiedy są w main, lub kiedy wykonujemy je w GHCI. Kiedy wpiszemy wartość (np. 3 lub [1,2,3]) i naciśniemy klawisz return, GHCI użyje print aby wyświetlić wartość na ekranie. ghci> 3 3 ghci> print 3 3 ghci> map (++"!") ["hey","ho","woo"] ["hey!","ho!","woo!"] 8

9 ghci> print (map (++"!") ["hey","ho","woo"]) ["hey!","ho!","woo!"] Kiedy chcemy wyświetlić string, zazwyczaj używamy putstrln, gdyż nie chcemy mieć tekstu w cudzysłowach. Do innych typów używamy print. Akcja getchar czyta jeden znak z wejścia i ma następującą sygnaturę typu: getchar :: IO Char, bo wartość w tej akcji ma typ Char. Zauważcie że z powodu buforowania, wczytanie znaku nie nastąpi dopóki klawisz return nie zostanie wciśnięty. c <- getchar if c /= ' ' then do putchar c main else return () Po przyjrzeniu się programowi wygląda na to że powinien wczytać znak, sprawdzić czy jest to spacja jeśli tak to zakończyć wykonywanie programu, w przeciwnym wypadku wyświetli c literę na ekranie, po czym zrobić to samo od nowa. Ten program prawie tak działa: $ runhaskell getchar_test.hs hello sir hello W drugiej linii widać co wpisane zostało z klawiatury (hello sir). Z powodu buforowania wykonywanie programu rozpocznie się kiedy naciśniemy enter a nie po pierwszej literze. Ale kiedy wciśniemy enter, to działa z tym co zostało wpisane. Funkcja when znajduje się w Control.Monad (aby dostać dostęp do niej trzeba wpisać import Control.Monad) Interesujące jest to że sekcja do wygląda jak instrukcja kontroli przepływu, lecz jest zwykłą funkcją która bierze wartość typu boolean oraz akcje I/O. Jeśli wartość boolean jest True ta sama akcja I/O jest zwracana, w przeciwnym przypadku zwraca return () czyli akcję która nic nie robi. Moglibyśmy powyższy program zapisać tak: import Control.Monad c <- getchar when (c /= ' ') $ do putchar c main Jak widać można użyć when w przypadku wzorca: if coś then do jakaś kacja IO esle return () sequence bierze listę akcji I/O i zwraca akcje I/O wykonującą akcje z listy jedna po drugiej. Wartością wewnątrz z tej nowej akcji I/O będzie lista wartości z każdej akcji na liście. Sygnatura typu to: sequence :: [IO a] IO [a]. Dwa poniższe programy są równoważne: 9

10 a <- getline b <- getline c <- getline print [a,b,c] rs <- sequence [getline, getline, getline] print rs Widać że sequence [getline, getline, getline] tworzy akcję I/O która wykona trzy razy getline. Jeśli powiążemy tę akcję z jakąś nazwą, wynikiem będzie lista wszystkich rezultatów, a w powyższym przykładzie lista trzech rzeczy które użytkownik wpisał z klawiatury. Często używamy sequence kiedy używamy funkcji map z print lub putstrln na listach, np. map print [1,2,3,4] nie stworzy akcji I/O, ale taką listę akcji I/O: [print 1, print 2, print 3, print 4]. Jeśli chcemy zmienić tę listę akcji I/O w akcję I/O to musimy użyć sequence. ghci> sequence (map print [1,2,3,4,5]) [(),(),(),(),()] A co z [(),(),(),(),()] na koncu? Kiedy GHCI wykona akcje I/O, wyświetla ich wynik chyba że wynikiem jest (), wtedy nie jest wyświetlany. Dlatego wykonanie putstrln hehe w GHCI wyświetla tylko hehe (gdyż wartością w środku jest ()), a kiedy wykonamy getline w GHCI to wynikiem jest akcja I/O której wartość jest wyświetlona.. getline ma typ IO String. Skoro użycie map z funkcją zwracającą akcję I/O na liście jest powszechne, stworzono funkcję mapm, która bierze funkcję i listę, wykonuje map funkcja na liście a na wyniku używa sequence. mapm_ robi to samo, lecz ignoruje wynik. ghci> mapm print [1,2,3] [(),(),()] ghci> mapm_ print [1,2,3] forever bierze akcję I/O i zwraca akcję która powtarza początkową akcje w nieskończoność, a znajduje się w Control.Monad. Następujący program zawsze będzie się pytał o wpisanie czegoś, po czym wyświetli owy tekst dużymi literami. import Control.Monad 10

11 import Data.Char main = forever $ do putstr "Give me some input: " l <- getline putstrln $ map toupper l form z Control.Monad jest jak mapm, z tą różnicą że ma parametry w odwrotnej kolejności. Pierwszym parametrem jest lista, drugim funkcja. Dlaczego jest to przydatne? W niektórych kreatywnych użyciach lambdy i notacji do można zrobić coś takiego: import Control.Monad colors <- form [1,2,3,4] (\a -> do putstrln $ "Which color do you associate with the number " ++ show a ++ "?" color <- getline return color) putstrln "The colors that you associate with 1, 2, 3 and 4 are: " mapm putstrln colors Funkcja (\a -> do... ) bierze liczbę i zwraca akcję I/O. Musieliśmy otoczyć ją nawiasami, w przeciwnym wypadku lambda myślałaby że dwie ostatnie akcję należą do niej. Zwróćcie uwagę na return color w bloku do. Robimy tak aby akcja I/O definiowana przez sekcję do zawierała w sobie color. Tak naprawdę nie trzeba by tego robić. Zamiast color getline return color można by użyć tylko samej getline. Odpakowywanie koloru przez i pakowanie go przez return jest zbędne. form (wywołane z dwoma parametrami) produkuje akcję I/O, których wynik wiążemy z nazwą colors. colors to zwykła lista z string-ami. Na końcu wyświetlamy kolory z listy przez użycie mapm putstrln colors Można myśleć o form tak: stwórz akcję I/Odla każdego elementu w liście. Co każda akcja I/O zrobi zależy na elemencie użytym do stworzenia akcji..na koniec wykonaj owe akcje, i zwiąż wyniki do jakieś nazwy. Nie musimy wiązać, można wyrzucić $ runhaskell form_test.hs Which color do you associate with the number 1? white Which color do you associate with the number 2? blue Which color do you associate with the number 3? red Which color do you associate with the number 4? orange The colors that you associate with 1, 2, 3 and 4 are: white blue 11

12 red orange Można by było powyższy program napisać bez użycia form, ale taki jest bardziej czytelny. Zazwyczaj używamy form kiedy chcemy zmapować sekwencje jakiś akcji które definiujemy w miejscu przy użyciu notacji do. Mogliśmy też ostatnią linię zapisać tak: colors putstrln W tej sekcji nauczyliśmy się podstaw wejścia i wyjścia. Dowiedzieliśmy się czym są akcje I/O, jak one umożliwiają wykonanie operacji wejścia/wyjścia podczas ich wywoływania. W skrócie, akcje I/O są wartościami takimi samymi jak każde inne wartości w Haskell-y. Mozna ich użyć jako parametrów do funkcji, funkcję mogą je (akcje I/O) zwracać jako wyniki. Co je odróżnia to że jeśli wpadną do funkcji main (lub jako wynik w GHCI), są wtedy wykonywane, i wtedy one wyświetlą rzeczy na ekranie, grają muzykę przez głośniki. Każda akcja I/O opakowuje także wartość którą pobrała ze świata zewnętrznego. Nie myślcie o funkcji putstrln i podobnych, jako o funkcji która bierze string i wyświetla go na ekranie. Myślcie jako o funkcji która bierze string a zwraca akcję I/O. Ta akcja I/O, kiedy wykonana wyświetli coś na ekranie np. piękną poezje. 12

13 Pliki i strumienie getchar to akcja I/O czytająca pojedynczy znak z terminala, a getline to akcja I/O czytająca linię. Są to proste funkcje i większość języków programowania ma funkcje lub wyrażenia o podobnym działaniu lub efekcie. Teraz spotkamy się z getcontent akcje I/O która czyta wszystko ze standardowego wejścia, aż do napotkania znaku końca pliku. Jej typ to getcontents :: IO String. Fajne jest to że getcontents wykonuje leniwe I/O. Wykonanie foo<- getcontents nie skutkuje wczytaniem całego wejścia naraz, przechowania w pamięci i powiązania z nazwą foo. Skoro jest leniwe to przeczyta dane z wejścia później,kiedy będą potrzebne. getcontents jest użyteczne kiedy łączymy wyjście jakiegoś programu z wejściem innego. Jeśli nie wiesz jak potoki działają na unix-owych systemach, tutaj jest krótki elementarz. Stwórzmy plik tekstowy z następującym haiku. I'm a lil' teapot What's with that airplane food, huh? It's so small, tasteless Tak, ten haiku jest do bani. Jeśli ktoś zna dobry wstęp do haiku, powiedzcie mi o tym. Przypomnijmy program wprowadzający funkcje forever. Pytał użytkownika o wprowadzenie linii, po czym wypisywał ale używając dużych liter, i tak w nieskończoność. import Control.Monad import Data.Char main = forever $ do putstr "Give me some input: " l <- getline putstrln $ map toupper l Zapiszcie ten program jako capslocker.hs i skompilujcie go. Użyjemy unixowych potoków aby wysłać zawartość pliku tekstowego do naszego krótkiego programu. Pomoże nam GNU cat program, który wyświetla zawartość pliku podanego jako argument. $ ghc --make capslocker [1 of 1] Compiling Main ( capslocker.hs, capslocker.o ) Linking capslocker... $ cat haiku.txt I'm a lil' teapot What's with that airplane food, huh? It's so small, tasteless $ cat haiku.txt./capslocker --program cat wyswietla zawartosc pliku na standardowym wyjściu zazwyczaj ekranie a kreska przekierowuje wyjście jednego programu do wejścia drugiego I'M A LIL' TEAPOT WHAT'S WITH THAT AIRPLANE FOOD, HUH? IT'S SO SMALL, TASTELESS 13

14 capslocker <stdin>: hgetline: end of file Jak widać, wysłanie wyjścia jednego programu (w tym przypadku cat) do wejśćia innego (capsloker) jest wynikiem użycia znaku. To co zrobiliśmy jest równoważne uruchomieniu capsloker i wpisaniu haiku na klawiaturze a potem wpisanie znaku końca pliku (zazwyczaj przez naciśnięcie ctrl-d ). To jest jak uruchomienie cat haiku.txt i powiedzenie Czekaj nie wyświetlaj tego w terminalu, przekaz to do capsloker-a. Widać że to co robimy przy użyciu forever to wczytywanie z wejścia, przemienianie tego, a następnie wysyłanie na wyjście. Z tego powodu możemy użyć getcontents aby bardziej skrócić nasz program. import Data.Char contents <- getcontents putstr (map toupper contents) Wykonujemy I/O akcje getcontents i powiązujemy string z nazwą contents. Potem używamy map touppper na tym string-u i wyświetlamy na ekranie. Miejcie na uwadze że skoro string-i są listami, które są leniwe, oraz getcontents jest I/O leniwe nie spróbuje wczytać wszystkiego naraz do pamięci przed wyświetleniem przy użyciu tylko dużych liter na ekranie, będzie wyświetlał zmienione dane podczas wczytywania, ponieważ przeczyta tylko kiedy będzie potrzebował. $ cat haiku.txt./capslocker I'M A LIL' TEAPOT WHAT'S WITH THAT AIRPLANE FOOD, HUH? IT'S SO SMALL, TASTELESS Fajnie to działa. Co jeśli uruchomimy capsloker i spróbujemy sami wpisywać linie.? $./capslocker hey ho HEY HO lets go LETS GO Kończymy działanie programu przez wciśnięcie ctrl-d. Całkiem miłe. Jak widać, wyświetlają się linie napisane tylko dużymi literami, linia po linii. Kiedy wynik z getcontents jest powiązany z contents, nie jest reprezentowany w pamięci jako string, lecz jako obietnica że string będzie wyprodukowany/dostarczony. Kiedy używamy map toupper na contents, to jest to też obietnicą że te funkcje w końcu kiedyś zostaną wykonane. W końcu putstr mówi: Hej potrzebuję linii do wyświetlenia, i mówi do contents : hej wczytaj wreszcie linię z terminala. Dopiero wtedy getcontetns naprawdę wczyta coś z terminala i da linie tekstu kodowi który faktycznie o to prosił. Ten kod używa wtedy map toupper i przekazuje wynik do putstr aby był wyświetlony. Po tym putstr mówi: Dajcie mi kolejna linię.cała sytuacja się powtarza dopóki są jakieś dane na wejściu, czyli dopóki nie napotka się znaku końca pliku. Napiszmy program który czyta jakieś dane, i wyświetla tylko linie krótsze niż 10 znaków: 14

15 contents <- getcontents putstr (shortlinesonly contents) shortlinesonly :: String -> String shortlinesonly input = let alllines = lines input shortlines = filter (\line -> length line < 10) alllines result = unlines shortlines in result Zrobiliśmy sekcję z I/O tak krótką jak tylko to możliwe. Skoro program ma wczytywać jakieś dane z wejścia i wyświetlać coś bazując na tym co wczytane,to można go zaimplementować tak aby wczytywał dane, wykonywał jakąś funkcję na nich, a potem wyświetlał to co funkcja zwróciła. Funkcja shortlinesonly działa w nastepujący sposób. Bierze string np. short\nlooooooooooooong\nshort again składający się z trzech linii dwie z nich są krótkie, środkowa długa. Omawiana funkcja wywołuje funkcję lines na tym string-u, która zamienia string na listę : ["short", "looooooooooooooong", "short again"] nazwaną alllines. Ta lista jest następnie filtrowana aby linie krótsze niż 10 liter zostały w liście ["short", "short again"]. Na końcu użyta jest funkcja unlines aby połączyć elementy listy w jeden string dając "short\nshort again". i'm short so am i i am a loooooooooong line!!! yeah i'm long so what hahahaha!!!!!! short line loooooooooooooooooooooooooooong short $ ghc --make shortlinesonly [1 of 1] Compiling Main ( shortlinesonly.hs, shortlinesonly.o ) Linking shortlinesonly... $ cat shortlines.txt./shortlinesonly i'm short so am i short Jak widać wysyłamy zawartość pliku shortlines.txt poprzez użycie unixowych strumieni do wejścia programu shortlines i w rezultacie wyjściowymi liniami są te krótkie. Widać że wzorzec wczytywania jakiś string-ów z wejścia, zmieniania ich funkcją, i potem wyprowadzania rezultatów działania funkcji na wyjście jest tak często spotykany że stworzono funkcje nazywaną interact, która bierze funkcję String -> String jako parametr i zwraca akcję I/O która pobierze coś z wejścia, wykona funkcję, a potem wydrukuje wynik działania funkcji. Zmodyfikujmy program: 15

16 main = interact shortlinesonly shortlinesonly :: String -> String shortlinesonly input = let alllines = lines input shortlines = filter (\line -> length line < 10) alllines result = unlines shortlines in result Powyższy program można jeszcze skrócić (ale będzie mniej czytelny) poprzez użycie złożenia funkcji. : main = interact $ unlines. filter ((<10). length). lines Ale fajnie skróciliśmy program do jednej linii! Funkcja interact może być użyta do napisania programów do których wejścia zostaną przesłane jakieś dane, a potem coś (dane) zostaną wysłane na wyjście, lub do napisania programów, które wydają się wczytywać linie od użytkownika, potem zwracające rezultaty bazujące na tej linii, po czym wczytujące kolejną linię i tak dalej. Tak naprawdę nie ma różnicy między takimi programami,wszystko zależy od tego jak użytkownik użyje programu. Napiszmy program który cały czas czyta linie potem mówi nam czy linia jest palindromem. Moglibyśmy użyć getline do wczytania linii, powiedzieć czy linia jest palindromem i uruchomić main jeszcze raz ale jest prościej użyć interact. Kiedy używacie interact, myślcie co potrzeba zrobić aby zmienić dane wejściowe na dane wyjściowe. W rozważanym programie trzeba zamienić linie na palindrome lub not a palindrome Trzeba więc napisać funkcję która zmieni "elephant\nabcba\nwhatever" w "not a palindrome\npalindrome\nnot a palindrome". Zróbmy to! respondpalindromes contents = unlines (map (\xs -> if ispalindrome xs then "palindrome" else "not a palindrome") (lines contents)) where ispalindrome xs = xs == reverse xs A teraz napiszmy w stylu zwanym point free czyli bez użycia nazwy parametru. respondpalindromes = unlines. map (\xs -> if ispalindrome xs then "palindrome" else "not a palindrome"). lines where ispalindrome xs = xs == reverse xs Całkiem proste. Najpierw zamieniamy "elephant\nabcba\nwhatever" w ["elephant", "ABCBA", "whatever"] a potem mapujemy lambdę na tym otrzymując ["not a palindrome", "palindrome", "not a palindrome"] a potem używamy unlines aby połączyć listę w jeden string ze znakiem nowa linia oddzielającym wiersze. A teraz można: main = interact respondpalindromes Przetestujmy: 16

17 $ runhaskell palindromes.hs hehe not a palindrome ABCBA palindrome cookie not a palindrome Mimo że stworzyliśmy program który zmienia jeden duży string z wejścia w inny to działa jak program robiący to samo linia po linii. Tak jest ponieważ Haskell jest leniwy, i chce wydrukować pierwszą linie wynikowego stringu, ale nie może gdyż nie ma jeszcze pierwszej linii z wejścia. Ale jak tylko podamy mu pierwsza linię to wypisze pierwszą linie rezultatu. Wyjdziemy z programu poprzez wpisanie znaku końca linii. Możemy też użyć tego programu strumieniując dane na wejście. Powiedzmy że mamy plik words.txt. dogaroo radar rotor madam A teraz użyjmy unixowych strumieni. $ cat words.txt runhaskell palindromes.hs not a palindrome palindrome palindrome palindrome Znowu otrzymalibyśmy taki sam wynik jeśli byśmy wpisywali słowa sami z klawiatury (standardowe wejście). Nie widać tylko danych wejściowych bo pochodzą z pliku a nie z pisania na klawiaturze. Wiec pewnie teraz wiesz jak działa leniwe I/O i możesz użyć tego dla własnych korzyści. Umiesz myśleć w takich kategoriach: jaki powinien być wynik mając określone dane wejściowe i napisać funkcje do potrzebnej zmiany danych wejściowych. W leniwym I/O nic nie jest zjedzone z wejścia dopóki nie jest całkowicie potrzebne, bo co chcemy wyświetlić teraz, zależy na tych danych. Jak na razie pracowaliśmy z I/O poprzez wyświetlanie czegoś na ekranie lub czytanie z klawiatury. A co z czytaniem i zapisywaniem plików. Już to robiliśmy. Jeden ze sposobów myślenia o czytaniu z klawiatury jest wyobrażenie sobie, że to jest takie same jak czytanie z (trochę specjalnego) pliku. To samo dotyczy wyświetlania jakiegoś tekstu na ekranie. To jest rodzaj zapisywania do pliku. Nazywamy owe pliki stdin i stdout, znaczy standardowe wejście i standardowe wyjście. Mając to na uwadze widzimy że zapisywanie i czytanie z plików jest bardzo podobne do czytania i zapisywania do standardowego wejścia i wyjścia. 17

18 Zacznijmy z bardzo prostym programem otwierającym plik nazwany girlfriend.txt, który zawiera wiersze z hitu piosenkarki Avril Lavigne i wyświetla je na ekranie. Oto plik girlfriend.txt Hey! Hey! You! You! I don't like your girlfriend! No way! No way! I think you need a new one! A tu nasz program: import System.IO handle <- openfile "girlfriend.txt" ReadMode contents <- hgetcontents handle putstr contents hclose handle Po uruchomieniu widać oczekiwany rezultat. $ runhaskell girlfriend.hs Hey! Hey! You! You! I don't like your girlfriend! No way! No way! I think you need a new one! Omówmy program linia po linii! Nasz program ma kilka akcji I/O sklejonych razem przez sekcję do. W pierwszej linii bloku do, zauważamy nową funkcję openfile. Jej sygnatura to openfile :: FilePath -> IOMode -> IO Handle, czyli openfile bierze ścieżkę dostępu wraz z nazwą pliku, IOMode i zwraca akcję I/O która otworzy plik, i będzie miała uchwyt do pliku zakapsułkowany w sobie. FilePath jest synonimem String definiowanym type FilePath = String IOMode to typ zdefiniowany tak: data IOMode = ReadMode WriteMode AppendMode ReadWriteMode Tak jak nasz typ reprezentujący siedem możliwych wartości dla dni tygodni, ten typ jest typem wyliczeniowym reprezentującym co możemy zrobić z naszym otwartym plikiem. Bardzo proste. Zauważcie tylko że ten typ jest IOMode a nie IO Mode. IO Mode byłby typem akcji I/O zawierającym w sobie wynik będący wartością jakiegoś typu Mode. IOMode to tylko prosty typ wyliczeniowy. Zwrócona akcja I/O otworzy odpowiedni plik w odpowiednim trybie. Jeśli powiążemy tą akcję do jakieś nazwy to otrzymamy (uchwyt pliku) Handle. Wartość typu Handle reprezentuje lokalizację pliku. Używamy tego uchwytu do operacji na pliku. Byłoby głupotą czytanie pliku ale nie 18

19 powiązanie z uchwytem pliku bo to by nic nie dało. W naszym przykładzie nazwa handle ma odpowiednia wartość typu Handle W kolejnej linii widzimy funkcję zwaną hgetcontents biorącą uchwyt pliku jako parametr, więc wie z którego pliku czytać dane i zwraca IO String akcje I/O zawierającą w sobie zawartość pliku. Ta funkcja jest prawie jak getcontents. Jedyną różnicą jest to że getcontent automatycznie czyta ze standardowego wejścia (z klawiatury). We wszystkich innych aspektach owe funkcje działają tak samo. Tak jak getcontents, hgetcontents nie pokusi się na wczytanie całego pliku naraz do pamięci, lecz będzie czytać tylko jak zajdzie potrzeba. To całkiem Fajne. Gdyż możemy traktować contents jako całą zawartość pliku, lecz nie jest tak naprawdę w pamięci. Więc jeśli mamy naprawdę duży plik, użycie hgetcontents nie zużyje naszej pamięci, lecz wczyta to co jest potrzebne w danym momencie. Zwróćcie uwagę na różnice między uchwytem do pliku używanym do zidentyfikowania pliku a zawartością pliku. Uchwyt do pliku jest czymś dzięki czemu wiemy czym nasz plik jest. Jeśli wyobrazicie sobie że cały system plików jest dużą książką, każdy plik rozdziałem, uchwyt pliku jest zakładką pokazującą skąd obecnie czytamy (lub piszemy), w którym rozdziale jesteśmy, a zawartość to cały rozdział. Funkcja putstr contents wyświetla zawartość na standardowym wyjściu, potem wykonujemy hclose biorącym handle jako parametr co zwraca akcje I/O zamykającą plik. Trzeba zamknąć plik po otwarciu przez openfile. Innym sposobem robienia tego co właśnie zrobiliśmy jest użycie funkcji withfile mającej sygnature: withfile :: FilePath -> IOMode -> (Handle -> IO a) -> IO a. Owa funkcja bierze ścieżkę z nazwa pliku (typ FilePath) oraz IOMode potem funkcję biorącą uchwyt pliku i zwracającą jakąś akcje I/O. Funkcja withfile zwraca akcję I/O otwierającą określony plik, robiącą to co chcemy z plikiem po czym zamykającą go. Wynik jest zakapsułkowany w akcji I/O która jest zwrócona, jest taki sam jak wynik I/O akcji funkcji będącej trzecim parametrem. To może wyglądać trochę skomplikowanie, ale jest całkiem proste, zwłaszcza z lambdami. Oto nasz poprzedni program napisany przy użyciu withfile import System.IO withfile "girlfriend.txt" ReadMode (\handle -> do contents <- hgetcontents handle putstr contents) Jak widać ten program jest bardzo podobny do poprzedniego. (\handle ->...) to funkcja biorąca uchwyt do pliku i zwracająca akcje I/O. Zazwyczaj robi się to jak tu przy użyciu lambda. Powodem na branie jako parametr funkcji biorącej uchwyt pliku i zwracającej akcję I/O zamiast brani akcji I/O jest to że aby stworzyć akcje I/O działającą na określonym pliku jest potrzebny uchwyt do tego pliku. Funkcja withfile otwiera plik, potem przekazuje uchwyt do funkcji która podaliśmy jako parametr, otrzymuje akcję I/O z owej funkcji. Potem tworzy nową akcję prawie taką samą jak ta stworzona prze funkcje, ale zamykającą plik. Oto jak byśmy zdefiniowali własne withfile 19

20 withfile' :: FilePath -> IOMode -> (Handle -> IO a) -> IO a withfile' path mode f = do handle <- openfile path mode result <- f handle hclose handle return result Wiemy że wynikiem będzie akcją I/O więc można zacząć z do. Najpierw otwieramy plik i powiązujemy uchwyt pliku z nazwą handle. Potem wywołujemy naszą funkcję dając mu uchwyt pliku jako parametr, dostając akcję I/O która zrobi całą pracę. Powiązujemy to co w akcji z nazwą result, zamykamy plik przez wywołanie hclose handle a Na końcu tworzymy akcję zwracaną przez sekcje do (return result). Jak pamiętacie użycie return result Jakaś_nazwa zwraca akcję I/O z zakapsułkowanymi jakimiś danymi, w tym przypadku danymi wyciągniętym z akcji zwróconej przez funkcję f. Widać więc że f handle zwróci akcję która przeczyta linie z standardowego wejścia i zapisze je do pliku i będzie miała zakapsułkowaną liczbę linii wczytanych ze standardowego wejścia. Jeśli użylibyśmy funkcję f z withfile, to końcowa akcja I/O także by miała w sobie liczbę linii wczytanych z wejścia. Tak jak mamy hgetcontents działający z plikami tak samo jak getcontents ze standardowym wejściem są funkcje hgetline, hputstr, hputstrln, hgetchar, itp. Działają tak jak odpowiedniki bez h, ale potrzebują parametru będącego uchwytem pliku, aby wiedzieć z jakim plikiem działają. I tak putstrln to funkcja biorąca string i zwracająca akcję I/O która wyświetli ten string na ekranie oraz przejdzie do nowej linii. Analogicznie hputstrln bierze uchwyt pliku oraz string i zwraca akcję I/O która zapisze string do pliku skojarzonego z uchwytem, zapisze znak nowej linii za stringiem. I tak samo hgetline bierze uchwyt pliku i zwraca akcję I/O czytającą linię z pliku, Czytanie i pisanie zawartości pliku jako string-ów jest tak częste że mamy funkcje robiące nasze życie łatwiejszym. Funkcja readfile ma sygnature typu: readfile :: FilePath -> IO String. Pamiętajcie ze FilePath to inna nazwa typu String. Funkcja readfile bierze ścieżkę dostępu razem z nazwą pliku jako pierwszy parametr i zwraca akcję I/O która wczyta zawartość pliku (oczywiście w leniwy sposób), i powiąże zawartość do jakiegoś string-u. Użycie owej funkcji jest poręczniejsze niż używanie openfile, powiązywanie uchwytu pliku do nazwy, po czym wywoływanie hgetcontents. Oto jak możemy zapisać poprzedni program używając readfile. import System.IO contents <- readfile "girlfriend.txt" putstr contents Skoro nie dostajemy uchwytu do pliku, sami nie możemy zamknąć pliku, Haskell i readfile zamykają plik automatycznie. 20

21 Funkcja writefile ma typ:writefile :: FilePath -> String -> IO (). Bierze ścieżkę dostępu wraz z nazwą pliku jako pierwszy parametr, String do zapisania do pliku jako drugi parametr i zwraca akcję I/O która wykona zapis do pliku. Jeśli plik już istnieje, zostanie skrócony do długości 0, przed zapisaniem danych. Oto jak zmienić plik grilfirend.txt w wersje zapisaną dużymi literami i zapisanie go jako girlfriendcaps.txt: import System.IO import Data.Char contents <- readfile "girlfriend.txt" writefile "girlfriendcaps.txt" (map toupper contents) $ runhaskell girlfriendtocaps.hs $ cat girlfriendcaps.txt HEY! HEY! YOU! YOU! I DON'T LIKE YOUR GIRLFRIEND! NO WAY! NO WAY! I THINK YOU NEED A NEW ONE! Funkcja appendfile ma sygnaturę typu taką samą jak writefile i appendfile nie skraca pliku do długości zero przed zapisanie jeśli plik już istnieje, ale dodaje nowe rzeczy na końcu pliku. Powiedzmy że mamy plik todo.txt który ma jedną rzecz do zrobienia w każdej linii. Zróbmy program który wczytuje linie ze standardowego wejścia i dodaje do listy to-do. import System.IO todoitem <- getline appendfile "todo.txt" (todoitem ++ "\n") $ runhaskell appendtodo.hs Iron the dishes $ runhaskell appendtodo.hs Dust the dog $ runhaskell appendtodo.hs Take salad out of the oven $ cat todo.txt Iron the dishes Dust the dog Take salad out of the oven Potrzeba dodać \n na koniec każdej linii ponieważ getline nie daje nam znaku nowej linii na końcu. Mówiliśmy wcześniej o contents <- hgetcontents handle nie wczytuje całego pliku naraz jest leniwe więc robiąc to: 21

22 withfile "something.txt" ReadMode (\handle -> do contents <- hgetcontents handle putstr contents) Jest jak łączenie strumienia danych z pliku do standardowego wyjścia. Tak jak można myśleć o strumieniach to można myśleć o plikach jako strumieniach. Powyższy program będzie czytać jedną linię, wypisywać na ekranie i tak dalej. Zadacie pytanie, jak szeroki jest strumień, jak często czyta się dane z dysku. Zazwyczaj pliki tekstowe domyślnie są buforowane linia po linii, co oznacza że najmniejsza cześć pliku tekstowego czytana na raz to linia. To jest powodem dlaczego program czyta jedna linię i wyświetla ją na ekranie, po czym czyta następną i tak dalej. Dla plików binarny zazwyczaj buforuje się jeden blok co oznacza ze plik będzie czytany kawałek po kawałku. Wielkość owego kawałka jest ustawiana przez system operacyjny. Można kontrolować jak dużo danych jest buforowanych przy użyciu funkcji hsetbuffering, biorącej uchwyt do pliku i zmienną typu BufferMode, Ta funkcja zwraca akcje I/O która ustawia buforowanie. BufferMode to typ wyliczeniowy z następującymi wartościami: NoBuffering, LineBuffering lub BlockBuffering (Maybe Int). Typ Maybe Int ustawia wielkość wczytywanych oraz zapisywanych kawałków w bajtach. Jeśli ma wartość Nothing, to wtedy system operacyjny ustawia wielkość. NoBuffering znaczy że plik będzie czytany znak po znaku. NoBuffering jest zazwyczaj mało przydatny bo powoduje bardzo dużo operacji dyskowych. Oto poprzedni program ale czytający plik w kawałkach o wielkości 2048 bajtów. withfile "something.txt" ReadMode (\handle -> do hsetbuffering handle $ BlockBuffering (Just 2048) contents <- hgetcontents handle putstr contents) Czytanie plików przy użyciu większych kawałków powoduje minimalizację liczby dostępów do dysku, lub zasobu sieciowego. Można używać hflush funkcji biorącej uchwyt pliku i zwracającej akcję I/O, która opróżni bufor pliku skojarzonego z uchwytem. Kiedy buforujemy każda linię, opróżniamy bufory co każdą linię. Kiedy używamy buforowania blokowego, opróżniamy po przeczytaniu kawałka. Bufor też jest opróżniany po zamknięciu pliku. Kiedy doszliśmy do znaku nowej linii, mechanizm zapisu(odczytu) zatwierdza wszystkie dane. Można użyć hflush do wymuszenia zatwierdzenia danych wczytanych lub zapisanych. Po użyciu hflush dane są dostępne dla innych działających programów w tym samym czasie. Myślcie o czytaniu pliku buforowanego blok po bloku tak: Sedes będzie spuszczał wodę automatycznie po uzbieraniu 4 litrów w zbiorniku. Wiec jeśli zaczniesz wlewać wodę i kiedy nalejesz 4 litry, ta woda automatycznie zostanie spuszczona i dane w tej wodzie właśnie wlanej będą przeczytane. Można spuścić wodę ręcznie przez wciśniecie dźwigni - metafora hflush. Nie jest zbyt dobrą analogia. Mamy już program do dodania nowej rzeczy do listy to-do w todo.txt. Stwórzmy program do usunięcia rzeczy z listy. Użyjemy nowych funkcji z System.Directory i System.IO 22

23 import System.IO import System.Directory import Data.List handle <- openfile "todo.txt" ReadMode (tempname, temphandle) <- opentempfile "." "temp" contents <- hgetcontents handle let todotasks = lines contents numberedtasks = zipwith (\n line -> show n ++ " - " ++ line) [0..] todotasks putstrln "These are your TO-DO items:" putstr $ unlines numberedtasks putstrln "Which one do you want to delete?" numberstring <- getline let number = read numberstring newtodoitems = delete (todotasks!! number) todotasks hputstr temphandle $ unlines newtodoitems hclose handle hclose temphandle removefile "todo.txt" renamefile tempname "todo.txt" Najpierw otwieramy plik todo.txt w trybie do odczytu i powiązujemy uchwyt pliku z nazwą handle. Następnie używamy funkcji z System.IO opentempfile. Nazwa wyjaśnia wszystko otwiera plik tymczasowy. Jej parametrami są nazwa katalogu i nazwa pliku tymczasowego. Użyliśmy. Jako nazwy katalogu bo. oznacza obecny katalog w większości systemów operacyjnych. Użyliśmy temp jako szablonu nazwy pliku tymczasowego co oznacza ze nazwa pliku tymczasowego będzie maiła nazwę temp plus jakieś losowe znaki. Owa funkcja zwraca akcje I/O tworzącą plik tymczasowy. Wynikiem w tej akcji jest para wartości, nazwa pliku tymczasowego oraz uchwyt do niego. Można by było otworzyć zwykły plik nazwany todo2.txt ale lepiej jest użyć OpenTempFile aby mieć pewność że nie modyfikujemy już istniejącego pliku, Powód nie użycia getcuttentdirectory do dowiedzenia się jaki jest obecny katalog i potem podania go do opentempfile, ale użycie. jest taki że. oznacza obecny katalog w Windowsie i w unix-ie. Potem powiązujemy zawartość todo.txt do zmiennej contents. Później tworzymy ze string-u listę string-ów, każdy będący jedną linią. W wyniku mamy coś takiego : ["Iron the dishes", "Dust the dog", "Take salad out of the oven"]. Używamy funkcji zip z liczbami od 0 do nieskończoności listą i z funkcją biorącą liczbę np. 3 i string np.: hey i zwracającą string 3 hey wiec tworzymy listę nazwaną numberedtasks ["0 - Iron the dishes", "1 - Dust the dog".... Następnie łączymy tą listę przez użycie unlines i wyświetlamy na ekranie. Można by było użyć mapm putstrln numberedtasks Pytamy użytkownika o numer linii którą chcemy usunąć, i czekamy na wpisanie liczby. Powiedzmy że chcemy usunąć linie o numerze 1 czyli Dust the dog, czyli wpisujemy 1.Nazwa numberstring ma wartość 1, a ponieważ chcemy liczbę a nie string to wykonujemy read dostając liczbę 1 i nazywając ją number. 23

24 Pamiętacie funkcje delete oraz!! z Data.List.!! zwraca element z listy o określonym indeksie a delete usuwa pierwsze wystąpienie elementu w liście i zwraca nową listę bez tego elementu. (todotasks!! number) (number to 1) zwraca Dust the dog. Nazywamy todotask bez Dust the dog nazwą newtodolist i łączymy przy użyciu unlines w jeden string potem zapisujemy do pliku tymczasowego otwartego wcześniej. Poprzedni plik jest niezmieniony a tymczasowy zawiera wszystkie linie poza linią o psie. Potem zamykamy oba pliki, usuwamy oryginalny przy użyciu removefile, który jak widzicie bierze ścieżkę dostępu z nazwą pliku. Po usunięciu, używamy renamefile aby zmienić nazwę tymczasowego pliku na todo.txt. Pamiętajcie że funkcje removefile oraz renamefile nie biorą uchwytu pliku tylko nazwę pliku ze ścieżką jako parametr. I to wszystko. Moglibyśmy napisać ten program przy użyciu mniejszej ilości linii, ale byliśmy ostrożni aby nie nadpisać czegoś i poprosiliśmy system operacyjny o stworzenie pliku tymczasowego. $ runhaskell deletetodo.hs These are your TO-DO items: 0 - Iron the dishes 1 - Dust the dog 2 - Take salad out of the oven Which one do you want to delete? 1 $ cat todo.txt Iron the dishes Take salad out of the oven $ runhaskell deletetodo.hs These are your TO-DO items: 0 - Iron the dishes 1 - Take salad out of the oven Which one do you want to delete? 0 $ cat todo.txt Take salad out of the oven 24

WEJŚCIE/WYJŚCIE HASKELL ŁUKASZ PAWLAK DARIUSZ KRYSIAK

WEJŚCIE/WYJŚCIE HASKELL ŁUKASZ PAWLAK DARIUSZ KRYSIAK WEJŚCIE/WYJŚCIE HASKELL ŁUKASZ PAWLAK DARIUSZ KRYSIAK W Haskellu funkcje nie mogą zmieniać stanów (w tym np. zmieniać wartości zmiennej). Funkcja wywołana z pewnymi ustalonymi argumentami musi zwracać

Bardziej szczegółowo

Zatem w jaki sposób nasze programy mają komunikować się ze światem zewnętrznym?

Zatem w jaki sposób nasze programy mają komunikować się ze światem zewnętrznym? Wprowadzenie Haskell jest językiem czysto funkcyjnym. W uproszczeniu oznacza to, że w przeciwieństwie do języków imperatywnych (w których podajemy komputerowi ciąg kroków do wykonania) definiujemy co,

Bardziej szczegółowo

Wskaźniki a tablice Wskaźniki i tablice są ze sobą w języku C++ ściśle związane. Aby się o tym przekonać wykonajmy cwiczenie.

Wskaźniki a tablice Wskaźniki i tablice są ze sobą w języku C++ ściśle związane. Aby się o tym przekonać wykonajmy cwiczenie. Część XXII C++ w Wskaźniki a tablice Wskaźniki i tablice są ze sobą w języku C++ ściśle związane. Aby się o tym przekonać wykonajmy cwiczenie. Ćwiczenie 1 1. Utwórz nowy projekt w Dev C++ i zapisz go na

Bardziej szczegółowo

Nazwa implementacji: Nauka języka Python wyrażenia warunkowe. Autor: Piotr Fiorek. Opis implementacji: Poznanie wyrażeń warunkowych if elif - else.

Nazwa implementacji: Nauka języka Python wyrażenia warunkowe. Autor: Piotr Fiorek. Opis implementacji: Poznanie wyrażeń warunkowych if elif - else. Nazwa implementacji: Nauka języka Python wyrażenia warunkowe Autor: Piotr Fiorek Opis implementacji: Poznanie wyrażeń warunkowych if elif - else. Nasz kalkulator umie już liczyć, ale potrafi przeprowadzać

Bardziej szczegółowo

znajdowały się różne instrukcje) to tak naprawdę definicja funkcji main.

znajdowały się różne instrukcje) to tak naprawdę definicja funkcji main. Część XVI C++ Funkcje Jeśli nasz program rozrósł się już do kilkudziesięciu linijek, warto pomyśleć o jego podziale na mniejsze części. Poznajmy więc funkcje. Szybko się przekonamy, że funkcja to bardzo

Bardziej szczegółowo

Wskaźnik może wskazywać na jakąś zmienną, strukturę, tablicę a nawet funkcję. Oto podstawowe operatory niezbędne do operowania wskaźnikami:

Wskaźnik może wskazywać na jakąś zmienną, strukturę, tablicę a nawet funkcję. Oto podstawowe operatory niezbędne do operowania wskaźnikami: Wskaźniki są nieodłącznym elementem języka C. W języku C++ także są przydatne i korzystanie z nich ułatwia pracę, jednak w odróżnieniu do C wiele rzeczy da się osiągnąć bez ich użycia. Poprawne operowanie

Bardziej szczegółowo

Programowanie w języku Python. Grażyna Koba

Programowanie w języku Python. Grażyna Koba Programowanie w języku Python Grażyna Koba Kilka definicji Program komputerowy to ciąg instrukcji języka programowania, realizujący dany algorytm. Język programowania to zbiór określonych instrukcji i

Bardziej szczegółowo

Informatyka I: Instrukcja 4.2

Informatyka I: Instrukcja 4.2 Informatyka I: Instrukcja 4.2 1 Wskaźniki i referencje - bezboleśnie Nauczyliśmy się do tej pory, że funkcje w języku C mogą zwracać wartość. Co jednak, gdybyśmy chcieli napisać funkcję, która rozwiąże

Bardziej szczegółowo

1 Podstawy c++ w pigułce.

1 Podstawy c++ w pigułce. 1 Podstawy c++ w pigułce. 1.1 Struktura dokumentu. Kod programu c++ jest zwykłym tekstem napisanym w dowolnym edytorze. Plikowi takiemu nadaje się zwykle rozszerzenie.cpp i kompiluje za pomocą kompilatora,

Bardziej szczegółowo

TWORZENIE SWOICH TYPÓW I TYPÓW KLAS HASKELL (RODZIAŁ 8) ZAJĘCIA 4

TWORZENIE SWOICH TYPÓW I TYPÓW KLAS HASKELL (RODZIAŁ 8) ZAJĘCIA 4 TWORZENIE SWOICH TYPÓW I TYPÓW KLAS HASKELL (RODZIAŁ 8) ZAJĘCIA 4 Wprowadzenie do typów algebraicznych WPROWADZENIE DO TYPÓW ALGEBRAICZNYCH Słowo data oznacza zdefiniowanie nowego typu danych Typ Bool

Bardziej szczegółowo

lekcja 8a Gry komputerowe MasterMind

lekcja 8a Gry komputerowe MasterMind lekcja 8a Gry komputerowe MasterMind Posiadamy już elementarną wiedzę w zakresie programowania. Pora więc zabrać się za rozwiązywanie problemów bardziej złożonych, które wymagają zastosowania typowych

Bardziej szczegółowo

Systemy operacyjne. Laboratorium 9. Perl wyrażenia regularne. Jarosław Rudy Politechnika Wrocławska 28 lutego 2017

Systemy operacyjne. Laboratorium 9. Perl wyrażenia regularne. Jarosław Rudy Politechnika Wrocławska 28 lutego 2017 Systemy operacyjne Laboratorium 9 Perl wyrażenia regularne Jarosław Rudy Politechnika Wrocławska 28 lutego 2017 Temat obejmuje wykorzystanie wyrażeń regularnych w perlu. Wyrażenia same w sobie są w zasadzie

Bardziej szczegółowo

Wstęp do programowania INP001213Wcl rok akademicki 2017/18 semestr zimowy. Wykład 12. Karol Tarnowski A-1 p.

Wstęp do programowania INP001213Wcl rok akademicki 2017/18 semestr zimowy. Wykład 12. Karol Tarnowski A-1 p. Wstęp do programowania INP001213Wcl rok akademicki 2017/18 semestr zimowy Wykład 12 Karol Tarnowski karol.tarnowski@pwr.edu.pl A-1 p. 411B Plan prezentacji (1) Obsługa łańcuchów znakowych getchar(), putchar()

Bardziej szczegółowo

Ćwiczenie 4. Obsługa plików. Laboratorium Podstaw Informatyki. Kierunek Elektrotechnika. Laboratorium Podstaw Informatyki Strona 1.

Ćwiczenie 4. Obsługa plików. Laboratorium Podstaw Informatyki. Kierunek Elektrotechnika. Laboratorium Podstaw Informatyki Strona 1. Laboratorium Podstaw Informatyki Strona 1 Laboratorium Podstaw Informatyki Kierunek Elektrotechnika Ćwiczenie 4 Obsługa plików Kraków 2010 Laboratorium Podstaw Informatyki Strona 2 Obsługa plików Zanim

Bardziej szczegółowo

Obsługa plików. Laboratorium Podstaw Informatyki. Kierunek Elektrotechnika. Laboratorium Podstaw Informatyki Strona 1. Kraków 2013

Obsługa plików. Laboratorium Podstaw Informatyki. Kierunek Elektrotechnika. Laboratorium Podstaw Informatyki Strona 1. Kraków 2013 Laboratorium Podstaw Informatyki Strona 1 Laboratorium Podstaw Informatyki Kierunek Elektrotechnika Obsługa plików Kraków 2013 Laboratorium Podstaw Informatyki Strona 2 Obsługa plików Zanim będziemy mogli

Bardziej szczegółowo

Podstawy programowania skrót z wykładów:

Podstawy programowania skrót z wykładów: Podstawy programowania skrót z wykładów: // komentarz jednowierszowy. /* */ komentarz wielowierszowy. # include dyrektywa preprocesora, załączająca biblioteki (pliki nagłówkowe). using namespace

Bardziej szczegółowo

1 Podstawy c++ w pigułce.

1 Podstawy c++ w pigułce. 1 Podstawy c++ w pigułce. 1.1 Struktura dokumentu. Kod programu c++ jest zwykłym tekstem napisanym w dowolnym edytorze. Plikowi takiemu nadaje się zwykle rozszerzenie.cpp i kompiluje za pomocą kompilatora,

Bardziej szczegółowo

Python jest interpreterem poleceń. Mamy dwie możliwości wydawania owych poleceń:

Python jest interpreterem poleceń. Mamy dwie możliwości wydawania owych poleceń: W pierwszym kroku nauczymy się uruchamiać w Pythonie tradycyjny* program ". Dzięki temu nauczysz się pisać w języku Python, a także zapisywać i uruchamiać swoje pythonowe programy. *Jest taka tradycja,

Bardziej szczegółowo

Bash - wprowadzenie. Bash - wprowadzenie 1/39

Bash - wprowadzenie. Bash - wprowadzenie 1/39 Bash - wprowadzenie Bash - wprowadzenie 1/39 Bash - wprowadzenie 2/39 Czym jest bash? Rysunek : Zadanie powłoki to ukrycie wywołań systemowych Bash - wprowadzenie 3/39 Czym jest bash? Przykład polecenia:

Bardziej szczegółowo

Widoczność zmiennych Czy wartości każdej zmiennej można zmieniać w dowolnym miejscu kodu? Czy można zadeklarować dwie zmienne o takich samych nazwach?

Widoczność zmiennych Czy wartości każdej zmiennej można zmieniać w dowolnym miejscu kodu? Czy można zadeklarować dwie zmienne o takich samych nazwach? Część XVIII C++ Funkcje Widoczność zmiennych Czy wartości każdej zmiennej można zmieniać w dowolnym miejscu kodu? Czy można zadeklarować dwie zmienne o takich samych nazwach? Umiemy już podzielić nasz

Bardziej szczegółowo

Laboratorium 3: Tablice, tablice znaków i funkcje operujące na ciągach znaków. dr inż. Arkadiusz Chrobot dr inż. Grzegorz Łukawski

Laboratorium 3: Tablice, tablice znaków i funkcje operujące na ciągach znaków. dr inż. Arkadiusz Chrobot dr inż. Grzegorz Łukawski Laboratorium 3: Tablice, tablice znaków i funkcje operujące na ciągach znaków dr inż. Arkadiusz Chrobot dr inż. Grzegorz Łukawski 7 kwietnia 2014 1. Wprowadzenie Pierwsza część instrukcji zawiera informacje

Bardziej szczegółowo

Zasady programowania Dokumentacja

Zasady programowania Dokumentacja Marcin Kędzierski gr. 14 Zasady programowania Dokumentacja Wstęp 1) Temat: Przeszukiwanie pliku za pomocą drzewa. 2) Założenia projektu: a) Program ma pobierać dane z pliku wskazanego przez użytkownika

Bardziej szczegółowo

1 Powtórzenie wiadomości

1 Powtórzenie wiadomości 1 Powtórzenie wiadomości Zadanie 1 Napisać program, który w trybie dialogu z użytkownikiem przyjmie liczbę całkowitą, a następnie wyświetli informację czy jest to liczba parzysta czy nieparzysta oraz czy

Bardziej szczegółowo

Po uruchomieniu programu nasza litera zostanie wyświetlona na ekranie

Po uruchomieniu programu nasza litera zostanie wyświetlona na ekranie Część X C++ Typ znakowy służy do reprezentacji pojedynczych znaków ASCII, czyli liter, cyfr, znaków przestankowych i innych specjalnych znaków widocznych na naszej klawiaturze (oraz wielu innych, których

Bardziej szczegółowo

Lab 9 Podstawy Programowania

Lab 9 Podstawy Programowania Lab 9 Podstawy Programowania (Kaja.Gutowska@cs.put.poznan.pl) Wszystkie kody/fragmenty kodów dostępne w osobnym pliku.txt. Materiały pomocnicze: Wskaźnik to specjalny rodzaj zmiennej, w której zapisany

Bardziej szczegółowo

1. Wypisywanie danych

1. Wypisywanie danych 1. Wypisywanie danych Przykłady 1.1. Napisz program, który wypisze na ekran słowa Hello, world!. 1 // Przyklad 1: Hello, world! 3 using namespace std; 5 int main() { 6 cout

Bardziej szczegółowo

Języki i metodyka programowania. Typy, operatory, wyrażenia. Wejście i wyjście.

Języki i metodyka programowania. Typy, operatory, wyrażenia. Wejście i wyjście. Typy, operatory, wyrażenia. Wejście i wyjście. Typy, operatory, wyrażenia Zmienna: [] [ '[' ']' ] ['=' ]; Zmienna to fragment pamięci o określonym

Bardziej szczegółowo

Programowanie proceduralne INP001210WL rok akademicki 2018/19 semestr letni. Wykład 6. Karol Tarnowski A-1 p.

Programowanie proceduralne INP001210WL rok akademicki 2018/19 semestr letni. Wykład 6. Karol Tarnowski A-1 p. Programowanie proceduralne INP001210WL rok akademicki 2018/19 semestr letni Wykład 6 Karol Tarnowski karol.tarnowski@pwr.edu.pl A-1 p. 411B Plan prezentacji Wskaźnik do pliku Dostęp do pliku: zapis, odczyt,

Bardziej szczegółowo

Skrypty powłoki Skrypty Najcz ciej u ywane polecenia w skryptach:

Skrypty powłoki Skrypty Najcz ciej u ywane polecenia w skryptach: Skrypty powłoki Skrypty są zwykłymi plikami tekstowymi, w których są zapisane polecenia zrozumiałe dla powłoki. Zadaniem powłoki jest przetłumaczenie ich na polecenia systemu. Aby przygotować skrypt, należy:

Bardziej szczegółowo

Narzędzia informatyczne w językoznawstwie

Narzędzia informatyczne w językoznawstwie Narzędzia informatyczne w językoznawstwie Wiersz poleceń - Potoki i pliki wsadowe Marcin Junczys-Dowmunt junczys@amu.edu.pl Zakład Logiki Stosowanej http://www.logic.amu.edu.pl 22. października 2008 Marcin

Bardziej szczegółowo

Podstawy programowania. Wykład Funkcje. Krzysztof Banaś Podstawy programowania 1

Podstawy programowania. Wykład Funkcje. Krzysztof Banaś Podstawy programowania 1 Podstawy programowania. Wykład Funkcje Krzysztof Banaś Podstawy programowania 1 Programowanie proceduralne Pojęcie procedury (funkcji) programowanie proceduralne realizacja określonego zadania specyfikacja

Bardziej szczegółowo

Strumienie, pliki. Sortowanie. Wyjątki.

Strumienie, pliki. Sortowanie. Wyjątki. Strumienie, pliki. Sortowanie. Wyjątki. Operacje I/O w Javie Serializacja Zapisuje całą klasę Plik binarny Delimiter nieokreślony Nie da się podglądać Pliki tekstowe Zapisuje wybrane informacje Plik tekstowy

Bardziej szczegółowo

Uwagi dotyczące notacji kodu! Moduły. Struktura modułu. Procedury. Opcje modułu (niektóre)

Uwagi dotyczące notacji kodu! Moduły. Struktura modułu. Procedury. Opcje modułu (niektóre) Uwagi dotyczące notacji kodu! Wyrazy drukiem prostym -- słowami języka VBA. Wyrazy drukiem pochyłym -- inne fragmenty kodu. Wyrazy w [nawiasach kwadratowych] opcjonalne fragmenty kodu (mogą być, ale nie

Bardziej szczegółowo

Informatyka I. Typy danych. Operacje arytmetyczne. Konwersje typów. Zmienne. Wczytywanie danych z klawiatury. dr hab. inż. Andrzej Czerepicki

Informatyka I. Typy danych. Operacje arytmetyczne. Konwersje typów. Zmienne. Wczytywanie danych z klawiatury. dr hab. inż. Andrzej Czerepicki Informatyka I Typy danych. Operacje arytmetyczne. Konwersje typów. Zmienne. Wczytywanie danych z klawiatury. dr hab. inż. Andrzej Czerepicki Politechnika Warszawska Wydział Transportu 2019 1 Plan wykładu

Bardziej szczegółowo

Być może jesteś doświadczonym programistą, biegle programujesz w Javie,

Być może jesteś doświadczonym programistą, biegle programujesz w Javie, Kompendium PHP 01 Być może jesteś doświadczonym programistą, biegle programujesz w Javie, C++, Pythonie lub jakimś innym języku programowania, których jak myślę, powstało już tyle, że chyba nie ma osoby,

Bardziej szczegółowo

Informatyka II. Laboratorium Aplikacja okienkowa

Informatyka II. Laboratorium Aplikacja okienkowa Informatyka II Laboratorium Aplikacja okienkowa Założenia Program będzie obliczał obwód oraz pole trójkąta na podstawie podanych zmiennych. Użytkownik będzie poproszony o podanie długości boków trójkąta.

Bardziej szczegółowo

Warunek wielokrotnego wyboru switch... case

Warunek wielokrotnego wyboru switch... case Warunek wielokrotnego wyboru switch... case Działanie instrukcji switch jest zupełnie inne niż w przypadku instrukcji if o czym będziesz mógł się przekonać w niniejszym rozdziale. Różnice pomiędzy instrukcjami

Bardziej szczegółowo

Niezwykłe tablice Poznane typy danych pozwalają przechowywać pojedyncze liczby. Dzięki tablicom zgromadzimy wiele wartości w jednym miejscu.

Niezwykłe tablice Poznane typy danych pozwalają przechowywać pojedyncze liczby. Dzięki tablicom zgromadzimy wiele wartości w jednym miejscu. Część XIX C++ w Każda poznana do tej pory zmienna może przechowywać jedną liczbę. Jeśli zaczniemy pisać bardziej rozbudowane programy, okaże się to niewystarczające. Warto więc poznać zmienne, które mogą

Bardziej szczegółowo

Technologie Informacyjne - Linux 2

Technologie Informacyjne - Linux 2 Technologie Informacyjne - 2 Instytut Matematyki Uniwersytet Gdański Powłoka - polecenia pośredniczace Polecenie grep wypisuje z pliku lub strumienia wejściowego te wiersze, które sa zgodne z podanym wyrażeniem.

Bardziej szczegółowo

TECHNOLOGIE INTERNETOWE WYKŁAD 6. JavaScript Funkcje i obiekty

TECHNOLOGIE INTERNETOWE WYKŁAD 6. JavaScript Funkcje i obiekty 1. Co to jest funkcja? Funkcja jest oddzielnym blokiem kodu, który może być wielokrotnie wykonywany w danym programie, poprzez jej wielokrotne wywoływanie. Do funkcji przekazujemy przeważnie jakieś argumenty,

Bardziej szczegółowo

Stałe, znaki, łańcuchy znaków, wejście i wyjście sformatowane

Stałe, znaki, łańcuchy znaków, wejście i wyjście sformatowane Stałe, znaki, łańcuchy znaków, wejście i wyjście sformatowane Stałe Oprócz zmiennych w programie mamy też stałe, które jak sama nazwa mówi, zachowują swoją wartość przez cały czas działania programu. Można

Bardziej szczegółowo

Jak napisać program obliczający pola powierzchni różnych figur płaskich?

Jak napisać program obliczający pola powierzchni różnych figur płaskich? Część IX C++ Jak napisać program obliczający pola powierzchni różnych figur płaskich? Na początku, przed stworzeniem właściwego kodu programu zaprojektujemy naszą aplikację i stworzymy schemat blokowy

Bardziej szczegółowo

1 Wskaźniki i zmienne dynamiczne, instrukcja przed zajęciami

1 Wskaźniki i zmienne dynamiczne, instrukcja przed zajęciami 1 Wskaźniki i zmienne dynamiczne, instrukcja przed zajęciami Celem tych zajęć jest zrozumienie i oswojenie z technikami programowania przy pomocy wskaźników w języku C++. Proszę przeczytać rozdział 8.

Bardziej szczegółowo

4. Funkcje. Przykłady

4. Funkcje. Przykłady 4. Funkcje Przykłady 4.1. Napisz funkcję kwadrat, która przyjmuje jeden argument: długość boku kwadratu i zwraca pole jego powierzchni. Używając tej funkcji napisz program, który obliczy pole powierzchni

Bardziej szczegółowo

Strumienie, pliki. Sortowanie. Wyjątki.

Strumienie, pliki. Sortowanie. Wyjątki. Strumienie, pliki. Sortowanie. Wyjątki. Serializacja Zapisuje całą klasę Plik binarny Delimiter nieokreślony Nie da się podglądać Pliki tekstowe Zapisuje wybrane informacje Plik tekstowy Delimiter ustawiamy

Bardziej szczegółowo

Wstęp do Informatyki i Programowania Laboratorium: Lista 0 Środowisko programowania

Wstęp do Informatyki i Programowania Laboratorium: Lista 0 Środowisko programowania Wstęp do Informatyki i Programowania Laboratorium: Lista 0 Środowisko programowania Przemysław Kobylański Wprowadzenie Każdy program w C musi zawierać przynajmniej funkcję o nazwie main(): Aby możliwe

Bardziej szczegółowo

Zastanawiałeś się może, dlaczego Twój współpracownik,

Zastanawiałeś się może, dlaczego Twój współpracownik, Kurs Makra dla początkujących Wiadomości wstępne VBI/01 Piotr Dynia, specjalista ds. MS Office Czas, który poświęcisz na naukę tego zagadnienia, to 15 20 minut. Zastanawiałeś się może, dlaczego Twój współpracownik,

Bardziej szczegółowo

Jak zawsze wyjdziemy od terminologii. While oznacza dopóki, podczas gdy. Pętla while jest

Jak zawsze wyjdziemy od terminologii. While oznacza dopóki, podczas gdy. Pętla while jest Pętle Pętla to pewien fragment kodu, który jest wykonywany wielokrotnie. Wyobraź sobie taką sytuację. Piszesz program do szyfrowania danych. Dane są szyfrowane kolejno bajt po bajcie. Załóżmy, że plik

Bardziej szczegółowo

PROE wykład 2 operacje na wskaźnikach. dr inż. Jacek Naruniec

PROE wykład 2 operacje na wskaźnikach. dr inż. Jacek Naruniec PROE wykład 2 operacje na wskaźnikach dr inż. Jacek Naruniec Zmienne automatyczne i dynamiczne Zmienne automatyczne: dotyczą kontekstu, po jego opuszczeniu są usuwane, łatwiejsze w zarządzaniu od zmiennych

Bardziej szczegółowo

Argumenty wywołania programu, operacje na plikach

Argumenty wywołania programu, operacje na plikach Temat zajęć: Argumenty wywołania programu, operacje na plikach Autor: mgr inż. Sławomir Samolej Zagadnienie 1. (Zmienne statyczne) W języku C można decydować o sposobie przechowywania zmiennych. Decydują

Bardziej szczegółowo

Tworzenie własnych typów. danych oraz klas typów

Tworzenie własnych typów. danych oraz klas typów Justyna Łowicka Tworzenie własnych typów danych oraz klas typów Algebraiczne typy danych konstruktorów umieszczonych w deklaracji data. Zobaczmy, jak typ Bool jest zdefiniowany w bibliotece standardowej.

Bardziej szczegółowo

Programowanie strukturalne i obiektowe. Funkcje

Programowanie strukturalne i obiektowe. Funkcje Funkcje Często w programach spotykamy się z sytuacją, kiedy chcemy wykonać określoną czynność kilka razy np. dodać dwie liczby w trzech miejscach w programie. Oczywiście moglibyśmy to zrobić pisząc trzy

Bardziej szczegółowo

Struktury, unie, formatowanie, wskaźniki

Struktury, unie, formatowanie, wskaźniki Struktury, unie, formatowanie, wskaźniki 1. Napisz aplikację, która na wejściu dostaje napis postaci W Roku Pańskim 1345, władca Henryk 12, na rzecz swoich 143209 poddanych uchwalił dekret o 20 procentowej

Bardziej szczegółowo

Programowanie obiektowe

Programowanie obiektowe Programowanie obiektowe Laboratorium 1. Wstęp do programowania w języku Java. Narzędzia 1. Aby móc tworzyć programy w języku Java, potrzebny jest zestaw narzędzi Java Development Kit, który można ściągnąć

Bardziej szczegółowo

Typy danych, cd. Łańcuchy znaków

Typy danych, cd. Łańcuchy znaków Typy danych, cd. Łańcuchy znaków Typ danych string, jest rozumiany jako łańcuch znaków - liter, cyfr i symboli. Stringi definiuje się w podwójnych lub pojedyńczych cudzysłowach. typ_ kawy = " latte " typ_herbaty

Bardziej szczegółowo

Algorytm. a programowanie -

Algorytm. a programowanie - Algorytm a programowanie - Program komputerowy: Program komputerowy można rozumieć jako: kod źródłowy - program komputerowy zapisany w pewnym języku programowania, zestaw poszczególnych instrukcji, plik

Bardziej szczegółowo

Pliki. Operacje na plikach w Pascalu

Pliki. Operacje na plikach w Pascalu Pliki. Operacje na plikach w Pascalu ścieżka zapisu, pliki elementowe, tekstowe, operacja plikowa, etapy, assign, zmienna plikowa, skojarzenie, tryby otwarcia, reset, rewrite, append, read, write, buforowanie

Bardziej szczegółowo

Systemy operacyjne. System operacyjny Linux - wstęp. Anna Wojak

Systemy operacyjne. System operacyjny Linux - wstęp. Anna Wojak Systemy operacyjne System operacyjny Linux - wstęp Anna Wojak 1 1 Wstęp Linux jest systemem z rodziny Unix. Pierwsza wersja systemu została opracowana w 1969 roku przez K.Thompsona i D.Ritchie Jest to

Bardziej szczegółowo

Powłoka I. Popularne implementacje. W stylu sh (powłoki zdefiniowanej w POSIX) W stylu csh. bash (najpopularniejsza) zsh ksh mksh.

Powłoka I. Popularne implementacje. W stylu sh (powłoki zdefiniowanej w POSIX) W stylu csh. bash (najpopularniejsza) zsh ksh mksh. Powłoka I Popularne implementacje W stylu sh (powłoki zdefiniowanej w POSIX) bash (najpopularniejsza) zsh ksh mksh W stylu csh csh tcsh 12 października 2018 1 / 16 Powłoka II Zachęta Komunikuje się z użytkownikiem

Bardziej szczegółowo

Przedrostkowa i przyrostkowa inkrementacja i dekrementacja

Przedrostkowa i przyrostkowa inkrementacja i dekrementacja Część VIII C++ Przedrostkowa i przyrostkowa inkrementacja i dekrementacja W poprzednim ćwiczeniu operatory inkrementacji i dekrementacji występowały w wersji przyrostkowej. Istnieje inny sposób zapisu

Bardziej szczegółowo

Ćwiczenie: JavaScript Cookies (3x45 minut)

Ćwiczenie: JavaScript Cookies (3x45 minut) Ćwiczenie: JavaScript Cookies (3x45 minut) Cookies niewielkie porcje danych tekstowych, które mogą być przesyłane między serwerem a przeglądarką. Przeglądarka przechowuje te dane przez określony czas.

Bardziej szczegółowo

C++ Przeładowanie operatorów i wzorce w klasach

C++ Przeładowanie operatorów i wzorce w klasach C++ i wzorce w klasach Andrzej Przybyszewski numer albumu: 89810 14 listopada 2009 Ogólnie Przeładowanie (przeciążanie) operatorów polega na nadaniu im nowych funkcji. Przeładowanie operatora dokonuje

Bardziej szczegółowo

Podstawy i języki programowania

Podstawy i języki programowania Podstawy i języki programowania Laboratorium 8 - wprowadzenie do obsługi plików tekstowych i wyjątków mgr inż. Krzysztof Szwarc krzysztof@szwarc.net.pl Sosnowiec, 11 grudnia 2017 1 / 34 mgr inż. Krzysztof

Bardziej szczegółowo

Wstęp do Programowania, laboratorium 02

Wstęp do Programowania, laboratorium 02 Wstęp do Programowania, laboratorium 02 Zadanie 1. Napisać program pobierający dwie liczby całkowite i wypisujący na ekran największą z nich. Zadanie 2. Napisać program pobierający trzy liczby całkowite

Bardziej szczegółowo

Zakład Systemów Rozproszonych

Zakład Systemów Rozproszonych Zakład Systemów Rozproszonych Politechnika Rzeszowska Moduł 5: Wybrane programy użytkowe Edytor Vi Edytor Vi uruchamiany jest w oknie terminala. Przy jego pomocy możemy dokonywać następujących operacji:

Bardziej szczegółowo

Rozdział 4 KLASY, OBIEKTY, METODY

Rozdział 4 KLASY, OBIEKTY, METODY Rozdział 4 KLASY, OBIEKTY, METODY Java jest językiem w pełni zorientowanym obiektowo. Wszystkie elementy opisujące dane, za wyjątkiem zmiennych prostych są obiektami. Sam program też jest obiektem pewnej

Bardziej szczegółowo

Warsztaty dla nauczycieli

Warsztaty dla nauczycieli WPROWADZENIE Wyprowadzanie danych: Wyprowadzanie na ekran komunikatów i wyników umożliwia instrukcja wyjścia funkcja print(). Argumentami funkcji (podanymi w nawiasach) mogą być teksty, wyrażenia arytmetyczne

Bardziej szczegółowo

Podstawy programowania, Poniedziałek , 8-10 Projekt, część 1

Podstawy programowania, Poniedziałek , 8-10 Projekt, część 1 Podstawy programowania, Poniedziałek 30.05.2016, 8-10 Projekt, część 1 1. Zadanie Projekt polega na stworzeniu logicznej gry komputerowej działającej w trybie tekstowym o nazwie Minefield. 2. Cele Celem

Bardziej szczegółowo

1 Przygotował: mgr inż. Maciej Lasota

1 Przygotował: mgr inż. Maciej Lasota Laboratorium nr 1 1/7 Język C Instrukcja laboratoryjna Temat: Programowanie w powłoce bash (shell scripting) 1 Przygotował: mgr inż. Maciej Lasota 1) Wprowadzenie do programowania w powłoce Skrypt powłoki

Bardziej szczegółowo

Ok. Rozbijmy to na czynniki pierwsze, pomijając fragmenty, które już znamy:

Ok. Rozbijmy to na czynniki pierwsze, pomijając fragmenty, które już znamy: Kurs C++ częśd II Podstawowa obsługa konsoli + zmienne. Autor: Dawid Chróścielski. Wprowadzanie i wyprowadzanie danych z/do konsoli. Jak wyprowadzad dane dowiedzieliśmy się już wcześniej (metoda cout z

Bardziej szczegółowo

Podstawy programowania. Wykład: 9. Łańcuchy znaków. dr Artur Bartoszewski -Podstawy programowania, sem 1 - WYKŁAD

Podstawy programowania. Wykład: 9. Łańcuchy znaków. dr Artur Bartoszewski -Podstawy programowania, sem 1 - WYKŁAD Podstawy programowania Wykład: 9 Łańcuchy znaków 1 dr Artur Bartoszewski -Podstawy programowania, sem 1 - WYKŁAD Rodzaje plików Dane przechowywane w pliku mogą mieć reprezentację binarną (taką samą, jak

Bardziej szczegółowo

3. Instrukcje warunkowe

3. Instrukcje warunkowe . Instrukcje warunkowe Przykłady.1. Napisz program, który pobierze od użytkownika liczbę i wypisze na ekran słowo ujemna lub nieujemna, w zależności od tego czy dana liczba jest ujemna czy nie. 1 #include

Bardziej szczegółowo

Rekurencja (rekursja)

Rekurencja (rekursja) Rekurencja (rekursja) Rekurencja wywołanie funkcji przez nią samą wewnątrz ciała funkcji. Rekurencja może być pośrednia funkcja jest wywoływana przez inną funkcję, wywołaną (pośrednio lub bezpośrednio)

Bardziej szczegółowo

Część XVII C++ Funkcje. Funkcja bezargumentowa Najprostszym przypadkiem funkcji jest jej wersja bezargumentowa. Spójrzmy na przykład.

Część XVII C++ Funkcje. Funkcja bezargumentowa Najprostszym przypadkiem funkcji jest jej wersja bezargumentowa. Spójrzmy na przykład. Część XVII C++ Funkcje Funkcja bezargumentowa Najprostszym przypadkiem funkcji jest jej wersja bezargumentowa. Spójrzmy na przykład. 2 3 Tworzymy deklarację i definicję funkcji o nazwie pobierzln() Funkcja

Bardziej szczegółowo

Uniwersytet Zielonogórski Instytut Sterowania i Systemów Informatycznych. Ćwiczenie 3 stos Laboratorium Metod i Języków Programowania

Uniwersytet Zielonogórski Instytut Sterowania i Systemów Informatycznych. Ćwiczenie 3 stos Laboratorium Metod i Języków Programowania Uniwersytet Zielonogórski Instytut Sterowania i Systemów Informatycznych Ćwiczenie 3 stos Laboratorium Metod i Języków Programowania Celem ćwiczenia jest zapoznanie studentów z najprostszą dynamiczną strukturą

Bardziej szczegółowo

PROE wykład 3 klasa string, przeciążanie funkcji, operatory. dr inż. Jacek Naruniec

PROE wykład 3 klasa string, przeciążanie funkcji, operatory. dr inż. Jacek Naruniec PROE wykład 3 klasa string, przeciążanie funkcji, operatory dr inż. Jacek Naruniec Przypomnienie z ostatnich wykładów Konstruktory/destruktory i kolejność ich wywołania w złożonej klasie. Referencja Obiekty

Bardziej szczegółowo

Python wprowadzenie. Warszawa, 24 marca PROGRAMOWANIE I SZKOLENIA

Python wprowadzenie. Warszawa, 24 marca PROGRAMOWANIE I SZKOLENIA Python wprowadzenie Warszawa, 24 marca 2017 Python to język: nowoczesny łatwy w użyciu silny można pisać aplikacje Obiektowy klejący może być zintegrowany z innymi językami np. C, C++, Java działający

Bardziej szczegółowo

Informatyka I. Klasy i obiekty. Podstawy programowania obiektowego. dr inż. Andrzej Czerepicki. Politechnika Warszawska Wydział Transportu 2018

Informatyka I. Klasy i obiekty. Podstawy programowania obiektowego. dr inż. Andrzej Czerepicki. Politechnika Warszawska Wydział Transportu 2018 Informatyka I Klasy i obiekty. Podstawy programowania obiektowego dr inż. Andrzej Czerepicki Politechnika Warszawska Wydział Transportu 2018 Plan wykładu Pojęcie klasy Deklaracja klasy Pola i metody klasy

Bardziej szczegółowo

Blockly Kodowanie pomoc.

Blockly Kodowanie pomoc. 1 Blockly Kodowanie pomoc. Słowniczek: Zmienna posiada nazwę wywoływaną w programie oraz miejsce na przechowywanie wartości. Instrukcja warunkowa pozwala na wykonanie instrukcji w zależności od warunku

Bardziej szczegółowo

Wprowadzenie do programowania w języku Visual Basic. Podstawowe instrukcje języka

Wprowadzenie do programowania w języku Visual Basic. Podstawowe instrukcje języka Wprowadzenie do programowania w języku Visual Basic. Podstawowe instrukcje języka 1. Kompilacja aplikacji konsolowych w środowisku programistycznym Microsoft Visual Basic. Odszukaj w menu startowym systemu

Bardziej szczegółowo

Warto też w tym miejscu powiedzieć, że w C zero jest rozpoznawane jako fałsz, a wszystkie pozostałe wartości jako prawda.

Warto też w tym miejscu powiedzieć, że w C zero jest rozpoznawane jako fałsz, a wszystkie pozostałe wartości jako prawda. Nazwa implementacji: Nauka języka C wyrażenia warunkowe if- Autor: Piotr Fiorek Opis implementacji: Poznanie struktury oraz zastosowania wyrażeń warunkowych if- w języku C. W programie realizującym jakiś

Bardziej szczegółowo

Program 6. Program wykorzystujący strukturę osoba o polach: imię, nazwisko, wiek. W programie wykorzystane są dwie funkcje:

Program 6. Program wykorzystujący strukturę osoba o polach: imię, nazwisko, wiek. W programie wykorzystane są dwie funkcje: Program 6 Program wykorzystujący strukturę osoba o polach: imię, nazwisko, wiek. W programie wykorzystane są dwie funkcje: Funkcja pobierz_osobe wczytuje dane osoby podanej jako argument. Funkcja wypisz_osobe

Bardziej szczegółowo

Podstawy Pythona. Krzysztof Gdawiec. Instytut Informatyki Uniwersytet Śląski

Podstawy Pythona. Krzysztof Gdawiec. Instytut Informatyki Uniwersytet Śląski Podstawy Pythona Krzysztof Gdawiec Instytut Informatyki Uniwersytet Śląski Słownik jest typem mutowalnym. Każdy element to para: klucz wartość. W celu stworzenia słownika pary klucz wartość umieszczamy

Bardziej szczegółowo

6. Pętle while. Przykłady

6. Pętle while. Przykłady 6. Pętle while Przykłady 6.1. Napisz program, który, bez użycia rekurencji, wypisze na ekran liczby naturalne od pewnego danego n do 0 włącznie, w kolejności malejącej, po jednej liczbie na linię. Uwaga!

Bardziej szczegółowo

Programowanie funkcyjne wprowadzenie Specyfikacje formalne i programy funkcyjne

Programowanie funkcyjne wprowadzenie Specyfikacje formalne i programy funkcyjne Programowanie funkcyjne wprowadzenie Specyfikacje formalne i programy funkcyjne dr inż. Marcin Szlenk Politechnika Warszawska Wydział Elektroniki i Technik Informacyjnych m.szlenk@elka.pw.edu.pl Paradygmaty

Bardziej szczegółowo

Temat 1: Podstawowe pojęcia: program, kompilacja, kod

Temat 1: Podstawowe pojęcia: program, kompilacja, kod Temat 1: Podstawowe pojęcia: program, kompilacja, kod wynikowy. Przykłady najprostszych programów. Definiowanie zmiennych. Typy proste. Operatory: arytmetyczne, przypisania, inkrementacji, dekrementacji,

Bardziej szczegółowo

Języki programowania obiektowego Nieobiektowe elementy języka C++

Języki programowania obiektowego Nieobiektowe elementy języka C++ Języki programowania obiektowego Nieobiektowe elementy języka C++ Roman Simiński roman.siminski@us.edu.pl www.programowanie.siminskionline.pl Przetwarzanie tablic znaków Łańcuchy znakowe jako tablice znaków

Bardziej szczegółowo

Lekcja 5 - PROGRAMOWANIE NOWICJUSZ

Lekcja 5 - PROGRAMOWANIE NOWICJUSZ Lekcja 5 - PROGRAMOWANIE NOWICJUSZ 1 Programowanie i program według Baltiego Najpierw sprawdźmy jak program Baltie definiuje pojęcia programowania i programu: Programowanie jest najwyższym trybem Baltiego.

Bardziej szczegółowo

Nazwa implementacji: Nauka języka Python pętla for. Autor: Piotr Fiorek

Nazwa implementacji: Nauka języka Python pętla for. Autor: Piotr Fiorek Nazwa implementacji: Nauka języka Python pętla for Autor: Piotr Fiorek Opis implementacji: Poznanie innego rodzaju pętli, jaką jest pętla for w języku Python. Składnia pętli for jest następująca: for

Bardziej szczegółowo

Przygotowanie własnej procedury... 3 Instrukcja msgbox wyświetlanie informacji w oknie... 6 Sposoby uruchamiania makra... 8

Przygotowanie własnej procedury... 3 Instrukcja msgbox wyświetlanie informacji w oknie... 6 Sposoby uruchamiania makra... 8 Przygotowanie własnej procedury... 3 Instrukcja msgbox wyświetlanie informacji w oknie... 6 Sposoby uruchamiania makra... 8 Podstawy programowania makr w Excelu 1 Aby rozpocząć pracę z makrami, należy

Bardziej szczegółowo

Programowanie w C++ Wykład 1. Katarzyna Grzelak. 26 luty K.Grzelak (Wykład 1) Programowanie w C++ 1 / 28

Programowanie w C++ Wykład 1. Katarzyna Grzelak. 26 luty K.Grzelak (Wykład 1) Programowanie w C++ 1 / 28 Programowanie w C++ Wykład 1 Katarzyna Grzelak 26 luty 2018 K.Grzelak (Wykład 1) Programowanie w C++ 1 / 28 Dlaczego programowanie? K.Grzelak (Wykład 1) Programowanie w C++ 2 / 28 Umiejętność, która otwiera

Bardziej szczegółowo

Paradygmaty programowania

Paradygmaty programowania Paradygmaty programowania Jacek Michałowski, Piotr Latanowicz 15 kwietnia 2014 Jacek Michałowski, Piotr Latanowicz () Paradygmaty programowania 15 kwietnia 2014 1 / 12 Zadanie 1 Zadanie 1 Rachunek predykatów

Bardziej szczegółowo

Przedstawię teraz tzw. podstawowe symbole wyrażenia regularne (BRE, Basic Regular Expression)

Przedstawię teraz tzw. podstawowe symbole wyrażenia regularne (BRE, Basic Regular Expression) Sed edytor strumieniowy,sed wczytuje bieżący wiersz pliku do wewnętrznego bufora celem manipulowania tekstem. Wynik jest wysyłany na standardowe wyjście. Oryginalny plik nie jest nigdy zmieniany. Jeżeli

Bardziej szczegółowo

Podstawy Programowania Podstawowa składnia języka C++

Podstawy Programowania Podstawowa składnia języka C++ Podstawy Programowania Podstawowa składnia języka C++ Katedra Analizy Nieliniowej, WMiI UŁ Łódź, 3 października 2013 r. Szablon programu w C++ Najprostszy program w C++ ma postać: #include #include

Bardziej szczegółowo

VII. Ciągi znaków łańcuchy

VII. Ciągi znaków łańcuchy VII. Ciągi znaków łańcuchy 7.1. Wczytywanie tekstu Do tej pory poznaliśmy metodę wczytywania i wyświetlania liczb. Tak samo jak liczby moŝemy wczytać jeden znak, jednak co zrobić jeśli chcielibyśmy wczytać

Bardziej szczegółowo

Naukę zaczynamy od poznania interpretera. Interpreter uruchamiamy z konsoli poleceniem

Naukę zaczynamy od poznania interpretera. Interpreter uruchamiamy z konsoli poleceniem Moduł 1 1. Wprowadzenie do języka Python Python jest dynamicznym językiem interpretowanym. Interpretowany tzn. że kod, który napiszemy możemy natychmiast wykonać bez potrzeby tłumaczenia kodu programistycznego

Bardziej szczegółowo

INFORMATYKA Studia Niestacjonarne Elektrotechnika

INFORMATYKA Studia Niestacjonarne Elektrotechnika INFORMATYKA Studia Niestacjonarne Elektrotechnika Wydział Elektrotechniki i Informatyki dr inż. Michał Łanczont Wydział Elektrotechniki i Informatyki p. E419 tel. 81-538-42-93 m.lanczont@pollub.pl http://lanczont.pollub.pl

Bardziej szczegółowo

Linux Polecenia. Problem nadpisywania plików. Zmienna noclobber i noglob. Filtry i metaznaki. Problem nadpisywania plików. Opracował: Andrzej Nowak

Linux Polecenia. Problem nadpisywania plików. Zmienna noclobber i noglob. Filtry i metaznaki. Problem nadpisywania plików. Opracował: Andrzej Nowak Linux Polecenia Opracował: Andrzej Nowak Problem nadpisywania plików. Zmienna noclobber i noglob. Filtry i metaznaki. Utwórz katalog lab_5 i przejdź do niego. $ mkdir lab_5 ; cd lab_5 Problem nadpisywania

Bardziej szczegółowo