WYKŁAD 4, 5 i 6. Wprowadzenie do języka C Mój pierwszy, drugi,..., n-ty program w języku C. Programy: c1_1.c... c1_9.c.



Podobne dokumenty
METODY I JĘZYKI PROGRAMOWANIA PROGRAMOWANIE STRUKTURALNE. Wykład 02

WYKŁAD 10. Zmienne o złożonej budowie Statyczne i dynamiczne struktury danych: lista, kolejka, stos, drzewo. Programy: c5_1.c, c5_2, c5_3, c5_4, c5_5

Temat: Dynamiczne przydzielanie i zwalnianie pamięci. Struktura listy operacje wstawiania, wyszukiwania oraz usuwania danych.

Programowanie strukturalne i obiektowe

Zmienne, stałe i operatory

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

Część 4 życie programu

WYKŁAD 8. Funkcje i algorytmy rekurencyjne Proste przykłady. Programy: c3_1.c..., c3_6.c. Tomasz Zieliński

Argumenty wywołania programu, operacje na plikach

1 Podstawy c++ w pigułce.

Wstęp do Programowania, laboratorium 02

Wykład VI. Programowanie. dr inż. Janusz Słupik. Gliwice, Wydział Matematyki Stosowanej Politechniki Śląskiej. c Copyright 2014 Janusz Słupik

Język C zajęcia nr 11. Funkcje

Programowanie w C++ Wykład 5. Katarzyna Grzelak. 26 marca kwietnia K.Grzelak (Wykład 1) Programowanie w C++ 1 / 40

2 Przygotował: mgr inż. Maciej Lasota

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

1 Podstawy c++ w pigułce.

Tablice, funkcje - wprowadzenie

Wskaźniki. Informatyka

wykład III uzupełnienie notatek: dr Jerzy Białkowski Programowanie C/C++ Język C - zarządzanie pamięcią, struktury,

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

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

Biblioteka standardowa - operacje wejścia/wyjścia

Wskaźniki w C. Anna Gogolińska

Podstawy programowania C. dr. Krystyna Łapin

Język ludzki kod maszynowy

Podstawy Programowania C++

wykład II uzupełnienie notatek: dr Jerzy Białkowski Programowanie C/C++ Język C - funkcje, tablice i wskaźniki wykład II dr Jarosław Mederski Spis

I - Microsoft Visual Studio C++

Pliki w C/C++ Przykłady na podstawie materiałów dr T. Jeleniewskiego

ISO/ANSI C - funkcje. Funkcje. ISO/ANSI C - funkcje. ISO/ANSI C - funkcje. ISO/ANSI C - funkcje. ISO/ANSI C - funkcje

Wstęp do programowania INP003203L rok akademicki 2018/19 semestr zimowy. Laboratorium 3. Karol Tarnowski A-1 p.

Pliki. Informacje ogólne. Obsługa plików w języku C

Programowanie I C / C++ laboratorium 03 arytmetyka, operatory

Stałe i zmienne znakowe. Stała znakowa: znak

Funkcje zawarte w bibliotece < io.h >

1. Pierwszy program. Kompilator ignoruje komentarze; zadaniem komentarza jest bowiem wyjaśnienie programu człowiekowi.

Funkcje zawarte w bibliotece < io.h >

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

#include <stdio.h> int main( ) { int x = 10; long y = 20; double s; s = x + y; printf ( %s obliczen %d + %ld = %f, Wynik, x, y, s ); }

Programowanie w C++ Wykład 2. Katarzyna Grzelak. 4 marca K.Grzelak (Wykład 1) Programowanie w C++ 1 / 44

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

Pliki. Informacje ogólne. Obsługa plików w języku C

KURS C/C++ WYKŁAD 1. Pierwszy program

main( ) main( void ) main( int argc, char argv[ ] ) int MAX ( int liczba_1, liczba_2, liczba_3 ) źle!

Dr inż. Grażyna KRUPIŃSKA. D-10 pokój 227 WYKŁAD 7 WSTĘP DO INFORMATYKI

Wskaźniki. Programowanie Proceduralne 1

Podstawy programowania w języku C++

Laboratorium Podstaw Informatyki. Kierunek Elektrotechnika. Ćwiczenie 1. Podstawy. Wprowadzenie do programowania w języku C. Katedra Metrologii AGH

Język C : programowanie dla początkujących : przewodnik dla adeptów programowania / Greg Perry, Dean Miller. Gliwice, cop

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

Wykład VII. Programowanie. dr inż. Janusz Słupik. Gliwice, Wydział Matematyki Stosowanej Politechniki Śląskiej. c Copyright 2014 Janusz Słupik

#include <stdio.h> void main(void) { int x = 10; long y = 20; double s; s = x + y; printf ( %s obliczen %d + %ld = %f, Wynik, x, y, s ); }

Programowanie w języku Python. Grażyna Koba

Programowanie I C / C++ laboratorium 02 Składnia pętli, typy zmiennych, operatory

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

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

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

Operatory. Operatory bitowe i uzupełnienie informacji o pozostałych operatorach. Programowanie Proceduralne 1

Uzupełnienie dot. przekazywania argumentów

INFORMATYKA Studia Niestacjonarne Elektrotechnika

1. Wprowadzanie danych z klawiatury funkcja scanf

Funkcja (podprogram) void

Pascal typy danych. Typy pascalowe. Zmienna i typ. Podział typów danych:

OPERACJE WEJŚCIA / WYJŚCIA. wysyła sformatowane dane do standardowego strumienia wyjściowego (stdout)

Języki i metodyka programowania. Wprowadzenie do języka C

IX. Wskaźniki.(3 godz.)

ISO/ANSI C - funkcje. Funkcje. ISO/ANSI C - funkcje. ISO/ANSI C - funkcje. ISO/ANSI C - funkcje. ISO/ANSI C - funkcje

Elementy języka C. ACprogramislikeafastdanceonanewlywaxeddancefloorbypeople carrying razors.

Programowanie w C++ Wykład 2. Katarzyna Grzelak. 5 marca K.Grzelak (Wykład 1) Programowanie w C++ 1 / 41

Podstawy programowania. Wykład 7 Tablice wielowymiarowe, SOA, AOS, itp. Krzysztof Banaś Podstawy programowania 1

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

Programowanie w C++ Wykład 5. Katarzyna Grzelak. 16 kwietnia K.Grzelak (Wykład 1) Programowanie w C++ 1 / 27

Język C, tablice i funkcje (laboratorium, EE1-DI)

Lab 9 Podstawy Programowania

Microsoft IT Academy kurs programowania

DYNAMICZNE PRZYDZIELANIE PAMIECI

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

Tablice i struktury. czyli złożone typy danych. Programowanie Proceduralne 1

Laboratorium 6: Ciągi znaków. mgr inż. Leszek Ciopiński dr inż. Arkadiusz Chrobot dr inż. Grzegorz Łukawski

Wskaźniki. Przemysław Gawroński D-10, p marca Wykład 2. (Wykład 2) Wskaźniki 8 marca / 17

Podstawy programowania w języku C++

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

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

Wstęp do programowania INP001213Wcl rok akademicki 2018/19 semestr zimowy. Wykład 2. Karol Tarnowski A-1 p.

iii. b. Deklaracja zmiennej znakowej poprzez podanie znaku

tablica: dane_liczbowe

/* dołączenie pliku nagłówkowego zawierającego deklaracje symboli dla wykorzystywanego mikrokontrolera */ #include <aduc834.h>

Mikrokontroler ATmega32. Język symboliczny

Wprowadzenie do języka Java

Grzegorz Cygan. Wstęp do programowania mikrosterowników w języku C

JĘZYKI PROGRAMOWANIA Z PROGRAMOWANIEM OBIEKTOWYM. Wykład 6

Wstęp do programowania INP003203L rok akademicki 2018/19 semestr zimowy. Laboratorium 2. Karol Tarnowski A-1 p.

Wykład 2 Składnia języka C# (cz. 1)

ZASADY PROGRAMOWANIA KOMPUTERÓW

Instrukcja do ćwiczeń nr 4 typy i rodzaje zmiennych w języku C dla AVR, oraz ich deklarowanie, oraz podstawowe operatory

Laboratorium 1 Temat: Przygotowanie środowiska programistycznego. Poznanie edytora. Kompilacja i uruchomienie prostych programów przykładowych.

Zmienne i struktury dynamiczne

Podstawy Informatyki sem. I 2014/2015 studia zaoczne Elektronika i Telekomunikacja!

utworz tworzącą w pamięci dynamicznej tablicę dwuwymiarową liczb rzeczywistych, a następnie zerującą jej wszystkie elementy,

Transkrypt:

WYKŁAD 4, 5 i 6 Wprowadzenie do języka C Mój pierwszy, drugi,..., n-ty program w języku C Programy: c1_1.c... c1_9.c Tomasz Zieliński

KOMPILATOR vs. INTERPRETER (1) - ogólnie C/C++ = kompilatory tłumaczą od razu cały program na kod maszynowy potem dopiero program jest wykonywany stosowane kiedy jest już znany algorytm rozwiązania Basic = interpretery Matlab tłumaczona i wykonywana jest linia po linii programu stosowane kiedy jest poszukiwany algorytm rozwiązania Kompilator Interpreter Zalety Szybkie działanie programu Możliwość optymalizacji kodu programu, np. minimalizacji potrzebnej pamięci Krótka droga do pomysłu do jego weryfikacji Wady Długa droga do pomysłu do jego weryfikacji Wolne działanie programu

KOMPILATOR vs. INTERPRETER (2) - praca nad programem f1.obj, f2.obj,... statyczne (lib) i dynamiczne (dll) dołączanie bibliotek system.lib Lib Maker Konsolidator my.lib system.dll my.dll wykonanie całego programu Edytor tekstu KOMPILATOR programu Linker System operacyjny prog.c prog.obj prog.exe INTERPRETER to oddzielny program / aplikacja 1 2 Edytor linii Program czyli zbiór linii 1 2 INTERPRETER Interpreter linii >>...?... (CR) Egzekutor linii

KOMPILATOR vs. INTERPRETER (3) szybkość pisania vs. szybkość działania czas napisania i uruchamiania (usunięcia błędów) programu czas wykonania programu Asembler Język C/C++ Matlab Simulink WNIOSEK: kiedy poszukuję rozwiązania problemu, wybieram język wysokiego poziomu, nawet graficzny, z dużą liczbą bibliotek (szybko piszę program, który wolno działa) kiedy znam rozwiązanie problemu wybieram język niskiego poziomu (wolno piszę program, który szybko działa)

Kod znak-moduł 0 0 0 1 0 0 0 0 = +16 (16) + 1 0 0 1 0 0 0 0 = 16 (144) --------------------------------- 1 0 1 0 0 0 0 0 = 32 (160) Kod uzupełnień do dwóch U2 ARYTMETYKA KOMPUTEROWA (1) (problem zapisu znaku liczby) 0 0 0 1 0 0 0 0 = +16 1 1 1 0 1 1 1 1 (zaneguj wszystkie bity) + 1 (dodaj 1 do wyniku negacji) ------------------------- 1 1 1 1 0 0 0 0 = 16 (128+64+32+16 = 240) +16 = 0 0 0 1 0 0 0 bez zmiany do pierwszej 1 włacznie, a potem negacja + 0 0 0 1 0 0 0 0 (+16) 1 1 1 1 0 0 0 0 (-16) -16 = 1 1 1 1 0 0 0 1 0.0 0 0 0 0 0 0 (+0)

ARYTMETYKA KOMPUTEROWA (2) (przykład zastosowania kodu U2) 00000110 = 6 00000101 = 5 00000110 = 6 -------------- + 11111011 = 5 11111010 ------------------------ + 1 1 00000001 = 1 -------------------- 11111011 = 5

ARYTMETYKA KOMPUTEROWA (3) (problem zapisu liczb niecałkowitych, ułamkowych w kodzie U2) 0 1 0 0 0 1 1 0 binarnie (70) ----------------------------------------------------------------------------------- 1 2 1 2 2 2 3 2 4 2 5 2 6 2 7 wagi 1 1/2 1/4 1/8 1/16 1/32 1/64 1/128 ----------------------------------------------------------------------------------- wynik 1/2 1/32 1/64 = 35/64 = 0.546875 1 0 1 1 1 0 1 0 binarnie (-70) ---------------------------------------------------------------------------------- 1 2 1 2 2 2 3 2 4 2 5 2 6 2 7 wagi 1 1/2 1/4 1/8 1/16 1/32 1/64 1/128 ---------------------------------------------------------------------------------- wynik 1 1/4 1/8 1/16 1/64 = 35/64 = 0.546875 PRZYKŁADY: 00000110 = 0 + (1/32 + 1/64) = 3/64 11111011 = 1 + (1/2 + 1/4 + 1/8 + 1/16 + 1/64 + 1/128) = 1 + 123/128 = 5/128

ARYTMETYKA KOMPUTEROWA (4) (problem zapisu bardzo małych/dużych liczb rzeczywistych) x = 0,009765625 = 0,9765625*10-2 = 0,625 * 2-6 x = (-1) z * m * 2 c x = z 1 bit c 8 bitów (p) m 23 bity, c 8 bitów (p) = c + 127, -126 c 127 8bitów 23 bity x = 1 01111001 1010 0000 0000 0000 0000 000 1/2 + 1/8 = 5/8 = 0,625 121 = 0 + 1*64 +1*32 + 1*16 + 1*8 + 0*4 + 0*2 + 1*1 121 = -6+127

/* Przyklad 1 - ver. 1 - mój pierwszy program */ // komentarz #include <stdio.h> // opis użycia funkcji z biblioteki stdio.h // w tym opis wywołania funkcji printf main() // początek programu // otwarcie bloku instrukcji programu float kasa, moje; // deklaracja zmiennych int osoby; // kasa, moje, osoby kasa = 1500.45; osoby = 4; // inicjalizacja wartości zmiennych // kasa i osoby moje = kasa/osoby; // użycie zmiennych kasa i osoby // obliczenie mojego kieszonkowego // nowa linia printf(" moje kieszonkowe = %7.3f \n", moje ); // wydruk na monitor // nowa linia return(0); // wyjście z programu // zamknięcie bloku instrukcji programu /* OPIS PROGRAMU 1) Program powinien zaczynać komentarz co dany program robi: /*... co ja robię?.. */. 2) Następnie dołączany jest zbiór opisów wywołań funkcji bibliotecznych: np. #include <stdio.h> - biblioteka standardowego wejścia (input) i wyjścia (output) #include <math.h> - biblioteka funkcji matematycznych sin(), cos(), exp(), log(),... #include <string.h> - biblioteka operacji na łańcuchach znaków 3) main()... mój program... - program główny (funkcja główna) char to kod znaku zapisany na 8 bitach (1 bajt) int to liczba całkowita ze znakiem zapisana na 16 bitach (2 bajtach) long to liczba całkowita ze znakiem zapisana na 32 bitach (4 bajtach) float to liczba zmiennoprzecinkowa zapisana na 32 bitach (4 bajtach) double to liczba zmiennoprzecinkowa zapisana na 64 bitach (8 bajtach) 4) W wyniku deklaracji typu zmiennych (liczba bitów i sposób zapisu) kompilator przydziela pamięć poszczególnym zmiennym. 5) W wyniku inicjalizacji zmiennych do przydzielonych pamięci zostają zapisane ich wartości. 6) Użycie zmiennych to operacja na ich nazwach (operatory arymetyczne: +, -, *, /, % - reszta z dzielenia dwóch liczb całkowitych). Przykładowo operacja moje = kasa/osoby oznacza: a) pobierz z pamięci wartości zmiennych kasa i osoby do rejestrów procesora b) podziel zawartość tych rejestrów c) zapisz wynik do pamięci przydzielonej do przechowywania zmiennej moje 7) Funkcja printf( moje kieszonkowe = %f PLN \n, moje) wypisze na ekranie monitora: moje kieszonkowe = 375.1125 PLN %d %f %c %s... - znaki przekształceń (decimal, float, character, string) \n \t \b - znaki sterujące kursorem */

/* Przyklad 1 ver. 2 - #define, scanf */ #include <stdio.h> #define OSOBY 4 // definicja stałej tekstowej OSOBY // podczas kompilacji tekst OSOBY main() // będzie zawsze zastępowany przez 4 float kasa, moje; printf("ile do podzialu? "); scanf("%f", &kasa); moje = kasa/osoby; // na ekranie monitora: nowa linia // na ekranie monitora: pytanie // wczytanie liczby z klawiatury // do zmiennej kasa printf(" moje kieszonkowe = %7.3f \n", moje ); return(0); /* OPIS PROGRAMU 1) Stałe tekstowe są definiowane na początku programu: dlatego jest je bardzo łatwo znaleźć oraz zmienić ich wartość. Np. liczba znaków w wierszu, długość bufora,... 2) Są one pisane dużymi literami: dlatego łatwo jest je odróżnić od zmiennych w tekście programu. 3) Funkcja scanf("%f", &kasa): a) wczytuje z klawiatury sekwencję znaków ASCII (zakończonych klawiszem ENTER), b) zamienia ją na liczbę binarną o zadanym formacie (u nas %f, czyli float) c) zapisuje ją do komórek pamięci, przydzielonych zmiennej kasa. 4) WAŻNE: kasa - nazwa zmiennej, &kasa - adres w pamięci zmiennej kasa, *adres - wartość liczby znajdującej się w pamięci pod zadanym adresem wskaźnik to zmienna będąca adresem w pamięci, pokazująca na liczbę określonego typu */ PRZYKŁAD definicji wskaźników do pamięci, pokazujących na liczby określonego typu: int x, y; // deklaracja zmiennych x i y int *pa, *pb; // deklaracja wskaźników pa i pb do zmiennych typu int pa = &x; pb = &y; // wskaźnik pa ma wskazywać na zmienną x, zaś pb - na zmienną y *pa = 10; *pb = 20; // zapisanie liczb 10 i 20 pod zadane adresy, czyli inicjalizacja // wartości zmiennych x oraz y

/* Przyklad 1 - ver. 3 - funkcja prosta */ #include <stdio.h> #define OSOBY 4 // deklaracja sposobu wywołania funkcji // z biblioteki stdio float wzor( float forsa ); // deklaracja sposobu wywołania // mojej funkcji /* program glowny ---------------------------------------------------------- */ main() float kasa, moje; printf("ile do podzialu? "); scanf("%f", &kasa); // wywołanie mojej funkcji moje = wzor( kasa ); // jest do niej przekazana wartość zmiennej // kasa, a odebrana wartość zmiennej moje printf("moje kieszonkowe = %7.3f \n", moje); return(0); /* definicja funkcji pomocniczej --------------------------------------------- */ float wzor( float forsa ) float temp; // funkcja otrzymuje i zwraca liczbę typu float // wewnętrzna zmienna pomocnicza temp = forsa/osoby; // obliczenie wartości zmiennej temp return( temp ); // przekazanie tej wartości do programu /* OPIS PROGRAMU 1) Sposób wywołania funkcji pisanych przez nas musi być zdefiniowany przed programem głównym, analogicznie jak dla funkcji bibliotecznych. 2) Należy podać: a) typy zmiennych przekazywanych do funkcji b) typ zmiennej odbieranej z funkcji za pomocą komendy return()

3) Do funkcji są przekazywane wartości zmiennych, tzn. liczby odczytane z pamięci spod adresów komórek przydzielonych zmiennym, lub sam adres do pamięci. W tym drugim przypadku funkcja może sama odczytać wartość zmiennej oraz ją zmodyfikować zapisując nową liczbę pod adres zmiennej. moje = wzór( kasa ) - przekazanie wartości zmiennej (kopii liczby z pamięci) moje = wzór( &kasa ) - przekazanie adresu zmiennej w pamięci W naszym przykładzie przekazujemy wartość zmiennej (kopię tego co jest w pamięci). 4) Funkcja ma dostęp do następujących wartości zmiennych: a) otrzymanych z programu nadrzędnego (wartość lub adres) b) globalnych, tzn. zdefiniowanych poza nawiasami programu głównego, a więc nie ukrytych wewnątrz jego nawiasów, czyli dostępnych dla wszystkich ; c) lokalnych, tzn. takich które sama powołała do życia W naszym przypadku: a) forsa to przekazana wartość kasy, b) stała tekstowa OSOBY jest zdefiniowana poza wszystkimi nawiasami, a więc może być także używana wewnątrz funkcji, c) temp to lokalna zmienna funkcji. 5) Wewnętrzne nazwy zmiennych, których używa funkcja, mogą być różne niż nazwy zmiennych, których wartości przekazano do funkcji. Pierwsze z nich są nazwami formalnymi a drugie nazwami wywołania. W naszym przykładzie możemy do funkcji wzor() przekazać wartość budżetu dowolnej rodziny, tzn. kasę1, kasę2 lub kasę3. Wewnątrz funkcji ta wartość zawsze będzie nazywana forsą. Oznacza to, że można wywoływać funkcję dla różnych danych. Funkcję piszemy raz, a używamy wielokrotnie. Prowadzi to do tzw. programowania strukturalnego (modułowego): program główny to pień, z którego wchodzimy do konarów - funkcji pomocniczych (z których możemy zagłębiać się dalej do dalszych gałęzi bocznych, czyli pod-funkcji). */

/* Przyklad 1 - ver. 4 - funkcja zlozona wieloargumentowa */ #include <stdio.h> #define OSOBY 3 void wzor( float forsa, float *osoba1, float *osoba2, float *osoba3 ); /* program glowny ----------------------------------------------------------------- */ main() float kasa; float tata, mama, ja; printf(" ile do podzialu? "); scanf("%f", &kasa); // wywołanie funkcji wzor( kasa, &tata, &mama, &ja ); // wartość kasy // adres do taty, mamy i do mnie printf("tata = %7.3f, mama = %7.3f, ja = %7.3f \n", tata, mama, ja); return(0); /* funkcja wlasna - pomocnicza ---------------------------------------------- */ void wzor( float forsa, float *osoba1, float *osoba2, float *osoba3 ) float srednia; /* wewnetrzna zmienna pomocnicza */ srednia = forsa/osoby; *osoba1 = 1.25 * srednia; *osoba2 = 1.00 * srednia; *osoba3 = 0.75 * srednia;

/* OPIS PROGRAMU 1) Nie jesteśmy już egoistami. Interesuje nas teraz także kieszonkowe taty, mamy, a nie tylko własne. 2) W związku z czym deklarujemy trzy zmienne typu float: tata, mama, ja. 3) Do funkcji wzor() przekazujemy adresy w pamięci do tych zmiennych: &tata, &mama, &ja. 4) Wewnątrz funkcji adresy te oznaczone jako: osoba1, osoba2, osoba3. Pisząc float *osoba1, mówimy: wartość pod adresem osoba1 jest liczbą typu float. Czyli mówimy, że osoba1 jest wskaźnikiem pokazującym na liczbę typu float. 4) Wewnątrz funkcji wyliczamy co trzeba i podstawiamy wynik pod adresy przekazane podczas wywołania funkcji, np.: *osoba1 = 1.25*srednia, czyli wartość pod adresem osoba1 ma być równa 1.25*srednia; tzn. podstaw wartość 1.25*srednia pod adres osoba1. 5) Teraz możemy pisać funkcje wieloargumentowe: wzor(a, b, c, &x, &y, &z) - wartości (kopie) zmiennych a, b,c, adresy do zmiennych x, y, z - funkcja nie może zmienić wartości zmiennej, której kopię otrzymała; może z niej tylko skorzystać; - funkcja może korzystać i zmieniać wartości zmiennych, których zna adres w pamięci */

/* Przyklad 1 ver. 5 - tablice, for, if */ #include <stdio.h> #define OSOBY 3 // void = funkcja nic nie void wzor( float forsa, float czlonkowie[] ); // zwraca poprzez return // przekazanie tablicy /* program glowny -------------------------------------------------------------------- */ main() float kasa; float rodzina[ OSOBY ]; char *imiona[ OSOBY ] = "tata", "mama", "ja"; int i; printf( "\n" ); printf( "ile do podzialu?" ); scanf( "%f", &kasa ); wzor( kasa, rodzina ); for( i=0; i<osoby; i++ ) printf( "osoba nr %d, czyli %s = %7.3f \n", i, imiona[i], rodzina[i] ); if ( rodzina[1] > rodzina[2] ) // >, >=, <, <=, ==,!= printf( "Jakis kant! Mam za malo! \n" ); else printf( "Jest dobrze! \n" ); printf( "\n" ); return(0);

/* funkcja wlasna - pomocnicza --------------------------------------------- */ void wzor( float forsa, float czlonkowie[] ) float srednia; /* wewnetrzna zmienna pomocnicza */ srednia = forsa/osoby; czlonkowie[0] = 1.25 * srednia; czlonkowie[1] = 1.00 * srednia; czlonkowie[2] = 0.75 * srednia; /* OPIS PROGRAMU 1) void wzor() - oznacza, że funkcja nic nie zwraca poprzez return. 2) void wzor( float forsa, float czlonkowie[] ) - do funkcji jest przekazana wartość zmiennej forsa oraz tablica czlonkowie[] liczb typu float; Tablica jest blokiem wartości liczbowych tego samego typu zapisanych w pamięci jedna za drugą. Przekazanie tablicy, to przekazanie adresu do początku tego bloku komórek pamięci. 3) float rodzina[ OSOBY ] - deklaracja tablicy 3-elementowej (gdyż OSOBY = 3), czyli trzech liczb zmiennoprzecinkowych typu float umieszczonych w pamięci jedna za drugą, jako jeden wspólny blok danych, oraz oznaczanych jako: rodzina[0], 0 - zerowe przesunięcie w stosunku do początku bloku rodzina[1], 1 - przesunięcie o szerokość jednej liczby typu float od początku bloku rodzina[2], 2 - przesunięcie o szerokość dwóch liczb typu float od początku bloku PRZYKŁAD: int a[3]; a[0] = 1; a[1] = 10; a[2] = a[0] + a[1]; 4) char *imiona[ OSOBY ] = "tata", "mama", "ja"; Deklaracja 3-elementowej tablicy adresów do łańcuchów znaków (tekstów, napisów) oraz równoczesna inicjalizacja wartości znajdujących się pod tymi adresami, czyli zapisanie do pamięci pod przydzielone adresy następujących słów: tata, mama, ja. 5) wzor( kasa, rodzina ) - wywołanie funkcji wzor() oraz przekazanie do niej wartości (kopii) zmiennej kasa oraz adresu do początku bloków komórek pamięci, w których jest przechowywana tablica rodzina, czyli trzy liczby typu float: rodzina[0], rodzina[1], rodzina[2]. Wewnątrz funkcji tablica rodzina nosi nazwę członkowie. Ponieważ adres początkowy bloku komórek pamięci jest ten sam, dlatego: czlonkowie[0] = rodzina[0] czlonkowie[1] = rodzina[1] czlonkowie[2] = rodzina[2] Wyliczone wartości kieszonkowe są podstawiane w następujący sposób: czlonkowie[0] = 1.25 * srednia; i tak dalej

6) Instrukcja sterująca for: for( inicjalizacja1, warunek2, operacja4 ) zbiór instrukcji 3 Kolejność: a) dokonaj inicjalizacji1 b) sprawdź warunek2 c) jeśli jest prawdziwy, to wykonaj zbiór instrukcji 3; w przeciwnym wypadku KONIEC instrukcji for d) wykonaj operację4 e) skocz do punktu b) W naszym programie dla kolejnych wartości 0, 1, 2 zmiennej i są wypisywane wartości tablic imiona[i] oraz rodzina[1], czyli: osoba nr 0, czyli tata = 625.187 osoba nr 1, czyli mama = 500.150 osoba nr 2, czyli ja = 375.112 7) Instrukcja sterująca if: if ( warunek ) if ( warunek ) wersja zbiór instrukcji A zbiór instrukcji A uproszczona else zbiór instrukcji B Kolejność: a) sprawdź warunek b) jeśli jest prawdziwy, to wykonaj zbiór instrukcji A c) w przeciwnym przypadku, wykonaj zbiór instrukcji B W naszym programie: ponieważ rodzina[1] > rodzina[2] (500.150 > 375.112) dlatego na monitorze zostanie wyświetlony napis Jakiś kant! Mam za mało!. Złożony warunek logiczny: AND (warunek1 && warunek2) np. if( (a>1) && (b<2) ) OR (warunek1 warunek 2) np. if( (a>b) (b>c) ) 8) Inne instrukcje sterujące: while( warunek ) do np. int i; i = 10; zbiór instrukcji zbiór instrukcji do ----------------------------- while( warunek ) i = i-1; a) sprawdź warunek ----------------------------------- while( i > 0) b) jeśli jest prawdziwy, a) wykonaj zbiór instrukcji to wykonaj zbiór instrukcji b) sprawdź warunek c) powrót do pkt. a) c) jeśli jest prawdziwy, to powrót do pkt. a) goto ETYKIETA switch( wyrażenie ) np. char c; c = getchar();... case wyrażenie-stałe: instr switch( c ) ETYKIETA: default: case a : printf( a ); break; case b : printf( b ); break; default: printf( NIE a, NIE b ); 9) Operatory bitowe są podobne do operatorów logicznych: AND = & np. c = a & b (AND odpowiadających sobie bitów liczb a, b) OR = np. c = a b (OR...) XOR = ^ np. c = a ^ b (XOR...) Przesuniecie bitowe liczby: >> - w prawo np. b = a >> 1 (przesuń bity liczby a o 1 bit w prawo, b 2x mniejsze) << - w lewo np. b = a << 1 (przesuń bity liczby a o 1 bit w lewo, b 2x większe) np. c = a << b (przesuń bity liczby a o b bitów w lewo) */

/* Przyklad 1 ver. 6 - wartości argumentów z linii wywolania */ /* Uruchomienie programu: c1_6 <liczba> <Enter> */ /* np.: c1_6 1500 <Enter> */ #include <stdio.h> #include <stdlib.h> #define OSOBY 3 void wzor( float forsa, float czlonkowie[] ); // funkcja obliczająca /* program glowny ----------------------------------------------------------- */ main(argc, argv) /* argc to liczba parametrów, u nas argc = 2 */ int argc; /* parametr 1 - argv[ 0 ] = nazwa programu */ char *argv[]; /* parametr 2 - argv[ 1 ] = wartość kasy */ float kasa; float rodzina[ OSOBY ]; char *imiona[ OSOBY ] = "tata", "mama", "ja"; int i; if (argc < 2) // sprawdzenie liczby argumentów, // powinny być dwa printf("\n Blad! Wywolanie programu: c1_6 <liczba> \n"); return(0); // konwersja łancucha znaków ASCII kasa = atof( argv[ 1 ] ); // na liczbę typu float i podstawienie do kasy printf( "\n kasa = %7.3f \n", kasa ); wzor( kasa, rodzina ); printf( "\n" ); // nowa linia na monitorze for( i=0; i<osoby; i++) printf( "osoba nr %d, czyli %s = %7.3f \n", i, imiona[i], rodzina[i] ); // nowa linia na monitorze return(0);

/* funkcja wlasna - pomocnicza ------------------------------------------------- */ void wzor( float forsa, float czlonkowie[] ) float srednia; // wewnętrzna zmienna pomocnicza srednia = forsa/osoby; *czlonkowie++ = 1.25 * srednia; // podstaw, zwiększ wskaźnik *czlonkowie++ = 1.00 * srednia; // podstaw, zwiększ wskaźnik *czlonkowie = 0.75 * srednia; // podstaw /* OPIS PROGRAMU Wprowadzanie wartości parametrów bezpośrednio z linii wywołania jest bardzo często stosowane (na niebiesko - nazwa programu, na czerwono - parametr zawsze wprowadzany jako sekwencja znaków ASCII): edit program.c gcc program.c Przykładowo w programach c9_3.c, c9_4.c oraz c9_5.c wprowadza się w ten sposób parametry nagrywania zbiorów dźwiękowych typu WAVE: c9_5 <nazwa.wav> < 44/32/24/22/16/11/8 > < s/m > < 16/8 > czestotliwości liczba próbkowania bitow nazwa w khz zbioru Mono wave Stereo np. c9_5 test.wav 44 s 16 = zbiór test.wav, 44 khz, stereo, 16 bitów Ponieważ parametry są wprowadzane jako sekwencja znaków ASCII, muszą być potem zamienione na zmienną określonego typu: i = atoi( argv[ 1 ] ); f = atof( argv[ 2 ] ); // ASCII to integer // ASCII to float */

/* Przyklad 1 ver. 7 - wartości argumentów ze zbioru */ #include <stdio.h> #include <stdlib.h> #define OSOBY 3 void wzor( float forsa, float czlonkowie[] ); /* program glowny -------------------------------------------------------------------- */ main() FILE *FileIn, *FileOut; // deklaracja uchwytów FileIn, FileOut // do zbiorów float kasa; float rodzina[ OSOBY ]; char *imiona[ OSOBY ] = "tato", "mama", "ja"; int i; // przyporządkuj zbiory do uchwytów FileIn = fopen( "we.dat", "r"); // otwórz zbior we.dat do czytania FileOut = fopen( "wy.dat", "w"); // otwórz zbior wy.dat do zapisu fscanf( FileIn, "%f", &kasa); // przeczytaj ze zbioru (uchwyt FileIn) fprintf( FileOut, "kasa = %7.3f \n", kasa ); // zapisz do zbioru (FileOut) wzor( kasa, rodzina ); // oblicz ile komu for( i=0; i<osoby; i++) fprintf( FileOut, " %s = %7.3f \n", imiona[i], rodzina[i] ); // zapisz fclose( FileIn ); fclose( FileOut ); // zamknij zbior (uchwyt FileIn), czyli we.dat // zamknij zbior (uchwyt FileOut), czyli wy.dat return(0); /* Kolejność: 1) zdefiniuj uchwyty do zbiorów, 2) otwórz odpowiednie zbiory do czytania ( r ), pisania ( w ), czytania & pisania ( rw ) i przyporządkuj je do uchwytów, 4) czytaj ze zbiorów i zapisuj do zbiorów, 5) zamknij zbiory */

/* Przykład 1 ver. 8 - struktury, czyli zmienne złożone */ #include <stdio.h> #define OSOBY 3 // DEKLARACJA STRUKTURY osoba struct osoba // Przykład inicjalizacji zmiennej "x" o tej strukturze char imie[10]; // struct osoba x; // deklaracja typu x float kieszonkowe; // strcpy( x.imie, "tata"); // imienia x ; // x.kieszonkowe = 500.123; // kieszonkowego x void wzor( float forsa, struct osoba iksinscy[] ); // program główny -------------------------------------------------------------------- main() // tablica zmiennych o strukturze osoba float kasa = 1500.45; // kowalscy[0].imie struct osoba kowalscy[ OSOBY ]; // kowalscy[0].kieszonkowe char *imiona[ OSOBY ] = "tata", "mama", "ja"; int i; for( i=0; i<osoby; i++ ) // To samo prościej: // kowalscy[0].imie = imiona[0]; strcpy( kowalscy[i].imie, imiona[i] ); // kowalscy[1].imie = imiona[1]; // kowalscy[2].imie = imiona[2]; wzor( kasa, kowalscy ); // wywołanie funkcji liczącej kieszonkowe for( i=0; i<osoby; i++) // wydruk kieszkonkowego członków rodziny printf("osoba %d, czyli %s = %7.3f \n", i, kowalscy[i].imie, kowalscy[i].kieszonkowe); getchar(); return(0);

// funkcja własna - pomocnicza --------------------------------------------- void wzor( float forsa, struct osoba iksinscy[] ) float srednia; // wewnętrzna zmienna pomocnicza srednia = forsa/osoby; iksinscy[0].kieszonkowe = 1.25 * srednia; iksinscy[1].kieszonkowe = 1.00 * srednia; iksinscy[2].kieszonkowe = 0.75 * srednia; /* OPIS PROGRAMU W języku C można definiować zmienne złożone ( wielozmienne ) o złożonej strukturze. struct wielozmienna // deklaracja struktury o nazwie wielozmienna int a; // która się składa z jednej liczby a typu int float b; // jednej liczby b typu float char c; // oraz jednego znaku c ; struct wielozmienna x; x.a = 1; x.b = 1.2345; x.c = r ; // deklaracja zmiennej złożonej x typu wielozmienna // inicjalizacja podzmiennej a zmiennej x (int) // inicjalizacja podzmiennej b zmiennej x (float) // inicjalizacja podzmiennej c zmiennej x (char) Wskaźnik (adres) do zmiennych złożonych można przekazywać do funkcji, np. funkcja( &x ); // wywołanie funkcji. przekazanie wskaźnika (adresu) void funkcja( struct wielozmienna *y) // definicja funkcji (*y).a = 1; // inaczej: y->a = 1; (*y).b = 1.2345; // inaczej: y->b = 1.2345; (*y).c = r // inaczej: y->c = r ; Możemy definiować tablice zmiennych złożonych, np. struct wielozmienna x[10]; x[0].a = 1; x[0].b = 1.2345; x[0].c = r ; Stuktury mogą mieć budowę drzewiastą, tzn. jedna struktura może wchodzić w skład innej struktury, np. struktura adres może wchodzić w skład struktur pacjent, student,... itp. struct student struct adres char nazwisko[30]; char miasto[20]; char imie[20]; long kod; struct adres adr; char ulica[40]; int wiek; int numer; int wzrost; long mieszkanie; zm; ; zm.adr.kod = 30059; */

/* Przykład 1 ver. 9 - lista dynamiczna członków rodziny */ /* patrz wykład nr 7 i 8 */ #include <stdio.h> #include <stdlib.h> #define OSOBY 3 // DEKLARACJA STRUKTURY osoba struct osoba // Przykład inicjalizacji zmiennej x o strukturze osoba: char imie[10]; // struct osoba x; float kieszonkowe; ; // strcpy( x.imie, "tata"); // inicjalizacja imienia x // x.kieszonkowe = 500.123; // inicjalizacja kieszonkowego x struct wezel struct osoba ktos; // wewnątrz węzła jest zmienna o strukturze osoba struct wezel *nastepny; // oraz adres do następnego węzła ; // np. struct wezel w; // strcpy(w.ktos.imie,"tata"); // w.ktos.kieszonkowe = 500.123; // (*w).nastepny =?; lub w->nastepny =?; // DEKLARACJA WĘZŁA LISTY JEDNOKIERUNKOWEJ typedef struct wezel *ADRwezel; // ADRwezel jest teraz nazwą nowego typu, // czyli adresu węzła void wzor( float forsa, ADRwezel lista ); // deklaracja wywołania funkcji // program główny --------------------------------------------------------------------- main() float kasa = 1500.45; // deklaracja i inicjalizacja wartości ADRwezel lista, w, w0, w1, w2; // deklaracja 5 adresów węzłów int i; // deklaracja zmiennej pomocniczej // dynamiczna alokacja pamięci dla 3 węzłów w0 = (ADRwezel) malloc( sizeof( struct wezel ) ); w1 = (ADRwezel) malloc( sizeof( struct wezel ) ); w2 = (ADRwezel) malloc( sizeof( struct wezel ) ); lista = w0; // lista = adres pierwszego węzła strcpy(w0->ktos.imie,"tata"); // podstaw imię osoby w węźle 0 strcpy(w1->ktos.imie,"mama"); // podstaw imię osoby w węźle 1 strcpy(w2->ktos.imie,"ja"); // podstaw imię osoby w węźle 2

// każdy węzeł, poza ostatnim, pokazuje na węzeł następny w0->nastepny = w1; // węzeł 0 pokazuje na węzeł 1 w1->nastepny = w2; // węzeł 1 pokazuje na węzeł 2 w2->nastepny = NULL; // węzeł 2 na nic nie pokazuje wzor( kasa, lista ); // wywołanie funkcji // nowa linia w = lista; // ustaw wskaźnik na początek listy while( w!= NULL ) // wydruk kieszonkowego printf( "osoba nr %d, czyli %s = %7.3f \n", i, w->ktos.imie, w->ktos.kieszonkowe ); w = w->nastepny; // ustaw wskaźnik na następny węzeł // nowa linia getchar(); // czekaj na znak z klawiatury free( w0 ); free( w1 ); free( w2 ); // zwolnienie pamięci węzłów return(0); // funkcja własna - pomocnicza -------------------------------------------------- void wzor( float forsa, ADRwezel w ) float srednia; // wewnętrzna zmienna pomocnicza srednia = forsa/osoby; w->ktos.kieszonkowe = 1.25 * srednia; // kieszonkowe w węźle 0 w = w->nastepny; // adres następnego węzła w->ktos.kieszonkowe = 1.00 * srednia; // kieszonkowe w węźle 1 w = w->nastepny; // adres następnego węzła w->ktos.kieszonkowe = 0.75 * srednia; // kieszonkowe w węźle 2