tutaj - KKiEM AGH
Transkrypt
tutaj - KKiEM AGH
Elementarne wiadomości o języku C Oprac.: Zbigniew Rudnicki 1. Wprowadzenie Pierwszą wersję języka C opracował Dennis Ritchie w roku 1972 (wykorzystując niektóre roz wiazania z opracowanych w latach1967-1970 języków BCPL oraz B). Pełny opis został zawarty w książce Briana W. Kernighana i Dennisa M. Ritchie: "The C programming language" w roku 1978. Język C opracowano głównie dla potrzeb programistów tworzących systemy operacyjne (w nim napisano w r.1973 system UNIX) i dlatego jest znacznie trudniejszy i bardziej złożony niż np. BASIC - przeznaczony dla początkujących, czy Matlab przeznaczony dla szerokich rzesz użytkowników. Dalszy rozwój języka C doprowadził m.in. do ogłoszenia w roku 1988 standardu języka ANSI C. W latach osiemdziesiątych Bjarne Stroustrup opracował znacznie rozszerzony, obiektowy i do stosowany do graficznego interfejsu język C++ w którym m.in. opracowano system Ms Windows. Poniższy opis jest bardzo okrojony i uproszczony zarówno ze względu na znaczną trudnośc bar dziej zaawansowanych środków języka jak przewidziany niewielki udział tego języka w aktualnie skonstruowanym programie nauczania oraz preferowaniem Matlaba. 1.1. Struktura programu Program w języku C składa się z funkcji(1). Funkcja jest wydzieloną częścią programu, realizu jącą pewne zadanie. Główny program musi mieć postać funkcji o nazwie main() - od niej rozpoczyna się wykonanie programu. Instrukcje składające się na treść funkcji zwaną jej "ciałem" umieszcza się w nawiasach klamrowych { }. Nawiasy klamrowe { } są także używane wszędzie tam gdzie dwie lub więcej instrukcji ma utworzyć blok, na przykład wewnątrz pętli lub w opcjach instrukcji warun kowej. Dla ilustracji podaję najprostszy przykład programu: /* Program wyświetla napis: WITAM */ #include <stdio.h> main() { printf("WITAM \n"); } Pozostałe objaśnienia: W dowolnych miejscach mogą być umieszczane komentarze ujęte między znakami /* ... */ Na początku programu niezbędne są zazwyczaj tak zwane "dyrektywy preprocesora" rozpoczy nające się znakiem #. Dyrektywa #include pozwala wstawić zawartość określonego pliku (w tym przypadku stdio.h), dokładnie w miejscu tej dyrektywy. W szczególności wstawiane są pod programy. Plik stdio.h to tak zwany plik nagłówkowy (header - o czym świadczy rozszerzenie .h). Zawiera on funkcje obsługi standardowego ("std") wejścia i wyjścia ("io" = input-otput) a wśród nich definicję funkcji printf(). Funkcja printf() kopiuje na ekran znaki zawarte między cudzysłowami " ", za wyjątkiem sekwencji znaków specjalnych poprzedzonych znakiem backslash "\" i nazywanych "sekwencjami 1 ) W innych językach program składa się z podprogramów wśród których jako funkcje definiowane są te które zwracają pojedynczą wartość (tak jest np. w językach BASIC oraz FORTRAN) lub macierz (w Matlabie) a inne definiowane są jako procedury, które nie muszą dawać w wyniku wartości liczbowych . W języku C są tylko funkcje, dlatego wprowadzono typ void czyli "wartości których nie ma" escape". Znak \n to polecenie zmiany linii - spowoduje, że kolejny wydruk (w tym przypadku na ekranie) pojawi się w następnej linii. Złożone programy składają się z wielu funkcji pełniących rolę podprogramów (zarówno funkcyjnych jak i proceduralnych). Oto kolejny przykład programu z objaśnieniami: Program ten wczytuje długość w metrach, przelicza ją na centymetry i milimetry i wyświetla na ekranie. Program kończy działanie po wprowadzeniu liczby ujemnej. #include <stdio.h> dołączenie pliku nagłówkowego stdio.h main () funkcja main() - to główny blok programu { początek ciała funkcji main(), w nawiasach { } int metr, centymetr, milimetr; deklaracja typu zmiennych printf (“ \n Podaj długość”); w nowej linii wyświetla napis "Podaj..." scanf ("%d" ,& metr); wczytanie wartości całkowitej ("%d") do zmien nej metr while (metr >=0) początek pętli while() dla dodatnich wart. metr { ciało pętli umieszcza się w nawiasach {} centymetr = 100*metr; nadanie wartości zmiennej centymetr milimetr=1000*metr; nadanie wartości zmiennej milimetr printf ("\n %d w metrach\n", metr); wyświetlenie wyniku w metrach printf ("%d w centymetrach \n", centymetr); wyświetlenie wyniku w centymetrach printf ("%d w milimetrach \n", milimetr); wyświetlenie wyniku w milimetrach printf ("Podaj następną długość"); wyświetlenie napisu: "Podaj następną ..." scanf ("%d", &metr); wczytanie wartości do zmiennej metr } koniec pętli while printf (" *** koniec programu *** \n"); wyświetlenie napisu: "***koniec programu.." return (0) funkcja main() zwraca zero } koniec ciała funkcji main() 1.2. Podstawowe pliki nagłówkowe Pliki nagłówkowe zawierają deklaracje (tzw. prototypy) różnorodnych funkcji z bibliotek standar dowych niezbędnych dla działania konkretnego programu. Najczęściej dołączane dyrektywą #include pliki nagłówkowe to: stdio.h, conio.h, stdlib.h, math.h, float.h 1.3. Typy. Deklaracje typów zmiennych Wszystkie zmienne i struktury danych muszą być zadeklarowane na początku tej funkcji w której są używane. Omówimy tylko deklaracje zmiennych prostych oraz tablic. 1.3.1. Zmienne proste i ich deklarowanie Deklaracja zmiennych prostych składa się z nazwy typu i listy zmiennych: lista zmiennych nazwa_typu zmienna, zmienna, ...zmienna; Przykład: int metr, centymetr, milimetr; deklaracja ta rezerwuje obszary pomięci dla trzech zmiennych: metr, centymetr, milimetr; typu całkowitego - o czym świadczy nazwa typu: int. 2 Oprócz konieczności zadeklarowania trzeba jeszcze dobrać typy odpowiednie do roli zmiennych i operacji w jakich mają brać udział. Na przykład wskaźniki (indeksy) elementów wektorów i macierzy muszą być typu całkowitego, a zmienne dla których ma sens dzielenie, pierwiastkowanie i inne działania dające wynik niecałkowity - muszą być typu rzeczywistego. W języku C są cztery podstawowe proste typy zmiennych o nazwach: char - znak, int - wartości całkowite, float oraz double - wartości rzeczywiste void - typ bezwartościowy (to znaczy brak zmiennej tam gdzie teoretycznie powinna być, na przykład brak argumentu funkcji lub jej rezultatu) Typy te mogą być zmodyfikowane przez poprzedzenie nazwy typu (w deklaracji) jednym ze słów: • unsigned - bez znaku; • short - krótki • long - długi Wymienione typy scharakteryzowano w tabeli: Nazwa typu void Typ Zakres brak wartości Całkowite używane dla znaków drukarskich: char całkowity -128...127 unsigned char całkowity 0...255 Całkowite int całkowity -2^31...2^31-1 unsigned int całkowity 0...2^32 short int całkowity -32768...32767 unsigned short int całkowity 0...65535 long int całkowity -2^31...2^31-1 unsigned long int całkowity 0...2^32 Rzeczywiste float rzeczywisty 6 znaków precyzji double rzeczywisty 10 znaków precyzji Bajtów 1 1 4 (lub 2) 4 (lub 2) 2 2 4 4 4 8 1.3.2. Tablice i deklaracje tablic Tablica jednowymiarowa czyli wektor jest zbiorem ponumerowanych elementów jed nakowego typu. Numer pierwszego elementu w tablicy jest zawsze równy zero. Tablice muszą - tak jak inne zmienne - być deklarowane. Deklaracja tablicy zawiera: nazwę typu listę nazw tablic z ich wymiarami - czyli po każdej nazwie w nawiasach prostokątnych muszą być podane maksymalne przewidywane wartości wskaź ników (zwanych też indeksami lub numerami elementów). Przykład deklaracji dwu tablic o nazwach "a" oraz "wektor": int a[5], wektor[10]; Tablicę można także inicjować podając w deklaracji po jej nazwie i znaku równości listę war tości oddzielonych przecinkami i zamkniętych w nawiasach klamrowych. Przykład: int a1[5] = {1, 5, 3, 4, 2}; W programach posługujemy się elementami tablic określanymi przez nazwę tablicy oraz indeksy ujęte w nawiasy kwadratowe. Jako indeks czyli numer elementu może służyć 3 stała całkowita, zmienna typu całkowitego lub dowolne wyrażenie, którego wynikiem jest liczba całkowita. Przykłady: a[5] = 10; b[i+1] = b[i]*2; Możliwe jest zadeklarowanie tablicy tablic (odpowiadającej tablicy dwu- lub więcej wy miarowej): int a[10][15]; Powyższa instrukcja deklaruje 10-cio elementową tablicę a, której polami są piętnasto elementowe tablice zmiennych typu int. Przy odwoływaniu się do elementów tablicy najpierw podaje się numer elementu pierwszej tablicy, potem numer elementu wewnątrz tej tablicy: a[4][5] = 10; 1.4. Stałe, zmienne, wyrażenia arytmetyczne, instrukcje przypisania Uwaga: duże i małe litery w języku C są rozróżniane! 1.4.1. Stałe Deklarowanie stałych jest możliwe przy pomocy dyrektyw #define w których podaje się na zwę stałej i oddzieloną odstępem jej wartość. Np.: # define NUMBER 3.15 # define NUMBER1 3.0 # define CHARACTER ‘A’ # define STRING “ABC” 1.4.2. Identyfikatory (nazwy) Jeżeli piszemy program musimy wybrać nazwy dla zmiennych, funkcji i innych obiek tów. Identyfikator w C musi spełniać następujące wymagania: musi się zaczynać od litery (A do Z, a do z) lub też od znaku podkreślenia _; musi się składać z liter (A do Z, a do z), cyfr lub też od znaków podkreślenia _; nie może być słowem kluczowym (Słowo kluczowe to takie słowo jak int czy while, które ma specjalne znaczenie). 1.4.3. Operatory arytmetyczne Priorytet 3 3 2 2 2 1 1 Operator + * / % + ++ oraz -- Uwagi jednoargumentowy jednoargumentowy + mnożenie dzielenie (rzeczywiste lub całkowite) reszta z dzielenia odejmowanie dodawanie objaśniono poniżej Operator ++ oraz - Operator ++ użyty jako przyrostek to tzw. postinkrementacja, natomiast użyty jako przedrostek to tzw. preinkrementacja. Różnicę w ich działaniu pokazuje przykład: Załóżmy, że zmienna a ma wartość pięć i wykonujemy taką oto instrukcję: c = a++; 4 W takim przypadku zmiennej c zostanie przypisana wartość zmiennej a (czyli pięć) i dopiero po tym przypisaniu zmienna a zostanie zwiększona o jeden. Czyli w efekcie po wykonaniu tej instrukcji zmienna c będzie zawierała wartość pięć, natomiast zmienna a będzie równa sześć. Teraz przy założeniach takich samych jak powyżej wykonujemy taką instrukcję: c = ++a; W takim przypadku najpierw zmienna a zostanie zwiększona o jeden (czyli teraz będzie rów na sześć) i następnie ta wartość będzie przypisana zmiennej c. Czyli w efekcie po wykonaniu tej instrukcji obie zmienne będą równe sześć. Analogicznie działa operator -- tylko zamiast zwiększania, zmniejsza wartość o jeden. 1.5. Funkcje wejścia i wyjście (liczbowe i tekstowe) Podstawowymi funkcjami dla wyprowadzania wyników są printf oraz fprintf. Funkcja printf ma najczęściej ogólną postać następującą: printf("format", lista_zmiennych) gdzie: lista_zmiennych - to ciąg nazw zmiennych lub elementów tablic pooddzielanych przecinkami "format" - to ciąg znaków umieszczony między cudzysłowami i zawierający: dowolne teksty kopiowane na ekran zaczynające się od znaku backslash "\" - sekwencje znaków specjalnych (m.in. steru jących drukowaniem), nazywane "sekwencjami escape". W szczególności znak \n to po lecenie zmiany linii - spowoduje, że kolejny wydruk pojawi się w następnej linii. zaczynające się od znaku "%" opisy formatów w jakich mają być wyprowadzane war tości zmiennych Na przykładach poniżej objaśniono najprostsze i najczęściej używane formaty: %d - dla wartości typu całkowitego %6d - dla wartości typu całkowitego, która ma zająć co najmniej 6 znaków %f - dla wartości typu rzeczywistego (typ float) %8.4f - dla wartości typu rzeczywistego (typ float), która ma zająć co najmniej 8 znakówa w tym 4 miejsca po kropce dziesiętnej (nie przecinek tylko kropka zwyczajem anglosaskim) 1.6. Wyrażenia logiczne i instrukcja warunkowa IF Operatory relacji: Operator == > >= < <= != Znaczenie równe większe większe lub równe mniejsze mniejsze lub równe nierówne Instrukcja if jest stosowana by komputer mógł - zależnie spełnienia lub nie spełnienia określo nego warunku - wybrać odpowiednią sekwencję operacji. Najprostsza z form instrukcji if: if (warunek) { blok instrukcji; } umożliwia wykonanie {bloku instrukcji} tylko wtedy gdy jest spełniony podany warunek. Warunek jest wyrażeniem logicznym i musi być zawarty w nawiasach okrągłych, a blok instrukcji jest ujęty w nawiasy klamrowe, które pomija się gdy blok składa się tylko z jednej instrukcji. 5 Najpierw komputer określa czy ma wartość logiczną "prawda" czy "fałsz". Jeżeli warunek ma wartość logiczną "prawda" to zostaje wykonany {blok instrukcji} i sterowanie przechodzi do instrukcji następnej. Druga forma instrukcji if realizuje wykonanie {blok instrukcji 1} gdy podany warunek ma wartość "prawda" natomiast {blok instrukcji 2} gdy ma wartość "fałsz": if (wyrażenie) { blok instrukcji 1; } else { blok instrukcji 2; } 1.7. Pętle 1.7.1. Pętla FOR for(początek; warunek; zmiana) { instrukcje wielokrotnie wykonywane } Przykład: for (fahr=0; fahr<=300; fahr=fahr+20) printf("Temperatura w stopniach Fahrnheita %3d w St.Celsjusza %6.1f\n",fahr, (5.0/9.0)*(fahr-32)); Instrukcja continue Instrukcja continue może wystąpić tylko wewnątrz instrukcji pętli i powoduje przeskok do końca pętli czyli do sprawdzenia możliwości dalszego wykonywania (kontynuacji) pętli. Instrukcja break Instrukcja break może wystąpić tylko wewnątrz pętli i powoduje wyskoczenie z tej pętli. 1.7.2. Pętla WHILE while(warunek) { } instrukcje wielokrotnie wykonywane Pętla ta powtarza instrukcje zawarte w nawiasach klamrowych tak długo dopóki spełniony jest warunek. 6