METODY I JĘZYKI PROGRAMOWANIA Programowanie w języku C notatki z wykładów - Różnice zapisu algorytmu w C i PASCALu - Formatowane WE/WY w C. Funkcje printf() i scanf() - Stałe i zmienne języku C. Typy wartości. - Podstawowe instrukcje - Operatory - Funkcje - Tablice 1
Programowanie w C dla znających PASCAL /* 1 przykladowy program C */ #include <stdio.h> void main(void) printf( Dzien ); printf( dobry!\n ); 1 przykladowy program PAS begin write( Dzien ); writeln( dobry! ); end. #include dyrektywa dołączenia tekstu zawartego w pliku stdio.h (StandardInputOutput) plik definicji funkcji Wej/Wyj main zastrzeżona nazwa głównej funkcji programu void typ danej pustej \n przejscie do nowego wiersza \t znak tabulacji \ znak cudzysłowu \\ jeden znak \ // 2 przyklad dodawanie liczb #include <stdio.h> #include <conio.h> int x,y,s; void main(void) clrscr(); printf( Podaj x = ); scanf( %d, &x ); printf( Podaj y = ); scanf( %d, &y ); s = x+y; printf( Suma x+y = %d\n, s ); getch(); (* 2 przyklad dodawanie *) uses crt; var x,y,s:integer; begin clrscr; write( Podaj x = ); readln( x ); write( Podaj y = ); readln( y ); s := x+y; writeln( Suma x+y =, s ); readkey; end. 2
Ilustracja podstawowych różnic pomiędzy składnią języków C #include <nazwa_biblioteki> #define Pi 3.14 typedef int tablica[10]; int i, j, k; float x, y, z; char znak; void NazwaProc( void ) int x; x = 10 * 5; scanf( %f, &y ); //-------------------------NazwaProc float NazwaF( float x ) float z; if( x == 0 ) z = -1; z = 1/x; return( z ); //-----------------------------NazwaF void main( void) double wynik; printf( Podaj liczbe y = ); NazwaProc(); wynik = NazwaF( y ); if( wynik!= -1 ) printf( Wynik = %f, wynik ); printf( Dzielenie przez zero ); znak=getch(); PASCAL program nazwa_programu ; uses nazwa_biblioteki ; const Pi = 3.14; type tablica=array[0..9]of integer; var i, j, k : integer; x, y, z : real; znak : char; procedure NazwaProc; var x : integer; begin x := 10 * 5; read( y ); end; (*----------------NazwaProc*) function NazwaF( x:real ):real; var z:real; begin if x = 0 then z := -1 z := 1/x; NazwaF := z; end;(*----------------------nazwaf*) var wynik : real; begin write( Podaj liczbe y = ); NazwaProc; wynik := nazwaf( y ); if wynik <> -1 then write( Wynik =, wynik ) write( Dzielenie przez zero ); znak:=readkey; end. 3
Stałe i zmienne w języku C Definiowanie zmiennych ustalenie nazwy, typu, rezerwacja pamięci nazwa_typu nazwa_zmiennej ; nazwa_typu zmienna_1, zmienna_2, zmienna_3 ; Podstawowe typy: Nazwa typu Zawartość Przedział wartości Zajęt. pamięć char znak -128 127 1 bajt int liczba całkowita -32768 32767 2 bajty long liczba całkowita -2147mln 2147mln 4 bajty float liczba rzeczyw. 10-38 10 38 (7cyfr) 4 bajty double liczba rzeczyw. 10-308 10 308 (15 cyfr) Modyfikatory typu: 8 bajtów signed ze znakiem (±), int char unsigned bez znaku, int char short krótka (mniejsza), int long długa (większa) int double np. unsigned long int dluga_liczba_bez_znaku ; Wartości domyślne: long = long int int = signed int char = signed char Type Length Range unsigned char 8 bits 0 255 char 8 bits -128 127 enum 16 bits -32,768 32,767 unsigned int 16 bits 0 65,535 short int 16 bits -32,768 32,767 int 16 bits -32,768 32,767 unsigned long 32 bits 0 4,294,967,295 long 32 bits -2,147,483,648 2,147,483,647 float 32 bits 3.4 * (10**-38) 3.4 * (10**+38) double 64 bits 1.7 * (10**-308) 1.7 * (10**+308) long double 80 bits 3.4 * (10**-4932) 1.1 * (10**+4932) 4
Formatowane WE/WY w języku C Funkcja: printf() <stdio.h> format wysyła sformatowane dane do standardowego strumienia wyjściowego int printf ( format, argument_1, argument_2,... ) ; jest to stała łańcuchowa (w podwójnych cudzysłowach) zawierająca: zwykłe znaki (które są po prostu kopiowane na ekran) kody formatujące kolejnych argumentów: %c pojedynczy znak %s łańcuch znaków %d liczba dziesiętna ze znakiem %f liczba zmiennoprzecinkowa (notacja dziesiętna) %e liczba zmiennoprzecinkowa (notacja wykładnicza) %g liczba zmiennoprzecinkowa (krótszy z formatów %f %e) %u liczba dziesiętna bez znaku %x liczba w kodzie szesnastkowym (bez znaku) %o liczba w kodzie ósemkowym (bez znaku) l przedrostek (long) stosowany przed: d u x o np. #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 ); efekt na ekranie Wynik obliczen 10 + 20 = 30.000000 Aby określić ilość drukowanych cyfr do kodu formatującego można dodać kody długości: %Xd %X.Xf np. %4d liczba dziesiętna na czterech pozycjach %10f liczba rzeczywista na 10 pozycjach %10.2f liczba rzeczywista na 10 pozycjach, 2 cyfry po przecinku %.3f liczba rzeczywista z dokladnoscią do 3 cyfr po przecinku 5
Funkcja: scanf() <stdio.h> odczytuje dane ze standardowego strumienia wejściowego w/g zadanego formatu i zapamiętuje je pod zadanymi adresami pamięci int scanf ( format, adres_1, adres_2,... ) ; format jest to stała łańcuchowa (w podwójnych cudzysłowach) zawierająca instrukcję jak traktować kolejne dane wczytywane ze strumienia (jakie typy zmiennych są pod adresami adres_1, adres_2,... ) Kody formatujące (podobne jak dla printf() ): %c pojedynczy znak %s łańcuch znaków %d liczba dziesiętna ze znakiem %f lub %e liczba zmiennoprzecinkowa %u liczba dziesiętna bez znaku %x liczba w kodzie szesnastkowym (bez znaku) %o liczba w kodzie ósemkowym (bez znaku) l przedrostek stosowany przed: d u x o (long int) l przedrostek stosowany przed: f e (double) L przedrostek stosowany przed: f e (long double) & operator referencji (zwraca adres zmiennej podanej po operatorze) np. #include <stdio.h> void main(void) int x; double y; char znak; printf( Podaj jedna liczbe calkowita: ); scanf ( %d, &x ); printf( Podaj jedna liczbe rzeczywista i jeden znak: ); scanf ( %lf %c, &y, &znak ); Wydruk Podaj jedna liczbe calkowita: Odczyt 123 Wydruk Podaj jedna liczbe rzeczywista i jeden znak: Odczyt 456.789 a Wynik wczytywania: x == 123, y == 456.789, znak == a 6
OPERATORY operatory arytmetyczne: + dodawanie - odejmowanie mnożenie / dzielenie % reszta z dzielenia operatory przypisania: = zwykłe przypisanie x = 2; += przypisanie sumy x+=2; x = x + 2; -= przypisanie różnicy x =2; x = x 2; = przypisanie iloczynu x =2; x = x 2; /= przypisanie ilorazu x /=2; x = x / 2; %= przypisanie reszty x%=2; x = x % 2; operatory inkrementacji i dekrementacji: zmienna++ ++zmienna zmienna zmienna inkrementacja zmiennej po wyliczeniu wyrażenia inkrementacja zmiennej przed wyliczeniem wyrażenia dekrementacja zmiennej po wyliczeniu wyrażenia dekrementacja zmiennej przed wyliczeniem wyrażenia np. int x, y = 1; x = ++ y ; / rezultat: x=2, y=2 / x = y ++ ; / rezultat: x=1, y=2 / operatory relacyjne: == równe!= różne < mniejsze > większe <= mniejsze lub równe >= większe lub równe operatory logiczne: && koniunkcja (AND) alternatywa (OR)! negacja (NOT) bitowe operatory logiczne: & bitowa koniunkcja (AND) bitowa alternatywa (OR) ^ bitowa różnica symetryczna (XOR) << przesunięcie bitów w lewo >> przesunięcie bitów w prawo ~ negacja bitów 7
Priorytety operatorów w języku C: Operator Opis Przykład ( ) wywołanie funkcji sin() [ ] element tablicy tab[10]. element struktury osoba.nazwisko > wskazanie elemenu struktury wsk_osoby >nazwisko! negacja logiczna if(! (x >max) ) kontynuuj; ~ negacja bitowa ~(001101) (110010) zmiana znaku (negacja) x = 10 ( y) ++ inkrementacja (zwiększenie o 1) x + + + y (x+ +) + y dekrementacja (zmiejszenie o 1) y y ( y) & operator referencji (adres elementu) wsk_x = &x operator dereferencji wsk_x = 10 (type) zmiana typu (typecast) (double) 10 10.0 sizeof rozmiar zmiennej lub typu (w bajtach) sizeof( int ) 2 mnożenie / dzielenie % operacja modulo (reszta z dzielenia) if( x%2 == 0 ) parzyste; + dodawanie odejmowanie << przesunięcie bitowe w lewo 1 << 2 (0001) << 2 (0100) >> przesuniecie bitowe w prawo x = 4 >>1 x = 2 < mniejszy niż if( liczba < max ) max = liczba; <= mniejszy lub równy > wiekszy niż >= wiekszy lub równy == równy!= nierówny (różny od) & iloczyn bitowy ^ suma bitowa modulo (różnica symetryczna) suma bitowa && iloczyn logiczny suma logiczna? : wyrażenie warunkowe = przypisanie wartości = /= %= += skrócone formy przypisania arytmetycznego = <<= >>= &= ^= =, operator przecinka 8
JĘZYK C fi PODSTAWOWE INSTRUKCJE Nawiasy klamrowe są używane do grupowania wielu deklaracji i instrukcji w jedną instrukcję złożoną (jeden blok). Instrukcja warunkowa: if ( wyrażenie ) instrukcja_1 ; instrukcja_2 ; część od słowa można pominąć, instrukcja sprawdza czy wyrażenie jest różne od zera tzn. if ( wyrażenie ) jest równoważne if ( wyrażenie!= 0 ) Konstrukcja -if: if ( wyrażenie_1 ) Instrukcja wyboru: instrukcja_1; if ( wyrażenie_2 ) instrukcja_2; if ( wyrażenie_3 ) instrukcja_3; instrukcja_4; switch ( wyrażenie_całkowite ) case wartość_1 : instrukcja_1; break; case wartość_2 : case wartość_3 : case wartość_4 : instrukcja_234; break; default : instrukcja_domyslna; break; 9
Przykłady dla instrukcji warunkowej: #include <stdio.h> // Wartość maksymalna z trzech wczytanych liczb void main(void) int A, B, C, max; printf( Podaj pierwsza liczbe: ); scanf( %d, &A ); printf( Podaj druga liczbe: ); scanf( %d, &B ); printf( Podaj trzecia liczbe: ); scanf( %d, &C ); max = A; if( max < B ) max = B; if( max < C ) max = C; printf( \n Maksymalna wartosc = %d, max ); getchar(); #include <stdio.h> // Pierwiastki trójmianu kwadratowego Ax 2 +Bx+C=0 #include <conio.h> #include <math.h> void main( void ) double a, b, c, delta, x1, x2; clrscr(); printf( "Podaj pierwsza liczbe A= " ); scanf( "%lf", &a ); // Uwaga!!! %lf a nie %f printf( "Podaj druga liczbe B= " ); scanf( "%lf", &b ); printf( "Podaj trzecia liczbe C= " ); scanf( "%lf", &c ); delta = b b 4 a c; if( delta < 0 ) printf( "\n Brak rozwiazan" ); if( delta == 0 ) x1 = x2 = b/(2 a); printf( "Jest jedno rozwiazanie x1=x2= %f", x1 ); x1 = ( b sqrt(delta)) / (2 a); x2 = ( b + sqrt(delta)) / (2 a); printf( "Sa dwa rozwiazania x1= %.2f, x2= %.2f", x1, x2 ); 10
Przykład dla instrukcji wyboru: #include <stdio.h> void main( void ) char znak; double a, b, wynik; printf( "Podaj pierwsza liczbe A =" ); scanf( "%lf", &a ); printf( "Podaj druga liczbe B =" ); scanf( "%lf", &b ); printf( "\n\nmozliwe operacje:" ); printf( "\n (+) wynik = A + B" ); printf( "\n ( ) wynik = A B" ); printf( "\n ( ) wynik = A B" ); printf( "\n ( / ) wynik = A / B" ); printf( "\n\npodaj znak operacji: " ); // Program zawierający proste menu // wczytanie dwóchliczb z klawiatury // wyswietlenie menu flushall( ); // wyczyszczenie wszystkich buforów (tutaj->klawiatury) znak = getchar( ); // wczytanie znaku wybranej operacji switch( znak ) // instrukcja wyboru jednej z operacji arytmetycznych case '+' : wynik = a + b; break; case ' ' : wynik = a b; break; case ' ' : wynik = a b; break; case '/' : wynik = a / b; break; default: wynik = 0; printf( "\nbład operatora: podano zły znak operacji" ); break; // wydruk liczb i wyniku z zadana dokladnoscia miejsc po przecinku printf( "\nwynik obliczen: %.1f %c %.1f = %.2f ", a, znak, b, wynik ); printf( "\n\nkoniec programu. Nacisnij dowolny klawisz" ); fflush( stdin ); getchar( ); // wyczyszczenie bufora strumienia <stdin> tzn. klawiatury 11
Programowanie iteracji - INSTRUKCJE PĘTLI Pętla while( ): while ( wyrażenie ) instrukcja; while ( wyrażenie ) instrukcja_1; instrukcja_2;... instrukcja_n; Pętla wykonywana jest tak długo jak wartość wyrażenie jest różna od zera int i = 10; while( i!= 0 ) printf ( %2d\n, i ); i = i 1; int i = 10; while( i ) printf ( %2d\n, i ); Pętla do while( ): do instrukcja; while ( wyrażenie ); do instrukcja_1; instrukcja_2;... instrukcja_n; while ( wyrażenie ); Pętla wykonywana jest tak długo jak wartość wyrażenie jest różna od zera 12
Pętla for( ): for( wyrazenie_inicjujace ; wyrazenie_testujace ; wyrazenie_modyfikujace ) wykonywana_instrukcja ; jest równoważna konstrukcji: wyrazenie_inicjujace ; while( wyrazenie_testujace ) wykonywana_instrukcja ; wyrazenie_modyfikujace ; int i ; i = 10; while( i!= 0 ) printf ( %2d\n, i ); i = i 1; lub int i ; for( i = 10; i!= 0 ; i = i 1 ) printf( %2d\n, i ); int i ; for( i = 10; i ; printf( %2d\n, i ) ) ; //przykładowy program wypisujacy tabele kodów ASCII #include <stdio.h> void main(void) int n; printf( \n ); for( n=32; n<256; n++ ) printf( %3d = %c\n, n, n ); //prymitywny kalkulator biurowy #include <stdio.h> void main(void) double suma=0, liczba; while( scanf( %lf, &liczba ) > 0 ) printf( \t%.2f\n, suma+=liczba ); 13
#include <stdio.h> // program zliczający naciskane klawisze #include <conio.h> void main(void) int licznik = 0, klawisz; printf( Program zliczajacy naciskane klawisze. Koniec = ESC ); do klawisz = getch(); licznik++; while( klawisz!= 27 ) // 27 = kod klawisza Escape printf( \n Ilosc nacisnietych klawiszy = %d, licznik ); // ten sam program z użyciem pętli for int licznik; for( licznik = 0 ; getch()!= 27 ; licznik++ ) #include <stdio.h> //program klasyfikujący naciskane klawisze #include <conio.h> #define ESC 27 //definicja kodu klawisza «Escape» void main(void) int klawisz=0; clrscr(); while( klawisz!= ESC ) printf( \n\nnacisnij jakis klawisz (ESC->Koniec): ); klawisz = getch(); if( a <=klawisz && klawisz<= z ) printf( -> To jest mala litera. ); if( A <=klawisz && klawisz<= Z ) printf( -> To jest duza litera. ); if( 0 <=klawisz && klawisz<= 9 ) printf( -> To jest cyfra. ); if( klawisz == 13 ) printf( -> To jest klawisz ENTER. ); if( klawisz == ) printf( -> To jest klawisz spacji ); printf( -> To jest inny klawisz. ); 14
#include <stdio.h> //program rozpoznajacy klawisze funkcyjne #include <conio.h> #include "def_klaw.h" //dołaczenie pliku zawierajacego definicje klawiszy void main( void ) int klawisz; clrscr(); do printf( "\n\n Nacisnij jakis klawisz: " ); klawisz = getch( ); switch( klawisz ) case ENTER : printf( "To jest ENTER" ); break; case ESC : printf( "To jest ESCAPE" ); break; case ZERO : // pierwszy odczytany znak mial kod równy 0 klawisz = getch( ); switch( klawisz ) case DELETE : printf( "Delete" ); break; case UP_ARROW : printf( "Up arrow" ); break; case DOWN_ARROW : printf( "Down arrow" ); break; break; case BACKSPACE : printf( "To jest BACKSPACE" ); break; default : printf( "Nieznany pojedynczy klawisz" ); break; 15
Funkcja (podprogram) Funkcja jest częścią programu, realizującą pewne ściśle określone zadanie. Program w języku C składa się ze zbioru funkcji napisanych prze programistę. Ponadto, może on korzystać z funkcji zewnętrznych, np. napisanych przez twórców systemu operacyjnego, kompilatora, a także inne osoby. Funkcje te umieszczone są w specjalnych plikach nazywanych bibliotekami. Każdy program w języku C/C++ MUSI zawierać przynajmniej jedną funkcję o predefiniowanej nazwie: main( ). Składnia definicji funkcji: zwracany_typ NAZWA_FUNKCJI ( lista parametrów ) instrukcja lub sekwencja instrukcji ; przykład: int MAX ( int liczba_1, int liczba_2 ) if( liczba_1 > liczba_2 ) return liczba_1 ; return liczba_2 ; lista parametrów może być pusta lub zawierać opisy kolejnych parametrów (pooddzielane przecinkami): main( ) main( void ) main( int argc, char argv[ ] ) parametry definiowane są tak jak zmienne. Uwaga: nie można grupować sekwencji parametrów tego samego typu: int MAX ( int liczba_1, liczba_2 ) źle! ciało funkcji jest zawarte pomiędzy nawiasami:... (bez średnika na końcu) działanie funkcji kończy się po napotkaniu polecenia return lub po wykonaniu sekwencji wszystkich instrukcji zawartych w ciele funkcji, jeżeli funkcja jest typu void, to używamy samego słowa return, bez żadnego wyrażenia po nim, jeżeli funkcja jest typu innego niż void to po poleceniu return musi się pojawić wyrażenie odpowiedniego typu (może być w nawiasach), np.: 16
return liczba_1; lub return( liczba_1 ) ; Prototyp funkcji deklaracja uprzedzająca, (objaśnienie identyfikatora funkcji) określa tylko nazwę funkcji oraz typy zwracanej wartości i parametrów (sam nagłówek funkcji zakończony średnikiem) Deklaracja funkcji jest konieczna w przypadkach, gdy wywołanie funkcji występuje wcześniej niż jej definicja. Np. // program wyznaczający maksimum 3 liczb poprzez wywołanie funkcji MAX #include <stdio.h> int MAX ( int, int ) ; // Prototyp - deklaracja funkcji MAX void main( void ) int a, b, c, m. ; printf( " Podaj liczbe A = " ); scanf( " %d ", &a ); printf( " Podaj liczbe B = " ); scanf( " %d ", &b ); printf( " Podaj liczbe C = " ); scanf( " %d ", &c ); m = MAX( a, b ); // Wywolanie funkcji MAX printf( " \n\nmaksimum z liczb A i B rowna sie = %d ", m ) ; printf( " \n\nmaksimum z liczb B i C rowna sie = %d ", MAX( b,c ) ) ; printf( " \n\nmaksimum z A,B,C rowna sie = %d ", MAX( a, MAX(b,c) ) ) ; flushall(); getchar(); int MAX ( int liczba_1, int liczba_2 ) if( liczba_1 > liczba_2 ) return liczba_1 ; return liczba_2 ; // Definicja funkcji MAX 17
FUNKCJE / PRZEKAZYWANIE PARAMETRÓW 1. Funkcja bezparametrowa nie zwracająca żadnej wartości void nazwa_funkcji(void) return; // powoduje natychmiastowe zakończenie wykonywania funkcji // na końcu funkcji można pominąć przykład void odwrotność(void) // obliczenie odwrotności liczby wczytanej z klawiatury double liczba; scanf( %lf, &liczba ); if( liczba == 0 ) return; printf( %f, 1/liczba ); return; // to «return» można pominąć 2. Funkcja pobierająca parametr i zwracająca wartość UWAGA! w języku C parametry przekazywane są tylko przez wartość tzn. po wywołaniu funkcji tworzone są nowe zmienne (lokalne), których zawartość inicjowana jest wartościami parametrów (zmiennych, stałych lub wyrażeń) podanych przy wywołaniu. przykład double odwrotność( double liczba ) if( liczba == 0 ) return( 0 ); return( 1/liczba ); // definicja funkcji «odwrotność» void main( void ) double x=10, y; y = odwrotnosc( 20 ); // przykłady wywoływania funkcji «odwrotnosc» y = odwrotnosc( x ); odwrotnosc( 3 (15-x) ); 18
przykład // przykład funkcji zwracającej wartość większego z argumentów double maksimum( double a, double b ) if( a > b) return( a ); return( b ); przykład void posortuj_1 ( double a, double b ) // UWAGA!!! double buf; // błędny sposób przekazywania if( a > b) // paramerów (przez wartość). // Sortowane są zmienne lokalne a i b buf = a; // (kopie parametrów x i y). a = b; // Zawartość x i y nie ulegnie zmianie! b = buf; void main( void ) double x=7, y=5; posortuj_1( x, y ); // do funkcji przekazywane są wartości zmiennych przykład void posortuj_2 ( double a, double b ) // przekazywanie parametrów przez adres double buf; if( a > b) // porównywane są zawartości miejsc // wskazywanych przez wskazniki a i b buf = a; a = b; b = buf; void main( void ) double x=7, y=5; posortuj_2( &x, &y ); //do funkcji przekazywane są adresy zmiennych 19
W języku C++ parametry mogą być przekazywane przez wartość lub przez referencję (przekazywanie przez referencję jest odpowiednikiem przekazywania przez zmienną) Typ referencyjny zmienne tego typu nie zajmują nowego miejsca w pamięci, służą do reprezentacji innych zmiennych w programie. nazwa_typu nazwa_zmiennej; utworzenie zwykłej zmiennej nazwa_typu & nazwa_zmiennej_referencyjnej = nazwa_zmiennej; (jest to zdefiniowanie aliasu innej nazwy dla tej samej zmiennej) przykład int wzrost=175; int sredni_wzrost = wzrost; int& wysokosc = wzrost; // utworzenie zmiennej referencyjnej // związanej z tym samym obszarem // pamięci co wzrost wysokosc = wysokosc + 1; // równoważne: wzrost = wzrost + 1 przykład void posortuj_3 ( double & a, double & b ) double buf; // przekazywanie parametrów if( a > b) // przez referencję buf = a; // a i b są referencyjnymi nazwami x i y a = b; b = buf; void main( void ) double x=7, y=5; posortuj_3( x, y ); // parametry x i y inicjują zmienne referencyjne 20
Argumenty domniemane. W deklaracji funkcji można podać jej argumenty domniemane, tj. takie które będą użyte gdy funkcja zostanie wywołana z niekompletną listą argumentów. Argument domniemany występuje w deklaracji odpowiedniego parametru jako wyrażenie po znaku '='. Przykład. Char buffer[256] = "bufor testowy"; int cnt = 5; int Init(char* buf=null, int arg1=cnt, char arg2='\n'); main() int err = 0; err += Init(); // Init(NULL, 5, '\n'); err += Init(buffer); // Init(buffer, 5, '\n'); err += Init(buffer, 6); // Init(buffer, 6, '\n'); err += Init(buffer, 6, '\0'); return err; int Init(char* buf, int arg1, char arg2) if(buf == NULL) return 1; if(arg1 < 0 arg1 > strlen(buf)) return 2; buf[arg1] = arg2; return 0; 21
Funkcje przeciążone. Funkcją przeciążona jest rodzina funkcji o takich samych nazwach, ale różnych sygnaturach. Wywołanie funkcji przeciążonej polega na wyborze tego aspektu (wersji), który najlepiej zgadza się z argumentami podanymi przy wywołaniu. Przykład. // deklaracje zmiennych glob. double dbl = 5.0; struct complex /* struktury nie były dotąd omawiane */ double re; double im comp = 1., 5.; /* tak używano struktur w klasycznym C */ // deklaracje funkcji double Abs(double d); double Abs(struct complex c); //definicje funkcji main() double dlug; dlug = Abs(dbl); dlug = Abs(comp); return 0; double Abs(double d) return d; double Abs(struct complex c) return sqrt(c.re * c.re + c.im * c.im); while( klawisz!= ESC ); 22
// Zbior «def_klaw.h» zawierający definicje kodów klawiszy #ifndef DEF_KLAW #define DEF_KLAW #define ZERO 0 // klawisze "zwykle" - kodowane za pomoca jednego znaku #define ESC 27 #define ENTER 13 #define BACKSPACE 8 //klawisze "funkcyjne" - kodowane za pomoca dwoch znakow #define DELETE 83 // 0, 83 #define UP_ARROW 72 // 0, 72 #define DOWN_ARROW 80 // 0, 80 #define LEFT_ARROW 75 // 0, 75 #define RIGHT_ARROW 77 // 0, 77 #define HOME 71 // 0, 71 #define END 79 // 0, 79 #endif 23
Tablice w języku C/C++ Ogólna postać definicji tablicy: typ_elementu nazwa_tablicy [wymiar_1][wymiar_2]... [wymiar_n] ; np. int tablica [ 10 ]; // 10-cio elementowa tablica liczb całkowitych char tekst [ 255 ]; // 255-cio elementowa tablica znaków float macierz [ 5 ] [ 2 ]; // dwuwymiarowa tablica: 5 wierszy po 2 kolumny, UWAGA: w języku C tablice są zawsze indeksowane od zera np. pierwszym elementem tablicy «macierz» jest: macierz[ 0 ][ 0 ] a ostatnim elementem jest:macierz[ wymiar_1-1 ][wymiar_2-1] tzn. macierz[ 4 ][ 1 ] w języku C nie jest sprawdzana zgodność indeksu z wymiarami tablicy!!! często jest to przyczyną trudnych do wykrycia błędów. np. odwołanie: macierz[ 1 ][ 2 ] zwróci w rzeczywistości wartość pierwszego elementu z trzeciego wiersza tzn. macierz[ 2 ][ 0 ] 0, 0 0, 1 1, 0 1, 1 1, 2 2, 0 2, 1 3, 0 3, 1 4, 0 4, 1 reprezentacja tej macierzy fl w pamięci komputera 0, 0 0, 1 1, 0 1, 1 2, 0 2, 1 3, 0 3, 1 4, 0 4, 1 macierz[ 1 ][ 2 ] Obszar pamięci zajmowany przez tablicę musi być mniejszy od 64 kb W implementacji C++ firmy Borland to ograniczenie można obejść używając przy definicji tablicy słowo kluczowe huge. np. definicja: long double huge tab[ 20000 ]; jest poprawna, chociaż tablica «tab» zajmuje 200 000 bajtów 196 kb 24
Definicję tablicy można połączyć z inicjacją jej zawartości: int tab[ 10 ]; // sama definicja bez inicjacji int tab_inicjowana[ 10 ] = 20, -3, 12, 1, 0, 7, -5, 100, 2, 5 ; char tab_znakow[ 5 ] = a, B, \n, 1, \0 ; float macierz_a[ 3 ][ 2 ] = 1,1, 3.5,7.0, -15,100 ; float macierz_b[ 3 ][ 2 ] = 1, 1, 3.5, 7.0, -15, 100 ; Kolejne inicjatory zawsze wstawiane są do kolejnych komórek tablicy (w związku z tym można pominąć wewnętrzne nawiasy klamrowe). Jeżeli lista inicjatorów jest krótsza niż ilość elementów tablicy to pozostałe elementy są uzupełniane zerami lub wskaźnikami NULL np. definicja: int tab[ 10 ] = 20, -3, 12, 1 ; jest równoważna: int tab[ 10 ] = 20, -3, 12, 1, 0, 0, 0, 0, 0, 0 ; a definicja: float macierz[ 3 ][ 2 ] = 1, 3.5,7.0 ; jest równoważna: float macierz[ 3 ][ 2 ] = 1,0, 3.5,7.0, 0,0 ; lub: float macierz[ 3 ][ 2 ] = 1, 0, 3.5, 7.0, 0, 0 ; W języku C inicjatorami muszą być stałe, natomiast w języku C++ inicjatorami mogą być zarówno stałe jak i zmienne. Wykorzystanie stałych do definiowania ilości elementów tablicy: int tablica [ 100 ] ; #define ROZMIAR 100 int tablica [ ROZMIAR ] ; // rozmiar zadany bezpośrednio // definicja stałej w stylu języka C const ROZMIAR_2 = 100 ; // definicja stałej w stylu języka C++ int tablica_2 [ ROZMIAR_2 ] ; for( int i=0 ; i < ROZMIAR ; i++ ) printf ( %d, tablica[ i ] ); // przykład dalszego wykorzystania stałej 25
Przypisywanie / odczytywanie wartości elementów tablicy void main( ) const ROZM = 4 ; int Tab [ ROZM ] ; // bezpośrednie przypisanie wartości Tab[ 0 ] = 0 ; Tab[ 1 ] = 10 ; Tab[ 2 ] = - 20 ; Tab[ 3 ] = 3 ; // wczytanie zawartości z klawiatury scanf( %d, &Tab[ 0 ] ) ; scanf( %d %d, &Tab[ 1 ], &Tab[ 2 ] ) ; printf( Podaj 4 element tablicy = ); scanf( %d, &Tab[ 3 ] ) ; // wykorzystywanie i wyświetlanie zawartości elementów tablicy long suma = Tab[0] + Tab[1] + Tab[2] + Tab[3] ; printf( Tab[1] = %5d, Tab[0] ); printf( Tab[2] = %5d, Tab[1] ); printf( Tab[3] = %5d, Tab[2] ); printf( Tab[4] = %5d, Tab[3] ); // pośrednie zadawanie wartości indeksu za pomocą zmiennej pomocniczej int i = 2 ; Tab[ i ] = 10; // równoważne poleceniu: Tab[ 2 ] = 10; // zadawanie indeksu elementu z klawiatury printf( Podaj indeks elementu którego wartość chcesz wczytać ); scanf( %d, &i ); printf( Podaj nową wartość Tab[ %d ] =, i ); scanf( %d, &Tab[ i ] ); printf( Nowa wartość Tab[ %d ] wynosi %d, i, Tab[ i ] ); 26
Zastosowanie instrukcji pętli for do operacji na tablicach #include <stdio.h> void main( void ) #define ROZMIAR 10 float tablica[ ROZMIAR ]; int i ; // definicja tablicy liczb rzeczywistych // inicjowanie zawartości tablicy liczbami parzystymi: 0, 2, 4, 6,... for( i = 0 ; i < ROZMIAR ; i++ ) tablica[ i ] = 2 i ; // wczytanie zawartości elementów tablicy z klawiatury for( i = 0 ; i < ROZMIAR ; i++ ) printf( Podaj Tab[%2d] =, i+1 ); scanf( %f, &tablica[ i ] ); // wyświetlenie zawartości elementów tablicy for( i = 0 ; i < ROZMIAR ; i++ ) printf( Tab[%2d] = %10.3f, i+1, tablica[ i ] ); // zsumowanie wartości elementów tablicy float suma = 0 ; for( i = 0 ; i < ROZMIAR ; i++ ) suma = suma + tablica[ i ]; // suma += tablica[ i ]; printf( Suma wartości elementów tablicy wynosi: %.2f, suma ); // zliczenie ilości elementów o dodatnich wartościach int ilosc = 0 ; for( i = 0 ; i < ROZMIAR ; i++ ) if( tablica[ i ] > 0 ) ilosc = ilosc + 1 ; // ilość += 1; lub ilość++; if( ilość>0 ) printf( Ilość dodatnich elementów = %d, ilosc ); printf( W tablicy nie ma ani jednego dodatniego elementu ); 27
Przykłady prostych algorytmów tablicowych #include <stdio.h> void main( void ) #define ROZMIAR 10 int tab[ ROZMIAR ]; int i, ilosc, max, poz; long suma; double srednia; for( i = 0 ; i < ROZMIAR ; i++ ) printf( Tab[%2d] =, i+1 ); scanf( %d, &tablica[ i ] ); //--------- wczytanie liczb z klawiatury i=0; //--------------------------- zliczenie elementów niezerowych ilosc=0; while( ROZMIAR i ) if( tab[i++] ) ilosc++; suma=0; //----------- wyznaczenie średniej z elementów niezerowych ilosc=0; i=0; do if( tab[ i ]!= 0 ) suma += tab[ i ]; ilosc++; while( ++i < ROZMIAR ); if( ilosc ) srednia = (double)suma / ilosc; printf( "\nsrednia niezerowych = %.2f", srednia ); printf( "\nnie ma elementow niezerowych" ); max=tab[0]; //----------- wyznaczenie wartości i pozycji maksimum poz=0; for( i=1; i<rozmiar ; i++ ) if( max<tab[ i ] ) max = tab[ i ]; poz = i ; printf( "\nnajwieksza wartosc jest rowna %d", max ); printf( "i wystapila na pozycji %d", poz+1 ); 28
Przekazywanie tablic jednowymiarowych przez parametry funkcji #include <stdio.h> #include <conio.h> #define ROZMIAR 10 void WczytajTablice( double tablica[ ] ) clrscr(); printf( Podaj wartości elementów tablicy \n ); for( int i = 0 ; i < ROZMIAR ; i++ ) printf( Tab[%2d] =, i+1 ); scanf( %lf, &tablica[ i ] ); //------------------------------------------------------------ funkcja WczytajTablicę void WyswietlTablice( double tablica[ ] ) clrscr(); printf( Wartości elementów tablicy są równe: \n ); for( int i = 0 ; i < ROZMIAR ; i++ ) printf( Tab[%2d] = %f, i+1, tablica[ i ] ); printf( Nacisnij dowolny klawisz ); getch(); //------------------------------------------------------------ funkcja WyswietlTablicę void DodajTablice( double wejscie_1[ ], double wejscie_1[ ], double wynik [ ] ) for( int i = 0 ; i < ROZMIAR ; i++ ) wynik[ i ] = wejscie_1[ i ] + wejscie_2[ i ] ; //------------------------------------------------------------ funkcja DodajTablice void main( void ) double A[ ROZMIAR ] ; double B[ ROZMIAR ], C[ ROZMIAR ] ; WczytajTablice( A ); WyswietlTablice( A ); WczytajTablice( B ); DodajTablice( A, B, C ); WyswietlTablice( C ); 29