METODY I JĘZYKI PROGRAMOWANIA Programowanie w języku C

Transkrypt

METODY I JĘZYKI PROGRAMOWANIA Programowanie w języku C
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 */
{ 1 przykladowy program PAS }
#include <stdio.h>
void main(void)
{
printf(”Dzien ”);
printf(”dobry!\n”);
}
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
(* 2 przyklad → dodawanie *)
#include <stdio.h>
#include <conio.h>
uses crt;
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();
}
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
PASCAL
−−−
program nazwa_programu ;
#include <nazwa_biblioteki>
uses nazwa_biblioteki ;
#define Pi 3.14
const Pi = 3.14;
typedef int tablica[10];
type
tablica=array[0..9]of integer;
int i, j, k;
float x, y, z;
char znak;
var
i, j, k : integer;
x, y, z : real;
znak : char;
void NazwaProc( void )
{
int x;
x = 10 * 5;
scanf( ”%f”, &y );
}//-------------------------NazwaProc
procedure NazwaProc;
var x : integer;
begin
x := 10 * 5;
read( y );
end; (*----------------NazwaProc*)
float NazwaF( float x )
{
float z;
if( x == 0 )
z = -1;
else
z = 1/x;
return( z );
}//-----------------------------NazwaF
function NazwaF( x:real ):real;
var z:real;
begin
if x = 0 then
z := -1
else
z := 1/x;
NazwaF := z;
end;(*----------------------NazwaF*)
void main( void)
{
double wynik;
printf(”Podaj liczbe y = ”);
NazwaProc();
wynik = NazwaF( y );
if( wynik != -1 )
printf(”Wynik = %f” , wynik );
else
printf(”Dzielenie przez zero”);
znak=getch();
}
var wynik : real;
begin
write(‘Podaj liczbe y = ’);
NazwaProc;
wynik := nazwaf( y );
if wynik <> -1 then
write(‘Wynik =’ , wynik )
else
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
float
liczba rzeczyw.
10-38 ÷ 1038 (7cyfr)
4 bajty
double
liczba rzeczyw.
10-308 ÷ 10308 (15
cyfr)
8 bajtów
4 bajty
Modyfikatory typu:
signed
unsigned
short
long
→
→
→
→
ze znakiem (±),
bez znaku,
krótka (mniejsza),
długa (większa)
int
int
int
int
char
−
char
−
−
−
− double
np. unsigned long int dluga_liczba_bez_znaku ;
Wartości domyślne:
Type
unsigned char
char
enum
unsigned int
short int
int
unsigned long
long
float
double
long double
long
int
char
Length
8 bits
8 bits
16 bits
16 bits
16 bits
16 bits
32 bits
32 bits
32 bits
64 bits
80 bits
=
=
=
long int
signed int
signed char
Range
0 ÷ 255
-128 ÷ 127
-32,768 ÷ 32,767
0 ÷ 65,535
-32,768 ÷ 32,767
-32,768 ÷ 32,767
0 ÷ 4,294,967,295
-2,147,483,648 ÷ 2,147,483,647
3.4 * (10**-38) ÷ 3.4 * (10**+38)
1.7 * (10**-308) ÷ 1.7 * (10**+308)
3.4 * (10**-4932) ÷ 1.1 * (10**+4932)
4
Formatowane WE/WY w języku C
Funkcja: printf()
<stdio.h>
wysyła sformatowane dane do standardowego strumienia wyjściowego
int printf ( format , argument_1 , argument_2 , . . . ) ;
format
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
%s
%d
%f
%e
%g
%u
%x
%o
l
−
−
−
−
−
−
−
−
−
−
pojedynczy znak
łańcuch znaków
liczba dziesiętna ze znakiem
liczba zmiennoprzecinkowa (notacja dziesiętna)
liczba zmiennoprzecinkowa (notacja wykładnicza)
liczba zmiennoprzecinkowa (krótszy z formatów %f %e)
liczba dziesiętna bez znaku
liczba w kodzie szesnastkowym (bez znaku)
liczba w kodzie ósemkowym (bez znaku)
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
%s
%d
%f lub %e
%u
%x
%o
l
l
L
−
−
−
−
−
−
−
−
−
−
pojedynczy znak
łańcuch znaków
liczba dziesiętna ze znakiem
liczba zmiennoprzecinkowa
liczba dziesiętna bez znaku
liczba w kodzie szesnastkowym (bez znaku)
liczba w kodzie ósemkowym (bez znaku)
przedrostek stosowany przed: d u x o (long int)
przedrostek stosowany przed: f e (double)
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 →
Odczyt ←
Wydruk →
Odczyt ←
Podaj jedna liczbe calkowita:
123 ↵
Podaj jedna liczbe rzeczywista i jeden znak:
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
przypisanie sumy
przypisanie różnicy
przypisanie iloczynu
przypisanie ilorazu
przypisanie reszty
x = 2;
x+=2;
x−=2;
x∗=2;
x /=2;
x%=2;
→
→
→
→
→
x = x + 2;
x = x − 2;
x = x ∗ 2;
x = x / 2;
x = x % 2;
operatory inkrementacji i dekrementacji:
zmienna++
− inkrementacja zmiennej po wyliczeniu wyrażenia
++zmienna
− inkrementacja zmiennej przed wyliczeniem wyrażenia
zmienna−−
− dekrementacja zmiennej po wyliczeniu wyrażenia
−−zmienna
− 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
()
[]
.
−>
!
~
−
++
−−
&
∗
(type)
sizeof
∗
/
%
+
−
<<
>>
<
<=
>
>=
==
!=
&
^
|
&&
||
?:
=
∗= /= %= +=
−= <<=
>>=
&= ^= |=
,
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
zmiana typu (typecast)
(double) 10 ≡ 10.0
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 → 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 ;
else
instrukcja_2 ;
− część od słowa else 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 else-if:
if ( wyrażenie_1 )
instrukcja_1;
else
if ( wyrażenie_2 )
instrukcja_2;
else
if ( wyrażenie_3 )
instrukcja_3;
else
instrukcja_4;
• Instrukcja wyboru:
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 Ax2+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" );
else
if( delta == 0 )
{
x1 = x2 = −b/(2∗a);
printf( "Jest jedno rozwiazanie x1=x2= %f", x1 );
}
else
{
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>
// Program zawierający proste “menu”
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: " );
flushall( );
// wczytanie dwóchliczb z klawiatury
// wyswietlenie “menu”
// 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;
}
int i ;
for( i = 10; i != 0 ; i = i − 1 )
printf( ”%2d\n” , i );
lub
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.” );
else if( ‘A’<=klawisz && klawisz<=’Z’ )
printf( ”-> To jest duza litera.” );
else if( ‘0’<=klawisz && klawisz<=’9’ )
printf( ”-> To jest cyfra.” );
else if( klawisz == 13 )
printf( ”-> To jest klawisz ENTER.” );
else if( klawisz == ‘ ‘ )
printf(“-> To jest klawisz spacji”);
else
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 ;
else
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 ;
else
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 );
else
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
{
double re;
double im
} comp = { 1., 5.};
/* struktury nie były dotąd omawiane */
/* 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
2,0
2,1
3,0
3,1
4,0
4,1
reprezentacja tej macierzy
0,0
0,1
1,0
1,1
2 ,0
↓
1,2
w pamięci komputera
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:
// ← sama definicja bez inicjacji
int
tab[ 10 ];
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 ] ;
// rozmiar zadany bezpośrednio
#define ROZMIAR 100
int tablica [ ROZMIAR ] ;
// definicja stałej w stylu języka C
const ROZMIAR_2 = 100 ;
int tablica_2 [ ROZMIAR_2 ] ;
// definicja stałej w stylu języka C++
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 );
else
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 );
}
else
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

Podobne dokumenty