• Nie Znaleziono Wyników

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

N/A
N/A
Protected

Academic year: 2021

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

Copied!
29
0
0

Pełen tekst

(1)

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

(2)

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.

(3)

Ilustracja podstawowych różnic pomiędzy składnią języków

C PASCAL

− −−

#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;

else 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 );

else

printf(”Dzielenie przez zero”);

znak=getch();

}

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 else 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 ) else

write(‘Dzielenie przez zero’);

znak:=readkey;

end.

(4)

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)

8 bajtów Modyfikatory typu:

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)

(5)

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

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

(6)

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’

(7)

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++

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

(8)

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

(9)

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;

}

(10)

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 );

} }

(11)

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 =" ); // wczytanie dwóchliczb z klawiatury scanf( "%lf" , &a );

printf( "Podaj druga liczbe B =" );

scanf( "%lf" , &b );

printf( "\n\nMozliwe operacje:" ); // wyswietlenie “menu”

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( ); // 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 ); // wyczyszczenie bufora strumienia <stdin> tzn. klawiatury getchar( );

}

(12)

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

(13)

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 );

}

(14)

#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.”);

}

(15)

#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;

}

(16)

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ć

(17)

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 ) // Definicja funkcji MAX {

if( liczba_1 > liczba_2 ) return liczba_1 ; else

return liczba_2 ; }

(18)

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 ) // definicja funkcji «odwrotność»

{

if( liczba == 0 ) return( 0 );

else

return( 1/liczba );

}

void main( void ) {

double x=10, y;

y = odwrotnosc( 20 ); // przykłady wywoływania funkcji «odwrotnosc»

y = odwrotnosc( x );

odwrotnosc( 3∗(15-x) );

(19)

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 }

(20)

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 }

(21)

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;

}

(22)

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 );

}

(23)

// 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

(24)

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

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

(25)

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 ] ; // rozmiar zadany bezpośrednio

#define ROZMIAR 100 // definicja stałej w stylu języka C int tablica [ ROZMIAR ] ;

const ROZMIAR_2 = 100 ; // definicja stałej w stylu języka C++

int tablica_2 [ ROZMIAR_2 ] ;

for( int i=0 ; i < ROZMIAR ; i++ ) // przykład dalszego wykorzystania stałej printf ( ”%d” , tablica[ i ] );

(26)

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 ] );

}

(27)

Zastosowanie instrukcji pętli ”for” do operacji na tablicach

#include <stdio.h>

void main( void ) {

#define ROZMIAR 10

float tablica[ ROZMIAR ]; // definicja tablicy liczb rzeczywistych int i ;

// 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 ” );

(28)

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++ ) //--- wczytanie liczb z klawiatury {

printf( ”Tab[%2d] = ”, i+1 );

scanf( ”%d” , &tablica[ i ] );

}

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 );

(29)

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 );

}

Cytaty

Powiązane dokumenty

[r]

Stałe to obiekty programu, których wartość w trakcjie realizacji programu NIE MOŻE ulec zmianie. Zmienne - wartość może

Definicja klasy ostream jest zawarta również w pliku &lt;iostream.h&gt;. Najważniejsze metody

void ∗malloc( size_t rozmiar ); // przydział bloku o zadanej wielkosci void ∗calloc( size_t il_elementow, size_t rozmiar); // przydział tablicy void free( void ∗wskaznik);

Ochrona danych poprzez argumenty typu static. Przeładowanie operatora

Parametry funkcji łączących mogą być estymowane różnymi metodami. Na potrzeby dalszych rozważań przytoczono definicję gęstości funkcji po- łączeń. Majewska: Testing for

Zdarza się też użycie zaimka sam w bezpośrednim zwróceniu się do rozmówców zamiast zaimka wy (w odniesieniu do liczby mnogiej):.. Już sami mi nie zrobicie tej krzywdy,

• Deklaracja funkcji określa nazwę funkcji, typy argumentów i typ wartości zwracanej. • Definicja funkcji to deklaracja + ciało