43
Wprowadzenie do programowania Wprowadzenie do programowania w języku C w języku C Łagodny start Część pierwsza Niniejsze opracowanie zawiera skrót treści wykładu, lektura tych materiałów nie zastąpi uważnego w nim uczestnictwa. Opracowanie to jest chronione prawem autorskim. Wykorzystywanie jakiegokolwiek fragmentu w celach innych niż nauka własna jest nielegalne. Dystrybuowanie tego opracowania lub jakiejkolwiek jego części oraz wykorzystywanie zarobkowe bez zgody autora jest zabronione. Roman Simiński [email protected] www.us.edu.pl/~siminski Autor Kontakt

Wprowadzenie do programowania w języku C - USNETprac.us.edu.pl/~siminski/jp/pjp_c_01.pdf · Wprowadzenie do programowania w języku C Łagodny start Część pierwsza Niniejsze opracowanie

Embed Size (px)

Citation preview

Wprowadzenie do programowania Wprowadzenie do programowania w języku Cw języku C

Łagodny start

Część pierwsza

Niniejsze opracowanie zawiera skrót treści wykładu, lektura tych materiałów nie zastąpi uważnego w nim uczestnictwa.Opracowanie to jest chronione prawem autorskim. Wykorzystywanie jakiegokolwiek fragmentu w celach innych niż nauka własna jest nielegalne.

Dystrybuowanie tego opracowania lub jakiejkolwiek jego części oraz wykorzystywanie zarobkowe bez zgody autora jest zabronione.

Roman Simiński

[email protected]/~siminski

Autor

Kontakt

Jak powstawał język C?Jak powstawał język C?

Łagodny startJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 2Strona :

Ludzie

Kenneth Thompson

Urodzony w 1943 roku w Nowym Orleanie. Otrzymuje tytuł magistra Uniwersytetu Kalifornijskiego w 1966, jest entuzjastą elektroniki, jednak to informatyka staje się jego pasją.

Zaraz po studiach dołącza do grupy z laboratorium firmy Bell, pracującej wspólnie z GE i MIT nad systemem Multics.

W 1969 projektuje i opracowuje system Unix, wkrótce potem język B. W 1971 przenosi system Unix na komputer PDP-11, potem przepisuje jego kod w języku C. Rozwija system Unix (np. implementuje koncepcję potoków opracowaną przez D.McIlroy'a).

W połowie lat 70-tych rozpoczyna również pracę dydaktyczną, na początku lat 80-tych stworzony przez niego komputer szachowy Belle zdobywa mistrzostwo świata w zawodach komputerów szachowych. Kontynuuje pracę dydaktyczną, otrzymuje wiele nagród. W roku 2000 odchodzi z Laboratorium firmy Bell.

Jak powstawał język C?Jak powstawał język C?

Łagodny startJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 3Strona :

Ludzie

Dennis M. Ritchie

Urodzony w 1941 w Bronxville (N.Y.), w 1963 kończy Harvard z dyplomem fizyka, pięć lat później broni doktorat z matematyki.

Zainteresowany teoretycznymi podstawami informatyki trafia, wzorem ojca, do laboratorium firmy Bell. W 1968 dołącza do zespołu pracującego nad systemem Multics. Tu spotyka się z K. Thompsonem.

Po wycofaniu się firmy Bell z projektu Multics kontynuuje współpracę z K. Thompsonem, w 1972 roku tworzy język C w oparciu o opracowany przez Thompsona język B.

Kieruje i bierze udział w wielu projektach związanych z rozwojem systemów operacyjnych. Wielokrotnie nagradzany, wybrany do U.S. National Academy of Engineering .

Napisana wspólnie z Brianem Kernighan'em książka The C Programming Language staje się biblią entuzjastów języka C.

Jak powstawał język C?Jak powstawał język C?

Łagodny startJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 4Strona :

Ludzie

Brian Kernighan

Urodzony w 1942 w Toronto (Ontario), w roku 1964 kończy Uniwersytet w Toronto i otrzymuje dyplom w zakresie fizyki inżynieryjnej, w roku 1969 broni doktorat z elektroniki na Uniwersytecie w Princeton.

W 1969 rozpoczyna pracę w laboratorium badawczym firmy Bell. Opracowuje i współuczestniczy w opracowaniu wielu programów dla systemu Unix – AWK, ditroff, opracowuje język AMPL.

Jest, wspólnie z Dennisem Ritchie, współautorem książki The C Programming Language, która staje się biblią entuzjastów języka C.

Jest autorem książki The UNIX Programming Environment. Aktualnie, jego zainteresowania koncentrują się na rozwoju języków programowania, metodykach programowania i budowaniu interfejsów użytkownika.

Jak powstawał język C?Jak powstawał język C?

Łagodny startJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 5Strona :

Początki języka C są związane z wczesną fazą rozwoju systemu Unix.

Prace nad protoplastą tego systemu zostały rozpoczęte pod koniec lat sześćdziesiątych w laboratoriach telekomunikacyjnej firmy Bell – BTL – wspólnie z General Electric Company oraz MIT. Powstać miał wielodostępny system operacyjny Multics – Multiplexed Information and Computing Service.

Mimo iż system działa, prace przerwano w 1969 roku, programiści z BTL szukają innych projektów. Ciągle chcą napisać uniwersalny system operacyjny. Jednak w BTL nie ma dla takiego projektu dobrej atmosfery.

Jeden z członków zespołu — Ken Thompson — pisze grę Space Travel. Thompson pisze ją na komputerze GE Honeywell 635, następnie używa asemblera skrośnego i przenosi kod binarny na komputer PDP-7 używając taśmy papierowej.

Komputer DEC PDP-7 ma w 1968 roku pamięć 8K 18-sto bitowych słów.

Praca nad rozwojem gry Space Travel wymaga napisania systemu operacyjnego dla PDP-7, Ken Thompson wspólnie z Denisem Ritchie rozpoczynają pracę nad tym systemem.

Powstaje pierwsza wersja systemu nazwanego Unix — jego nazwa jest kalamburem nazwy Multics.

Prehistoria

Jak powstawał język C?Jak powstawał język C?

Łagodny startJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 6Strona :

Powstaje wersja systemu obejmującej proste jądro oraz podstawowe narzędzia (edytor, asembler, powłoka). Wszystko zostało zaimplementowane w języku symbolicznym, jednak rozpoczynają się próby wykorzystania języka programowania wywodzącego się z języka BCPL.

Komputer PDP-7 jest przestarzały. Zespół podejmuje próbę zdobycia komputera PDP-11. Kosztuje on wtedy 65 000$.

Ostatecznie zespół otrzymuje komputer w lecie 1970r., jednak prace nad przeniesieniem nań systemu Unix startują dopiero w grudniu, po doposażeniu go w dysk.

Oficjalnie prace poświęcone są opracowaniu systemu dla wydziału patentowego BTL.

Prehistoria, cd...

Jak powstawał język C?Jak powstawał język C?

Łagodny startJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 7Strona :

Prehistoria, cd...

Ken Thompson potrzebuje nowego języka programowania do tworzenia oprogra-mowania systemowego.

Istnieje już jego własny język o nazwie B. Nazwa ta prawdopodobnie pochodzi od języka BCPL, alternatywna teoria mówi, iż nazwa pochodzi od języka Bon.

Język Bon został stworzony przez Thompson'a wcześniej, a jego nazwa miała pochodzić ponoć od imienia jego żony — Bonnie.

Język B miał sporo ograniczeń, co spowodowało rozpoczęcie przez Ritchie’go w roku 1971 prac nad rozszerzeniem tego języka. Doprowadziło to do powstania dialektu NB (ang. new B).

Denis Ritchie i Ken Thompson przenoszą

system Unix na PDP-11 za pośrednictwem

terminalu telegraficznego.

Jak powstawał język C?Jak powstawał język C?

Łagodny startJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 8Strona :

Nazwa NB nie oddaje w pełni różnicy pomiędzy tym językiem a językiem B.

Nowy język otrzymuje nazwę C, otwartą pozostaje kwestię jego pochodzenia — czy C pochodzi od następnej litery w alfabecie po B czy też od drugiej litery z protoplasty języków B i C — czyli języka BCPL.

W roku 1973 powstaje specyfikacja języka C (zawierającego typ strukturalny) oraz odpowiednie narzędzia – rozpoczynają się prace nad przepisanie jądra Unix’a dla komputera PDP-11.

Również w tym okresie następuje przeniesienia kompilatora języka C na inne platformy sprzętowe (np. Honeywell 635, IBM 360/370) oraz przygotowania bibliotek podprogramów — np. podprogramów obsługi standardowego wejścia i wyjścia .

W 1978 roku Dennis Ritchie i Brian Kernighan publikują książkę Język programowania C (oryginał ang. The C Programming Language).

W latach siedemdziesiątych, w trakcie prac nad implementacją jądra Unix’a, okazało się, że język jest na tyle elastyczny i efektywny, że rozpoczęto proces przepisywania narzędzi systemowych. Aby wspomóc programistów Steve Johnson tworzy narzędzie lint analizujące zawartość plików źródłowych i sygnalizujące niebezpieczne konstrukcje.

Czas na C

Jak powstawał język C?Jak powstawał język C?

Łagodny startJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 9Strona :

Na początku lat osiemdziesiątych stało się jasne, że język C wymaga standaryzacji. Stało się to konieczne między innymi ze względu na wzrost zainteresowania językiem C w projektach rządowych.

Ostatecznie w lecie 1983 roku ANSI powołało komitet X3J11, którego celem było opracowanie standardu języka C. Komitet ten opracował raport (ANSI 89) w końcu roku 1989, standard ten został zaakceptowany przez ISO jako ISO/IEC 9899-1990.

Standaryzacja przyczynia się do poprawy przenośności kodu źródłowego. Kompilatory języka C dostępne są na każdej, szanującej się platformie sprzętowej. Pośrednio ułatwia to przenoszenie systemu Unix i powstawanie jego dedykowanych wersji.

Czas na standard języka C

Jak powstawał język C?Jak powstawał język C?

Łagodny startJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 10Strona :

Najbardziej znane rozwinięcia języka C: Concurrent C, Objective C, C*, C++.

Z pnia języka C wyrosły również: Java oraz dialekt JavaScript, PHP, C#, i wiele innych.

Po określeniu standardu języka C, jego specyfikacja przez dłuższy czas nie zmienia się. W tym samym czasie specyfikacja języka C++ ciągle ewoluuje.

Rozwój języka C++ pośrednio wpływa na modyfikację standardu C.

Powstaje standard C99, opublikowany przez ISO w 1999 r. Standard ten zostaje przyjęty przez ANSI w marcu 2000 r.

Większość zmian standardu C99 zbliża język C do C++. Z tego powodu wielu producentów kompilatorów nie jest zainteresowanych implementacją C99, preferując zamiast niego programowania w C++ bez wykorzystania obiektów .

Powstają – specjalizowane i niszowe – języki: C––, D, P.

Co po C?

Literatura Literatura —— setki książek na temat programowaniu w C setki książek na temat programowaniu w C

Łagodny startJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 11Strona :

Brian W. Kernigham, Dennis M. Richie, Język ANSI C, Wydawnictwo Naukowo–Techniczne, Warszawa, 2003.

Clovis L. Tondo, Scott E. Gimpel, Język ANSI C, ćwiczenia i rozwiązania, Wydawnictwo Naukowo–Techniczne, Warszawa, 2003.

Adam Sapek, Wgłąb języka C, Helion, Gliwice, 1993.

Pewne i sprawdzone

Zaczynamy Zaczynamy — pierwszy program w języku C— pierwszy program w języku C

Łagodny startJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 12Strona :

Problem

Zadaniem programu jest obliczanie, ile średnio litrów paliwa zużywa pojazd na trasie 100 km.

`

Pierwsza przymiarka – program który robi nic

int main(){ return 0;}

int main(){ return 0;}

Typ rezultatu

Wartość przekazywnaw miejscu wywołania

Instrukcja powrotu z podprogramu

Nazwa funkcji

Parametry

Ciało funkcji

Każdy program C/C++musi posiadać funkcję o nazwie main, stanowiącą tzw. punkt wejściowy programu.

Od niej się rozpoczyna wykonanie programu napisanego w języku C/C++.

Zaczynamy Zaczynamy — pierwszy program w języku C— pierwszy program w języku C

Łagodny startJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 13Strona :

Kto wywołuje funkcję main?

Typowy scenariusz uruchomienia programu wykonywalnego :

Użytkownik przekazuje systemowi operacyjnemu zlecenie uruchomienia programu.

System ładuje kod programu do pamięci, przygotowuje jego środowisko, przekazuje sterowanie do bloku kodu startowego programu (tzw. startup).

Kod startowy wykonuje czynności inicjalizujące. Na zakończenie wywołuje funkcje main.

Po zakończeniu działania funkcji main

bieżący proces jest kończony i do systemu przekazywany jest kod wyjścia.

Pamięć operacyjna

Systemoperacyjny

kod startowy

call main

kod

prog

ram

u te

st.e

xe

Plik wykonywalnynp. test.exe

main

kod powrotu

resztaprogramu

+dane

Zaczynamy Zaczynamy — pierwszy program w języku C— pierwszy program w języku C

Łagodny startJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 14Strona :

Po co przekazywać kod zakończenia programu?

@echo offecho Testowanie kodu powrotuprog.exeif errorlevel 2 goto dwaif errorlevel 1 goto jedenif errorlevel 0 goto zero: zero echo Kod powrotu 0 goto koniec: jeden echo Kod powrotu 1 goto koniec: dwa echo Kod powrotu 2 goto koniec: koniecpause

Kod zakończenia programu może być wykorzystywany w skryptach systemu operacyjnego oraz jako środek komunikacji pomiędzy procesami.

@echo offecho Testowanie kodu powrotu 1: petla prog.exe if errorlevel 1 goto koniec if errorlevel 0 goto petla: koniececho Koniec programupause

Przykładowe skrypty (będący w istocie plikami wsadowymi systemu DOS) testujący kod wyjścia programu prog.exe:

Przykłady

Pierwszy program w języku C — wariacje na temat funkcji mainPierwszy program w języku C — wariacje na temat funkcji main

Łagodny startJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 15Strona :

Cztery formy deklaracji funkcji main ― która doba jest, którą wybrać?

main(){ return 0;}

int main(){ return 0;}

int main(){ }

void main(){ }

Prawidłowa deklaracja funkcji main zalecana przez normę ANSI.

To jest (prawie) najlepsza wersja.

Prawidłowa deklaracja funkcji main. Przy braku typu rezultatu, kompilator domyślnie przyjmuje, że typem rezultatu jest int.

Dozwolone, lecz lepsza jest postać nr 1.

Specyfikacja void oznacza brak wartości. Zatem ta funkcja nie udostępnia rezultatu – brak instrukcji return.

Dozwolone, lecz niezgodne ze standardem ANSI.

Brak instrukcji return nie jest błędem dla kompilatora.

Programista otrzyma ostrzeżenie (ang. warning) o braku rezultatu.

Mimo braku błędu kompilacji to jest konstrukcja błędna!

Pierwszy program w języku C — wariacje na temat funkcji mainPierwszy program w języku C — wariacje na temat funkcji main

Łagodny startJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 16Strona :

Po co przekazywać kod zakończenia programu?

Zamiast rezultatu w postaci bezwzględnych wartości można wykorzystać symbole:

EXIT_SUCCESS — oznacza bezbłędne zakończenie programu.

EXIT_FAILURE —zakończenie z informacją o błędzie.

Jednak aby z nich skorzystać, należy uzupełnić program o linię:

#include <stdlib.h>

int main(){ return EXIT_SUCCESS;}

#include <stdlib.h>

Najlepsza wersja programu z punktu widzenia przenośności kodu

Ta dyrektywa informuje, że program będzie korzystał ze standardowej biblioteki języka C, w niej właśnie zdefiniowane są symbole EXIT_SUCCES oraz EXIT_FAILURE.

Pierwszy program w języku C — komunikacja z użytkownikiemPierwszy program w języku C — komunikacja z użytkownikiem

Łagodny startJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 17Strona :

Wyprowadzamy komunikat do strumienia wyjściowego programu

#include <stdlib.h>#include <stdio.h>

int main(){ printf( "Obliczam ile Twoj pojazd spala paliwa na 100 km" );

return EXIT_SUCCESS;}

#include <stdlib.h>

Ta dyrektywa informuje, że program będzie korzystał ze standardowych strumieni: standardowego strumienia wejściowego, wyjściowego, oraz strumienia błędów.

Obsługa standardowych strumieni programu

printf to nazwa funkcji wyprowadzającej dane do strumienia wyjściowego. Dane

mogą być przez funkcję odpowiednio formatowane.

”Obliczam ile Twoj pojazd spala paliwa na 100 km” to stała łańcu-

chowa, literał w postaci napisu.

Wykorzystanie funkcji printf

Pierwszy program w języku C — komunikacja z użytkownikiemPierwszy program w języku C — komunikacja z użytkownikiem

Łagodny startJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 18Strona :

Standardowe strumienie programu

standardowy strumień wejściowy programu (ang. stdin), który jest zwykle skojarzony z klawiaturą;

standardowy strumień wyjściowy programu (ang. stdout), który jest zwykle skojarzony z ekranem monitora;

standardowy strumień wyjściowy błędów programu (ang. stderr), który jest zwykle skojarzony również z ekranem monitora.

Program jakoproces

Pamięć operacyjna

stdoutstderrstdin

C:\>test.exe > wyjscie.txtC:\>test.exe < wejscie.txtC:\>test.exe < wejscie.txt > wyjscie.txt

Redyrekcja strumieni

Strumienie stdin, stdout reprezentują normalny kanał komunikacji programu z użytkownikiem.

Strumień stderr zarezerwowany jest do wyświetlania komunikatów diagnostycznych programu.

Pierwszy program w języku C — komunikacja z użytkownikiemPierwszy program w języku C — komunikacja z użytkownikiem

Łagodny startJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 19Strona :

Kosmetyka programu – komunikat zawsze od początku nowego wiersza

#include <stdlib.h>#include <stdio.h>

int main(){ printf( "\nObliczam ile Twoj pojazd spala paliwa na 100 km\n" );

return EXIT_SUCCESS;}

Znaki sterujące w napisach

Znak sterujący Symbol Znaczenie

\a BELL Sygnał dźwiękowy

\b BS (backspace) Spacja wsteczna

\n LF (newline, linefeed) Nowa linia

\r CR (Carriage return) Powrót „karetki”

\t TAB Tabulacja

Pierwszy program w języku C — deklarujemy zmiennePierwszy program w języku C — deklarujemy zmienne

Łagodny startJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 20Strona :

Wprowadzamy zmienne, symulujemy obliczenia

#include <stdlib.h>#include <stdio.h>

int main(){ float dystans, paliwo, spalanie;

printf( "\nObliczam ile Twoj pojazd spala paliwa na 100 km\n" );

/* Dane wpisane na prób */ę dystans = 500; paliwo = 37.45;

spalanie = ( paliwo * 100 ) / dystans;

return EXIT_SUCCESS;}

Tekst zapisany w /* */ jest komentarzem, zawartość komentarza nie podlega kompilacji.

float to typ zmiennopozycyjny, służący do reprezentowania liczb rzeczywistych

pojedynczej precyzji.

Zmienne mogą być deklarowane na początku każdego bloku określonego nawiasami { }.

Wyrażenia wykorzystujące operator przypisania =

Pierwszy program w języku C — deklarujemy zmiennePierwszy program w języku C — deklarujemy zmienne

Łagodny startJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 21Strona :

Zmiana stanu pamięci, czyli wartości zmiennych się zmieniają

paliwodystans

37.45500

spalanie 7.49

.

.

.

.

.

.

Pamięćoperacyjna

spalanie = ;( paliwo * 100 ) / dystans

paliwodystans

37.45500

spalanie ?

.

.

.

.

.

.

Pamięćoperacyjna

paliwo = ;

dystans = ;

37.45

500

paliwodystans

??

spalanie ?

.

.

.

.

.

.

Pamięćoperacyjna

Po deklaracji Przypisanie

Przypisanie

Pierwszy program w języku C — wyprowadzamy wyniki obliczeńPierwszy program w języku C — wyprowadzamy wyniki obliczeń

Łagodny startJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 22Strona :

Wyprowadzenie wyniku do strumienia wyjściowego programu

#include <stdlib.h>#include <stdio.h>

int main(){ float dystans, paliwo, spalanie;

printf( "\nObliczam ile Twoj pojazd spala paliwa na 100 km\n" );

/* Dane wpisane na prób */ę dystans = 500; paliwo = 37.45;

spalanie = ( paliwo * 100 ) / dystans;

printf( "Spalanie %4.2f l na 100 km", spalanie );

return EXIT_SUCCESS;}

Przyjrzyjmy się temu dokładniej...

Pierwszy program w języku C — wyprowadzamy wyniki obliczeńPierwszy program w języku C — wyprowadzamy wyniki obliczeń

Łagodny startJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 23Strona :

Koncepcja funkcji formatowanego wyjścia

Funkcja printf wyprowadzane sformatowane dane do stdout. Pierwszy parametr funkcji, będący łańcuchem znaków, może zawierać specyfikacje przekształceń.

printf( "Spalanie l na 100 km", spalanie );%4.2fspalanie: 7.49

Sekwencje rozpoczynające się od znaku % stanowią specyfikacje przekształceń kolejnych parametrów funkcji printf:

%d — wyprowadza liczbę całkowitą dziesiętną,

%f — wyprowadza liczbę rzeczywistą,

%c — wyprowadza znak,

%s — wyprowadza napis.

Liczba parametrów musi odpowiadać liczbie sekwencji formatujących. Ewentualna niezgodność nie będzie wykryta przez kompilator.

Pierwszy program w języku C — drobna optymalizacjaPierwszy program w języku C — drobna optymalizacja

Łagodny startJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 24Strona :

Eliminujemy niepotrzebną zmienną

#include <stdlib.h>#include <stdio.h>

int main(){ float dystans, paliwo, spalanie;

printf( "\nObliczam ile Twoj pojazd spala paliwa na 100 km\n" );

/* Dane wpisane na prób */ę dystans = 500; paliwo = 37.45;

spalanie = ( paliwo * 100 ) / dystans;

printf( "Spalanie %4.2f l na 100 km", spalanie );

return EXIT_SUCCESS;}

printf( "Spalanie %4.2f l na 100 km", ( paliwo * 100 ) / dystans );

Pierwszy program w języku C — wczytujemy danePierwszy program w języku C — wczytujemy dane

Łagodny startJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 25Strona :

Wczytujemy dane ze strumienia wejściowego

#include <stdlib.h>#include <stdio.h>

int main(){ char linia[ 20 ]; float dystans, paliwo;

printf( "\nObliczam ile Twoj pojazd spala paliwa na 100 km\n" );

printf( "Dystans : " ); gets( linia ); dystans = atof( linia );

printf( "Paliwo : " ); gets( linia ); paliwo = atof( linia );

printf( "Spalanie %4.2f l na 100 km", ( paliwo * 100 ) / dystans ); return EXIT_SUCCESS;}

Deklaracja 20-sto znakowej tablicy przeznaczonej do przechowywania napisów

Wyświetlenie zachęty, wczytanie napisu, konwersja do liczby rzeczywistej.

Przyjrzyjmy się temu dokładniej...

Pierwszy program w języku C — wczytujemy danePierwszy program w języku C — wczytujemy dane

Łagodny startJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 26Strona :

Funkcje gets i atof

paliwo

linia

dystans

Pamięć operacyjna

gets( linia )

dystans = atof( linia )

5 01234

191817

OO\O

500 + znak Enter

500.0

Funkcja wczytuje łańcuch znaków ze strumienia wejściowego programu i zapisuje go w tablicy będącej parametrem wywołania. Na końcu łańcucha zapisywany jest znacznik końca napisu -- znak '. '\0

Funkcja przekształca napis zawarty w tablicy będącej parametrem wywołania na odpowiadającą mu liczbę rzeczywistą.

atof

Pierwszy program w języku C — wczytujemy danePierwszy program w języku C — wczytujemy dane

Łagodny startJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 27Strona :

Funkcja gets jest niebezpieczna ― problem przepełnienia bufora

paliwo

linia

dystans

Pamięć operacyjna

gets( linia ) 01234

191817

To jest napis...

To jest napis zbyt długi aby się zmieścić w 20-sto znakowym buforze + znak Enter

Nadmiarowe znaki wczytanego napisu niszczą zawartość komórek pamięci operacyjnej obok zmiennej linia.

Pierwszy program w języku C — wczytujemy danePierwszy program w języku C — wczytujemy dane

Łagodny startJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 28Strona :

Funkcja fgets jest bezpieczniejsza

char linia[ 20 ];. . .printf( "Dystans : " );fgets( linia, 20, stdin );. . .

Funkcja fgets :

Pierwszy parametr określa bufor, do którego mają być zapisane wczytywane dane.

Drugi parametr określa N ― maksymalną pojemność bufora, uwzględniającą miejsce na znacznik końca napisu.

Trzeci parametr określa strumień (plik), z którego funkcja ma odczytywać dane, może to być również standardowy strumień wejściowy ― stdin.Działąnie funkcji kończy się gdy funkcja odczyta N – 1 znaków lub wcześniej zostanie odczytany znak nowego wiersza (Enter).

Znacznik końca napisu dopisywany jest na jego końcu.

Pierwszy program w języku C — wczytujemy danePierwszy program w języku C — wczytujemy dane

Łagodny startJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 29Strona :

Mimo użycia bezpieczniejszej funkcji też można popełnić błąd

char linia[ 20 ];. . .printf( "Dystans : " );fgets( linia, 80, stdin );. . .

Również w tym przypadku bufor może się przepełnić. Aby tego uniknąć stosuje się stałe symboliczne.

Taka stała to identyfikator, reprezentujący pewną wartość.

#define MAKS_DL 20. . . char linia[ MAKS_DL ];. . .printf( "Dystans : " );fgets( linia, MAKS_DL, stdin );. . .

Pierwszy program w języku C — wczytujemy danePierwszy program w języku C — wczytujemy dane

Łagodny startJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 30Strona :

Program po modyfikacjach

#include <stdlib.h>#include <stdio.h>

#define MAKS_DL 20

int main(){ char linia[ MAKS_DL ]; float dystans, paliwo;

printf( "\nObliczam ile Twoj pojazd spala paliwa na 100 km\n" );

printf( "Dystans : " ); fgets( linia, MAKS_DL, stdin ); dystans = atof( linia );

printf( "Paliwo : " ); fgets( linia, MAKS_DL, stdin ); paliwo = atof( linia );

printf( "Spalanie %4.2f l na 100 km", ( paliwo * 100 ) / dystans );

return EXIT_SUCCESS;}

#include <stdlib.h>#include <stdio.h>#include <math.h>

#define MAKS_DL 20

int main(){ char linia[ MAKS_DL ]; float dystans, paliwo;

printf( "\nObliczam ile Twoj pojazd spala paliwa na 100 km\n" );

printf( "Dystans : " ); fgets( linia, MAKS_DL, stdin ); dystans = fabs( atof( linia ) );

printf( "Paliwo : " ); fgets( linia, MAKS_DL, stdin ); paliwo = fabs( atof( linia ) );

printf( "Spalanie %4.2f l na 100 km", ( paliwo * 100 ) / dystans );

return EXIT_SUCCESS;}

Pierwszy program w języku C — dane nie muszą być poprawnePierwszy program w języku C — dane nie muszą być poprawne

Łagodny startJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 31Strona :

Zabezpieczenie przed cwaniaczkami co wpiszą ujemne wartości ;-)

Wyznaczenie modułu liczby będącej rezultatem funkcji atof.

Pierwszy program w języku C — dane nie muszą być poprawnePierwszy program w języku C — dane nie muszą być poprawne

Łagodny startJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 32Strona :

Zabezpieczenie przed dzieleniem przez zero

#include <stdlib.h>#include <stdio.h>#include <math.h>

int main(){ . . .

printf( "Dystans : " ); fgets( linia, MAKS_DL, stdin ); dystans = fabs( atof( linia ) );

printf( "Paliwo : " ); fgets( linia, MAKS_DL, stdin ); paliwo = fabs( atof( linia ) );

if( dystans != 0 ) printf( "Spalanie %4.2f l na 100 km", ( paliwo * 100 ) / dystans ); else printf( "Nie dokonam obliczen dla takiego dystansu." ); return EXIT_SUCCESS;}

Instrukcja alternatywy

Pierwszy program w języku C — dane nie muszą być poprawnePierwszy program w języku C — dane nie muszą być poprawne

Łagodny startJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 33Strona :

if( wyra enie )ż instrukcja

if( wyra enie )ż instrukcja_1else instrukcja_2

prawda fałszwyrażenie

instrukcja_1instrukcja_1

prawda

fałsz

wyrażenie

instrukcja

Instrukcja alternatywyInstrukcja warunkowa

if( dystans != 0 ) printf( "Spalanie %4.2f l na 100 km", ( paliwo * 100 ) / dystans );

if( dystans != 0 ) printf( "Spalanie %4.2f l na 100 km", ( paliwo * 100 ) / dystans );else printf( "Nie dokonam obliczen dla takiego dystansu." );

Instrukcja warunkowa czy alternatywy?Operator != oznacza różne, nierówne

Średnik!

Pierwszy program w języku C — wersja prawie ostatecznaPierwszy program w języku C — wersja prawie ostateczna

Łagodny startJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 34Strona :

#include <stdlib.h>#include <stdio.h>#include <math.h>#define MAKS_DL 20

int main(){ char linia[ MAKS_DL ]; float dystans, paliwo;

printf( "\nObliczam ile Twoj pojazd spala paliwa na 100 km\n" );

printf( "Dystans : " ); fgets( linia, MAKS_DL, stdin ); dystans = fabs( atof( linia ) );

printf( "Paliwo : " ); fgets( linia, MAKS_DL, stdin ); paliwo = fabs( atof( linia ) ); if( dystans != 0 ) printf( "Spalanie %4.2f l na 100 km", ( paliwo * 100 ) / dystans ); else printf( "Nie dokonam obliczen dla takiego dystansu." );

return EXIT_SUCCESS;}

Program po modyfikacjach ― czego tu brakuje?

Pierwszy program w języku C — wersja prawie ostatecznaPierwszy program w języku C — wersja prawie ostateczna

Łagodny startJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 35Strona :

#include <stdlib.h>#include <stdio.h>#include <math.h>#define MAKS_DL 20

int main(){ . . . if( dystans != 0 ) printf( "Spalanie %4.2f l na 100 km", ( paliwo * 100 ) / dystans ); else printf( "Nie dokonam obliczen dla takiego dystansu." );

printf( "\nNacisnij Enter by zakonczyc program..." ); getchar();

return EXIT_SUCCESS;}

Program po modyfikacjach ― daj szansę użytkownikowi, niech zdąży przeczytać!

Pierwszy program w języku C — zignorowane rezultaty funkcjiPierwszy program w języku C — zignorowane rezultaty funkcji

Łagodny startJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 36Strona :

Dlaczego wywołując funkcje gets, fgets i getchar ignorujemy ich rezultat?

Jeżeli rezultatem gets i fgets jest wartość NULL, to oznacza, że odczytany został znacznik końca strumienia lub wystąpił błąd. W przeciwnym wypadku jest OK.

printf( "Dystans : " );if( fgets( linia, MAKS_DL, stdin ) != NULL ) dystans = fabs( atof( linia ) );else printf( "\nBlad odczytu dystansu." );

Testowanie rezultatu funkcji fgets (gets)

char c;. . .c = getchar();

Rezultatem funkcji getchar jest znak...

. . .getchar();

... ale ten znak nie jest przecież nikomu potrzebny!

Tak napisze większość programistów...

. . .( void )getchar();

Tak napisze programista-esteta...

Pierwszy program w języku C — wykorzystanie rezultatu funkcji fgetsPierwszy program w języku C — wykorzystanie rezultatu funkcji fgets

Łagodny startJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 37Strona :

Testowanie rezultatu funkcji fgets ― rozwiązanie naiwne

. . .int main(){ . . . printf( "Dystans : " ); if( fgets( linia, MAKS_DL, stdin ) != NULL ) dystans = fabs( atof( linia ) ); else printf( "\nBlad odczytu dystansu." );

printf( "Paliwo : " ); if( fgets( linia, MAKS_DL, stdin ) != NULL ) paliwo = fabs( atof( linia ) ); else printf( "\nBlad odczytu paliwa." );

if( dystans != 0 ) printf( "Spalanie %4.2f l na 100 km", ( paliwo * 100 ) / dystans ); else printf( "Nie dokonam obliczen dla takiego dystansu." );

printf( "\nNacisnij Enter by zakonczyc program..." ); getchar();

return EXIT_SUCCESS;}

Pierwszy program w języku C — wykorzystanie rezultatu funkcji fgetsPierwszy program w języku C — wykorzystanie rezultatu funkcji fgets

Łagodny startJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 38Strona :

Testowanie rezultatu funkcji fgets ― „nadużycie” instrukcji return

. . .int main(){ . . . printf( "Dystans : " ); if( fgets( linia, MAKS_DL, stdin ) != NULL ) dystans = fabs( atof( linia ) ); else { printf( "\nBlad odczytu dystansu." ); return EXIT_FAILURE; } printf( "Paliwo : " ); if( fgets( linia, MAKS_DL, stdin ) != NULL ) paliwo = fabs( atof( linia ) ); else { printf( "\nBlad odczytu paliwa." ); return EXIT_FAILURE; }

. . .

return EXIT_SUCCESS;}

Pierwszy program w języku C — wykorzystanie rezultatu funkcji fgetsPierwszy program w języku C — wykorzystanie rezultatu funkcji fgets

Łagodny startJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 39Strona :

Testowanie rezultatu funkcji fgets ― filtrowanie błędów

. . .int main(){ . . . printf( "Dystans : " ); if( fgets( linia, MAKS_DL, stdin ) != NULL ) { dystans = fabs( atof( linia ) ); printf( "Paliwo : " ); if( fgets( linia, MAKS_DL, stdin ) != NULL ) { paliwo = fabs( atof( linia ) ); if( dystans != 0 ) printf( "Spalanie %4.2f l na 100 km", ( paliwo * 100 ) / dystans ); else printf( "Nie dokonam obliczen dla takiego dystansu." ); } else printf( "\nBlad odczytu paliwa." ); } else printf( "\nBlad odczytu dystansu." );

printf( "\nNacisnij Enter by zakonczyc program..." ); . . .}

Pierwszy program w języku C — defensywne podejście do wczytywania dystansuPierwszy program w języku C — defensywne podejście do wczytywania dystansu

Łagodny startJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 40Strona :

Nie pozwalamy na wprowadzenie 0-ego dystansu

. . .do{ printf( "Dystans : " ); fgets( linia, MAKS_DL, stdin ); dystans = atof( linia ); if( dystans <= 0 ) printf( "Prosze wprowadzic prawidlowy dystans\n" );}while( dystans <= 0 );. . .

Technika programowania defensywnego

Instrukcja iteracyjna do-while

do instrukcjawhile( wyra enie );ż

do{ ci g instrukcjią}while( wyra enie );ż

lub

Instrukcja do-while wykonuje się dopóty, dopóki wyrażenie jest prawdziwe.

W języku C wyrażenie jest fałszywe jeżeli ma wartość zero, każda wartość niezerowa traktowana jest jako prawda.

Pierwszy program w języku C — na zakończeniePierwszy program w języku C — na zakończenie

Łagodny startJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 41Strona :

Pozostaje jeszcze jeden nierozwiązany problem

printf( "Dystans : " );fgets( linia, MAKS_DL, stdin );dystans = fabs( atof( linia ) );

Co się stanie, gdy użytkownik nie wpisze prawidłowej liczby?

Należy sprawdzić, czy wczytany napis zawiera prawidłową liczbę. Ale tym zajmiemy się później... .

Podsumowanie programu przykładowegoPodsumowanie programu przykładowego

Łagodny startJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 42Strona :

Należy pamiętać, że:

Każdy program w języku C/C++ musi posiadać funkcję main. Od niej rozpoczyna się

wykonanie programu.

Funkcja main według standardu ANSI C powinna „zwracać” wartość całkowitą,

stanowiącą kod zakończenia programu przekazywany systemowi operacyjnemu lub procesowi — rodzicowi.

Każda funkcja posiada swoje ciało ujęte w nawiasy klamrowe { }.

Zakończenie wykonania funkcji następuje wraz z osiągnięciem klamry zamykającej ciało funkcji lub po napotkaniu instrukcji powrotu z podprogramu — instrukcji return. Wartość umieszczona po tej instrukcji stanowi rezultat funkcji.

Instrukcja return może wystąpić w ciele funkcji wielokrotnie, w miejscach

dozwolonych syntaktyką języka.

Zmienne wewnątrz funkcji wolno deklarować na początku każdego bloku. Na etapie deklaracji zmienne mogą być inicjowane.

Podsumowanie programu przykładowegoPodsumowanie programu przykładowego

Łagodny startJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 43Strona :

Należy pamiętać, że:

W języku C nie ma funkcji standardowych. Wszystkie funkcje pochodzą z bibliotek lub są napisane przez programistę.

Aby kompilator mógł sprawdzić poprawność wywołania funkcji bibliotecznych wykorzystuje się pliki nagłówkowe. Zawierają one informacje o typie rezultatu funkcji, parametrach i są włączane do kodu źródłowego programu dyrektywą #include.

Wywołanie funkcji bez włączenia odpowiedniego pliku nagłówkowego nie spowoduje błędu kompilacji (ang. error) a jedynie ostrzeżenie (ang. warning), a kod wynikowy zostanie wygenerowany. Jednak, być może, wywołanie funkcji jest nieprawidłowe, zatem i działanie programu może być niepoprawne.

W instrukcji if-else, przed słowem kluczowym else występuje średnik. W języku

C średnik nie rozdziela instrukcji, a kończy je.

Instrukcja iteracyjna do-while pozornie odpowiada pascalowej instrukcji repeat-until. Różnica polega na interpretacji warunku – w do-while iteracja jest przerywana gdy warunek przestanie być prawdziwy, w repeat-until iteracja

przerywana jest, gdy warunek zacznie być prawdziwy.