Programowanie strukturalne w C

background image

1

Programowanie strukturalne – j

ę

zyk C





Struktura programu


Przykład programu:

# include <stdio.h>

main()

{

printf(”Program w j

ę

zyku C \n”);


return 0;

}

Komentarze

W j

ę

zykach programowania wyst

ę

puj

ą

specjalne znaczniki

powoduj

ą

ce i

ż

umieszczony tekst nie jest cz

ęś

ci

ą

programu, a

jedynie dodatkow

ą

informacj

ą

o tre

ś

ci i zadaniach programu.


/* - znak otwarcia komentarza

*/ - znak zamkni

ę

cia komentarza


/* komentarz */

/*

komentarz

*/

// komentarz



Dyrektywa #include

# include - dyrektywa preprocesora - polecenia dla
preprocesora aby w tym miejscu doł

ą

czy

ć

do programu zawarto

ść

wskazanego pliku

background image

2

preprocesor – specjalny program wykonuj

ą

cy czynno

ś

ci

przygotowawcze do kompilacji (przed kompilacj

ą

)






Pliki nagłówkowe

Po dyrektywie #include wyst

ę

puj

ą

pliki nagłówkowe, s

ą

to pliki

dodawane do programów za pomoc

ą

tej dyrektywy, nazwa ich

wywodzi si

ę

st

ą

d ,

ż

e s

ą

zawsze doł

ą

czane na pocz

ą

tku programu

(w jego nagłówku)

stdio.h - plik nagłówkowy standardowego wej

ś

cia – wyj

ś

cia


stdlib.h – standardowa biblioteka funkcji

string.h – operacje na ła

ń

cuchach tekstowych


math.h – funkcje matematyczne

conio.h – funkcje obsługi konsoli



<stdio.h> i ”stdio.h”

< ... > - plik nagłówkowy b

ę

dzie poszukiwany w katalogu innym

ni

ż

bie

żą

cy; wskazanym w opcjach kompilatora – jest to

najcz

ęś

ciej katalog /..../INCLUDE


” ... ” - plik nagłówkowy b

ę

dzie poszukiwany w katalogu

bie

żą

cym




Funkcja main()

Funkcja specjalna w j

ę

zyku C, w ka

ż

dym programie musi ona

wyst

ą

pi

ć

i jest tylko jedna.


Mo

ż

na j

ą

wstawi

ć

w dowolne miejsce w programie , jednak

program zacznie zawsze wykonywa

ć

si

ę

od funkcji main() i

zako

ń

czy swoje działanie w tej funkcji. Je

ż

eli wszystkie

instrukcje zawarte w funkcji main() zostały wykonane i
zako

ń

czone program ko

ń

czy swoje działanie.


W zamieszczonym powy

ż

ej przykładzie funkcja main() zawiera

funkcje biblioteczn

ą

printf() , której argumentami jest tekst

background image

3

wyprowadzany na urz

ą

dzenie wej

ś

ciowe , oraz specjalny znak

steruj

ą

cy :


\n - znak steruj

ą

cy przej

ś

cia do nast

ę

pnego wiersza.


zasad

ą

tego j

ę

zyka programowania jest to,

ż

e ka

ż

da funkcja w

tym main() zwraca wynik; domy

ś

lnie wynikiem jest liczba typu

całkowitego (integer)

wykorzystywana jest do tego celu instrukcja :

return 0;

Zwrócenie przez funkcj

ę

warto

ś

ci 0 - oznacza i

ż

zako

ń

czyła si

ę

ona poprawnie, ka

ż

da inna warto

ść

całkowita wi

ę

ksza od zera

oznacza zako

ń

czenie działania funkcji z bł

ę

dem.


funkcja biblioteczna (stdlib.h) exit() - mo

ż

e by

ć

równie

ż

u

ż

yta do zako

ń

czenia działania programu.


Funkcja exit() nie zwraca

ż

adnego wyniku, ale argument

przekazany do funkcji wskazuje czy program zako

ń

czył si

ę

normalnie czy z bł

ę

dem.


exit(0) – zako

ń

czenie poprawne


exit(n) – zako

ń

czenie z bł

ę

dem n<>0




#include <stdio.h>

#include <stdlib.h>

void main()

{

printf(”Program w j

ę

zyku C\n”);


exit(0);

}



typ danych: void

void - pusty, nijaki

background image

4

słowo to pojawiaj

ą

ce si

ę

przed nazw

ą

funkcji oznacza,

ż

e nie

b

ę

dzie ona zwraca

ć

ż

adnej warto

ś

ci


main() à zwraca domy

ś

lnie warto

ść

typu integer


void main() à funkcja main() nie zwraca

ż

adnej warto

ś

ci



linia instrukcji w j

ę

zyku C zako

ń

czona jest

ś

rednikiem

j

ę

zyk ten rozró

ż

nia małe i du

ż

e litery


Podstawowe elementy programu


Stałe i zmienne

stała – nigdy nie zmienia swojej warto

ś

ci


zmienna – mo

ż

e by

ć

u

ż

ywana do reprezentowania ró

ż

nych warto

ś

ci


Stałe i zmienne mog

ą

wystepowa

ć

razem w wyra

ż

eniach.


i = 1;
- jest stał

ą

;


i = 10;
- jest stał

ą

;


i - mo

ż

e przyjmowa

ć

ż

ne warto

ś

ci (1,10, lub inne) zatem jest

zmienn

ą

.




Wyra

ż

enie


Wyra

ż

enie to kombinacja stałych, zmiennych i operatorów


( 3 + 6 ) * 20

4/2

20 * ( 2 + 1 )



Operatory arytmetyczne

+ - dodawanie
- odejmowanie

* - mno

ż

enie

background image

5


/ - dzielenie

% - reszta z dzielenia (dzielenie modulo)

8 % 5 à 3

* / % - operatory o wy

ż

szym priorytecie


+ - - operatory o ni

ż

szym priorytecie


Priorytet okre

ś

la kolejno

ść

wykonywanych działa

ń

, chyba,

ż

e

wystepuj

ą

nawiasy, wtedy w pierwszej kolejno

ś

ci wykonywane s

ą

wyra

ż

enia w nawiasach.




Instrukcje

W j

ę

zyku C instrukcja to polecenie zako

ń

czone

ś

rednikiem.


i = 5;

j = (12+4 ) * 2;

k = i + j;

return 0;

exit(0);

printf(”To jest program w C”);



Bloki instrukcji

Grupa instrukcji tworzy blok instrukcji, który jest traktowany
przez kompilator jako pojedyncza instrukcja.

{

i = 5;

j = 8;

k = i + j;

}

background image

6

Blok instrukcji to sposób poł

ą

czenia kilku instrukcji

prostych, tak aby zawsze były wykonywane razem – tak jak jedna
instrrukcja.



Struktura funkcji

Funkcje w j

ę

zyku c mog

ą

by

ć

albo funkcjami bibliotecznymi,

albo stworzonymi przez programist

ę

, albo przez innych

programistów.

Funkcja składa si

ę

z:

typu funkcji
nazwy funkcji
argumentów funkcji
nawiasu otwieraj

ą

cego

ciała funkcji
nawiasu zamykaj

ą

cego


int nazwa_funkcji(int x, int y)

{

int rezult;

rezult = x + y;

return rezult;

}



typ funkcji :

to rodzaj warto

ś

ci wyniku, który funkcja zamierza zwróci

ć

po

jej wykonaniu.



nazwa funkcji :

nazwa funkcji musi by

ć

zwi

ą

zana z zadaniem wykonywanym przez

funkcje
nazwa funkcji nie mo

ż

e rozpoczyna

ć

si

ę

do cyfry

nazwa funkcji nie mo

ż

e rozpoczyna

ć

si

ę

od znaku *

nazwa funkcji nie mo

ż

e rozpoczyna

ć

si

ę

od znaku operatora

arytmetycznego
nazwa funkcji nie mo

ż

e rozpoczyna

ć

si

ę

od znaku .

nazwa funkcji nie mo

ż

e zawiera

ć

(wewn

ą

trz) znaku -

background image

7

nazwa funkcji nie mo

ż

e zawiera

ć

(wewn

ą

trz) znaku ‘


argumenty przekazywane do funkcji
dla prawidłowego wykonania pewne funkcje potrzebuj

ą

przekazania im pewnych informacji , przekazywanych w postaci
tzw. argumentów
argumenty umieszczane s

ą

w nawiasach okr

ą

głych tu

ż

po nazwie

funkcji
je

ż

eli do prawidłowego działania funkcji niezb

ę

dne jest

podanie wi

ę

cej ni

ż

jednego argumentu, wtedy tworzymy tzw.

list

ę

argumentów, w które argumenty oddzielone s

ą

od siebie

przecinkami
je

ż

eli funkcja nie wymaga

ż

adnych argumentów to lista

argumentów jest pusta

pocz

ą

tek i koniec funkcji :


{ } znaki słu

żą

ce do zaznaczenia pocz

ą

tku i ko

ń

ca funkcji;


pomi

ę

dzy nimi zawarte jest ciało funkcji;




ciało funkcji :

zawiera :
deklaracje zmiennych
instrukcje j

ę

zyka C


wykonanie funkcji à wykonanie instrukcji stanowi

ą

cych jej

ciało

wywołanie funkcji polega na podaniu jej nazwy i okre

ś

leniu

argumentów wywołania;

// p_0

# include <stdio.h>int dodaj(int x, int y)

{

int wynik;

wynik=x+y;

return wynik;

}

int main()

background image

8

{

int suma;

suma=dodaj(2,3);

printf("Wynik dodawania 2 + 3 = %d\n",suma);

return 0;

}

// p_01

# include <stdio.h># include <conio.h>

int dodaj(int x, int y)

{

int wynik;

wynik=x+y;

return wynik;

}

int main()

{

int suma;

suma=dodaj(2,3);

clrscr();

printf("Wynik dodawania 2 + 3 = %d\n",suma);

return 0;

}

// p_02

# include <stdio.h>

# include <conio.h>

int dodaj(int ax,int ay);

background image

9


int main()

{

int suma;

suma=dodaj(2,3);

clrscr();

printf("Wynik dodawania 2 + 3 = %d\n",suma);

return 0;

}

int dodaj(int x, int y)

{

int wynik;

wynik=x+y;

return wynik;

}







Słowa kluczowe j

ę

zyka C



auto break case char const continue

default do double else enum extern

float for goto if int long

register return short signed sizeof static

struct switch typedef union unsigned void

volatile while

słowa kluczowe j

ę

zyka C pisane s

ą

małymi literami

background image

10






Typy danych

Typ danych - char



obiekty typu charakter to znaki : a, b, z, A,B,7,,0,2,W,w
ka

ż

dy z tych znaków przechowywany jest w pami

ę

ci w postaci

numerycznego kodu liczbowego
tablica kodów ASCII 27 =128
rozszerzona tablica kodów ASCII 28 =256
obiekt typu char zajmuje 1 bajt (8 bitów)



zmienne znakowe - mog

ą

reprezentowa

ć

ż

ne znaki


deklaracja zmiennej znakowe jest sposobem przyporz

ą

dkowania

tej zmiennej okre

ś

lonego miejsca w pami

ę

ci o rozmiarze

odpowiadaj

ą

cym typowi tej zmiennej


char lista nazw zmiennych /oddzielone przecinkami/;

char c1,c2,c_znak;

Stałe znakowe

znak uj

ę

ty w apostrofy (‘) jest nazywany stał

ą

znakow

ą


‘a’ , ‘A’ , ‘b’
stałe znakowe (pojedyncze znaki ASCII) s

ą

ujmowane w apostrofy

(‘) ;
ła

ń

cuchy znakowe (teksty) s

ą

ujmowane w znaki (”);

poszczególnym znakom przyporz

ą

dkowane s

ą

ich kody ASCII;


‘A’ à 65

‘a’ à 97

‘B’ à 66

‘b’ à 98

dlatego dla zmiennej x

char x;

background image

11


x=’A’; i x=65 to równowa

ż

ne zapisy




znak specjalny : \

tworzy wraz z innymi znakami znaki steruj

ą

ce:


np.:

\n - przej

ś

cie do nast

ę

pnej linii


\b - cofni

ę

cie kursora o jeden znak w lewo


\f - przej

ś

cie do nast

ę

pnej strony


\r - powrót na pocz

ą

tek bie

żą

cego wiersza


\t - tabulacja



drukowanie znaków :

do wyprowadzania znaków na ekran mo

ż

na stosowa

ć

funkcj

ę

printf();

W funkcji tej do wyprowadzenia pojedynczego znaku słu

ż

y format

: %c



# include <stdio.h># include <conio.h>void main(void){char
c1,c2; c1='a'; clrscr(); printf("Oto c1 %c \n",c1); c2='A';
c1='B'; printf("Oto c1 %c \n",c1);

printf("Oto c2 %c \n",c2);

getch();

}



# include <stdio.h># include <conio.h>int main(){char c1,c2;
c1=97; c2=65; clrscr(); printf("Oto c1 %c \n",c1); printf("Oto
c2 %c \n",c2);}

background image

12

Specyfikator formatu %c, u

ż

yty w funkcji printf(), okre

ś

la

sposób wy

ś

wietlenia zmiennej - w tym przypadku jest to sposób

wy

ś

wietlenia w postaci znaku;










Typ danych int /integer/
typ danych int wykorzystywany jest dla danych numerycznych –
całkowitych;
liczby całkowite nie zawieraj

ą

ani cz

ęś

ci ułamkowej, ani

przecinka dziesi

ę

tnego;

wynik dzielenie liczb całkowitych ulega obci

ę

ciu o cz

ęść

ułamkow

ą

;

w najprostszym przypadku obiekty typu int zajmuj

ą

2 bajty / w

innych systemach mo

ż

e to by

ć

4 bajty/

zakres warto

ś

ci 16 bitowych liczb całkowitych (2bajty)


32 767 (215 – 1) do -32 768 dla liczb ze znakiem

lub
do 216 dla liczb bez znaku

deklarowanie zmiennych dla obiektów typu int

int lista zmiennych;

int x, zm_1,i;

drukowanie numerycznych kodów znaków

%d - jest specyfikatorem formatu, który zawarto

ść

komórek

pami

ę

ci interpretuje jako warto

ść

typu integer


// p_1

# include <stdio.h># include <conio.h>void main(void){char
c1,c2; c1='a'; clrscr(); printf("Oto c1 %c %d \n",c1,c1);
c2='A'; c1='B'; printf("Oto c1 %c %d \n",c1,c1);

printf("Oto c2 %c %d \n",c2,c2);

getch();

}

background image

13

//p_2

# include <stdio.h># include <conio.h>int main(){char c1,c2;
c1=97; c2=65; clrscr(); printf("Oto c1 %c %d \n",c1,c1);
printf("Oto c2 %c %d \n",c2,c2);

}



zmienne znakowe mog

ą

by

ć

wyprowadzane na ekran albo w postaci

znaków, albo w postaci ich kodów numerycznych ; zale

ż

y to od

specyfikatora formatu.





typ danych - float

zmienne przecinkowe (z pływaj

ą

cym przecinkiem) – float


- stałe 6,56f lub 6,56F oznaczaj

ą

stałe typu float


6,56 domy

ś

lnie jest traktowane jako typ double

typ float zajmuje 4 bajty pami

ę

ci

co najmniej 6 miejsc znacz

ą

cych po przecinku

deklaracja:

float lista zmiennych;

float y, zm_1, x;

%f jest zmiennoprzecinkowym specyfikatorem formatu

//p_3

# include <stdio.h># include <conio.h>int main(){int i1,i2,d;
i1=3; i2=2; d=i1/i2; clrscr(); printf("Oto wynik 3/2 = %d
\n",d); getch();}



//p_4

# include <stdio.h># include <conio.h>void main(void){int
int_1,int_2,int_3,int_4;

float flt_1,flt_2,flt_3,flt_4;

clrscr();

background image

14


int_1=32/10;

flt_1=32/10;

int_2=32.0/10;

flt_2=32.0/10;

int_3=32/10.0;

flt_3=32/10.0;

int_4=32.0/10.0;

flt_4=32.0/10.0;

printf("Dzielenie całkowite 32/10 %d\n",int_1);

printf("Dzielenie zmiennoprzecinkowe 32/10 %f\n",flt_1);

printf("Dzielenie całkowite 32.0/10 %d\n",int_2);

printf("Dzielenie zmiennoprzecinowe 32.0/10 %f\n",flt_2);

printf("Dzielenie całkowite 32/10.0 %d\n",int_3);

printf("Dzielenie zmiennoprzecinkowe 32/10.0 %f\n",flt_3);

printf("Dzielenie całkowite 32.0/10.0 %d\n",int_4);

printf("Dzielenie zmiennoprzecinkowe 32.0/10.0 %f\n",flt_4);

getch();

}



typ danych - double
w przeciwie

ń

stwie do typu float, typ zmiennopozycyjny double

zajmuje dwa razy wi

ę

cej miejsca w pami

ę

ci (8 bajtów)

co najmniej 10 miejsc znacz

ą

cych po przecinku


zapis wykładniczy liczb

w formacie wykładniczym liczba przedstawiona jest w postaci
mantysy i wykładnika; cecha i mantysa rozdzielone s

ą

litera E

(e)

mantysa E (e) wykładnik

background image

15

= 5e3

-300 = -3e2

przy wyprowadzaniu liczb w takim formacie na ekran, funkcja
printf() u

ż

ywa specyfikatora:


%e lub %E

Identyfikatory

s

ą

to nazwy zmiennych i funkcji j

ę

zyka C


Znaki, które mo

ż

na stosowa

ć

przy nadawaniu nazw zmiennych:

litery du

ż

e A,...,Z i małe a,...,z;

cyfry 0,...,9 /cyfra nie mo

ż

e by

ć

pierwszym znakiem nazwy/;

znak podkre

ś

lenia (_);


Znaki zabronione przy nadawaniu nazw zmiennych:
nazwa zmiennej nie mo

ż

e zawiera

ć

znaku jakiejkolwiek operacji

arytmetycznej;
nazwa zmiennej nie mo

ż

e zawiera

ć

kropki (.);

nazwa zmiennej nie mo

ż

e zawiera

ć

apostrofu (‘);

nazwa zmiennej nie mo

ż

e zawiera

ć

ż

adnego spo

ś

ród pozostałych

symboli specjalnych : *,@,#,?, itp.
nie mo

ż

na stosowa

ć

słów kluczowych j

ę

zyka C, nazw funkcji

bibliotecznych jako nazw zmiennych w programach pisanych w

j

ę

zyku C;






Obsługa standardowego wej

ś

cia/wyj

ś

cia



Miejscem przechowywania informacji s

ą

pliki. Poniewa

ż

informacje s

ą

reprezentowane jako ci

ą

gi bitów pogrupowane po 8

w bajty, j

ę

zyk C traktuje plik jako ci

ą

g bajtów.


Ci

ą

g bajtów mo

ż

e by

ć

nazwany plikiem b

ą

d

ź

strumieniem. W

j

ę

zyku C wszystkie strumienie danych i wszystkie pliki

traktowane s

ą

tak samo.


W j

ę

zyku C mamy do czynienia z 3 strumieniami plikowymi:

stdin - standardowe wej

ś

cie do odczytu

stdout - standardowe wyj

ś

cie do zapisu

stderr - standardowe wyj

ś

cie diagnostyczne dla komunikatów o

ę

dach

background image

16

zazwyczaj stdin à klawiatura

stdout , stderr à ekran monitora


Wprowadzanie danych

Funkcja getc() - wczytuje pojedynczy znak ze strumienia
(pliku) wej

ś

ciowego , zwracaj

ą

c kod wczytanego znaku w postaci

liczby całkowitej (int).

int getc(FILE *stream);

int getc(stdin);

//P_5

# include <stdio.h># include <conio.h>void main(void){ int c;
clrscr(); printf("Naci

ś

nij klawisz : \n"); c=getc(stdin);

printf("Nacisn

ą

łe

ś

klawisz < %c > ,którego kod ASCII wynosi %d

\n",c,c); getch();}





Funkcja getchar() - jest równowa

ż

na funkcji getc(stdin);


int getchar(void);

//p_6

# include <stdio.h># include <conio.h>void main(void){ int c;
clrscr(); printf("Naci

ś

nij klawisz : \n"); c=getchar();

printf("Nacisn

ą

łe

ś

klawisz < %c > ,którego kod ASCII wynosi %d

\n",c,c);

getch();

}

Wyprowadzanie danych

Funkcja putc() - wysyła znak do wskazanego jej jako argument
strumienia /pliku.

int putc(int c, FILE *stream);

int c - pierwszy argument funkcji to nazwa zmiennej
numerycznej przechowuj

ą

cej kod znaku do przesłania;

background image

17

drugi argumnet to wska

ź

nik do pliku wyj

ś

ciowego


je

ż

eli operacja si

ę

powiodła funkcja zwraca numer kodu

przesłanego znaku; w przeciwnym przypadku (bł

ą

d) funkcja

zwraca EOF (-1)













//P_7



# include <stdio.h># include <conio.h>void main(void)

{

int c;

clrscr();

c=70;

printf("Znak o kodzie ASCII 70 to \n");

putc(c,stdout);

getch();

}

Funkcja putchar() - funkcja ta w przeciwie

ń

stwie do putc()

potrzebuje tylko jednego argumentu tj. znaku przeznaczonego do
wyprowadzenia;

drugiego argumentu nie trzeba wprowadza

ć

poniewa

ż

jest on

domy

ś

lny tj. stdout


// p_8

background image

18

# include <stdio.h># include <conio.h>void main(void){ int c;
clrscr(); c=70; printf("Znak o kodzie ASCII 70 to \n");
putchar(c); getch();}



//p_9

# include <stdio.h>

# include <conio.h>

void main(void)

{

clrscr();

putchar(65);

putchar(10);

putchar(66);

putchar(10);

putchar(67);

putchar(10);

getch();

}

Funkcja printf()

int printf(const char *format_string, ...);

const – stała

char - typ znakowy

* - wska

ź

nik (wskazanie)


format_string - ła

ń

cuch formatuj

ą

cy


... - nastepne elementy
pierwszy element format_string to ła

ń

cuch znaków zawieraj

ą

cy

równie

ż

specyfikatory formatu (%c, %d, %f, itp.)

background image

19

cz

ęść

druga to ewentualna lista wyra

ż

e

ń

, które powinny by

ć

sformatowane w cz

ęś

ci pierwszej zgodnie ze specyfikatorami

formatu;

ilo

ść

tych wyra

ż

e

ń

musi by

ć

równa ilo

ś

ci specyfikatorów

formatu w cz

ęś

ci pierwszej


funkcja printf() zwraca (int) ilo

ść

poprawnie sformatowanych

wyra

ż

e

ń

, w przeciwnym przypadku zwraca warto

ść

ujemn

ą


Specyfikatory formatu, które mo

ż

na stosowa

ć

w wywołaniu

funkcji printf()
%c - znak (typ char)
%d - liczba (typ int)
%i - liczba (typ int) to samo co %d
%f - liczba zmiennoprzecinkowa (typ float)
%e - format wykładniczy z u

ż

yciem małej litery e

%E - format wykładniczy z u

ż

yciem du

ż

ej litery E

%g - zastosuj %f lub %e – wybierz format, w którym wynik
b

ę

dzie krótszy

%G - zastosuj % f lub %E – wybierz format, w którym wynik
b

ę

dzie krótszy

%o - liczba ósemkowa bez znaku
%s - ła

ń

cuch znaków (string)

%u - liczba całkowita (typu unsigned) jak int, ale bez znaku
%x - liczba szesnastkowa bez znaku (z zastosowanie przyrostka
x, małe litery)
%X - liczba szesnastkowa bez znaku (z zastosowaniem przyrostka
X, du

ż

e litery)

%p - argument odpowiadaj

ą

cy wska

ź

nikowi (pointer)

%n - rejestruj ilo

ść

znaków wyprowadzon

ą

do tego momentu

%% - wyprowad

ź

znak ‘%’


Zamiana liczb dziesi

ę

tnych na szesnastkowe - wykorzystanie

formatu %x i %X

//p_10

# include <stdio.h># include <conio.h>void
main(void){clrscr(); printf("Liczba 16 X Liczba 16 x Liczba
10\n");

printf("%X %x %d\n",0,0,0);

printf("%X %x %d\n",1,1,1);

printf("%X %x %d\n",2,2,2);

printf("%X %x %d\n",3,3,3);

printf("%X %x %d\n",4,4,4);

background image

20


printf("%X %x %d\n",5,5,5);

printf("%X %x %d\n",6,6,6);

printf("%X %x %d\n",7,7,7);

printf("%X %x %d\n",8,8,8);

printf("%X %x %d\n",9,9,9);

printf("%X %x %d\n",10,10,10);

printf("%X %x %d\n",11,11,11);

printf("%X %x %d\n",12,12,12);

printf("%X %x %d\n",13,13,13);

printf("%X %x %d\n",14,14,14);

printf("%X %x %d\n",15,15,15);

printf("%X %x %d\n",16,16,16);

printf("%X %x %d\n",17,17,17);

printf("%X %x %d\n",18,18,18);

printf("%X %x %d\n",19,19,19);

printf("%X %x %d\n",20,20,20);

getch();

}









Minimalna szeroko

ść

pola


J

ę

zyk C umo

ż

liwia na wstawienie do specyfikatora formatu

pomi

ę

dzy znak % a liter

ę

specyfikatora liczby nazywanej

specyfikatorem minimalnej szeroko

ś

ci pola

background image

21

np. %10f - wyprowadzenie w formacie zmiennoprzecinkowym z
u

ż

yciem minimum 10 znaków (cyfr)




//p_11

# include <stdio.h># include <conio.h>void main(void){int
n1,n2;clrscr(); n1=12; n2=12345; printf("%d\n",n1);
printf("%d\n",n2); printf("%5d\n",n1); printf("%05d\n",n1);
printf("%2d\n",n2); getch();}





%5d - ustalenie na 5 minimalnej szeroko

ś

ci pola wyj

ś

ciowego


%05d - jak wy

ż

ej z tym

ż

e puste miejsca zostana wypełnione

zerami

%2d - gdy specyfikator formatu jest za mały w stosunku do
długo

ś

ci liczby to liczba jest wyprowadzana w cało

ś

ci




Wyrównanie pola wyj

ś

ciowego


Znaki wyj

ś

ciowe s

ą

wyrównywane do prawej strony.


Aby to zmieni

ć

, i doprowadzi

ć

do wyrównywania do lewej nale

ż

y


poprzedzi

ć

specyfikator minimalnej szeroko

ś

ci pola znakiem

minus (-);



//p_12



# include <stdio.h># include <conio.h>

void main(void)

{

int n1,n2;

clrscr();

background image

22

n1=12;

n2=12345;

printf("%-d\n",n1);

printf("%-d\n",n2);

printf("%-5d\n",n1);

printf("%-05d\n",n1);

printf("%-2d\n",n2);

getch();

}



//p_13

# include <stdio.h># include <conio.h>void main(void)

{

int n1,n2,n3,n4,n5;

clrscr();

n1=1;

n2=12;

n3=123;

n4=1234;

n5=12345;

printf("%10d %-10d\n",n1,n1);

printf("%10d %-10d\n",n2,n2);

printf("%10d %-10d\n",n3,n3);

printf("%10d %-10d\n",n4,n4);

printf("%10d %-10d\n",n5,n5);

getch();

background image

23


}



Specyfikator precyzji

Po specyfikatorze minimalnej szeroko

ś

ci pola mo

ż

na doda

ć

kropk

ę

(.) i liczb

ę

całkowit

ą

. Poł

ą

czenie .liczba tworzy

specyfikator precyzji.

Pozwala on okre

ś

li

ć

:

ilo

ść

cyfr dziesi

ę

tnych po przecinku dla liczb

zmiennoprzecinkowych;
albo maksymalna szeroko

ść

pola wyj

ś

ciowego /przypadek ten

odnosi si

ę

do liczb całkowitych i do ła

ń

cuchów tekstowych/




np.:

%10.3f
minimalna szeroko

ść

pola wyj

ś

ciowego 10 znaków

ilo

ść

cyfr dziesi

ę

tnych po przecinku : 3 /domy

ś

lna ilo

ść

cyfr

po przecinku to 6/

%3.8d
minimalna szeroko

ść

pola wyj

ś

ciowego – 3

maksymalna szeroko

ść

pola wyj

ś

ciowego - 8




//p_14

# include <stdio.h># include <conio.h>void main(void){int
n1;double d1;clrscr(); n1=123; d1=123.456789; printf("Format
całkowity domy

ś

lny %d\n",n1);


printf("j.w. ze spec. pracyzji %2.8d\n",n1);

printf("Format zmiennoprzecinkowy domy

ś

lny %f\n",d1);


printf("j.w. ze spec. praecyzji %10.2f\n",d1);

getch();

}

//p_15

# include <stdio.h># include <conio.h>void main(void){int n1;

background image

24


float d1;

clrscr();

n1=123;

d1=123.456789;

printf("Format całkowity domy

ś

lny %d\n",n1);


printf("j.w. ze spec. pracyzji %2.8d\n",n1);

printf("Format zmiennoprzecinkowy domy

ś

lny %f\n",d1);


printf("j.w. ze spec. precyzji %10.2f\n",d1);

getch();

}













Operatory


Operator przypisania

= operator przypisania

operand_lewostronny = operand_prawostronny

warto

ść

operandu prawostronnego zostaje przypisana operandowi

lewostronnemu; przypisanie polega na umieszczeniu w obszarze
pami

ę

ci zarezerwowanym dla operandu lewostronnego warto

ś

ci

operandu prawostronnego;

x = 10;

y = a + 5;

background image

25

Operatory arytmetyczne i operator przypisania

z = x + y;

x = x + y; ß à x += y

Poł

ą

czenie operatorów arytmetycznych z operatorem przypisania

tworzy w j

ę

zyku C


arytmetyczne operatory przypisania

+= operator przypisania z dodawaniem

-= operator przypisania z odejmowaniem

*= operator przypisania z mni

ż

eniem


/= operator przypisania z dzieleniem

%= operator przypisania reszty z dzielenia



x += y ß à x = x + y

x -= y ß à x = x - y

x *= y ß à x = x * y

x /= y ß à x = x / y

x %= y ß à x = x % y



z = z * x + y i z *= x + y nie s

ą

równowa

ż

ne ze wzgl

ę

du na

kolejno

ść


operacji



równowa

ż

ne s

ą

:


z *= x + y i z = z * ( x + y )

//p_16

# include <stdio.h># include <conio.h>void main(void){int
x,y,z;clrscr(); x=1; y=3; z=10; printf("x= %d y= %d z=

background image

26

%d\n",x,y,z); x=x+y; printf("\nx=x+y przypisuje zmiennej x
warto

ść

%d\n",x);


x=1;

x+=y;

printf("\nx+=y przypisuje zmiennej x warto

ść

%d\n",x);


x=1;

x=x-y;

printf("\nx=x-y przypisuje zmiennej x warto

ść

%d\n",x);


x=1;

x-=y;

printf("\nx-=y przypisuje zmiennej x warto

ść

%d\n",x);


x=1;

z=z*x+y;

printf("\nz=z*x+y przypisuje zmiennej z warto

ść

%d\n",z);


z=10;

z=z*(x+y);

printf("\nz=z*(x+y) przypisuje zmiennej z warto

ść

%d\n",z);


z=10;

z*=x+y;

printf("\nz*=x+y przypisuje zmiennej z warto

ść

%d\n",z);


getch();

}



Jednoargumentowy operator zmiany znaku

Operandem tego operatora mo

ż

e by

ć

warto

ść

numeryczna całkowita

lub zmiennoprzecinkowa – stała b

ą

d

ź

zmienna.

background image

27

Nie mo

ż

na myli

ć

jednoargumentowego operatora (-) z

dwuargumentowym operatorem (-) odejmowania.

W wyra

ż

eniu:


x - -y à pierwszy jest operatorem dwuargumentowym odejmowania,
za

ś

drugi minus operatorem jednoargumentowym zmiany znaku.


tj. x – (-y) à x + y





Zwi

ę

kszanie i zmniejszanie o 1. à Inkrementacja i

dekrementacja.



++ x ß à x = x+1 lub x += 1

-- x ß à x = x-1 lub x -= 1

Operatory inkrementacji i dekrementacji wystepuj

ą

w j

ę

zyku C w

dwóch wersjach ka

ż

dy :


++ x - operator pre-inkrementacji

x ++ - operator post-inkrementacji

-- x - operator pre-dekrementacji

x -- - operator post-dekrementacji

W przepadku pre- najpierw nast

ę

puje dodanie lub odjecie

jedynki a pó

ź

niej wykorzystanie zmiennej z now

ą

warto

ś

ci

ą

w

programie;

W przypadku post- najpierw nast

ę

puje wykorzystanie warto

ś

ci

zmiennej w programie a dopiero pó

ź

niej jej zwi

ę

kszenie lub

zmniejszenie o 1;



y = x ++;

1/ najpierw wykonane zostanie przypisanie y = x;

2/ potem x = x + 1;

praktycznie realizuje si

ę

to w nast

ę

puj

ą

cy sposób:

background image

28


1/ program wykonuje kopie tymczasow

ą

zmiennej x;


2/ inkrementuje zmienn

ą

x , a nie tymczasow

ą

kopi

ę

;


3/ wykorzystuje tymczasowa kopie x do przypisania y = x;

//p_17

# include <stdio.h># include <conio.h>void main(void){int
x,y,z,w,wynik;clrscr(); x=y=z=w=1; printf("x = %d y = %d z =
%d w = %d\n",x,y,z,w); wynik=++x; printf("\n++x wynosi
%d\n",wynik); wynik=y++;

printf("\ny++ wynosi %d\n",wynik);

wynik=--z;

printf("\n--z wynosi %d\n",wynik);

wynik=w--;

printf("\nw-- wynosi %d\n",wynik);

getch();

}



Operatory relacji

Mi

ę

dzy wyra

ż

eniami w j

ę

zyku C mog

ą

wyst

ę

powa

ć

nast

ę

puj

ą

ce

relacje:

== równe

!= ró

ż

ne od


> wi

ę

ksze od


< mniejsze od

>= wi

ę

ksze lub równe


<= mniejsze lub równe

Wszystkie operatory relacji maj

ą

ni

ż

szy priorytet ni

ż

operatory arytmetyczne, co oznacza

ż

e najpierw zostan

ą

wykonane operacje arytmetyczne a nast

ę

pnie zostan

ą

dokonane

porównania warto

ś

ci.

background image

29


Uj

ę

cie operacji w nawiasy powoduje ich wykonanie w pierwszej

kolejno

ś

ci.


W grupie operatorów logicznych, operatory > , < , >= , <= maja
wy

ż

szy priorytet ni

ż

== oraz != .


Je

ż

eli relacja jest prawdziwa to zwrócona zostanie warto

ść

1,

w przeciwnym przypadku warto

ść

0.




//p_18

# include <stdio.h># include <conio.h>void main(void){int
x,y;double z;clrscr(); x=7; y=25; z=24.46;

printf("x = %d y = %d z = %.2f\n",x,y,z);

printf("operacja %d >= %d daje wynik %d\n",x,y,x>=y);

printf("operacja %d == %d daje wynik %d\n",x,y,x==y);

printf("operacja %d < %.2f daje wynik %d\n",x,z,x<z);

printf("operacja %d > %.2f daje wynik %d\n",y,z,y>z);

printf("operacja %d != %d - 18 daje wynik %d\n",x,y,x!=y-18);

printf("operacja %d + %d != %.2f daje wynik
%d\n",x,y,z,x+y!=z);

getch();

}

1 / 2 + 1 / 2 == 1 à logiczny wynik 0 1 / 2 à 0

1.0 / 3.0 + 1.0 / 3.0 + 1.0 / 3.0 == 1 à logiczne 0 1.0 / 3.0
à 0.3333333

Operator rzutowania

W j

ę

zyku C mo

ż

na zamieni

ć

jeden typ danych na inny poprzez

poprzedzenie operandu operatorem rzutowania.

(typ_danych)x


typ danych na który ma zosta

ć

zamieniona warto

ść

x

background image

30



(float)5 à 5.0

x=1;

(float)(x+2) à 3.0

//p_19

# include <stdio.h># include <conio.h>void main(void){int
x,y;clrscr(); x=8; y=5;printf("x = %d y = %d \n",x,y);
printf("operacja %d / %d daje wynik %d\n",x,y,x/y);
printf("operacja float(%d) / %d daje wynik
%f\n",x,y,float(x)/y);

getch();

}











Operacje p

ę

tli



P

ę

tla for ( ... )


for ( wyra

ż

enie1; wyra

ż

enie2; wyra

ż

enie3 )


{

instrukcja1;

instrukcja2;

instrukcja3;

...........

...........

}

background image

31

wyra

ż

enie1 - wyra

ż

enie inicjuj

ą

ce p

ę

tli /wykonuje si

ę

tylko

raz/

wyra

ż

enie2 - wyra

ż

enie warunkowe 1 à wykonuje si

ę

p

ę

tla

à nie wykonuje si

ę


wyra

ż

enie3 - wykonuje si

ę

po ka

ż

dym przebiegu instrukcji

p

ę

tli, przed


sprawdzeniem warto

ś

ci wyra

ż

enia2;


//p_20

# include <stdio.h>

# include <conio.h>

void main(void)

{

int i;

clrscr();

printf("Kod 16 D.L. Kod 16 m.l. Kod 10 \n");

for (i=0;i<16;i++)

printf(" %X %x %d \n",i,i,i);

getch();

}



for (i=0; i<8; i++)

{

ciało p

ę

tli


}

for (i=0; i<8; i++ )

suma+=i;


background image

32

for (i=0; i<8; i++ ); à p

ę

tla pusta




rozbudowana p

ę

tla for


for ( i=0, j=10; i<10, j>0; i++, j-- )

{

}



//p_21

# include <stdio.h>

# include <conio.h>

void main(void)

{

int i,j;

clrscr();

for (i=0,j=8;i<8;i++,j--)

printf("%d + %d = %d\n",i,j,i+j);

getch();

}

//p_22

# include <stdio.h>

# include <conio.h>

void main(void)

{

int i,j;

clrscr();

for (i=0,j=8;i<8,j>5;i++,j--)

background image

33


printf("%d + %d = %d\n",i,j,i+j);

getch();

}

//p_23

# include <stdio.h>

# include <conio.h>

void main(void)

{

int i,j;

clrscr();

for (i=0,j=1;i<8;i++,j++)

printf("%d - %d = %d\n",j,i,j-i);

getch();

}





P

ę

tle niesko

ń

czone


for (;;)

{

ciało p

ę

tli


}



for(;;);

for(;1;);

for (;1;)

background image

34

{

ciało p

ę

tli


}

//p_24

# include <stdio.h>

# include <conio.h>

void main(void)

{

int c;

clrscr();

printf("Wpisz znak - jesli wpiszesz znak <x> to koniec
programu\n");

for (c=' ';c!='x';)

{

c=getc(stdin);

putchar(c);

}

printf("\nKoniec programu\n");

getch();

}



P

ę

tla while


while(wyra

ż

enie)


{

instrukcja1;

instrukcja2;

background image

35

)

Je

ż

eli wyra

ż

enie zwraca warto

ść

niezerow

ą

wykonywane s

ą

instrukcje wewn

ą

trz p

ę

tli. Po wykonaniu instrukcji p

ę

tli

wyra

ż

enie sprawdzane jest ponownie i je

ż

eli zwróci warto

ść

niezerowa instrukcje wewn

ą

trz p

ę

tli wykonywane s

ą

ponownie, a

ż

do chwili gdy po kolejnym sprawdzeniu wyra

ż

enie przyjmie

warto

ść

0.


//p_25

# include <stdio.h># include <conio.h>

void main(void)

{

int c;

clrscr();

printf("Wpisz znak - jesli wpiszesz znak <x> to koniec
programu\n");

while (c!='x')

{

c=getc(stdin);

putchar(c);

}

printf("\nKoniec programu\n");

getch();

}



Niesko

ń

czona p

ę

tla while


while(1)

{

instrukcja1;

instrukcja2;

background image

36


}



//p_26

# include <stdio.h># include <conio.h>void main(void){int
c;clrscr(); printf("Wpisz znak\n"); while (1) { c=getc(stdin);
putchar(c); break; } printf("\nKoniec programu\n"); getch();}



Petla do - while

W p

ę

tlach for i while wyra

ż

enia warunkowe znajduj

ą

si

ę

w

nagłówku p

ę

tli. W p

ę

tli do-while odwrotnie – wyra

ż

enie

znajduje si

ę

na ko

ń

cu p

ę

tli. Dzieki temu instrukcje znajduj

ą

ce

si

ę

wewn

ą

trz p

ę

tli b

ę

d

ą

wykonywane przynajmniej jeden raz

zanim dojdzie do sprawdzenia warunku.

do

{

instrukcja1;

instrukcja2;

} while (wyra

ż

enie);


Instrukcja do-while zako

ń

czona jest srednikiem.
















//p_26_1

#include <stdio.h>main(){ int i; i = 65; do { printf("The
numeric value of %c is %d.\n", i, i);

background image

37


i++;

} while (i<72);

return 0;

}



P

ę

tle zagnie

ż

d

ż

one


Wstawianie jednej p

ę

tli wewn

ą

trz innej p

ę

tli nazywa si

ę

zagnie

ż

d

ż

eniem p

ę

tli.


//p_27

# include <stdio.h># include <conio.h>void main(void){int i,j;
clrscr(); for(i=1;i<=3;i++)

{

printf("Poczatek iteracji %d p

ę

tli zewnetrznej \n",i);


for(j=1;j<=4;j++)

printf("Iteracja %d petli wewnetrznej \n",j);

printf("Koniec iteracji %d petli zewnetrznej \n",i);

}

getch();

}

Zanim rozpocznie si

ę

kolejna iteracja p

ę

tli zawn

ę

trznej, musi

zosta

ć

zako

ń

czone wykonywanie p

ę

tli wewn

ę

trznej. Gdy

rozpocznie si

ę

kolejne wykonanie p

ę

tli zewn

ę

trznej, p

ę

tla

wewn

ę

trzna jest ponownie wykonywana zadan

ą

ilo

ść

razy.






//p_28

# include <stdio.h># include <conio.h>void main(void)

{

background image

38


int i,j;

clrscr();

for(i=1;i<=3;i++)

{

printf("Poczatek iteracji %d p

ę

tli zewnetrznej \n",i);


for(j=1;j<=4;j++)

printf("Iteracja %d petli wewnetrznej \n",j);

printf("Koniec iteracji %d petli zewnetrznej \n",i);

}

getch();

}





Operatory - cd

Operator sizeof

sizeof(wyra

ż

enie)


wyra

ż

enie oznacza typ danych lub zmienn

ą

, warto

ść

jest zwraca

w bajtach;



//p_29

# include <stdio.h># include <conio.h>void main(void){char c='
';int i=0;float f=0.0f;double d=0.0;clrscr();

printf("Dane typu char zajmuj

Ą

: %d - bajt\n",sizeof(char));


printf("Zmienna typu char zajmuje %d - bajt\n",sizeof c);

printf("Dane typu int zajmuj

Ą

: %d - bajty\n",sizeof(int));


printf("Zmienna typu int zajmuje %d - bajty\n",sizeof i);

background image

39

printf("Dane typu float zajmuj

Ą

: %d - bajty\n",sizeof(float));


printf("Zmienna typu float zajmuje %d - bajty\n",sizeof f);

printf("Dane typu double zajmuj

Ą

: %d -

bajt˘w\n",sizeof(double));

printf("Zmienna typu double zajmuje %d - bajt˘w\n",sizeof d);

getch();

}

podaj

ą

c operatorowi sam typ danych np. sizeof(int) lub

identyfikator zmiennej np. sizeof int_1; poniewa

ż

identyfikator zmiennej nie jest słowem kluczowym j

ę

zyka C

zatem mo

ż

emy pomin

ąć

nawiasy.


Operatory logiczne

&& - iloczyn logiczny (AND)

| | - suma logiczna (OR)

! - negacja logiczna (NOT)

s

ą

to operatory dwu (&& , || ) lub jednoargumentowe, których

argumentami s

ą

wyra

ż

enia b

ą

d

ź

warto

ś

ci logiczne;


Operator iloczynu logiczne (AND)

wyr1 && wyr2



wyr1 wyr2 wyr1 && wyr2

1 1 1

1 0 0

0 1 0

0 0 0

//p_30

# include <stdio.h>

# include <conio.h>

background image

40

void main(void)

{

int num=0;

clrscr();

printf("Operator && zwraca: %d\n", (num%2==0)&&(num%3==0));

num =2;

printf("Operator && zwraca: %d\n", (num%2==0)&&(num%3==0));

num=3;

printf("Operator && zwraca: %d\n", (num%2==0)&&(num%3==0));

num=6;

printf("Operator && zwraca: %d\n", (num%2==0)&&(num%3==0));

getch();

}



Operator sumy logicznej (OR)

wyr1 | | wyr2



wyr1 wyr2 wyr1 | | wyr2

1 1 1

1 0 1

0 1 1

0 0 0







//p_31

background image

41


# include <stdio.h>

# include <conio.h>

void main(void)

{

int num;

clrscr();

printf("Wpisz jednocyfrow

ą

liczbe podzieln

ą

\n przez 2 i przez

3\n");

for (num=1; (num%2!=0)||(num%3!=0);)

num=getchar()-48;

printf("Szukana liczba to : %d\n",num);

getch();

}

Operator logicznej negacji

! wyr



wyr ! wyr

1 0

0 1


//p_32

# include <stdio.h>

# include <conio.h>

void main(void)

{

int num;

background image

42

clrscr();

num=7;

printf("Dana jest zmienna num o warto˜ci 7 \n");

printf("!(num<7) zwraca : %d\n",!(num<7));

printf("!(num>7) zwraca : %d\n",!(num>7));

printf("!(num==7) zwraca : %d\n",!(num==7));

getch();

}





//p_33

# include <stdio.h>

# include <conio.h>

void main(void)

{

int num;

clrscr();

printf("Wpisz jednocyfrow

ą

liczb

ę

podzieln

ą

\n przez 2 i przez

3\n");

for (num=1; !((num%2==0)&&(num%3==0));)

num=getchar()-48;

printf("Szukana liczba to : %d\n",num);

getch();

}




background image

43

Logiczne operatory bitowe

& - bitowy iloczyn logiczny AND (I)

| - bitowa suma logiczna OR (LUB)

^ - bitowa alternatywa wył

ą

czna XOR (ALBO)


~ - bitowe uzupełnienie do 2 (komplementarne)

>> - przesuni

ę

cie bitów w prawo


<< - przesuni

ę

cie bitów w lewo






HEX Binarnie Dziesi

ę

tnie


0 0000 0

1 0001 1

2 0010 2

3 0011 3

4 0100 4

5 0101 5

6 0110 6

7 0111 7

8 1000 8

9 1001 9

A 1010 10

B 1011 11

C 1100 12

D 1101 13

E 1110 14

F 1111 15

background image

44






x & y

Operator & porównuje ka

ż

dy bit operandu x z odpowiednim bitem

operandu y. Je

ż

eli oba bity s

ą

równe 1 operator ustawia 1 na

tej samej pozycji bitu wyniku. Je

ż

eli cho

ć

by jeden z

porównywanych bitów jest równy 0 to bit wyniku jest 0.
& 11 à 01



x | y

Operator bitowy sumy logicznej (alternatywy zwykłej) ustawia
bit wyniku na 1 je

ż

eli cho

ć

by jeden z bitów operandu (lub oba)

jest równy 1.
| 11 à 11

x ^ y

Operator alternatywy wył

ą

cznej ustawia bit wyniku na 1 ,

je

ż

elili dokładnie jeden z bitów obu operandów jest równy 1.

^ 11 à 10

~ x

Operator negacji (inwersji bitowej) – dokonuj

ą

cy operacji na

pojedynczym operandzie - odwraca warto

ść

ka

ż

dego bitu

operandu.

~ 01 à 10

//p_34

# include <stdio.h># include <conio.h>void main(void){int
x,y,z;x=4321;y=5678;clrscr(); printf("Dana jezt zmienna x = %u
, czyli 0x%04X\n",x,x); printf("oraz zmienna y = %u , czyli
0x%04X\n",y,y);

z=x&y;

printf("x&y zwraca %6u , czyli 0x%04X\n",z,z);

z=x|y;

printf("x|y zwraca %6u , czyli 0x%04X\n",z,z);

background image

45

z=x^y;

printf("x^y zwraca %6u , czyli 0x%04X\n",z,z);

printf("~x zwraca %6u , czyli x%04X\n",~x,~x);

getch();

}





Operatory przesuni

ę

cia bitowego


>> przesuwa bity operandu w prawo

<< przesuwa bity operandu w lewo

x >> y

x << y

x – operand, którego bity b

ę

d

ą

przesuwane


y – ilo

ść

miejsc o które nale

ż

y przesun

ąć

bity operandu


8 >> 2 à 1000>>2 à 0010 à 2

5 << 1 à 0101<<1 à 1010 à 10

//p_35

# include <stdio.h># include <conio.h>void main(void){int
x,y,z;x=255;y=5;clrscr(); printf("Dana jest zmienna x = %4d ,
czyli 0x%04X\n",x,x); printf("oraz zmienna y = %4d , czyli
0x%04X\n",y,y); z=x>>y; printf("x>>y zwraca %6d , czyli
0x%04X\n",z,z);

z=x<<y;

printf("x<<y zwraca %6d , czyli 0x%04X\n",z,z);

getch();

}

y > 0

x >> y ß à x / 2y

background image

46


x << y ß à x * 2y





Operator warunkowy – jedynym operatorem trójargumentowym.

?: - operator warunkowy

x ? y : z

operandy x , y , z

x - wyra

ż

enie logiczne – wyra

ż

enie warunkowe


y - wyra

ż

enie wynikowe , które jest wykonywane gdy x zwraca

warto

ść

niezerow

ą

(np. 1)


z - wyra

ż

enie wynikowe, które jest wykonywane gdy x zwraca

warto

ść

0.




//p_36

# include <stdio.h># include <conio.h>void main(void){int
x;x=sizeof(int);clrscr(); printf("%s\n", (x==2) ? "Typ danych
int ma 2 bajty.":"Typ int nie ma 2 bajtów");
printf("Maksymalna wartosc liczby typu int to : %d\n", (x!=2)
? ~(1<<x*8-1): ~(1<<15));

getch();

}






Typy danych - modyfikatory





Bit znaku

background image

47

Jeden bit liczby mo

ż

e by

ć

wykorzystany po to aby wskazywał czy

liczba jest dodatnia czy ujemna. Jest to tzw, bit znaku.



Modyfikator signed

Dla liczb całkowitych pierwszy od lewej bit jest u

ż

ywany jako

bit znaku. Je

ż

eli liczby całkowite typu int maj

ą

16 bitów, i

pierwszy bit od prawej jest okre

ś

lany bitem na pozycji 0 to

bit znaku znajduje si

ę

na pozycji 15. Je

ż

eli jego warto

ść

wynosi 0 to liczba jest dodatnia, za

ś

gdy 1 to liczba jest

ujemna.

Sposób implementacji liczb ujemnych zmiennopozycyjnych typu
float i double na razie pominiemy.

modyfikator signed jest u

ż

ywany dla wskazania, i

ż

jeden bit

danych jest bitem znaku;

deklaracja int à jest domyslnie traktowana jako signed int

deklaracja char à zakres warto

ś

ci 0 – 255 (28 – 1)


deklaracja signed char à zakres warto

ś

ci


od -128 (-27 )

do +127 (27 – 1)

Aby zamieni

ć

liczb

ę

dwójkow

ą

na równ

ą

jej co do warto

ś

ci

bezwzgl

ę

dnej lecz ujemn

ą

, nale

ż

y:


liczba 12 345 à 0011 0000 0011 1001

1/ znajdujemy kod odwrotny liczby:


1100 1111 1100 0110

2/ dodajemy 1

1100 1111 1100 0111

jest to kod dwójkowy liczby - 12 345





background image

48


Modyfikator unsigned

modyfikator unsigned stosowany jest dla okre

ś

lenia , i

ż

pierwszy bit liczby nie jest jej bitem znaku;

mo

ż

e on by

ć

stosowany jako :


unsigned int

unsigned char

unsigned int x; à x: 0 , 65 535 (216 – 1)

Standard ANSI C pozwala na stosowanie przyrostków U i u przy
stałych bez znaku:

unsigned int x,y;

x = 1234U;

y = 0xABCFu;



//p_37

# include <stdio.h># include <conio.h>// funkcja druk_bin
drukuje binarny podany dzisi

ę

tnie argument x typu intvoid

druk_bin(int x){ int n; for (n=15;n>=0;n--) ((x>>n&1) ?
putchar('1') : putchar('0'));

}

void main(void)

{

signed char ch;

int x;

unsigned int y;

ch=0xFF;

x=0xFFFF;

y=0xFFFF;

clrscr();

background image

49


printf("\nDziesi

ę

tnie ze znakiem 0xFF to : %d",ch);


printf("\nDziesi

ę

tnie ze znakiem 0xFFFF to : %d a binarnie

:",x);

druk_bin(0xFFFF);

printf("\nDziesietnie bez znaku 0xFFFF to : %u",y);

printf("\nDziesi

ę

tnie: 12345 to Hex: 0x%X i binarnie:

",12345);

druk_bin(12345);

printf("\nDziesi

ę

tnie: -12345 to Hex: 0x%X i binarnie: ",-

12345);

druk_bin(-12345);

getch();

}



Modyfikatory rozmiaru danych


Dla zmniejszenia lub zwi

ę

kszenia pami

ę

ci zajmowanej przez dane

słu

żą

modyfikatory short i long.






Modyfikator short

Modyyfikator short umo

ż

liwia np. w systemie 32 bitowym

skrócenie danych in z 32 bitów do 16 bitów

short x; oznacza short signed int x;

unsigned short x; oznacza short unsigned int x;





Modyfikator long

background image

50

Modyfikator long poszerza zakres warto

ś

ci iprzez to dane

zajmuja wi

ę

cej miejsca w pami

ę

ci.


Je

ż

eli zmienna typu int zajmuje domy

ś

lnie 16 bitów to

modyfikator long int powi

ę

ksza wielko

ść

tej zmiennej do 32

bitów;

long int x; à -2147483648 (-231 ) do 2147483647 (231 – 1)

Standard ANSI C pozwala na dodawanie do stałych typu long
przyrostków L i l .

long int x,y;

x=123456789L;

y=0xABCD1234l;

//p_38

# include <stdio.h># include <conio.h>void
main(void){clrscr(); printf(" Rozmiar int: %d \n
",sizeof(int)); printf("Rozmiar short int: %d \n
",sizeof(short int)); printf("Rozmiar long int: %d \n
",sizeof(long int));

printf("Rozmiar float: %d \n ",sizeof(float));

printf("Rozmiar double: %d \n ",sizeof(double));

printf("Rozmiar long double: %d \n ",sizeof(long double));

getch();

}



short int - 2 bajty - 16 bitów - liczby całkowite krótkie

long int - 4 bajty - 32 bity - liczby całkowite długie

float - 4 bajty - 32 bity - liczby zmiennoprzecinkowe krótkie

double - 8 bajtów – 64 bity - liczby zmiennoprzecinkowe o
podwójnej

precyzji

long double - 10 bajtów - 80 bitów - liczby zmiennoprzecinkowe
długie

background image

51




Specyfikatory formatu h l L



%hd %hi

dziesietnie, liczba całkowita krótka - short int



%hu

dziesi

ę

tnie, liczba całkowita krótka bez znaku - short

unsigned int







%ld %Ld

dziesi

ę

tnie, całkowita długa - long int




%lu %Lu

dziesi

ę

tnie, całkowita długa bez znaku - long unsigned int




//P_39

# include <stdio.h># include <conio.h>void main(void)

{

short int x;

unsigned int y;

long int s;

unsigned long int t;

x=0xFFFF;

background image

52


y=0xFFFFU;

s=0xFFFFFFFFl;

t=0xFFFFFFFFL;

clrscr();

printf("Short int 0xFFFF to: %hd\n",x);

printf("Unsigned int 0xFFFF to: %u\n",y);

printf("Long int 0xFFFFFFFF to: %ld\n",s);

printf("Unsigned long int 0xFFFFFFFF to %lu\n",t);

getch();

}





















Funkcje matematyczna




Grupy funkcji matematycznych

Trygonometryczne i hiperboliczne : sin() , cos() , cosh()
,......

background image

53

Wykładnicze i logarytmiczne : exp() , pow() , log10() , .....

Pozostałe : ceil() , fabs() , floor() , ....

Wykorzystanie funkcji sin(), cos(), tan();

argumentem funkcji jest k

ą

t x w radianach


radiany = stopnie * (3.141593 / 180.0 )

#include <math.h>

double sin(double x);

double cos(double x);

double tan(double x);



//p_40

# include <stdio.h># include <conio.h># include <math.h>void
main(void){double x;x=45.0;x*=3.141593/180.0;clrscr();
printf("Sinus 45 : %f\n",sin(x)); printf("Cosinus 45 :
%f\n",cos(x));

printf("Tangens 45 : %f\n",tan(x));

getch();

}





Wywołanie funkcji : pow() i sqrt();

#include <math.h>

double pow(double a, double b);

double sqrt(double x);



//p_41

background image

54

# include <stdio.h># include <conio.h># include <math.h>void
main(void){double x,y,z;x=64.0;y=3.0;z=0.5;clrscr();
printf("64 x 64 x 64 : %7.0f\n",pow(x,y));

printf("Pierw. kw. z 64 : %2.0f\n",sqrt(x));

printf("64 do pot

ę

gi 1/2 : %2.0f\n",pow(x,z));


getch();

}













Sterowanie programem


Instrukcja warunkowa if

if (wyra

ż

enie)


{

blok instrukcji

}



//p_42

# include <stdio.h>

# include <conio.h>

void main(void)

{

int i;

background image

55

clrscr();

printf("Liczby caˆkowite podzielne przez 2 i przez 3\n");

printf("\tw zakresie od 0 do 100 \n");

for (i=0;i<=100;i++)

if((i%2==0)&&(i%3==0))

printf(" %d\n",i);

getch();

}

Instrukcja warunkowa if-else

if (wyra

ż

enie)


{

blok instrukcji

}

else

{

blok instrukcji

}



//p_43

# include <stdio.h>

# include <conio.h>

void main(void)

{

int i;

clrscr();

printf("Liczby parzyste Liczby nieparzyste\n");

background image

56


for (i=0;i<10;i++)

if(i%2==0)

printf("%d",i);

else

printf("%30d\n",i);

getch();

}



Zagnie

ż

d

ż

one instrukcje warunkowe if




//p_44

# include <stdio.h>

# include <conio.h>

void main(void)

{

int i;

clrscr();

for (i=-5;i<=5;i++)

if(i>0)

if(i%2==0)

printf("%d to liczba parzysta \n",i);

else

printf("%d to liczba nieparzysta \n",i);

else

if (i==0)

background image

57

printf("To jest zero\n");

else

printf("Liczba ujemna %d\n",i);

getch();

}













Instrukcja switch

switch (wyra

ż

enie)


{

case wyra

ż

enie1:


instrukcja1;

case wyra

ż

enie2:


instrukcja2;

...........

default:

instrukcja-domyslna;

}

Najpierw sprawdzana jest warto

ść

wyra

ż

enia (wyra

ż

enie

sterujace)

Je

ż

eli warto

ść

wyra

ż

enia jest równa wyra

ż

enie1 to wykonywana

jest instrukcja1, je

ż

eli jest równa wyra

ż

enie2 to wykonywana

jest isntrukcja2, itd.

background image

58

wyra

ż

enie1, wyra

ż

enie2 i pozostałe wyra

ż

enia s

ą

wyra

ż

eniami

stałowarto

ś

ciowymi;


Je

ż

eli warto

ść

zwrócona przez wyra

ż

enie steruj

ą

ce nie jest

równa warto

ś

ci któregokolwiek z wyra

ż

e

ń

stałowarto

ś

ciowych,

zostanie wykonana instrukcja domyslna.



//p_45

# include <stdio.h>

# include <conio.h>

void main(void)

{

int day;

clrscr();

printf("Wpisz numer dnia z zakresu od 1 do 3\n");

day=getchar();

switch(day)

{

case '1':

printf("Dzie

ń

1\n");


case '2':

printf("Dzie

ń

2\n");


case '3':

printf("Dzie

ń

3\n");


default:

;

}

getch();

background image

59

}



Instrukcja break



//p_45p

# include <stdio.h>

# include <conio.h>

void main(void)

{

int day;

clrscr();

printf("Wpisz numer dnia z zakresu od 1 do 3\n");

day=getchar();

switch(day)

{

case '1':

printf("Dzie

ń

1\n");


break;

case '2':

printf("Dzien 2\n");

break;

case '3':

printf("Dzie

ń

3\n");


break;

default:

;

background image

60


}

getch();

}

//p_46

# include <stdio.h>

# include <conio.h>

void main(void)

{

int day;

clrscr();

printf("Wpisz numer dnia tygodnia od 1 do 7\n");

day=getchar();

switch(day)

{

case '1':

printf("Dzie

ń

1 - Niedziela\n");


break;

case '2':

printf("Dzie

ń

2 - Poniedziaˆek\n");


break;

case '3':

printf("Dzie

ń

3 - Wtorek\n");


break;

case '4':

printf("Dzie

ń

4 -

Ś

roda\n");

background image

61

break;

case '5':

printf("Dzie

ń

5 - Czwartek\n");


break;

case '6':

printf("Dzie

ń

6 - Pi

ą

tek\n");


break;

case '7':

printf("Dzie

ń

7 - Sobota\n");


break;

default:

printf("Liczba spoza zakresu 1 - 7");

break;

}

getch();

}

Przerwanie p

ę

tli niesko

ń

czonej


for(;;)

{

instr1;

instr2;

......

}



while(1)

{

background image

62


instr1;

instr2;

......

}



//p_47

# include <stdio.h>

# include <conio.h>

void main(void)

{

int c;

clrscr();

printf("Wpisz znak:\n");

printf("x + <Enter> = Koniec programu\n");

while (1)

{

c=getc(stdin);

if(c=='x')

break;

}

printf("Program zostaˆ przerwany - Koniec \n");

getch();

}



Instrukcja continue

background image

63

Czasem zamist przerywa

ć

p

ę

tl

ę

, trzeba tylko pomin

ąć

pewn

ą

grup

ę

instrukcji, ale p

ę

tla powinna wykonywa

ć

si

ę

dalej.


Instrukcja continue powoduje natychmiastowy skok na pocz

ą

tek

p

ę

tli i poj

ę

cie próby ponownego wykonania p

ę

tli od pocz

ą

tku.


//p_48

# include <stdio.h>

# include <conio.h>

void main(void)

{

int i,sum;

clrscr();

sum=0;

for(i=1;i<8;i++)

{

if((i==3) || (i==5))

continue;

sum+=i;

}

printf("Suma liczb 1 2 3 4 6 i 7 wynosi: %d\n",sum);

getch();

}



Instrukcja goto

etykieta:

instrukcja1;

instrukcja2;

.........

background image

64


goto etykieta;

etykieta pokazuje w które miejsce w programie ma nastapi

ć

skok

po wykonaniu instrukcji goto;

etykieta wyst

ę

puje w dwóch miejscach:


1/ ze znakiem : w miejscu do którego nastepuje skok (etykietaJ

2/ po instrukcji goto (goto etykieta:)









Wska

ź

niki







adres w pami

ę

ci = zmienna = stała




warto

ść

lewostronna warto

ść

prawostronna


zmiennej zmiennej






deklaracja nadaje zmiennej warto

ść

lewostronn

ą

przyporz

ą

dkowuj

ą

c jej adres w pami

ę

ci;



int x;


podstawienie nadaje zmiennej warto

ść

prawostronn

ą

– umiesza w

zarezerwowanym dla zmiennej obszarze pami

ę

ci dane;


background image

65

x=10;




Operator adresowy &


Operator adresowy zwraca warto

ść

lewostronn

ą

zmiennej



long int x,y;

y=&x;

przypisuje zmiennej y adres zmiennej x;













// p_49

# include <stdio.h># include <conio.h>void main(void){char
c;int x;float y;clrscr(); printf("c: adres=0x%p,
zawarto

ść

=%c\n",&c,c); printf("x: adres=0x%p,

zawarto

ś

c=%d\n",&x,x); printf("y: adres=0x%p,

zawarto

ś

c=%5.2f\n",&y,y);


c='A';

x=7;

y=123.45;

printf("c: adres=0x%p, zawarto

ść

=%c\n",&c,c);


printf("x: adres=0x%p, zawarto

ś

c=%d\n",&x,x);


printf("y: adres=0x%p, zawarto

ść

=%5.2f\n",&y,y);


getch();

background image

66

}



specyfikator formatu %p /’pointer’/ u

ż

ywany jest dla

wyprowadzania adresów zmiennych;


























Deklaracja wska

ź

ników



Wska

ź

nik to zmienna, w której przechowywany jest adres innej

zmiennej.


warto

ść

lewostronna warto

ść

prawostronna


wska

ż

nika to jego = wska

ź

nik = to adres innej zmiennej


adres





słu

ż

y do odwołania si

ę

background image

67

do samego wska

ź

nika





deklaracja wska

ż

nika



typ danych * nazwa_wska

ź

nika





typ danych , których adres operator jednoargumentowy

przechowywał b

ę

dzie wska

ź

nik
































// p_50

background image

68

# include <stdio.h># include <conio.h>void main(void){char
c,*ptr1;int x,*ptr2;float y,*ptr3;clrscr(); c='A'; x=7;
y=123.45; printf("c: adres=0x%p, zawarto

ść

=%c\n",&c,c);


printf("x: adres=0x%p, zawarto

ść

=%d\n",&x,x);


printf("y: adres=0x%p, zawarto

ść

=%5.2f\n",&y,y);


ptr1=&c;

printf("ptr_c adres=0x%p, zawiera=0x%p\n",&ptr1,ptr1);

printf("*ptr_c => %c\n",*ptr1);

ptr2=&x;

printf("ptr_x adres=0x%p, zawiera=0x%p\n",&ptr2,ptr2);

printf("*ptr_x => %d\n",*ptr2);

ptr3=&y;

printf("ptr_y adres=0x%p, zawiera=0x%p\n",&ptr3,ptr3);

printf("*ptr_y => %5.2f\n",*ptr3);

getch();

}





















background image

69










Operator dereferencji * /operator jednoargumentowy – unarny/

Poł

ą

czenie oparatora dereferencji * oraz nazwy wska

ź

nika

powoduje odwołanie do prawostronnej warto

ś

ci zmiennej

wskazywanej.

char c; - deklaracja zmiennej


char *ptrc; - deklaracja wska

ź

nika



ptrc=&c; - zainicjowanie wska

ź

nika





odwołanie do zmiennej c:


przez nazw

ę

c - bezpo

ś

rednie



przez *ptrc - posrednie ; przez wska

ź

nik



printf(”%c”,c) to samo co printf(”%c”,*ptrc)


int x=1234, *ptrx;

ptrx=&x;

printf(”%d”,(*ptrx+1)); à 1235




Wska

ż

nik pusty - to wska

ź

nik o prawostronnej warto

ś

ci = 0;



char *ptrc;

background image

70


int *ptrx;

ptrc=ptrx=0;

puste wska

ź

niki












Modyfikowanie zawarto

ś

ci zmiennej przez wska

ź

niki:



// p_51

# include <stdio.h># include <conio.h>void main(void){char
c,*ptr_c;clrscr(); c='A'; printf("c: adres=0x%p,
zawarto

ść

=%c\n",&c,c);


ptr_c=&c;

printf("ptr_c adres=0x%p, zawiera=0x%p\n",&ptr_c,ptr_c);

printf("*ptr_c => %c\n",*ptr_c);

*ptr_c='B';

printf("ptr_c adres=0x%p, zawiera=0x%p\n",&ptr_c,ptr_c);

printf("*ptr_c => %d\n",*ptr_c);

printf("c: adres=0x%p, zawiera=%c\n",&c,c);

getch();

}



Wskazanie tego samego adresu.


Ten sam adres w pami

ę

ci mo

ż

e by

ć

wskazywany przez wi

ę

cej ni

ż

jeden wska

ź

nik.

background image

71



char p1,p2;

char zmienna;

p1=&zmienna;

p2=&zmienna;

//p_52

# include <stdio.h># include <conio.h>void main(void){int
x;int *ptr_1,*ptr_2,*ptr_3;clrscr(); x=1234;

printf("x: adres=0x%p, zawarto˜†=%d\n",&x,x);

ptr_1=&x;

printf("ptr_1 adres=0x%p, zawiera=0x%p\n",&ptr_1,ptr_1);

printf("*ptr_1 => %d\n",*ptr_1);

ptr_2=&x;

printf("ptr_2 adres=0x%p, zawiera=0x%p\n",&ptr_2,ptr_2);

printf("*ptr_2 => %d\n",*ptr_2);

ptr_3=ptr_1;

printf("ptr_3 adres=0x%p, zawiera=0x%p\n",&ptr_3,ptr_3);

printf("ptr_3 => %d\n",*ptr_3);

getch();

}



Tablice


Zestaw danych tego samego typu, posiadaj

ą

cych podobne

przeznaczenie nazywany jest tablic

ą

.


Ka

ż

da zmienna wchodz

ą

ca w skł

ą

d tablicy nazywa si

ę

jej

elementem. Do wszystkich elementów tablicy mo

ż

na odwoływac si

ę

poprzez t

ę

sama nazw

ę

tablicy, zajmuj

ą

one poło

ż

one koło

siebie miejsca w pami

ę

ci.

background image

72


Deklaracja tablicy :

typ_danych nazwa_tablicy[rozmiar_tablicy];






wspólny typ identyfikator ilo

ść

elementów tablicy




np. tablica danych numerycznych 10-elementowa

int tab[10];



Indeksowanie elementów tablicy :

int tab[9];

element – 1 tab[0]

element - 2 tab[1]

..........

element - 9 tab[8]



wyra

ż

enia umieszczone w nawiasach umo

ż

liwiaj

ą

odwołanie do

elementów tablicy - s

ą

nazywane referencjami do elementów

tablicy;



Inicjowanie tablic

1/ przez referencje do elementów i operator podstawienia :


tab[6]=12;

2/ jednoczesnie :

int tab[5] = {2,4,3,66,1};

background image

73


//p_53

# include <stdio.h># include <conio.h>void main(void){int
i;int Tab[10];clrscr(); for(i=0;i<10;i++)

{

Tab[i]=i+1;

printf("Element tablicy Tab[%d] ma warto

ść

: %d. \n",i,Tab[i]);


}

getch();

}

Rozmiar tablicy


Obszar pami

ę

ci zajmowany przez tablic

ę

– adres jej pierwszego

i ostatniego elementu.


// p_54

# include <stdio.h># include <conio.h>void main(void){int
total;int list[10];clrscr(); total=sizeof(int)*10;
printf("Element typu int zajmuje %d - bajty \n",sizeof(int));

printf("Cała tablica zajmuje %d bajt˘w \n",total);

printf("Adres pierwszego elementu tablicy: 0x%x\n",&list[0]);

printf("Adres ostatniego elementu tablicy : 0x%x\n",&list[9]);

getch();

}

- operator adresowy & zwraca adres elementu tablicy

typ_danych nazwa_tablicy[rozmiar_tablicy];

Ilo

ść

bajtów zajmowanych przez tablic

ę

to :


sizeof(typ_danych) * rozmiar_tablicy

lub

background image

74

sizeof(nazwa_tablicy)





Wska

ź

nikowanie tablic


//p_55

# include <stdio.h># include <conio.h>void main(void){int
*ptr_int;int list_int[10];int i;clrscr(); for(i=0;i<10;i++)
list_int[i]=i+1; ptr_int=list_int; printf("Adres startowy
tablicy 0x%p\n",ptr_int);

printf("Warto

ść

pierwszego elementu tablicy %d\n",*ptr_int);


ptr_int=&list_int[0];

printf("Adres pierwszego elementu : 0x%p\n",ptr_int);

printf("Warto

ść

pierwszego elementu : %d\n",*ptr_int);


getch();

}
podstawienie pod wska

ź

nik adres pierwszego elementu tablicy


p_tab=&tab[0];
podstawienie pod wska

ź

nik nazwy tablicy;


p_tab=tab;
wykorzystanie nazwy tablicy jako adresu jej pierwszego
elementu





// p_55p

# include <stdio.h># include <conio.h>void main(void)

{

int *ptr_int;

int list_int[10];

int i;

background image

75

clrscr();

for(i=0;i<10;i++)

list_int[i]=i+1;

ptr_int=list_int;

printf("Adres startowy tablicy 0x%p\n",ptr_int);

printf("Warto

ść

pierwszego elementu tablicy %d\n",*ptr_int);


ptr_int=&list_int[0];

printf("Adres pierwszego elementu : 0x%p\n",ptr_int);

printf("Adres drugiego elementu : 0x%p\n",ptr_int+1);

printf("Warto

ść

pierwszego elementu : %d\n",*ptr_int);


printf("Warto

ść

drugiego elementu : %d\n",*(ptr_int+1));


getch();

}

Tablice znakowe

Tablice znakowe posiadaj

ą

elementy, z których ka

ż

dy zajmuje 1

bajt; zatem rozmiar tablicy jest jednocze

ś

nie obszarem w

bajtach zajmowanym przez tablic

ę

;


W j

ę

zyku C ła

ń

cuchy znaków (teksty) s

ą

okre

ś

lane jako

jednowymiarowe tablice znakowe, w których ostatni element to
tzw. znak zerowy, oznaczany symbolicznie ‘\0’ o kodzie ASCII =
0.



//p_56

# include <stdio.h>

# include <conio.h>

void main(void)

{

char tab_ch[7]={'W','i','t','a','j','!','\0'};

background image

76

int i;

clrscr();

for(i=0;i<7;i++)

printf("Tab_ch[%d] zawiera %c\n",i,tab_ch[i]);

// Metoda I

printf("Wszystkie elementy razem - metoda I: \n");

for(i=0;i<7;i++)

printf("%c",tab_ch[i]);

// Metoda II

printf("\nWszystkie elementy razem - metoda II: \n");

printf("%s\n",tab_ch);

getch();

}



Znak zerowy ‘\0’

Jest to pojedynczy znak specjalny okre

ś

laj

ą

cy koniec ła

ń

cucha

znakowego. Funkcja printf() przetwarzaj

ą

c ła

ń

cuch znaków w

formacie %s przetwarza znak po znaku, a

ż

do napotkania znaku

zerowego. Zank zerowy uto

ż

samiany z fałszem mo

ż

e by

ć

równie

ż

stosowany to testowania warto

ś

ci logicznej w p

ę

tlach

steruj

ą

cych.




//p_57

# include <stdio.h>

# include <conio.h>

void main(void)

{

char tab_ch[18]={'C',' ',

background image

77

't','o',' ',

'j','

ę

','z','y','k',' ',


'p','r','o','g','r','.','\0'};

int i;

clrscr();

for(i=0;tab_ch[i]!='\0';i++)

printf("%c",tab_ch[i]);

getch();

}



Tablice wielowymiarowe

typ_danych
nazwa_tablicy[rozmiar_tab1][rozmiar_tab2]....[rozm_tabN];

N - jest całkowite i dodatnie



tablica dwuwymiarowa 2 x 3 :

int tab [2][3];

inicjowanie :

tab[0][0] = 1;

tab[0][1] = 2;

tab[0][2] = 3;

tab[1][0]= 4;

tab[1][1] = 5;

tab[1][2] = 6;

lub

int tab[2][3] = {1,2,3,4,5,6};

background image

78

lub

int tab[2][3] = { {1,2,3},{4,5,6}};

/p_58

# include <stdio.h>

# include <conio.h>

void main(void)

{

int tab[3][5]={1,2,3,4,5,

10,20,30,40,50,

100,200,300,400,500};

int i,j;

clrscr();

for(i=0;i<3;i++)

{

printf("\n");

for(j=0;j<5;j++)

printf("%6d",tab[i][j]);

}

getch();

}

//p_59

# include <stdio.h>

# include <conio.h>

void main(void)

{

int tab[3][5]={1,2,3,4,5,10,20,30,40,50,100,200,300,400,500};

background image

79


int i,j;

clrscr();

for(i=0;i<3;i++)

{

printf("\n");

for(j=0;j<5;j++)

printf("%6d",tab[i][j]);

}

getch();

}

//p_60

# include <stdio.h>

# include <conio.h>

void main(void)

{

int
tab[3][5]={{1,2,3,4,5},{10,20,30,40,50},{100,200,300,400,500}}
;

int i,j;

clrscr();

for(i=0;i<3;i++)

{

printf("\n");

for(j=0;j<5;j++)

printf("%6d",tab[i][j]);

}

background image

80

getch();

}

//p_61

# include <stdio.h>

# include <conio.h>

void main(void)

{

int
tab[][5]={{1,2,3,4,5},{10,20,30,40,50},{100,200,300,400,500}};

int i,j;

clrscr();

for(i=0;i<3;i++)

{

printf("\n");

for(j=0;j<5;j++)

printf("%6d",tab[i][j]);

}

getch();

}







Tablice bezwymiarowe

Mo

ż

emy deklarowac tablic

ę

bez wpisywania jej rozmiaru w

nawiasach kwadratowych. Kompilator mo

ż

e sam obliczy

ć

rozmiar

tablicy je

ż

eli zadeklarowana zostanie jako bezwymiarowa,


int tab[] = {12,45,56,78,34,2,34,5,6,78,98};

background image

81

w przypadku tablic wielowymiarowych bez wymiaru mo

ż

na

pozostawi

ć

tylko jeden wymiar (pierwszy z lewej);


int tab_2[ ][4] = {

‘a’,’A’,

‘b’,’B’,

‘c’,’C’,

‘d’,’D’};



//p_62

# include <stdio.h>

# include <conio.h>

void main(void)

{

char tab_ch[]={'C',' ',

't','o',' ',

'j','

ę

','z','y','k','\0'};


int
tab[][5]={{1,2,3,4,5},{10,20,30,40,50},{100,200,300,400,500}};

clrscr();

printf("Rozmiar tablicy tab_ch[] wynosi %d
bajt˘w.\n",sizeof(tab_ch));

printf("Rozmiar tablicy tab[][5] wynosi %d
bajt˘w.\n",sizeof(tab));

getch();

}





background image

82










Ła

ń

cuchy znakowe



Ła

ń

cuch znakowy czyli string to tablica znakowa, której

ostatnim elementem jest znak ‘\0’.

Szereg znaków uj

ę

ty w cudzysłów (” ”) jest nazywany stał

ą

ła

ń

cuchow

ą

lub stał

ą

tekstow

ą

, kompilator mo

ż

e automatycznie

doda

ć

znacznik ko

ń

ca [\0].


char tab1[5] = {‘J’,’a’,’n’,’e’,’k’};

char tab2[6] = {‘J’,’a’,’n’,’e’,’k’,’\0’};

tab1 - jest traktowana jako tablica znakowa

tab2 - jest teraz tak

ż

e traktowana jako ła

ń

cuch znakowy

poniewa

ż

posiada znacznik ko

ń

ca ła

ń

cucha;


char tab3[6] = ”Janek”;

kompilator automatycznie doda znak ‘\0’;

inicjowanie tablicy przy pomocy stałej ła

ń

cuchowej oraz

inicjacja tab2 s

ą

równowa

ż

ne;




Stałe ła

ń

cuchowe i stałe znakowe


Stała ła

ń

cuchowa to szereg znaków uj

ę

tych w znak (” ”);


Stał

ą

znakowa to pojedynczy znak umieszczony w (‘ ’);


char znak = ‘x’;

char string = ”x”;

zadeklarowanie zmiennej znakowej znak powoduje zarezerwowanie
w pami

ę

ci 1 bajtu;

background image

83

zadeklarowanie zmiennej ła

ń

cuchowej string powoduje

zarezerwowanie 2 bajtów : dla znaku ‘x’ i dla znacznika ko

ń

ca

ła

ń

cucha;


Ła

ń

cuch znakowy jest traktowany jako wska

ź

nik do zmiennej typu

char (wskazuj

ą

cy pierwszy znak ła

ń

cucha).


Dlatego identyfikator ła

ń

cucha znakowego mo

ż

na przypisa

ć

wska

ź

nikowi wprost bez stosowania operatora adresowego;


char *ptr_str;

ptr_str = ”Ła

ń

cuch znakowy”;


Za

ś

stałej znakowej nie mo

ż

na w ten sposób przypisa

ć

:


char *ptr_str;

ptr_str = ‘x’; /operator przypisania próbuje przypisa

ć

prawostronna

warto

ść

(‘x’), natomiast wska

ź

nik oczekuje warto

ś

ci

lewostronnej (adresu)/

Natomiast prawidłowe jest :

char *ptr_str;

*ptr_str = ‘x’;



wykorzystanie wska

ź

nika do przypisania mu ła

ń

cucha znaków


// p_63

# include <stdio.h># include <conio.h>void main(void){char
str1[]={'S','t','a','ł','a',' ',
'ł','a','

ń

','c','u','c','h','o','w','a','\0'};char

str2[]="Druga stała ła

ń

cuchowa";char *ptr_str;


int i;

clrscr();

// wydruk str1

for(i=0;str1[i];i++) // str1[i]=='\0' - synonim fałszu

printf("%c",str1[i]);

background image

84

printf("\n");

// wydruk str2

for(i=0;str2[i];i++)

printf("%c",str2[i]);

printf("\n");

// przypisanie ła

ń

cucha do wska

ź

nika


ptr_str="Przypisanie ła

ń

cucha do wska

ź

nika";


for(i=0;*ptr_str;i++) à i jest zb

ę

dne


printf("%c",*ptr_str++);

getch();

}

Długo

ść

ła

ń

cucha znaków


Ile znaków zawiera ła

ń

cuch ?


Funkcja strlen()

#include <string.h>

size_t strlen(const char *s)










ilo

ś

c bajtów wska

ź

nik do ła

ń

cucha znaków


zajmowanych przez /identyfikator ła

ń

cucha/


ła

ń

cuch





background image

85

//p_64

# include <stdio.h># include <conio.h># include <string.h>void
main(void){char str1[]={'S','t','a','ł','a',' ',

'ł','a','

ń

','c','u','c','h','o','w','a','\0'};


char str2[]="Druga stała ła

ń

cuchowa";


char *ptr_str="Przypisanie ła

ń

cucha do wska

ź

nika";


clrscr();

printf("Długo

ść

str1 wynosi: %d bajt˘w\n",strlen(str1));


printf("Długo

ść

str2 wynosi: %d bajt˘w\n",strlen(str2));


printf("Długo

ść

ła

ń

cucha przypisanego wska

ź

nikowi: %d

bajt˘w\n",strlen(ptr_str));

getch();

}





Kopiowanie ła

ń

cuchów – strcpy()




#include <string.h>

char *strcpy(char *dest, const char *src);

src à dest

kopiowanie ła

ń

cuchów bez u

ż

ycia wska

ź

ników


// p_65

# include <stdio.h># include <conio.h># include <string.h>void
main(void)

{

char str1[]="Kopiowanie ła

ń

cuchów";


char str2[25];

background image

86

char str3[25];

int i;

clrscr();

// kopiowanie przy pomocy strcpy()

strcpy(str2,str1);

// kopiowanie bez uzycia strcpy()

for(i=0;str1[i];i++)

str3[i]=str1[i];

str3[i]='\0';

printf("Zawarto

ść

str2 : %s\n",str2);


printf("Zawarto

ść

str3 : %s\n",str3);


getch();

}

kopiowanie ła

ń

cuchów z wykorzystaniem wska

ź

ników


// p_65p

# include <stdio.h># include <conio.h># include <string.h>void
main(void){char str1[]="Kopiowanie ła

ń

cuchów";


char str2[25];

char str3[25];

int i;

clrscr();

// kopiowanie przy pomocy strcpy()

strcpy(str2,str1);

// kopiowanie bez uzycia strcpy()

for(i=0;*(str1+i);i++)

*(str3+i)=*(str1+i);

background image

87

*(str3+i)='\0';

printf("Zawarto

ść

str2 : %s\n",str2);


printf("Zawarto

ść

str3 : %s\n",str3);


getch();

}



Odczyt i zapis ła

ń

cuchów znakowych


gets() - odczyt ła

ń

cuchów tekstowych ze standardowego

strumienia wej

ś

ciowego stdin


#include <stdio.h>

char *gets(char *s);

s – identyfikator tablicy znakowej, w której przechowywane s

ą

znaki wczytane ze standardowego wej

ś

cia;


gets() ko

ń

czy swoje działanie po wczytaniu ze standardowego

wej

ś

cia znaku przej

ś

cia do nast

ę

pnej linii (naci

ś

ni

ę

cie

Entera), albo po wczytaniu EOF – (koniec pliku) . Funkcja
dodaje do tablicy znakowej znacznik ‘\0’ i zwraca wska

ź

nik do

tablicy s, do której zapisała znaki, lub wska

ź

nik pusty je

ś

li

operacja nie powiodła si

ę

.


puts() - zapis ł

ąń

cuchów tekstowych do standardowego

strumienia wyj

ś

ciowego stdout


#include <stdio.h>

char puts(const char *s)

s – tablica (lub wska

ź

nik) odwołuj

ą

ca si

ę

do ła

ń

cucha

znakowego, który ma zosta

ć

wysłany do standardowego strumienia

(urz

ą

dzenia) wyj

ś

ciowego.


Funkcja puts() likwiduje znacznik ko

ń

ca ła

ń

cucha tekstowego,

dodaj

ą

c w jego miejsce znak przej

ś

cia do nowego wiersza.






we wprowadzonym tek

ś

cie zamiana małych liter na du

ż

e – bez

wska

ź

ników

background image

88


//p_66

# include <stdio.h># include <conio.h># include <string.h>void
main(void){char str[80];int i;clrscr(); printf("Wprowad

ź

ła

ń

cuch do max. 80 znaków\n");


gets(str);

i=0;

while(str[i])

{

if((str[i]>=97)&&(str[i]<=122))

str[i]-=32;

i++;

}

printf("Wprowadzony tekst po zamianie małych liter na du

ż

e

\n");

puts(str);

getch();

}



we wprowadzonym tek

ś

cie zamiana małych liter na du

ż

e – ze

wska

ź

nikami


//p_66p



# include <stdio.h>

# include <conio.h>

# include <string.h>

void main(void)

{

background image

89

char str[80];

int i;

clrscr();

printf("Wprowad

ź

ła

ń

cuch do max. 80 znak˘w\n");


gets(str);

i=0;

while(*(str+i))

{

if((*(str+i)>=97)&&(*(str+i)<=122))

*(str+i)-=32;

i++;

}

printf("Wprowadzony tekst po zamianie małych liter na du

ż

e

\n");

puts(str);

getch();

}





Specyfikator %s w funkcji printf() à wydrukowanie na ekranie
ła

ń

cucha znakowego.




Funkcja scanf()

Podobnie jak printf() funkcja scanf() słu

ż

y do wczytywania

danych ró

ż

nego typu.


# include <stdio.h>

int scanf(const char *format,[adres,......]);

background image

90

w ła

ń

cuchu formatuj

ą

cym mog

ą

znale

źć

si

ę

wszystkie

specyfikatory formatu, w tym %s. Je

ż

eli działanie funkcji

scanf() jest poprawne funkcja zwraca liczb

ę

wczytanych

elementów (nie bajtów), ze strumienia stdin.

W przypadku bł

ę

du zwraca EOF.


U

ż

ycie specyfikatora formatu %s nakazuje funkcji scanf()

wczyta

ć

dane ze standardowego wej

ś

cia traktuj

ą

c je jako

ła

ń

cuch znaków. Wczytywanie danych przez funkcje scanf()

zostaje zako

ń

czone je

ż

eli w strumieniu znaków wej

ś

ciowych

pojawi si

ę

jeden z nastepuj

ą

cych znaków : spacja, znak nowego

wiersza, tabulator, tabulacja pionowa, FF – znak ko

ń

ca strony.

Znaki wczytywane przez funkcj

ę

s

ą

przechowywane w tablicy

znakowej, która musi zosta

ć

wskazana funkcji jako jej

argument. Tablica powinna by

ć

wystarczaj

ą

co du

ż

a aby pomie

ś

ci

ć

wszystkie wczytane znaki.

Po zako

ń

czeniu wczytania ła

ń

cucha znaków jako ostatni element

tablicy znakowej zostaje automatyczne dodany znacznik ‘\0’.



//p_67

# include <stdio.h># include <conio.h># include <string.h>void
main(void)

{

char str[80];

int i;

clrscr();

printf("Wprowad

ź

ła

ń

cuch do max. 80 znak˘w\n");


gets(str);

i=0;

while(str[i])

{

if((str[i]>=97)&&(str[i]<=122))

str[i]-=32;

i++;

background image

91


}

printf("Wprowadzony tekst po zamianie małych liter na du

ż

e

\n");

puts(str);

printf("\n%s",str);

getch();

}





//p_68

# include <stdio.h># include <conio.h># include <string.h>

void main(void){char str[80];int i;clrscr(); printf("Wprowad

ź

ła

ń

cuch do max. 80 znak˘w\n");// gets(str);


scanf("%s",&str);

i=0;

while(str[i])

{

if((str[i]>=97)&&(str[i]<=122))

str[i]-=32;

i++;

}

printf("Wprowadzony tekst po zamianie małych liter na du

ż

e

\n");

puts(str);

printf("\n%s",str);

getch();

}

background image

92




//p_69



# include <stdio.h># include <conio.h>

# include <string.h>

void main(void)

{

char str[80];

int x,y;

float z;

clrscr();

printf("Po wpisaniu danych dowolnego typu naci

ś

nij

<Enter>\n");

printf("Wpisz dwie liczby całkowite:\n");

scanf("%d %d",&x,&y);

printf("Wpisz liczb

ę

zmiennoprzecinkow

ą

: \n");


scanf("%f",&z);

printf("Wpisz ła

ń

cuch znaków: \n");


scanf("%s",str);

printf("Wpisałe

ś

nast

ę

puj

ą

ce dane: \n");


printf("%d %d\n%f\n%s\n",x,y,z,str);

getch();

}

Po napotkaniu spacji wczytywanie znaków funkcja scanf()
zostaje przerwane.

background image

93

Funkcja scanf nie wczytuje znaków z wej

ś

cia dopóki nie

zostanie naci

ś

niety klawisz ENTER ( do tego czasu znaki

znajduj

ą

si

ę

w buforze wej

ś

ciowym ).






Widoczno

ść

zmiennych



W zło

ż

onym programie mog

ą

by

ć

zmienne, z których korzystaj

ą

ż

ne funkcje, a z drugiej strony u

ż

ycie niektórych zmiennych

mo

ż

e ogranicza

ć

si

ę

tylko do pojedynczych funkcji. Oznacza to

ż

e widoczno

ść

i dost

ę

pno

ść

tych zmiennych mo

ż

e by

ć

ograniczona, a warto

ś

ci przypisane tym zmiennym mog

ą

by

ć

ukryte z punktu widzenia innych funkcji.

W j

ę

zyku C mo

ż

na deklaruj

ą

c zmienn

ą

okre

ś

li

ć

zakres jej

dost

ę

pno

ś

ci i widoczno

ś

ci. Zmienne dost

ę

pne tylko lokalnie s

ą

dost

ę

pne tylko wewn

ą

trz tego bloku programu , w którym zostały

zadeklarowane.

Zmienne lokalne /blokowe/

Zmienna zadeklarowana wewnatrz bloku programu ma zasi

ę

g

blokowy. Jest ona dostepna od miejsca zadeklarowania do ko

ń

ca

bloku w którym zastała zadeklarowana. Takie zmienne nazywaj

ą

si

ę

lokalnymi lub blokowymi.




//p_70

# include <stdio.h># include <conio.h># include <string.h>

void main(void)

{

int i=32;

clrscr();

printf("W bloku zewnetrznym i=%d\n",i);

{

int i,j;

printf("W bloku wewn

ę

trznym \n");

background image

94


for (i=0,j=10;i<=10;i++,j--)

printf("i=%2d, j=%2d\n",i,j);

}

printf("Znowu w bloku zewn

ę

trznym: i=%d\n",i);


getch();

}

P

ę

tla for modyfikuje i wyprowadza warto

ś

ci zmiennych lokalnych

bloku wewn

ę

trznego, jednak

ż

e po zako

ń

czeniu i wyj

ś

ciu z tego

bloku lokalna zmienna i (wewn

ę

trzna) przestaje by

ć

dost

ę

pna.

Ponownie widoczna jest zewn

ę

trzna zmienna i, która nie uległa

zmianie. Dzi

ę

ki umiej

ę

tno

ś

ci ograniczania zakresu dost

ę

pno

ś

ci

zmiennych , nie nast

ą

piło ani nadpisanie warto

ś

ci ani

konflikt.

Zmienne widoczne w obr

ę

bie funkcji


Zmienne wewn

ę

trzne funkcji to takie zmienne, które s

ą

dost

ę

pne

i aktywne tylko pomi

ę

dzy pocz

ą

tkiem a ko

ń

cem danej funkcji.


W j

ę

zyku C tylko goto label ma taki zasi

ę

g. Je

ż

eli etykieta

przyporz

ą

dkowana instrukcji goto jako docelowy adres skoku

b

ę

dzie nazywa

ć

si

ę

start, to w obrebie funkcji main() jest

widoczna i dostepna z dowolnego punktu, czyli jej adres
widoczno

ś

ci to cała funkcja


int main()

{

int i;

....

start:

.....

goto start;

.....

return 0;

}

background image

95


Etykieta start jest widoczna od poczatku do konca funkcji
main(), dlatego w obr

ę

bie funkcji main() nie mo

ż

e wystapi

ć

druga etykieta o nazwie start: (natomiast zmienne i mog

ą

wyst

ę

powa

ć

lokalnie wewn

ą

trz zagnie

ż

d

ż

onych bloków).




Zmienne widoczne w całym programie

Je

ż

eli zmienna została zadeklarowana przed funkcj

ą

main() to

jej zasi

ę

giem widoczno

ś

ci jest cały program. Zmienne takie

nazywaj

ą

si

ę

zmiennymi globalnymi.




int a = 0;

float b = 2.0;

int main()

{

int i;

return 0;

}

//p_71

# include <stdio.h># include <conio.h># include <string.h>//
deklaracje zmiennych globalnychint x=1234;double
y=1.234567;void fun_1(){ printf("Wewn

ą

trz funkcji \n x=%d,

y=%f\n",x,y);

}

void main(void)

{

int x=4321;

clrscr();

fun_1();

printf("Blok główny funkcji main() \n x=%d, y=%f\n",x,y);

background image

96

{

double y=7.654321;

fun_1();

printf("Blok zagnie

ż

dzony funkcji main() \n x=%d,

y=%f\n",x,y);

}

getch();

}

Z wn

ę

trza funkcji widoczne s

ą

zmienne globalne.


Deklaracja lokalnej zmiennej x przysłania zmienn

ą

globalna w

obr

ę

bie bloku funkcji.






Specyfikatory i modyfikatory klasy pami

ę

ci


W j

ę

zyku C s

ą

cztery specyfikatory i dwa modyfikatory, które

mog

ą

by

ć

u

ż

ywane do okre

ś

lania czasu

ż

ycia zmiennej.


Specyfikator auto

Specyfikator auto okre

ś

la,

ż

e lokalizacja zmiennej w pami

ę

ci

jest tymczasowa tzn. kiedy zmienna przestanie by

ć

widoczna i

dost

ę

pna w programie, zmienna mo

ż

e zosta

ć

przemieszczona w

inne miejsce w programie albo skasowana.


Tylko zmienne o lokalnym zakresie dost

ę

pno

ś

ci mog

ą

by

ć

deklarowane jako zmienne auto. Auto jest rzadko u

ż

ywanym

słowem kluczowym, poniewa

ż

zmienne o blokowym zakresie

dostepno

ś

ci, s

ą

w sposób domy

ś

lny traktowane jako tymczasowe

(auto).




Specyfikator static

Specyfikator static (zmienna statyczna) mo

ż

e by

ć

stosowany

wobec zmiennych dost

ę

pnych w zakresie bloku lub w zakresie

programu. Je

ż

eli zmienna wewn

ą

trz funkcji zostanie

background image

97

zadeklarowana jako statyczna istnieje ona w sposób ci

ą

gły w

czasie. Miejsce w pami

ę

ci przeznaczona dla przechowywania tej

zmiennej nie podlega likwidacji, gdy zmienna ta wyjdzie poza
zakres swojej widoczno

ś

ci (warto

ść

zmiennej jest przechowywana

dalej pod tym samym adresem, mimo

ż

e jest niewidoczna). Po

powrocie przez program do zakresu widoczno

ś

ci zmiennej nadal

znajduje si

ę

tam jej ostatnio zapisana warto

ść

.


//p_72

# include <stdio.h># include <conio.h>int sumuj(int x,int
y){static int licznik=1;printf("Wywołanie funkcji, stan
licznika : %d, \n",licznik++);

return(x+y);

}

int main(void)

{

int i,j;

clrscr();

for(i=0,j=5;i<5;i++,j--)

printf("dodawanie liczb: %d oraz %d suma: %d.
\n",i,j,sumuj(i,j));

getch();

}

//p_73

# include <stdio.h># include <conio.h>int sumuj(int x,int
y){int licznik=1;

printf("Wywołanie funkcji, stan licznika : %d, \n",licznik++);

return(x+y);

}

int main(void)

{

int i,j;

background image

98


clrscr();

for(i=0,j=5;i<5;i++,j--)

printf("dodawanie liczb: %d oraz %d suma: %d.
\n",i,j,sumuj(i,j));

getch();

}

//p_74

# include <stdio.h>

# include <conio.h>

int sumuj(int x,int y)

{

static int licznik=1;

printf("Wywołanie funkcji, stan licznika : %d, \n",++licznik);

return(x+y);

}

int main(void)

{

int i,j;

clrscr();

for(i=0,j=5;i<5;i++,j--)

printf("dodawanie liczb: %d oraz %d suma: %d.
\n",i,j,sumuj(i,j));

getch();

}




background image

99



Zakresy dost

ę

pno

ś

ci :


zasi

ę

g blokowy

zasi

ę

g w obr

ę

bie funkcji

zasi

ę

g w obr

ę

bie programu

zasi

ę

g w obrebie pliku


W j

ę

zyku C zmienna globalna zadeklarowana jako static jest

nazywana zmienn

ą

o zasi

ę

gu obejmuj

ą

cym cały plik. Jest ona

dost

ę

pna od punktu zadeklarowania a

ż

do ko

ń

ca pliku. Słowo

plik oznacza

ź

ródłowy plik programu, czyli plik tekstowy

zawieraj

ą

cy tekst programu. ( Wi

ę

kszo

ść

du

ż

ych programów

składa si

ę

z wielu plików

ź

ródłowych)



int x = 0;

static int y = 0;

static float z = 0.0;

int main()

{

int i;

...

...

return 0;

}



Zasi

ę

g programu --------------------à


Zasi

ę

g pliku --------------à


Zasi

ę

g funkcji --------à


Zasi

ę

g blokowy -----à




Specyfikator register

background image

100

Ka

ż

dy komputer ma pewn

ą

ilo

ść

rejestrów do przechowywania

danych i wykonywania operacji arytmetycznych i logicznych.
Poniewa

ż

rejestry s

ą

umieszczone w pami

ę

ci procesora zatem

dost

ę

p do nich jest du

ż

o szybszy ni

ż

do pami

ę

ci RAM gdzie

znajduj

ą

si

ę

zmienne programu. Aby przy

ś

pieszy

ć

dost

ę

p do

pewnych zmiennych mo

ż

emy je umie

ś

ci

ć

bezpo

ś

rednio w pami

ę

ci

procesora, czyli w rejestrze.


Kompilator mo

ż

e zignorowa

ć

tak

ą

sugesti

ę

, je

ż

eli nie ma

dostepnego rejestru, b

ą

d

ź

inne ograniczenia uniemo

ż

liwiaj

ą

mu

takie postepowanie.


Pobranie adresu zmiennej zadeklarowanej jako rejestrowa jest
nielegalne.


int main()

{

register int i;

for (i=0;i<max;i++)

{

......

}

return 0;

}

Specyfikator extern

Zmienna globalna widoczna jest we wszystkich plikach

ź

ródłowych tworz

ą

cych program. Jak zmienna zadeklarowana jako

globalna w jednym pliku dyskowym (A) mo

ż

e by

ć

widoczna i

dost

ę

pna w innym pliku dyskowym (B). Sk

ą

d kompilator ma

wiedzie

ć

,

ż

e w pliku B chodzi o t

ę

sam

ą

zmienn

ą

, która została

zadeklarowana jako globalna w pliku A.


Aby w pliku B odwoła

ć

si

ę

do zmiennych globalnych

zadeklarowanych w A, nale

ż

y w pliku B zadeklarowa

ć

te zmienne

jako zmienne zewn

ę

trzne, u

ż

ywaj

ą

c specyfikatora extern.


plik A

background image

101


int a,b;

int main()

{

return 0;

}



plik B

int c;

extern int a;

int main()

{

extern int b;

int i;

return 0;

}

Zasady deklarowania i odwoływania si

ę

do zmiennych

zewn

ę

trznych :


Deklaruj

ą

c zmienna globaln

ą

:

pomin

ąć

słowo extern

zainicjowa

ć

zmienn

ą

przy deklaracji


Kiedy w innym pliku odwołujemy si

ę

do tej zmiennej:

u

ż

y

ć

słowa extern

nie inicjowa

ć

zmiennej w deklaracji




Modyfikatory sposobów odwoływania si

ę

do zmiennych.


Modyfikator const

Je

ż

eli zmienna zostanie zadeklarowana z u

ż

yciem modyfikatora

const, po jednorazowym zainicjowaniu jej warto

ść

nie mo

ż

e

zosta

ć

zmieniona.

background image

102


const double pi = 3.141593;

const char str[ ] = ”Tablica znakowa”;

str[0] = ‘x’; à bł

ą

d


Modyfikator volatile - dane ulotne

Zmienn

ą

której warto

ść

mo

ż

e by

ć

zmieniana w trakcie programu

bez stosowania operacji przypisania nale

ż

y zadeklarowa

ć

jako

ulotn

ą

– volatile.


Mo

ż

na np. zadeklarowa

ć

zmienn

ą

globalna do zapami

ę

tania znaku

wprowadzanego przez uzytkownika z klawiatury. W procesie
optymalizacji kodu kompilator mo

ż

e t

ą

zmienna potraktowa

ć

tak

jak inne zmienne , których warto

ś

ci ustalane s

ą

operacjami

podstawienia. Zadeklarowanie jej jako ulotn

ą

zabezpieczy j

ą

przed tym procesem i jej zmiana warto

ś

ci b

ę

dzie mo

ż

liwa

jedenie poprzez wprowadzenie nowego znaku z klawiatury.

void read_keyboard()

{

volatile char keyboard_ch;

.......

}



Funkcje


Deklaracja a definicja funkcji

Deklaracja zmiennej lub funkcji okre

ś

la interpretacj

ę

i

atrybuty zestawu identyfikatorów;


Definicja wymaga od kompilatora zarezerwowania pami

ę

ci dla

zmiennej lub funkcji okre

ś

lonej danym identyfikatorem;



Deklaracja zmiennej jest jej definicj

ą

.


Deklaracja funkcji nie stanowi jej definicji. Deklaracja
funkcji odwołuje si

ę

do jej definicji (znajduj

ą

cej si

ę

w innym

background image

103

miejscu), okre

ś

la natomiast jakiego typu warto

ść

zostanie

zwrócona przez funkcj

ę

.



Definicja funkcji okre

ś

la co ta funkcja robi, podaj

ą

c

jednocze

ś

nie liczb

ę

i typy argumentów przekazywanych do

funkcji.

Zadeklarowanie funkcji nie jest równoznaczne z jej definicj

ą

.

Je

ż

eli definicja funkcji jest umieszczona przed miejscem

pierwszego wywołania funkcji, to nie musimy funkcji wcze

ś

niej

deklarowa

ć

. W przeciwnym razie musimy przed pierwszym

wywołaniem funkcji umie

ś

ci

ć

jej deklaracj

ę

.



Typ warto

ś

ci zwracanej przez funkcj

ę

.


Funkcja mo

ż

e by

ć

zadeklarowana i zwraca

ć

dane dowolnego typu

(za wyj

ą

tkiem tablicy i funkcji). Instrukcja return z

definicji funkcji zwraca jedn

ą

warto

ść

, którejm typ powinien

by

ć

zgodny z typem zadeklarowanym przed nazw

ą

funkcji.


Domy

ś

lnym typem jest typ int.



specyfikator_typu_danych nazwa_funkcji();



Prototyp funkcji

Deklaracja funkcji zawiera tak

ż

e liczb

ę

i typy argumentów

przekazywanych do funkcji.

Liczba i typ argumentów funkcji nazywa si

ę

prototypem funkcji.





Ogólna forma deklaracji:

spec_typu_danych nazwa_funkcji ( spec_typ_danych argument1,

spec_typ_danych argument2,

spec_typ_danych argument3,

..................................................);

nazwy : argument1, argument2 itd. s

ą

opcjonalne

background image

104

Wywołanie funkcji

Po wywołaniu funkcji wykonanie programu przenosi si

ę

do kodu

funkcji, a

ż

do zako

ń

czenia jego wykonania. Po powrocie z

funkcji i ewentualnym zwrocie warto

ś

ci , wykonanie programu

jest podejmowane pocz

ą

wszy od nastepnej intrukcji nastepuj

ą

cej

po wywołaniu funkcji.

Wywołanie funkcji to wyra

ż

enie, które mo

ż

e by

ć

u

ż

ywane jako

samodzielna instrukcja, lub jako element wewn

ą

trz innych

wyra

ż

e

ń

.


//p_75

# include <stdio.h># include <conio.h>int funkcja1(int x,int
y);double funkcja2(double x,double y){printf("Jeste

ś

my w

funkcji2\n");return (x-y);}void main(void){int x1=80;int
y1=10;double x2=100.123456;

double y2=10.123456;

clrscr();

printf("Wywołanie funkcja1(%d,%d).\n",x1,y1);

printf("Funkcja1 zwraca : %d. \n",funkcja1(x1,y1));

printf("Wywołanie funkcja2(%f,%f).\n",x2,y2);

printf("Funkcja2 zwraca : %f.\n",funkcja2(x2,y2));

getch();

}

int funkcja1(int x,int y)

{

printf("Jeste

ś

my w funkcji1.\n");


return(x+y);

}






background image

105



Prototypy funkcji :

1/ Funkcja przy wywołaniu nie pobiera

ż

adnych argumentów –


bezargumantowa;

2/ Funkcja pobiera stał

ą

okre

ś

lon

ą

liczb

ę

argumentów;


3/ Funkcja pobiera zmienn

ą

liczb

ę

argumentów;




Funkcje bezargumentowe

int c;

c = getchar();

deklaracja: int getchar(void);

Dla wszystkich funkcji bezargumentowych w ich deklaracji
(prototypie) stosowany jest typ danych void.


//p_76

#include <stdio.h>#include <conio.h>#include <time.h>void
data_czas(void);main(){ printf("Przed wywołaniem \n");
data_czas(); printf("Po wywołaniu \n"); return 0;}void
data_czas(void){time_t t; printf("Wewn

ą

trz funkcji data_czas()

\n");

time(&t);

printf("Aktualna data i czas : %s",asctime(localtime(&t)));

getch();

}



Funkcja data_czas() wykorzystuje zmienna t typu time_t i
posługuje si

ę

funkcjami bibliotecznymi zadeklarowanymi w pliku

nagłówkowym time.h tj. time(), localtime(), asctime();

Funkcje czasowe daj

ą

nam 3 rodzaje czasów :

background image

106

1/ czas kalendarzowy – czas bie

żą

cy w oparciu o kalendarz

gregoria

ń

ski


2/ czas lokalny – czas kalendarzowy w okre

ś

lonej strefie

czasowej

3/ czas zimowy/letni – czas strefowy z uwzgl

ę

dnieniem

przesuni

ę

cia zimowego/letniego.




Funkcja time() zwraca czas kalendarzowy

#include <time.h>

time_t time(time_t *timer);

time_t - tzw. typ arytmetyczny, stosowany da zapisu czasu

timer - zmienna typu wska

ź

nik wskazuj

ą

ca miejsce w pami

ę

ci, w

którym powinny zosta

ć

zapisane dane dotycz

ą

ce daty i czasu

zwracane przez funkcje;

Je

ż

eli dane dotycz

ą

ce czasu kalendarzowego s

ą

niemo

ż

liwe do

odczytania na danym komputerze to funkcja zwraca –1.



Funkcja localtime() zwraca czas lokalny po przekształceniu
czasu kalendarzowego

#include <time.h>

struct tm *localtime(const time_t *timer);

tm - struktura danych, zawieraj

ą

ca składniki czasu

kalendarzowego

timer - wska

ź

nik do adresu pami

ę

ci, gdzie przechowywany jest

czas kalendarzowy zwrócony wcze

ś

niej przez funkcje time();


aby przekształci

ć

dane dotycz

ą

ce daty i czasu w strukturze tm

w ła

ń

cuch znaków nale

ż

y wywoła

ć

funkcje asctime();


#include <time.h>

char *acstime(const strunct tm *timeptr)

timeprt - wska

ź

nik odwołuj

ą

cy si

ę

do struktury tm zwróconej

przez funkcje localtime();

background image

107



Funkcje o stałej liczbie argumentów

int function_1(int x, int y);

Deklaruj

ą

c funkcj

ę

o stałej liczbie argumentów, nale

ż

y poda

ć

typy wszystkich argumentów (zalecane jest równie

ż

podanie ich

nazw);



Funkcje o zmiennej liczbie argumentów

np. printf()

int printf(const char *format , argument1,argument2,.....);

wielokropek jest oznaczeniem dla kompilatora C ,

ż

e ilo

ść

argumentów funkcji mo

ż

e by

ć

zmienna;


typ_danych nazwa_funkcji(typ_danych arg1,...);

wielokropek oznacza tu pozastałe argumenty, które nie zostały
wymienione na li

ś

cie argumentów;


printf(const char * format,...);

W pliku stdarg.h zadeklarowane zostały trzy podprogramy, które
pozwalaj

ą

na tworzenie i obsług

ę

funkcji o zmiennej liczbie

argumentów :


va_start()

va_arg()

va_end()

Aby zainicjowa

ć

tablic

ę

, która jest niezb

ę

dna do działania

makrorozkazów va_arg() oraz va_end() nale

ż

y zawsze najpierw

wywoła

ć

makro va_start().


Plik nagłówkowy stdarg.h zawiera tak

ż

e typ danych va_list,

który okre

ś

la typ tablicy odpowiedni do przechowywania danych

potrzebnych do działania makropolece

ń

va_start() , va_arg() ,

va_end() .


#include <stdarg.h>

background image

108

void va_start(va_list tab, lastfix);

tab - inicjowana tym poleceniem tablica

lastfix - okre

ś

la ostatni argument funkcji przed wielokropkiem

w

deklaracji

Poprzez u

ż

ycie makropolecenia va_arg() mo

ż

na obsługiwa

ć

wyra

ż

enia okre

ś

lajace typ i warto

ść

nastepnego argumentu

funkcji. Makro va_arg() mo

ż

e by

ć

u

ż

yte do pobrania kolejnego

argumentu przekazywanego do funkcji,

#include <stdarg.h>

typ_danych va_arg()(va_list tab, typ_danych);

tab - tablica zainicjowana w momencie działania makra
va_start()

typ_danych - typ danych argumentu przesłanego do funkcji

Aby zapewni

ć

normalny i poprawny zwrot warto

ś

ci przez funkcj

ę

o zmiennej liczbie argumentów, nale

ż

y zastosowa

ć

makro

va_end(), po tym jak wszystkie argumenty zostan

ą

przetworzone.


#include (stdarg.h>

void va_end(va_list tab);

//p_76_0

/* Funkcja ze zmienn

ą

liczb

ą

argumentów */#include

<stdio.h>#include <stdarg.h>double AddDouble(int x, ...);main
(){ double d1 = 1.5; double d2 = 2.5; double d3 = 3.5; double
d4 = 4.5;

printf("Wprowadzony argument: %2.1f\n", d1);

printf("Wynik zwrócony przez AddDouble() jest: %2.1f\n\n",

AddDouble(1, d1));

printf("Wprowadzone argumenty: %2.1f and %2.1f\n", d1, d2);

printf("Wynik zwrócony przez AddDouble() jest: %2.1f\n\n",

AddDouble(2, d1, d2));

background image

109

printf("Wprowadzone argumenty: %2.1f, %2.1f and %2.1f\n", d1,
d2, d3);

printf("Wynik zwrócony przez AddDouble() jest: %2.1f\n\n",

AddDouble(3, d1, d2, d3));

printf("Wprowadzone argumenty: %2.1f, %2.1f, %2.1f, and
%2.1f\n", d1, d2, d3, d4);

printf("Wynik zwrócony przez AddDouble() jest: %2.1f\n",

AddDouble(4, d1, d2, d3, d4));

return 0;

}

double AddDouble(int x, ...)

{

va_list arglist;

int i;

double result = 0.0;

printf("Liczba argumentów jest: %d\n", x);

va_start (arglist, x);

for (i=0; i<x; i++)

result += va_arg(arglist, double);

va_end (arglist);

return result;

}





Zastosowania wska

ź

ników




background image

110


Arytmetyka wska

ź

ników


Skalarny wymiar wska

ź

nika


spec_typu_danych *nazwa_wsk;

nazwa_wsk + n

oznacza w bajtach

nazwa_wsk + n * sizeof(spec_typu_danych);



//p_76_1

/* arytmetyka wska

ź

ników */


#include <stdio.h>

#include <conio.h>

main()

{

char *ptr_ch;

int *ptr_int;

double *ptr_db;

clrscr();

/* char wsk. ptr_ch */

printf("Warto

ść

ptr_ch: 0x%p\n", ptr_ch);


printf(" ptr_ch + 1: 0x%p\n", ptr_ch + 1);

printf(" ptr_ch + 2: 0x%p\n", ptr_ch + 2);

printf(" ptr_ch - 1: 0x%p\n", ptr_ch - 1);

printf(" ptr_ch - 2: 0x%p\n", ptr_ch - 2);

/* int wsk. ptr_int */

printf("Warto

ść

ptr_int: 0x%p\n", ptr_int);

background image

111

printf(" ptr_int + 1: 0x%p\n", ptr_int + 1);

printf(" ptr_int + 2: 0x%p\n", ptr_int + 2);

printf(" ptr_int - 1: 0x%p\n", ptr_int - 1);

printf(" ptr_int - 2: 0x%p\n", ptr_int - 2);

/* double wsk ptr_db */

printf("Warto

ść

ptr_db: 0x%p\n", ptr_db);


printf(" ptr_db + 1: 0x%p\n", ptr_db + 1);

printf(" ptr_db + 2: 0x%p\n", ptr_db + 2);

printf(" ptr_db - 1: 0x%p\n", ptr_db - 1);

printf(" ptr_db - 2: 0x%p\n", ptr_db - 2);

getch();

return 0;

}



Odejmowanie wska

ź

ników


typy odejmowanych wska

ź

ników musz

ą

by

ć

takie same;




// p_76_2

/* odejmowanie wska

ź

ników */


#include <stdio.h>

#include <conio.h>

main()

{

int *ptr_int1, *ptr_int2;

clrscr();

printf(" ptr_int1: 0x%p\n", ptr_int1);

background image

112


ptr_int2 = ptr_int1 + 5;

printf(" ptr_int2 = ptr_int1 + 5: 0x%p\n", ptr_int2);

printf(" ptr_int2 - ptr_int1: %d\n", ptr_int2 - ptr_int1);

ptr_int2 = ptr_int1 - 5;

printf(" ptr_int2 = ptr_int1 - 5: 0x%p\n", ptr_int2);

printf(" ptr_int2 - ptr_int1: %d\n", ptr_int2 - ptr_int1);

getch();

return 0;

}





Dost

ę

p do tablic i elementów tablic za pomoc

ą

wska

ź

ników:

nazwa tablicy jest wska

ź

nikiem do jej 1 elementu;

dodanie liczby całkowitej do nazwy tablicy jest dost

ę

pem do

jej elementu o indeksie równym liczbie całkowitej





// p_76_3

/* dostep do tablic i elementów tablic za pomoc

ą

wska

ź

ników */


#include <stdio.h>

#include <conio.h>

main()

{

char str[] = "It's a string!";

char *ptr_str;

int list[] = {1, 2, 3, 4, 5};

int *ptr_int;

background image

113



/* dost

ę

p do tablicy znaków */


clrscr();

ptr_str = str;

printf("Przed zmian

ą

str : %s\n", str);


printf("Przed zmian

ą

str[5] : %c\n", str[5]);


*(ptr_str + 5) = 'A';

printf("Po zmianie, str[5] : %c\n", str[5]);

printf("Po zmianie, str : %s\n", str);

/* dostep do tablicy liczb */

ptr_int = list;

printf("Przed zmian

ą

, list[2] : %d\n", list[2]);


*(ptr_int + 2) = -3;

printf("Po zmianie, list[2] : %d\n", list[2]);

getch();

return 0;

}







Przekazywanie tablicy jako argumentu do funkcji

jest metoda na proste przekazanie wi

ę

kszej ilo

ś

ci argumentów

do funkcji

//p_76_4

/* przekazywanie tablicy jako argumentu do funkcji */#include
<stdio.h>#include <conio.h>int AddThree(int list[]);main(){
int sum, list[3]; clrscr(); printf("Wprowad« 3 liczby :\n");

background image

114

scanf("%d%d%d", &list[0], &list[1], &list[2]);

sum = AddThree(list);

printf("Ich suma wynosi : %d\n", sum);

getch();

return 0;

}

int AddThree(int list[])

{

int i;

int result = 0;


for (i=0; i<3; i++)

result += list[i];

return result;

}





Przekazywanie wska

ź

ników jako argumentów do funkcji


Nazwa tablicy po której nie nast

ę

puje indeks jest wska

ź

nikiem

do pierwszego elementu. Zatem adres do pierwszego elementu
tablicy b

ę

d

ą

cy wska

ź

nikiem mo

ż

e by

ć

przekazany do funkcji tak

jak tablica.

//p_76_5

/* przekazywanie wska

ź

ników jako argumentów do funkcji

*/#include <stdio.h>#include <conio.h>void ChPrint(char
*ch);int DataAdd(int *list, int max);

main()

{

char str[] = "It's a string!";

background image

115


char *ptr_str;

int list[5] = {1, 2, 3, 4, 5};

int *ptr_int;


/* przypisanie adresu do wska

ź

nika */


clrscr();

ptr_str = str;

ChPrint(ptr_str);

ChPrint(str);

/* przypisanie adresu do wska

ź

nika */


ptr_int = list;

printf("The sum returned by DataAdd(): %d\n",

DataAdd(ptr_int, 5));

printf("The sum returned by DataAdd(): %d\n",

DataAdd(list, 5));

getch();

return 0;

}

void ChPrint(char *ch)

{

printf("%s\n", ch);

}

int DataAdd(int *list, int max)

{

int i;

int sum = 0;

background image

116



for (i=0; i<max; i++)

sum += list[i];

return sum;

}
tablice znakowe i liczbowe przekazywane s

ą

do funkcji

wska

ź

nikiem


poprzez:

ptr = n_tablicy

lub

n_tablicy





Przekazywanie tablic wielowymiarowych do funkcji

Mo

ż

na przekaza

ć

nazw

ę

tablicy lub wska

ź

nik zawieraj

ą

cy adres

startowy tablicy wielowymiarowej.

//p_76_6

/* przekazywanie tablic wielowymiarowych jako argumentów do
funkcji */#include <stdio.h>#include <conio.h>/* deklaracje
funkcji */

int DataAdd1(int list[][5], int max1, int max2);

int DataAdd2(int *list, int max1, int max2);

/* funkcja main() */

main()

{

int list[2][5] = {1, 2, 3, 4, 5,

5, 4, 3, 2, 1};

int *ptr_int;

background image

117

clrscr();

printf("Suma otrzymana przez DataAdd1(): %d\n",

DataAdd1(list, 2, 5));

ptr_int = &list[0][0];

printf("Suma otrzymana przez DataAdd2(): %d\n",

DataAdd2(ptr_int, 2, 5));

getch();

return 0;

}

/* definicja funkcji Data Add1 */

int DataAdd1(int list[][5], int max1, int max2)

{

int i, j;

int sum = 0;


for (i=0; i<max1; i++)

for (j=0; j<max2; j++)

sum += list[i][j];

return sum;

}

/* definicja funkcji DataAdd2 */

int DataAdd2(int *list, int max1, int max2)

{

int i, j;

int sum = 0;


for (i=0; i<max1; i++)

background image

118


for (j=0; j<max2; j++)

sum += *(list + i*max2 + j);

return sum;

}
do funkcji przekazywana jest tablica

Add1 à przez warto

ść

/nazw

ę

/


Add2 à przez wska

ź

nik


W przykładach p_76_4 do p_76_6 deklaracje wymiaru tablic w
programie głównym i w funkcjach.





Tablice wska

ź

ników


deklaracja tablicy wska

ź

ników


int *ptr_int[5];



//p_76_7

/* Tablice wska

ź

ników */#include <stdio.h>#include <conio.h>/*

deklaracje funkcji */

void StrPrint1(char **str1, int size);

void StrPrint2(char *str2);

/* funkcja main() */

main()

{

char *str[4] = {"To jest zdanie 1;",

"To jest zdanie 2;",

"To jest zdanie 3;",

"To jest zdanie 4.\n"

background image

119


};

int i, size;

clrscr();

size = 4;

StrPrint1(str, size);

for (i=0; i<4; i++)

StrPrint2(str[i]);

getch();

return 0;

}

/* definicja funkcji */

void StrPrint1(char **str1, int size)

{

int i;


for (i=0; i<size; i++)

printf("%s\n", str1[i]);

}

/* definicja funkcji */

void StrPrint2(char *str2)

{

printf("%s\n", str2);

}


deklarujemy i inicjujemy tablice składaj

ą

c

ą

si

ę

z wielu ci

ą

gów

znaków
mo

ż

emy ja potraktowac jako tablic

ę

dwuwymiarow

ą

background image

120

1 wymiar – ilo

ść

stringów


2 wymiar – ilo

ść

znaków w stringu

mo

ż

emy ja równie

ż

potraktowac jako tablice wska

ź

ników do

poszczególnych stringów
tablica jest wyprowadzana na ekran przez dwie funkcje

StrPrint1 (wska

ź

nik do tablicy wska

ź

ników, wymiar)





nazwa tablicy

str – w programie głównym jest nazw

ą

tablicy b

ę

d

ą

c

ą

tablic

ą

wska

ź

ników do stringów;


jest zatem jako nazwa tablicy wska

ź

nikiem do jej pierwszego

elementu zatem jest wska

ź

nikiem do wska

ź

nika


wywołanie StrPrint1(str,size)

Funkcja StrPrint1(char **str1, int size)

StrPrint2 - argumentem funkcji jest pojedynczy ła

ń

cuch

/string/;

Zatem argumentem wywołania jest wska

ź

nik do stringa i w

tablicy [i]

Wywołanie StrPrint2(str[i])

Deklaracja StrPrint(char *str2)








Wska

ź

nik do funkcji


Poniewa

ż

funkcja ma warto

ść

lewostronn

ą

w postaci adresu

startowego w pami

ę

ci, podobnie zatem jak w przypadku tablic

mo

ż

na zadeklarowa

ć

i zainicjowa

ć

wska

ź

nik przy pomocy

lewostronnej warto

ś

ci (adresu) funkcji.


//p_76_8

/* wska

ź

nik do funkcji */

background image

121


#include <stdio.h>

#include <conio.h>

/* deklaracja funkcji */

int StrPrint(char *str);

/* main() function */

main()

{

char str[22] = "Wskazanie funkcji.";

int (*ptr)(char *str);

clrscr();

ptr = StrPrint;

if (!(*ptr)(str))

printf("OK!\n");

getch();

return 0;

}

/* definicja funkcji */

int StrPrint(char *str)

{

printf("%s\n", str);

return 0;

}



funkcja zwraca typ int pobiera wska

ź

nik do znaku:



background image

122

deklaracja funkcji

int StrPrint(char *str)

deklaracja wska

ź

nika do funkcji


int (*ptr)(char *str)






deklaracja wska

ź

nika - wska

ź

nik uj

ę

ty w nawiasy okr

ą

głe

wskazuje funk.











typ (*nazwa_wska

ź

nika)(typ argumentu funkcji)





zgodny z typem funkcji wska

ź

nik funkcji






ptr = StrPrint à przypisanie lewostronnej warto

ś

ci funkcji


wska

ź

nikowi




(*ptr)(str) à wywołanie funkcji wskazywanej przez wska

ź

nik


ptr z argumentem str à jest to przekazanie

do funkcji tablicy str

Funkcja drukuje ła

ń

cuch znaków, a po zako

ń

czeniu zwraca 0

(return 0;) if(!0) à wydruk OK

background image

123



















































background image

124









Dynamiczne przyporz

ą

dkowanie pami

ę

ci


Je

ż

eli chcemy w trakcie realizacji programu zarz

ą

dza

ć

pami

ę

ci

ą

dostepn

ą

do jego realizacji to mamy do dyspozycji nastepuj

ą

ce

funkcje z biblioteki stdlib.h :

1/ malloc()

2/ calloc()

3/ realloc()

4/ free()



Funkcja malloc()

Słu

ż

y do przyporz

ą

dkowania okreslonego obszaru pami

ę

ci


#include <stdlib.h>

void *malloc(size_t size);

size – wielko

ść

obszaru pami

ę

ci w bajtach przeznaczony do

przyporz

ą

dkowania


funkcja zwraca wska

ź

nik typu void (nieokre

ś

lony), wskazuj

ą

cy

pocz

ą

tkowy adres zarezerwowanego obszaru pami

ę

ci à typ tego

wska

ż

nika jest automatycznie poddawany konwersji i zmieniany

na typ wska

ź

nika, który znajduje si

ę

po lewej stronie

operatora przypisania.

Funkcja zwraca wska

ź

nik pusty, gdy operacja zarezerwowania

żą

danego obszaru pami

ę

ci sko

ń

czy si

ę

niepowodzeniem. Dlatego

zawsze przed u

ż

yciem takiego wska

ź

nika nale

ż

y sprzwdzi

ć

czy

nie jest pusty.


//p_76_9

background image

125

/ U

ż

ycie funkcji malloc() */#include <stdio.h> #include

<stdlib.h>#include <string.h>/* function declaration */void
StrCopy(char *str1, char *str2);/* main() function */main(){

char str[] = "U

ż

ycie malloc() do rezerwacji pami

ę

ci.";


char *ptr_str;

int termination;

/* call malloc() */

ptr_str = malloc( strlen(str) + 1);

if (ptr_str != NULL){

StrCopy(str, ptr_str);

printf("Ła

ń

cuch okre

ś

lony wska

ź

nikiem ptr_str:\n%s\n",


ptr_str);

termination = 0;

}

else{

printf("malloc() function failed.\n");

termination = 1;

}

return termination;

}

/* function definition */

void StrCopy(char *str1, char *str2)

{

int i;


for (i=0; str1[i]; i++)

str2[i] = str1[i];

background image

126

str2[i] = '\0';

}

Zadaniem funkcji malloc() jest zarezerwowanie pami

ę

ci dla

ła

ń

cucha znaków. Wska

ź

nik zwracany przez funkcj

ę

malloc() jest

wykorzystywany w operacji kopiowania ła

ń

cuchów.


Je

ż

eli po wykorzystaniu przyporz

ą

dkowanej dynamicznie pami

ę

ci

ta nie zostanie zwolniona, a w dalszej cz

ęś

ci programu

nast

ą

pi

ą

kolejne operacje przyporz

ą

dkowania pami

ę

ci to pami

ę

ci

mo

ż

e po prostu zabrakn

ąć

.


Dynamicznie przyporz

ą

dkowan

ą

pami

ęć

zwalnia funkcja free().





Funkcja free()

poniewa

ż

pami

ęć

dost

ę

pna w ka

ż

dym komputerze jest ograniczona,

nale

ż

y przyporz

ą

dkowa

ć

tylko tyle pami

ę

ci ile jest jest jej

rzeczywi

ś

cie potrzebne, a po wykorzystaniu j

ą

zwolni

ć

.


//p_76_10

/ Use the free() function */#include <stdio.h> #include
<stdlib.h>/* function declarations */ void DataMultiply(int
max, int *ptr);void TablePrint(int max, int *ptr);/* main()
function */main(){ int *ptr_int, max;

int termination;

char key = 'c';

max = 0;

termination = 0;

while (key != 'x'){

printf("Enter a single digit number:\n");

scanf("%d", &max);

/* call malloc() */

ptr_int = malloc(max * max * sizeof(int));

if (ptr_int != NULL){

background image

127

DataMultiply(max, ptr_int);

TablePrint(max, ptr_int);

free(ptr_int);

}

else{

printf("malloc() function failed.\n");

termination = 1;

break;

}

printf("\nPress x-key to quit; other key to continue.\n");

scanf("%s", &key);

}

printf("\nBye!\n");

return termination;

}

/* function definition */

void DataMultiply(int max, int *ptr)

{

int i, j;


for (i=0; i<max; i++)

for (j=0; j<max; j++)

*(ptr + i * max + j) = (i+1) * (j+1);

}

/* function definition */

void TablePrint(int max, int *ptr)

background image

128

{

int i, j;

printf("The multiplication table of %d is:\n",

max);

printf(" ");

for (i=0; i<max; i++)

printf("%4d", i+1);

printf("\n ");

for (i=0; i<max; i++)

printf("----", i+1);

for (i=0; i<max; i++){

printf("\n%d|", i+1);

for (j=0; j<max; j++)

printf("%3d ", *(ptr + i * max + j));

}

}

Działanie programu ma na celu zbudowanie dwuwymiarowej
numerycznej tablicy n x n z elementami zaczerpni

ę

tymi z

tabliczki mno

ż

enia. P

ę

tle w programie b

ę

d

ą

powtarzane, a

ż

do

naci

ś

ni

ę

cia znaku ‘x’, lub niepowodzenia w przyporz

ą

dkowaniu

pami

ę

ci przez funkcj

ę

malloc().


Aby zademonstrowa

ć

działanie funkcji free(), program dokonuje

tymczasowego obszaru pami

ę

ci, do przechowywania elementów

tabliczki mno

ż

enia. Zaraz po wydrukowaniu na ekran pami

ęć

ta

zostaje zwolniona poprzez działanie funkcji free().




Funkcja calloc()

Funkcja ta podobnie jak malloc() mo

ż

na stosowa

ć

do

dynamicznego przyporz

ą

dkowania pami

ę

ci. Funkcja calloc()

background image

129

pobiera dwa argumenty i po zarezerwowaniu pami

ę

ci powoduje

dodatkowo wyzerowanie bajtów wchodz

ą

cych w skład tego obszaru.


#include <stdlib.h>

void *calloc(size_t nitem, size_t size);

nitem – oznacza ilo

ść

elementów, które chcemy przechowa

ć

w

pami

ę

ci


size – rozmiar pojedynczego elementu w bajtach

calloc() zwraca równie

ż

wska

ź

nik typu void


//p_76_11

/* 17L03.c: Use the calloc() function */

#include <stdio.h>

#include <stdlib.h>

/* main() function */

main()

{

float *ptr1, *ptr2;

int i, n;

int termination = 1;

n = 5;

ptr1 = malloc(n * sizeof(float));

ptr2 = calloc(n, sizeof(float));

if (ptr1 == NULL)

printf("malloc() failed.\n");

else if (ptr2 == NULL)

printf("calloc() failed.\n");

else{

for (i=0; i<n; i++)

background image

130


printf("ptr1[%d]=%5.2f, ptr2[%d]=%5.2f\n",

i, *(ptr1 + i), i, *(ptr2 + i));

free(ptr1);

free(ptr2);

termination = 0;

}

return termination;

}

Aby sprawdzi

ć

czy pami

ęć

zarezerwowana przez funkcj

ę

calloc()

zostaje wyzerowana , pocz

ą

tkowa zawarto

ść

pami

ę

ci zostaje

wydrukowana i porównana z zawarto

ś

cia pami

ę

ci rezerwowanej

funkcj

ą

malloc().




Funkcja realloc()

Funkcja ta pozwala na zmiane rozmiaru bloku w dynamicznie
przyporz

ą

dkowanym obszarze pami

ę

ci, który został uprzednio

zarezerwowany przez funkcje malloc(), calloc() i realloc().


#include <stdlib.h>

void *realloc(void *block, size_t size)
blok - wska

ź

nik do obszaru pami

ę

ci uprzednio przyporz

ą

kowanego

dynamicznie;
size – rozmiar bloku pami

ę

ci, który powinien zosta

ć

przeorganizowany

Funkcja zwraca wska

ź

nik typu void, albo wska

ź

nik zerowy.


Funkcja realloc() wywołana z pierwszym argumentem zerowym jest
równowa

ż

na funkcji malloc().


ptr_flt = realloc(NULL, 10*sizeof(float));

ptr_flt = malloc(10*sizeof(float)); à s

ą

równowa

ż

ne


J

ęż

eli funkcja realloc() b

ę

dzie miała 2 argument równy zero to

jest równowa

ż

na fnkcji free();

background image

131

free(prt);

realloc(prt,0); à sa równowa

ż

ne




//p_76_12

/* 17L04.c: Use the realloc() function */#include <stdio.h>
#include <stdlib.h>#include <string.h>/* function declaration
*/void StrCopy(char *str1, char *str2);

/* main() function */

main()

{

char *str[4] = {"There's music in the sighing of a reed;",

"There's music in the gushing of a rill;",

"There's music in all things if men had ears;",

"There earth is but an echo of the spheres.\n"

};

char *ptr;

int i;


int termination = 0;

ptr = malloc(strlen((str[0]) + 1) * sizeof(char));

if (ptr == NULL){

printf("malloc() failed.\n");

termination = 1;

}

else{

StrCopy(str[0], ptr);

printf("%s\n", ptr);

background image

132

for (i=1; i<4; i++){

ptr = realloc(ptr, (strlen(str[i]) + 1) * sizeof(char));

if (ptr == NULL){

printf("realloc() failed.\n");

termination = 1;

break;

}

else{

StrCopy(str[i], ptr);

printf("%s\n", ptr);

}

}

}

free(ptr);

return termination;

}

/* funciton definition */

void StrCopy(char *str1, char *str2)

{

int i;


for (i=0; str1[i]; i++)

str2[i] = str1[i];

str2[i] = '\0';

}

Funkcja ma za zadanie przyporz

ą

dkowa

ć

dynamicznie blok pami

ę

ci

do przechowywania ła

ń

cucha znakowego. W przykł

ą

dzie wyst

ę

puj

ą

background image

133

4 ła

ń

cuchy znakowe o ró

ż

nej długo

ś

ci. Aby przystosowa

ć

wielko

ść

poprzednio przyporz

ą

dkowanego obszaru pami

ę

ci do

nastepnego ła

ń

cucha znaków stosowana jest funkcja realloc().


Wykorzystano tablic

ę

wska

ź

ników str do 4 ła

ń

cuchów tekstowych.


Obszar pami

ę

ci zostaje przyporz

ą

dkowany, a jego rozmiar

dostosowany do aktualnych potrzeb w oparciu o długo

ść

ka

ż

dego

ł

ąń

cucha znaków. Obie stosowane funkcje malloc() i realloc()

dokonuj

ą

przydziału obszaru pami

ę

ci i regulacji jego rozmiaru

w sposób dynamiczny – tzn w ruchu programu.












Wyliczeniowy typ danych




Wyliczeniowy typ danych umo

ż

liwia skojarzenie nazw

symbolicznych ze stałymi numerycznymi typu integer.



Deklaracja:



enum nazwa {lista wyliczeniowa} lista zmiennych;





enum – słowo kluczowe;

nazwa – nazwa typu wyliczeniowego;

lista zmiennych – nazwy zmiennych danego typu wyliczeniowego;

background image

134

lista wyliczeniowa – identyfikatory – zdefiniowane stałe
tekstowe, u

ż

ywane do reprezentacji numerycznych stałych

całkowitych;




wariant 1:

enum auto {sedan, pick_up, sport} krajowe, zagraniczne;

wariant 2:

enum auto {sedan, pick_up, sport};

auto krajowe, zagraniczne;











Przypisanie warto

ś

ci liczbowych do typu wyliczeniowego.




Standardowo gdy programista nie zadeklaruje inaczej:

Stała symboliczna wymieniona na pocz

ą

tku listy wyliczeniowej

ma przypisan

ą

warto

ść

0, nast

ę

pne kolejno i 1 wi

ę

ksz

ą

.


Sposób przyporz

ą

dkowania stałych int w programie:


enum auto {sedan=60, pick_up=30, sport=10};

//p_77

#include <stdio.h>#include <conio.h>void main(void){enum jezyk
{human=100,animal=50,computer};enum dni
{pon,wto,sro,czw,pio,sob,nie};clrscr();printf("human %d,
animal %d, computer %d\n",human,animal,computer);

printf("pon %d\n",pon);

printf("wto %d\n",wto);

background image

135

printf("sro %d\n",sro);

printf("czw %d\n",czw);

printf("pio %d\n",pio);

printf("sob %d\n",sob);

printf("nie %d\n",nie);

getch();

}



powy

ż

szy przykład ilustruje automatyczne i r

ę

czne

przyporz

ą

dkowanie stałym symbolicznym warto

ś

ci numerycznych

typu int;









/p_78

#include <stdio.h>#include <conio.h>void main(void){enum
money_units{grosik=1,piatka=5,dycha=10,polowka=50,zlocisz=100}
; int money_units[5]={zlocisz,polowka,dycha,piatka,grosik};

char *unit_name[5]={"złocisz(-ów)","połów(-ka/ek)","dycha(-
ch)","pi

ą

tka(-ek)","grosik(-ow)"};


int cent,tmp,i;

clrscr();

printf("Wpisz sum

ę

w groszach:\n");


scanf("%d",&cent);

printf("Odpowiada to zestawowi monet:\n");

tmp=0;

for(i=0;i<5;i++)

background image

136

{

tmp=cent/money_units[i];

cent-=tmp*money_units[i];

if(tmp)

printf("%d %s ",tmp,unit_name[i]);

}

printf("\n");

getch();

}

Zadaniem programu jest wykorzystanie typu wyliczeniowego do
reprezentacji sumy wprowadzonej przez u

ż

ytkownika za pomoc

ą

zestawu monet.
typ wyliczeniowy money_units wykorzystywany jest do
przyporz

ą

dkowanie stałym symbolicznym warto

ś

ci monet złocisz –

100 (gr) , dycha – 10 (gr) itd;
deklarowana tablica numeryczna typu int inicjowana jest
stałymi symbolicznymi typu wyliczeniowego – co odpowiada :

int money_units[5]={100,50,10,5,1} à po zadeklarowaniu typu
wyliczeniowego mo

ż

na stosowa

ć

stałe symboliczne z listy

wyliczeniowej zamiast odpowiadaj

ą

cych im warto

ś

ci

numerycznych;
delaracja tablicy zło

ż

onej ze wska

ź

ników do ła

ń

cuchów

tekstowych umo

ż

liwi wyprowadzanie opisów;
















Definiowanie typów u

ż

ytkownika.


background image

137


typedef int liczba_2bajty;

liczba_2bajty i,j,k,l; ß à int i,j,k,l;



Definicja typu typedef tworzy synonim deklaracji typu i musi
wyst

ą

pi

ć

w programie zanim ten synonim zostanie u

ż

yty.

umo

ż

liwia uproszczenie nazwy skomplikowanego typu danych do

pojedynczego słowa;
po dokonaniu jednokrotnej korekty definicji synonimu, mo

ż

na

u

ż

ywac tego nowego synonimu wielokrotnie w przyszłosci;






































background image

138








Przekazywanie do funkcji main() argumentów z wiersza polece

ń

.




Argumenty z wiersza polece

ń

przekazujemy podczas uruchamiania

wersji exe programu napisanego w j

ę

zyku C.


Maj

ą

c program o nazwie prog.c à prog.exe


C:> prog argument1, argument2, argument3

Argumenty 1-3 sa argumentami z wiersza polece

ń


Funkcja main() posiada dwa wbudowane argumenty , które mog

ą

by

ć

wykorzystane do pobierania parametrów z wiersza polece

ń

systemu operacyjnego /trzeci odnosi si

ę

do otoczenia

systemowego/.

Pierwszy nazywa si

ę

argc – słu

ż

y on do przechowywania

całkowitej liczby parametrów przekazywanych do funkcji main()
z wiersza polece

ń

.


Drugi argv – jest wska

ź

nikiem do tablicy wska

ź

ników – ła

ń

cuchy

znaków. Ka

ż

dy element tej tablicy wskazuje jeden argument z

wiersza polece

ń

, traktowany jako ła

ń

cuch znaków;






typ_wy main(int argc, char *argv[])

{

}

Przy wywołaniu prog.exe argc=4 gdy

ż

nazwa programu jest

uznawana jako pierwszy argument z wiersza polece

ń

;


argv[0]=”c:\programy\prog.exe”

argv[1]=”argument1”

argv[2]=”argument2”

background image

139


argv[3]=”argument3”



//p_79

#include <stdio.h>#include <conio.h>void main(int argc,char
*argv[]){ int i; clrscr(); printf("%d\n",argc);
printf("%d\n",argc); for(i=0;i<argc;i++)
printf("%s\n",argv[i]); getch();

}





































background image

140
















Struktura – ł

ą

czenie ró

ż

nych typów danych


Struktura jest poł

ą

czeniem w cało

ść

danych ró

ż

nych typów, tak

aby mogły stanowi

ć

jeden moduł.


Róznica mi

ę

dzy strukturami a tablicami:

w obr

ę

bie struktury mog

ą

znajdowa

ć

ż

ne typy;

ka

ż

dy element w strukturze ma swoj

ą

własna nazw

ę

;


Elementy danych wchodz

ą

ce w skł

ą

d struktury – pola struktury;




Deklarowanie struktur



struct nazwa_struct{

typ zmienna1;

typ zmienna2;

typ zmienna3;

};

struct auto{

int rok;

char model[8];

int moc_silnika;

float masa;

background image

141


};





Definiowanie struktur



struct auto sedan,pick_up,sport;







struct auto{

int rok;

char model[8];

int moc_silnika;

float masa;

} seadan, pick_up, sport;





Odwoływanie si

ę

do elementów struktur – operator .




zmienna_struktury.nazwa_pola

ptr=sport.model;

//p_80

#include <stdio.h>#include <conio.h>void main(void){struct
komputer { float koszt; int rok; int cpu_cz; char cpu_typ[16];
} model; clrscr(); printf("Podaj typ CPU: \n");
gets(model.cpu_typ); printf("Podaj cz

ę

st. CPU w MHz: \n");


scanf("%d",&model.cpu_cz);

background image

142


printf("Podaj rok produkcji: \n");

scanf("%d",&model.rok);

printf("Podaj cene jego zakupu: \n");

scanf("%f",&model.koszt);

printf("Oto wprowadzone dane: \n");

printf("Rok produkcji : %d \n",model.rok);

printf("Cena zakupu : %6.2f \n",model.koszt);

printf("Typ CPU : %s \n",model.cpu_typ);

printf("Szybko

ść

CPU w MHZ : %d \n",model.cpu_cz);


getch();

}

powy

ż

szy program demonstruje dowołania do poszczególnych pól

struktury



Inicjowanie struktur

Poni

ż

szy program przedstawia sposób inicjowania struktury, a

nast

ę

pnie aktualizacj

ę

zawarto

ś

ci pól danych przez

u

ż

ytkownika.






//p_81

#include <stdio.h>#include <conio.h>void main(void){struct
pracownik

{

int nr;

char nazwisko[32];

};

background image

143

struct pracownik info = { 0001,"J.Nowak"};

clrscr();

printf("Wydruk pól struktury\n");

printf("Nazwisko pracownika: %s\n",info.nazwisko);

printf("Numer ID #: %04d\n",info.nr);

printf("Podaj swoje nazwisko: ? \n");

gets(info.nazwisko);

printf("Podaj swój numer: ? \n");

scanf("%d",&info.nr);

printf("Wprowadziłe

ś

dane: \n");


printf("Nazwisko pracownika: %s\n",info.nazwisko);

printf("Numer ID #: %04d\n",info.nr);

getch();

}





definicja, deklaracja i zainicjowanie struktury w pojedy

ń

czej

instrukcji

struct pracownik

{

int nr;

char nazwisko[30];

} info = {0001,”J.Nowak”};






background image

144



Struktury a funkcje

J

ę

zyk C pozwala przekaza

ć

cał

ą

struktur

ę

jako argument do

funkcji, jak równie

ż

funkcja mo

ż

e zwrócic struktur

ę

jako

warto

ść

.


Demonstruje to poni

ż

szy przykład.


//p_82

#include <stdio.h>#include <conio.h>struct komputer { float
koszt; int rok; int cpu_cz; char cpu_typ[16]; }; typedef
struct komputer SC; SC PobierzDane(SC s);

void main(void)

{

SC model;

clrscr();

model=PobierzDane(model);



printf("Dane, które wprowadziłe

ś

: \n");


printf("Rok: %d \n",model.rok);

printf("Cena: %6.2f \n",model.koszt);

printf("CPU typ: %s \n",model.cpu_typ);

printf("Predko

ść

: %d MHz \n",model.cpu_cz);


getch();

}

SC PobierzDane(SC s)

{

printf("Podaj typ CPU: \n");

gets(s.cpu_typ);

printf("Podaj cz

ę

st. CPU w MHz: \n");

background image

145


scanf("%d",&s.cpu_cz);

printf("Podaj rok produkcji: \n");

scanf("%d",&s.rok);

printf("Podaj cene jego zakupu: \n");

scanf("%f",&s.koszt);

return s;

}





Wska

ź

niki do struktur


Podobnie jak przekazuje si

ę

funkcjom wska

ź

niki do tablic, tak

mo

ż

na przekaza

ć

im równie

ż

w postaci argumentu wska

ź

nik

wskazuj

ą

cy struktur

ę

.


W przeciwie

ń

stwie do przekazywania całej struktury w formie

argumentu do funkcji , co powodowało na u

ż

ytek funkcji

tworzenie kopii całej struktury, przekazanie do funkcji
wska

ź

nika powoduje jedynie przekazanie jej adresu w pami

ę

ci,

pod którym zlokalizowana jest struktura. Funkcja mo

ż

e

posługiwac si

ę

tym adresem , odwołuj

ą

c si

ę

bezpo

ś

rednio do pól

struktury, a nie do kopii struktury.

Prezentuje to poni

ż

szy program.


//p_83

#include <stdio.h>#include <conio.h>struct komputer { float
koszt; int rok; int cpu_cz;

char cpu_typ[16];

};

typedef struct komputer SC;

void PobierzDane(SC *ptr_s);

void main(void)

{

background image

146


SC model;

clrscr();



PobierzDane(&model);



printf("Dane, które wprowadziłe

ś

: \n");


printf("Rok: %d \n",model.rok);

printf("Cena: %6.2f \n",model.koszt);

printf("CPU typ: %s \n",model.cpu_typ);

printf("Predko

ść

: %d MHz \n",model.cpu_cz);


getch();

}

void PobierzDane(SC *ptr_s)

{

float pomoc;

printf("Podaj typ CPU: \n");

gets((*ptr_s).cpu_typ);

printf("Podaj cz

ę

st. CPU w MHz: \n");


scanf("%d",&(*ptr_s).cpu_cz);

printf("Podaj rok produkcji: \n");

scanf("%d",&(*ptr_s).rok);



printf("Podaj cene jego zakupu: \n");

scanf("%f",&pomoc);

(*ptr_s).koszt=pomoc;

background image

147

// scanf("%f",&(*ptr_s).koszt);

}



(*ptr_s).pole à odwołanie si

ę

do pola struktury


co mo

ż

na zast

ą

pic przez


ptr_s à pole



natomiast wyra

ż

enie: &(*ptr_s).pole przez: &(ptr_s à pole)


ilustruje to poni

ż

szy przykład:


//p_84

#include <stdio.h>#include <conio.h>struct komputer {

float koszt;

int rok;

int cpu_cz;

char cpu_typ[16];

};

typedef struct komputer SC;

void PobierzDane(SC *ptr_s);

void main(void)

{

SC model;

clrscr();



PobierzDane(&model);



printf("Dane, kt˘re wprowadzi

e

: \n");

background image

148


printf("Rok: %d \n",model.rok);

printf("Cena: %6.2f \n",model.koszt);

printf("CPU typ: %s \n",model.cpu_typ);

printf("Predko

ść

: %d MHz \n",model.cpu_cz);


getch();

}

void PobierzDane(SC *ptr_s)

{

float pomoc;

printf("Podaj typ CPU: \n");

gets(ptr_s->cpu_typ);

printf("Podaj cz

ę

st. CPU w MHz: \n");


scanf("%d",&(ptr_s->cpu_cz));

printf("Podaj rok produkcji: \n");

scanf("%d",&(ptr_s->rok));



printf("Podaj cene jego zakupu: \n");

scanf("%f",&pomoc);

ptr_s->koszt=pomoc;

// scanf("%f",&(*ptr_s.koszt));

}








background image

149











Tablice struktur

W j

ę

zyku C mo

ż

na zadeklarowa

ć

tablic

ę

, której elementami b

ę

d

ą

struktury.

Nale

ż

y nazw

ę

tablicy (identyfikator) poprzedzi

ć

nazw

ą

typu

struktur.

struct x tablica[8];

jest deklaracj

ą

8-elementowej jednowymiarowej tablicy, której

elementami s

ą

struktury typu x.




//p_85

#include <stdio.h>#include <conio.h>struct wiersz { int
start_year; int end_year; char autor[16]; char str1[64]; char
str2[64]; char str3[64]; }; typedef struct wiersz WS;

void WyswietlDane(WS *ptr_s);

void main(void)

{

WS poemat[2]=

{

{1641,

1716,

"Autor1",

"Wiersz01",

"Wiersz02",

background image

150

"Wiersz03"

},

{1729,

1781,

"Autor2",

"Wiersz11",

"Wiersz12",

"Wiersz13"

}

};

int i;

clrscr();

for(i=0;i<2;i++)

WyswietlDane(&poemat[i]);

getch();

}

void WyswietlDane(WS *ptr_s)

{

printf("%s\n",ptr_s->str1);

printf("%s\n",ptr_s->str2);

printf("%s\n",ptr_s->str3);

printf("---%s\n",ptr_s->autor);

printf(" (%d-%d)\n\n",ptr_s->start_year,ptr_s->end_year);

}



background image

151




Struktury zagnie

ż

dzone


Struktury nazywane sa strukturami zagnie

ż

dzonymi je

ś

li co

najmniej jedno z pól struktury jest struktur

ą

.


struct x

{

int a;

float b;

};

struct y

{

int i;

char ch[10];

x strukt_wew

};

struktura y stanowi strukture zło

ż

ona z zagnie

ż

dzona wewn

ą

trz

struktur

ą

x


//p_86

#include <stdio.h>#include <conio.h>struct dzial { int kod;
char nazwa[32]; char stanowisko[16]; }; typedef struct dzial
DZ;

struct pracownik

{

DZ d;

int id;

char nazwisko[32];

};

background image

152

typedef struct pracownik PRAC;

void InfoWyswietl(PRAC *ptr);

void InfoWprowadz(PRAC *ptr);

void main(void)

{

PRAC info =

{

{ 01,

"Marketing",

"Manager"

},

0001,

"J.Nowak"

};

clrscr();

printf("Przykład: \n");

InfoWyswietl(&info);

InfoWprowadz(&info);

printf("\nOto dane, które wprowadziłe

ś

: \n");


InfoWyswietl(&info);

getch();

}

void InfoWyswietl(PRAC *ptr)

{

printf("Nazwisko: %s \n",ptr->nazwisko);

printf("Numer : %04d \n",ptr->id);

background image

153


printf("Nazwa działu : %s \n ",ptr->d.nazwa);

printf("Numer działu : %02d \n",ptr->d.kod);

printf("Stanowisko: %s \n",ptr->d.stanowisko);

}

void InfoWprowadz(PRAC *ptr)

{

printf("\n Wpisz swoje dane: \n");

printf("Nazwisko: \n");

gets((*ptr).nazwisko);

printf("Funkcja: \n");

gets((*ptr).d.stanowisko);

printf("Nazwa działu: \n");

gets((*ptr).d.nazwa);

printf("Numer działu: \n");

scanf("%d",&(ptr->d.kod));

printf("Twój numer ID : \n");

scanf("%d",&(ptr->id));

}



dost

ę

p do danych ptr à nazwa_zm_str_wew.nazwa_pola






Forward reference – wyprzedzaj

ą

ce odwoływanie si

ę

do struktur


Je

ż

eli jednym z elementów struktury jest wska

ź

nik do struktur

innego typu, który to typ struktur nie został jeszcze
zadeklarowany, to struktura taka nazywa si

ę

struktura ze

wskazaniem wyprzedzaj

ą

cym – forward referencing structure.

background image

154


struct x

{

int i;

char ch[10];

struct y *ptr;

};


oczywi

ś

cie przy zało

ż

eniu

ż

e typ struktury y nie został

jeszcze zadeklarowany;

je

ż

eli wska

ź

nik b

ę

d

ą

cy elementem struktury wskazuje na ni

ą

sam

ą

, to struktura taka nazywa si

ę

auto referencyjn

ą

:


struct x

{

int i;

char ch[10];

struct x *ptr;

};



//p_87

#include <stdio.h>#include <conio.h>struct dane

{

char name[16];

struct date *p;

struct date *d;

};

struct date

{

background image

155


int rok;

char szkola[32];

char stopien[8];

};

typedef struct dane DAN;

typedef struct date DAT;

void InfoWyswietl(DAN *ptr);

void main(void)

{

DAT pier =

{

1985,

"Politechnika",

"in

ľ

"


};

DAT drug =

{

1988,

"AGH",

"mgr in

ľ

"


};

DAT *pp,*pd;

pp=&pier;

pd=&drug;

DAN prac =

background image

156

{

"Marek",

pp,

pd

//&pier,

//&drug

};

clrscr();

printf("To sa dane Marka: \n");

InfoWyswietl(&prac);

getch();

}

void InfoWyswietl(DAN *ptr)

{

printf("Imie: %s \n",ptr->name);

printf("Nazwa szkoły: %s \n",ptr->p->szkola);

printf("Data uzyskania tytułu %d \n",ptr->p->rok);

printf("Stopie

ń

: %s \n",ptr->p->stopien);


printf("Nazwa szkoły: %s \n",ptr->d->szkola);

printf("Data uzyskania tytułu %d \n",ptr->d->rok);

printf("Stopie

ń

: %s \n",ptr->d->stopien);


}





nowy sposób odwołania do pola : ptr à d à stopien

background image

157


















































Unie

background image

158



Unia jest to blok pami

ę

ci u

ż

ywany do przechowywania róznych

elementów danych.

W j

ę

zyku C unia jest podobna do struktury , z tym wyj

ą

tkiem

ż

e

dane zawarte w unii nakładaj

ą

si

ę

wzajemnie na siebie –

poniewa

ż

dziel

ą

mi

ę

dzy siebie ten sam obszar pami

ę

ci.


Deklarowanie unii

union auto {

int rok;

char model[8];

int moc_silnika;

float waga;

};

union – słowo kluczowe /okresla kategorie typu danych/

auto - nazwa typu danych

{

} - struktura wewn

ę

trzna unii zawieraj

ą

ca jej pola nazywane

równie

ż

jej elementami; poniewa

ż

elementy unii mog

ą

si

ę

nawzajem nakładac zatem nazwa element jest zasadniejsza od
nazwy pole;





Definiowanie zmiennych unii



union auto sedan, pick_up, sport;

union auto {

int rok;

char model[8];

int moc_silnika;

background image

159


float waga;

} sedan, pick_up, sport;

je

ż

eli poł

ą

czymy deklaracj

ę

typu unii i definicj

ę

zmiennych

danego typu w pojedyncz

ą

instrukcj

ę

mo

ż

emy w tej instrukcji

pomin

ąć

identyfikator typu unii: (słowo auto)


union {

int rok;

char model[8];

int moc_silnika;

float waga;

} sedan, pick_up, sport;

podobnie jak w przypadku elementów struktury, tak i w
przypadku do elementów składowych unii mo

ż

e by

ć

stosowany

operator .

sedan.year=1997;

po zadeklarowaniu wska

ź

nika do zmiennych unii


union auto *ptr;

ptr à year = 1997;

//p_88

#include <stdio.h>#include <string.h>

#include <conio.h>

void main(void)

{

union menu

{

char nazwa[20];

double cena;

background image

160

} danie;

clrscr();

printf("Zawarto

ść

unii\n");


strcpy(danie.nazwa,"kotlet schabowy");

printf("Nazwa dania: %s\n",danie.nazwa);

danie.cena=12.95;

printf("Cena dania: %5.2f\n",danie.cena);

printf("Ko

ń

cowa zawarto

ść

unii %s",danie.nazwa);


getch();

}


przykład powy

ż

szy pokazuje sposób dost

ę

pu do elementów unii;

ostatnia instrukcja printf jest dowodem nakładania w pami

ę

ci

elementów unii na siebie;

potwierdzaj

ą

to dwa poni

ż

sze przykłady:


//p_89

#include <stdio.h>#include <string.h>#include <conio.h>void
main(void){ union menu { char nazwa[20]; double cena; } danie;
clrscr(); printf("Zawarto

ść

unii\n"); danie.cena=12.95;


printf("Cena dania: %5.2f\n",danie.cena);

strcpy(danie.nazwa,"kotlet schabowy");

printf("Nazwa dania: %s\n",danie.nazwa);

printf("Ko

ń

cowa zawarto

ś

c unii %s\n",danie.nazwa);


printf("Cena dania: %5.2f\n",danie.cena);

getch();

}



//p_90

background image

161

#include <stdio.h>#include <string.h>#include <conio.h>void
main(void){ union menu { char nazwa[20]; double cena; } danie;
clrscr(); printf("Zawarto

ś

c unii\n"); danie.cena=12.95;

printf("Cena dania: %5.2f\n",danie.cena);
strcpy(danie.nazwa,"kotlet schabowy");

printf("Nazwa dania: %s\n",danie.nazwa);

printf("Koäcowa zawarto

ść

unii %5.2f ",danie.cena);


getch();

}



Inicjowanie unii

Elementy danych unii nakładaj

ą

si

ę

nawzajem na siebie w

obr

ę

bie tego samego obszaru pami

ę

ci. Obszar ten jest

wykorzystywany do zapisu ró

ż

nych danych w ró

ż

nym czasie.

Rozmiar unii odpowiada rozmiarowi najwi

ę

kszego spo

ś

ród jej

elementów. Daltego nie ma sensu inicjowanie wszystkich
elementów unii jednoczesnie, poniewa

ż

warto

ść

ostatnio

inicjowanego elementu nadpisze si

ę

na warto

ść

poprzednich.

Element unii inicjuje si

ę

tylko wtedy gdy jeste

ś

my gotowi do

jego wykorzystania. Bie

żą

ca warto

ść

zawarta w unii jest zawsze

warto

ś

cia ostatniego elementu przypisanego unii.


union u {

char ch;

int x;

} n_unia;



n_unia.ch=’H’;

n_unia.x=365;


najpierw pami

ę

c przeznaczona na elementy unii zawierała ‘H’

potem warto

ś

c 365.


union u {

char ch;

background image

162

int x;

} n_unia = {‘H’);



















co si

ę

stanie gdy zainicjujemy wszystkie elementy unii

jednoczesnie ?

//p_91

#include <stdio.h>#include <string.h>#include <conio.h>void
main(void){ union sprawa { int rok; int dzial; int id; } info;
info.rok=1999; info.dzial=234; info.id=1234; clrscr();
printf("Rok: %d\n",info.rok);

printf("Numer dziaˆu: %d\n",info.dzial);

printf("Numer identyfikacyjny: %d\n",info.id);

getch();

}



wynik jest oczywisty à 1234





Rozmiar unii

background image

163

Wielko

ść

unii jest równa obszarowi zajmowanemu przez

najwi

ę

kszy jej element.


W przeciwie

ń

stwie do unii, w strukturze wszystkie elementy

(pola) struktury mog

ą

by

ć

zainicjowane jednocze

ś

nie i nie

nakładaja si

ę

nawzajem. Dzieje si

ę

tak dlatego,

ż

e ka

ż

dy

element struktury ma własny obszar pami

ę

ci. Rozmiar struktury

to suma rozmiarów wszystkich jej elementów (pól), a nie jak w
przypadku unii rozmiar jej najwi

ę

kszego elementu.


Pokazuje to przykład:



//p_92

#include <stdio.h>#include <string.h>#include <conio.h>

void main(void)

{

union u

{

double x;

int y;

} a_union;

struct s

{

double x;

int y;

} a_struct;

clrscr();

printf("Rozmiar double: %d-bajtowe \n",sizeof(double));

printf("Rozmiar int : %d-bajtowe \n",sizeof(int));

printf("Rozmiar unii a_union: %d-bajtowe \n",sizeof(a_union));

background image

164

printf("Rozmiar struktury a_struct: %d-bajtowe
\n",sizeof(a_struct));

getch();

}



































Zastosowania unii

Odwoływanie si

ę

do tego samego obszaru pami

ę

ci na dwa ró

ż

ne

sposoby

Np.:

//p_93

background image

165

#include <stdio.h>#include <string.h>#include <conio.h>union u
{ char ch[2]; int num; };int InicjalizacjaUnii(union u
val);void main(void){ union u val;

int x;

x=InicjalizacjaUnii(val);

clrscr();

printf("Dwie stałe znakowe zawarte w unii: \n");

printf("%c \n",x & 0x00FF); /*młodszy bajt*/

printf("%c \n",x>>8); /*starszy bajt*/

getch();

}

int InicjalizacjaUnii(union u val)

{

val.ch[0]='H';

val.ch[1]='i';

return val.num; /*posługujemy sie elementem numerycznym unii
*/

/*do przesłania danych do f. main()*/

}











Uelastycznienie struktur



Zagnie

ż

dzenie unii wewn

ą

trz struktury powoduje,

ż

e w polach

struktur mog

ą

by

ć

przechowywane dane ró

ż

nych typów.

background image

166


Przykład:

//p_94

#include <stdio.h>#include <conio.h>#include <string.h>struct
ankieta { char name[20]; char c_d_p; int wiek; int
hour_per_week; union { char cable[16]; char sat[16];

} dostawca;

};

void DataEnter(struct ankieta *s);

void DataDisplay(struct ankieta *s);

void main(void)

{

struct ankieta tv;

clrscr();

DataEnter(&tv);

DataDisplay(&tv);

getch();

}

void DataEnter(struct ankieta *ptr)

{

char jest_tak[4];

printf("Czy korzystasz w domu z telewizji kablowej T/N \n");

gets(jest_tak);

if ((jest_tak[0]=='T')||(jest_tak[0]=='t'))

{

printf("Wpisz nazw

ę

firmy dostawcy TV kablowej: \n");


gets(ptr->dostawca.cable);

background image

167

ptr->c_d_p='c';

}

else

{

printf("Czy korzystasz z TV sat T/N \n");

gets(jest_tak);

if((jest_tak[0]=='T')||(jest_tak[0]=='t'))

{

printf("Wpisz nazwe firmy diostwcy TV sat \n");

gets(ptr->dostawca.sat);

ptr->c_d_p='d';

}

else

ptr->c_d_p='p';

}

printf("Wpisz swoje nazwisko: \n");

gets(ptr->name);

printf("i sw˘j wiek: \n");

scanf("%d",&ptr->wiek);

printf("Ile godzin tygodniowo ogl

ą

dasz TV : \n");


scanf("%d",&ptr->hour_per_week);

}



void DataDisplay(struct ankieta *ptr)

{

printf("\nOto dane, kt˘re wprowadziłe

ś

: \n");

background image

168


printf("Nazwisko: %s\n",ptr->name);

printf("Wiek: %d \n",ptr->wiek);

printf("Godzin tygodniowo: %d\n",ptr->hour_per_week);

if(ptr->c_d_p=='c')

printf("Twoja firma TV kablowej :%s\n",ptr->dostawca.cable);

else

if(ptr->c_d_p=='d')

printf("Twoja firma TV Sat: %s \n",ptr->dostawca.sat);

else

printf("Niekorzystasz ani z kabla ani z TV sat\n");

printf("Dzi

ę

kujemy -- Koniec aniekty! \n");


}







Definiowanie pól bitowych przy pomocy słowa kluczowego struct

Typ char to najmniejszy typ danych w j

ę

zyku C. Dane te zajmuja

8 bitów.

Jednak posługuj

ą

c si

ę

słowem kluczowym struct mo

ż

na

zadeklarowa

ć

obiekt jeszcze mniejszy - pole bitowe /bit

field/.

Pole bitowe umo

ż

liwia łatwy dost

ę

p do pojedynczych bitów.

Pojedynczy bit mo

ż

e przyjmowa

ć

jedna z warto

ś

ci 0 lub 1.




Format deklaracji:

struct nazwa {

data_typ_1 nazwa1: dlugosc1;

background image

169

data_typ_2 nazwa2: dlugosc2;

.....................................................

data_typ_N nazwanN: dlugoscN;

} lista_zmiennych;

struct - słowo kluczowe

nazwa - nazwa typu zmiennych

data_typ_i - typ danych kolejnego pola bitowego (musi by

ć

jednym z typów : int, unsigned, signed)

nazwai - nazwy poszczególnych pól bitowych

długosci – długo

ś

ci poszczególnych pól bitowych, które nie

mog

ą

przekraczac długo

ś

ci typu danych int


lista_zmiennych - wyliczenie zmiennych danego typu



struct bf {

int jumper1: 1;

int jumper2: 2;

int jumper3: 3;

} jumpers;

jumper1 jumper2 jumper3 trzy pola bitowe o długo

ś

ciach

odpowiednio: 1, 2, 3 bity

zmienna o nazwie jumpers jest struktur

ą

zawieraj

ą

ca trzy pola

bitowe.



jumper1 jumepr2 jumper3




//p_95

#include <stdio.h>#include <conio.h>#include <string.h>struct
bit_field

background image

170


{

int cable: 1;

int sat: 1;

};

struct ankieta

{

char name[20];

struct bit_field c_d;

int wiek;

int hour_per_week;

union

{

char cable[16];

char sat[16];

} dostawca;

};

void DataEnter(struct ankieta *s);

void DataDisplay(struct ankieta *s);

void main(void)

{

struct ankieta tv;

clrscr();

DataEnter(&tv);

DataDisplay(&tv);

getch();

background image

171

}

void DataEnter(struct ankieta *ptr)

{

char jest_tak[4];

printf("Czy korzystasz w domu z telewizji kablowej T/N \n");

gets(jest_tak);

if ((jest_tak[0]=='T')||(jest_tak[0]=='t'))

{

printf("Wpisz nazw

ę

firmy dostawcy TV kablowej: \n");


gets(ptr->dostawca.cable);

ptr->c_d.cable=1;

ptr->c_d.sat=0;

}

else

{

printf("Czy korzystasz z TV sat T/N \n");

gets(jest_tak);

if((jest_tak[0]=='T')||(jest_tak[0]=='t'))

{

printf("Wpisz nazwe firmy diostwcy TV sat \n");

gets(ptr->dostawca.sat);

ptr->c_d.cable=0;

ptr->c_d.sat=1;

}

else

{

background image

172


ptr->c_d.cable=0;

ptr->c_d.sat=0;

}

}

printf("Wpisz swoje nazwisko: \n");

gets(ptr->name);

printf("i swój wiek: \n");

scanf("%d",&ptr->wiek);

printf("Ile godzin tygodniowo ogl

Ą

dasz TV : \n");


scanf("%d",&ptr->hour_per_week);

}



void DataDisplay(struct ankieta *ptr)

{

printf("\nOto dane, które wprowadziłe

ś

: \n");


printf("Nazwisko: %s\n",ptr->name);

printf("Wiek: %d \n",ptr->wiek);

printf("Godzin tygodniowo: %d\n",ptr->hour_per_week);

if(ptr->c_d.cable && !ptr->c_d.sat)

printf("Twoja firma TV kablowej :%s\n",ptr->dostawca.cable);

else

if(!ptr->c_d.cable && ptr->c_d.sat)

printf("Twoja firma TV Sat: %s \n",ptr->dostawca.sat);

else

printf("Nie korzystasz ani z kabla ani z TV sat\n");

background image

173

printf("Dzi©kujemy -- Koniec aniekty! \n");

}































Operacje na plikach dyskowych

Plik

Poj

ę

cie pliku odnosi si

ę

do urz

ą

dzenia peryferyjnego

(terminal, drukarka, plik na ta

ś

mie, plik na dysku) z którym

ma nast

ą

pi

ć

wymiana informacji.


Przed rozpocz

ę

ciem procesu wymiany informacji plik nale

ż

y

otworzy

ć

, za

ś

po zako

ń

czeniu tego procesu nale

ż

y go zamkn

ąć

.


Strumie

ń


Przepływ danych z programu do pliku lub odwrotnie nazywamy
strumieniem danych.

Strumie

ń

stanowi seri

ę

bajtów.

background image

174


Strumie

ń

nie jest zwi

ą

zany z

ż

adnym urz

ą

dzeniem.


Aby przeprowadzi

ć

operacj

ę

wej

ś

cia/wyj

ś

cia nale

ż

y skojarzy

ć

plik ze strumieniem.

Istniej

ą

dwa formaty strumieni :


1/ Strumie

ń

tekstowy - zawiera sekwencje znaków; stosowany do

przesyłania danych tekstowych;

2/ Strumie

ń

binarny - stanowi seri

ę

bajtów (np. plik exe);

Stosowany do danych nietektowych;

Buforowanie wej

ś

cia/wyj

ś

cia


Buforem nazywamy obszar pami

ę

ci słu

żą

cy do tymczasowego

przechowywania danych przed przesłaniem ich do miejsca
przeznaczenia.

Strumienie wej

ś

cia/wyj

ś

cia s

ą

buforowane w sposób domy

ś

lny.


Buforowane wej

ś

cie/wyj

ś

cie na zywane jest obsług

ą

We/Wy

wysokiego poziomu, za

ś

nie buforowane wej

ś

cie/wyj

ś

cie obsług

ą

We/Wy niskiego poziomu.









Podstawy operacji We/Wy

Wska

ź

niki typu FILE


Struktura FILE słu

ż

y do zarz

ą

dzania plikami, zdefiniowana w

pliku nagłówkowym stdio.h.

Wska

ź

nik typu FILE jest wska

ź

nikiem plikowym i jest

wykorzystywany przez strumie

ń

do sterowania operacjami We/Wy .


FILE *fptr;

W obr

ę

bie struktury FILE znajduje si

ę

wska

ź

nik pozycji w

pliku, który wskazuje bie

żą

c

ą

pozycje podczas operacji

zapisu/odczytu danych.

Otwieranie pliku

background image

175


Funkcja fopen() pozwala na otwarcie pliku i skojarzenie go ze
strumieniem danych. Wymaga ona podania dwóch argumentów: trybu
otwarcia i nazwy przedmiotowego pliku.

#include <stdio.h>

FILE *fopen(const char *filename, const char *mode);

filename - nazwa pliku do otwarcia /wska

ź

nik do stałego

ła

ń

cucha znaków/


mode - tryb otwarcia pliku /wska

ź

nik do stałego ła

ń

cucha

znaków/

Funkcja zwraca wska

ź

nik typu FILE.


Je

ż

eli wystapi bł

ą

d otwarcia , funkcja zwraca wska

ź

nik pusty.


Tryby otwarcia pliku – mode

r - otwiera istniej

ą

cy plik tekstowy tylko do odczytu


w - tworzy nowy plik tekstowy do zapisu

a - otwiera istniej

ą

cy plik tekstowy w trybie dopisywania do

ko

ń

ca pliku


r+ - otwiera istniej

ą

cy plik tekstowy do odczytu i/lub zapisu


w+ - tworzy plik tekstowy do zapisu i/lub odczytu

a+ - otwiera lub tworzy plik tekstowy do dopisywania na ko

ń

cu


rb - otwiera istniej

ą

cy plik binarny do odczytu


wb - tworzy nowy plik binarny do zapisu

ab - otwiera istneij

ą

cy plik binarny w trybie dopisywania do

ko

ń

ca pliku


r+b - otwiera istniej

ą

cy plik binarny dla odczytu i/lub zapisu


w+b - tworzy plik binarny do zapisu i/lub zapisu

a+b - otwiera lub tworzy plik binarny do dopisywania na ko

ń

cu


próba otwarcia pliku test.txt

FILE *fprt;

background image

176

if ((fptr = fopen(”test.txt”,”r”))==NULL)

{

printf(”Nie mog

ę

otworzy

ć

pliku test.txt \n”);


exit(1);

}

.........



Zamykanie pliku

Po wykonaniu operacji na otwartym pliku dyskowym (r,w,a),
nale

ż

y odł

ą

czy

ć

plik od strumienia danych – zamkn

ąć

go à

fclose().

#include <stdio.h>

int fclose(FILE *pointer);

pointer - wska

ź

nik skojarzony ze strumieniem do otwartego

pliku.

Je

ż

eli operacja zamkni

ę

cia powiedzie si

ę

funkcja zwraca 0, w

przeciwnym razie zwraca kod EOF, lub kod bł

ę

du je

ż

eli

dyskietka z plikiem została wyj

ę

ta z nap

ę

du b

ą

d

ż

brak jest

miejsca na dysku

Otwarcie i zamkni

ę

cie pliku dyskowego.


//p_96



/* Otwarcie i zamkni

ę

cie pliku */#include <stdio.h> enum

{SUCCESS, FAIL};main(void){ FILE *fptr; char filename[]=
"haiku.txt"; int reval = SUCCESS; clrscr();

if ((fptr = fopen(filename, "r")) == NULL){

printf("Nie mog

ę

otworzy

ć

%s.\n", filename);


reval = FAIL;

} else {

printf("Warto

ść

fptr: 0x%p\n", fptr);

background image

177


fclose(fptr);

getch();

}


return reval;

}

-------------------------

#include <stdio.h>enum {SUCCESS, FAIL};int CharRead(FILE
*fin);main(void){ FILE *fptr; char filename[]= "haiku.txt";
int reval = SUCCESS; clrscr(); if ((fptr = fopen(filename,
"r")) == NULL){ printf("Nie mog

ę

otworzy

ć

%s.\n", filename);


reval = FAIL;

} else {

printf("\nIlo

ść

znaków -> %d.\n",


CharRead(fptr));

fclose(fptr);

}

getch();

return reval;

}

int CharRead(FILE *fin)

{

int c, num;


num = 0;

while ((c=fgetc(fin)) != EOF)

{

putchar(c);

background image

178


++num;

}


return num;

}
















Odczyt i zapis plików dyskowych

Sposoby przeprowadzania operacji wej

ś

cia/wyj

ś

cia :


1/ czyta

ć

i pisa

ć

znak po znaku


2/ czyta

ć

i pisa

ć

wiersz po wierszu


3/ czyta

ć

i pisa

ć

blok po bloku


Odczyt i zapis po znaku

Funkcje fgetc() i fputc() mo

ż

na zastosowac do odczytu i zapisu

znak po znaku.



#include <stdio.h>

int fgetc(FILE *stream);

stream - wska

ź

nik do pliku, który jest skojarzony ze

strumieniem danych

Funkcja fgetc() wczytuje kolejny znak ze strumienia stream.

background image

179

Po przekształceniu wczytanego znaku na kod numeryczny int
funkcja zwraca t

ę

warto

ść

.




#include <stdio.h>

int fputc(int c, FILE *stream);

int c - numeryczny kod znaku c;



Odczyt i zapis metod

ą

znak po znaku


//p_97

/* Czytanie i pisanie znak po znaku */

#include <stdio.h>

enum {SUCCESS, FAIL};

void CharReadWrite(FILE *fin, FILE *fout);

main(void)

{

FILE *fptr1, *fptr2;

char filename1[]= "outhaiku.txt";

char filename2[]= "haiku.txt";

int reval = SUCCESS;

clrscr();

if ((fptr1 = fopen(filename1, "w")) == NULL){

printf("Bł

ą

d otwarcia %s.\n", filename1);


reval = FAIL;

} else if ((fptr2 = fopen(filename2, "r")) == NULL){

printf("Bł

ą

d otwarcia %s.\n", filename2);


reval = FAIL;

background image

180

} else {

CharReadWrite(fptr2, fptr1);

fclose(fptr1);

fclose(fptr2);

}

getch();

return reval;

}

/* definicja funkcji */

void CharReadWrite(FILE *fin, FILE *fout)

{

int c;


while ((c=fgetc(fin)) != EOF){

putchar(c);

fputc(c, fout);

}

}



-----------------------





#include <stdio.h>

#include <string.h>

enum {SUCCESS, FAIL, MAX_LEN = 80};

void LineWrite(FILE *fout, char *str);

background image

181

main(void)

{

FILE *fptr;

char str[MAX_LEN+1];

char filename[32];

int reval = SUCCESS;

clrscr();

printf("Podaj nazw

ę

pliku:\n");


gets(filename);


printf("Wprowad

ź

ła

ń

cuch znak˘w :\n");


gets(str);

if ((fptr = fopen(filename, "w")) == NULL){

printf("Bł

ą

d otwarcia %s dla zapisu.\n", filename);


reval = FAIL;

} else {

LineWrite(fptr, str);

fclose(fptr);

}

getch();

return reval;

}

/* definicja funkcji */

void LineWrite(FILE *fout, char *str)

{

fputs(str, fout);

background image

182

printf("OK!\n");

}



Odczyt i zapis wiersz po wierszu

Mo

ż

na przeprowadzi

ć

zarówno zapis jak i odczyt wiersz po

wierszu.

Słu

żą

do tego celu funkcje fgets() i fputs().


#include <stdio.h>

char *fgets((char *s, int n, FILE *stream);

s - wska

ź

nik do tablicy znakowej u

ż

ywanej do zapami

ę

tania

znaków wczytanych z otwartego pliku wskazanego przez wska

ź

nik

stream.

stream - wska

ź

nik do pliku


n – maksymalna ilo

ść

elementów tablicy znakowej /l. znaków w

wierszu/

Je

ż

eli operacja wczytania wiersza zako

ń

czy si

ę

powodzeniem ,

funkcja zwraca wska

ź

nik char *s. Je

ż

eli funkcja napotka znak

ko

ń

cz apliku EOF funkcja zwraca pusty wska

ź

nik i pozostawia

tablic

ę

znakowa w stanie nienaruszonym. Je

ż

eli wyst

ą

pi bł

ą

d,

funkcja zwraca pusty wska

ź

nik, ale zawarto

ść

tablicy jest tym

razem nieokre

ś

lona.


Funkcja fgets() mo

ż

e wczyta

ć

n-1 znaków i mo

ż

e doł

ą

czy

ć

znak

ko

ń

ca ła

ń

cucha tekstowego ‘\0’ po wczytaniu ostatniego znaku,

dopóki nie napotka znaku przej

ś

cia do nowego wiersza lub znaku

ko

ń

ca pliku /EOF/.


Po napotkaniu znaku przej

ś

cia do nowego wiersza funkcja wł

ą

czy

go do wyj

ś

ciowej tablicy znakowej.


#include <stdio.h>

int fputs(const char *s, FILE *stream);

s - wskazuje tablic

ę

znakow

ą

, wktórej znajduje si

ę

tekst

przeznaczony do zapisu w pliku dyskowym skojarzonym ze
wska

ź

nikiem plikowym stream.



background image

183

Odczyt i zapis metoda wiersz po wierszu

//p_98



/* Czytanie i zapis wierszami */

#include <stdio.h>

enum {SUCCESS, FAIL, MAX_LEN = 81};

void LineReadWrite(FILE *fin, FILE *fout);

main(void)

{

FILE *fptr1, *fptr2;

char filename1[]= "outhaiku.txt";

char filename2[]= "haiku.txt";

int reval = SUCCESS;

clrscr();

if ((fptr1 = fopen(filename1, "w")) == NULL){

printf("Bł

ą

d otwarcia %s dla zapisu.\n", filename1);


reval = FAIL;

} else if ((fptr2 = fopen(filename2, "r")) == NULL){

printf("Bł

ą

d otwarcia %s dla odczytu.\n", filename2);


reval = FAIL;

} else {

LineReadWrite(fptr2, fptr1);

fclose(fptr1);

fclose(fptr2);

}

getch();

background image

184


return reval;

}

/* definicja funkcji */

void LineReadWrite(FILE *fin, FILE *fout)

{

char buff[MAX_LEN];


while (!feof(fin)){

fgets(buff, MAX_LEN, fin);

printf("%s", buff);

fputs(buff, fout);

}

}


--------------------



#include <stdio.h>

enum {SUCCESS, FAIL};

void CharWrite(FILE *fout, char *str);

main(void)

{

FILE *fptr;

char filename[]= "test_21.txt";

char str[]= "Plik dyskowy I/O ";

int reval = SUCCESS;

clrscr();

background image

185

if ((fptr = fopen(filename, "w")) == NULL){

printf("Bł

ą

d otwarcia %s.\n", filename);


reval = FAIL;

} else {

CharWrite(fptr, str);

fclose(fptr);

}

getch();

return reval;

}

/* definicja funkcji */

void CharWrite(FILE *fout, char *str)

{

int i, c;


i = 0;

while ((c=str[i]) != '\0'){

putchar(c);

fputc(c, fout);

i++;

}

}





Odczyt i zapis blok po bloku

Do zapisu lub odczytu bloku danych do/z pliku wykorzystywane
s

ą

funkcje fread() , fwrite().

background image

186


#include <stdio.h>

size_t fread(void *ptr, size_t size, size_t n, FILE *stream);

ptr - oznacza wska

ź

nik do tablicy, w której sa przechowywane

dane wczytane

size - rozmiar ka

ż

dego elementu tablicy


n - liczba elementów do odczytu

stream - wska

ź

nik skojarzony z plikiem otwartym do odczytu


size_t - typ numeryczny całkowity zdefiniowany w pliku
nagłówkowym stdio.h

Funkcja fread() zwraca liczb

ę

elementów, które wczytała.


Ilo

ść

elementów wczytanych przez funkcje powinna by

ć

równa jej

trzeciemu argumentowi /chyba

ż

e zdarzy si

ę

ą

d lub funkcja

napotka na znak EOFà w takim przypadku zwróci rzeczywist

ą

ilo

ść

wczytanych elementów/.


#include <stdio.h>

size_t fwrite(const void *ptr, size_t size, size_t n, FILE
*stream);

ptr – wska

ź

nik do tablicy, wktórej s

ą

przechowywane dane,

które nale

ż

y zapisa

ć

do otwartego pliku wskazanego przez

wska

ź

nik stream.


Parametr size okre

ś

la wielko

ść

elementów tablicy.


n - okre

ś

la ilo

ść

elementów tablicy, które nale

ż

y zapisa

ć

do

pliku.

Funkcja zwraca liczb

ę

rzeczywi

ś

cie zapisanych do pliku

elementów.

Je

ż

eli nie wystapiły

ż

adne bł

ę

dy, liczba zwrócona przez

funkcj

ę

fwrite() powinna by

ć

równa jej trzeciemu elementowi.

Je

ż

eli wyst

ą

pił bł

ą

d to warto

ść

zwrócona mo

ż

e by

ć

mniejsza.


Bardzo istotne jest sprawdzenie czy tablica jest wystarczaj

ą

co

du

ż

a , by pomie

ś

ci

ć

dane dla funkcji fread() i fwrite(). Dla

sprawdzenia kiedy nastapi znak ko

ń

ca pliku słuzy funkcja

feof().

background image

187

Je

ż

eli w programie stwierdzimy napotkanie znaku ko

ń

ca pliku

(EOF) w obr

ę

bie pliku binarnego poprzez sprawdzenie warto

ś

ci

zwróconej przez funkcje fread(), mo

ż

emy zako

ń

czy

ć

prac

ę

w

nieprawidłowym miejscu (nie osi

ą

gn

ą

wszy rzeczywistego ko

ń

ca

pliku). Zastosowanie funkcji feof() pozwoli unikn

ąć

ę

dów

wykrywaj

ą

c rzeczywisty koniec pliku.


#include <stdio.h>

int feof(FILE *stream)

stream - wska

ź

nik plikowy skojarzony z otwartym plikiem.


Funkcja ta zwraca 0 je

ż

eli koniec pliku nie został osi

ą

gni

ę

ty

, w przeciwnym razie zwraca niezerow

ą

warto

ść

całkowit

ą

.












Zapis i odczyt bloku znaków



//p_99



/* Odczyt i zapis blokami */

#include <stdio.h>

enum {SUCCESS, FAIL, MAX_LEN = 80};

void BlockReadWrite(FILE *fin, FILE *fout);

int ErrorMsg(char *str);

main(void)

{

FILE *fptr1, *fptr2;

char filename1[]= "outhaiku.txt";

background image

188


char filename2[]= "haiku.txt";

int reval = SUCCESS;

clrscr();

if ((fptr1 = fopen(filename1, "w")) == NULL){

reval = ErrorMsg(filename1);

} else if ((fptr2 = fopen(filename2, "r")) == NULL){

reval = ErrorMsg(filename2);

} else {

BlockReadWrite(fptr2, fptr1);

fclose(fptr1);

fclose(fptr2);

}

getch();

return reval;

}

/* definicja funckji */

void BlockReadWrite(FILE *fin, FILE *fout)

{

int num;

char buff[MAX_LEN + 1];


while (!feof(fin)){

num = fread(buff, sizeof(char), MAX_LEN, fin);

buff[num * sizeof(char)] = '\0';

printf("%s", buff);

fwrite(buff, sizeof(char), num, fout);

background image

189


}

}

/* definicja funkcji */

int ErrorMsg(char *str)

{

printf("Bł

ą

d otwarcia %s.\n", str);


return FAIL;

}

--------------------



#include <stdio.h>

#include <string.h>

enum {SUCCESS, FAIL};

void BlkWrite(FILE *fout, char *str);

main(void)

{

FILE *fptr;

char filename[]= "test_21.txt";

char str[]= "Plik dyskowy I/O ";

int reval = SUCCESS;


if ((fptr = fopen(filename, "w")) == NULL){

printf("Bł

ą

d otwarcia %s.\n", filename);


reval = FAIL;

} else {

BlkWrite(fptr, str);

background image

190


fclose(fptr);

}


return reval;

}

/* definicja funkcji */

void BlkWrite(FILE *fout, char *str)

{

int num;


num = strlen(str);

fwrite(str, sizeof(char), num, fout);

printf("%s\n", str);

}











Dostep sekwencyjny i bezpo

ś

redni do pliku.


Zapis/Odczyt pliku od pocz

ą

tku bajt po bajcie, z mo

ż

liwo

ś

cia

dopisania danych na ko

ń

cu pliku nazywamy dospepem sekwencyjnym

do pliku,

Poszukiwanie informacji w pliku o taki dost

ę

pie odbywa si

ę

poprzez przegl

ą

ganie informacji od pierwszego bajtu zawartego

w pliku.

W przypadku pliku o dost

ę

pie swobodnym elementy danych mog

ą

by

ć

odczytywane w dowolnej kolejno

ś

ci /bez konieczno

ś

ci

odczytywania wszystkich poprzednich danych/.

background image

191

Jednym z elementów struktury FILE jest znacznik pozycji pliku,
który mo

ż

na ustawi

ć

na poprzedniej pozycji przed operacj

ą

zapisu lub odczytu.

Funkcja fseek() - słu

ż

y do przesuwania znacznika pozycji we

wła

ś

ciwe miejsce w obr

ę

bie pliku.


#include <stdio.h>

int fseek(FILE *stream, long offset, int relation);

stream - wska

ź

nik plikowy skojarzony z otwartym plikiem


offset - oznacza przesuni

ę

cie w bajtach od punktu okre

ś

lonego

przez trzeci argument

relation - punkt odniesienia, od którego rozpoczyna si

ę

odliczania

SEEK_SET - licz

ą

c od pocz

ą

tku pliku


SEEK_CUR - licz

ą

c od bie

żą

cej pozycji znacznika w pliku


SEEK_END - licz

ą

c od ko

ń

ca pliku


je

ż

eli operacja powiedzie si

ę

funkcja fseek() zwraca 0, w

przeciwnym przypadku warto

ść

ż

n

ą

od zera.


Je

ż

eli


relation = SEEK_SET offset > 0

relation = SEEK_END offset < 0

relation = SEEK_CUR

Aby odczyta

ć

bie

żą

c

ą

pozycj

ę

znacznika w pliku - funkcja

ftell()

#include <stdio.h>

long ftell(FILE *stream);

stream - wska

ź

nik plikowy skojarzony z otwartym plikiem


Funkcja zwraca bie

żą

c

ą

warto

ść

/typu long/ pozycji znacznika

licz

ą

c do bie

żą

cej pozycji od pocz

ą

tku pliku w bajtach. Je

ż

eli

wystapi bł

ą

d zwraca


-1L.

background image

192



Swobodny dost

ę

p do pliku.












//p_100

/* Dost

ę

p swobodny do pliku */


#include <stdio.h>

enum {SUCCESS, FAIL, MAX_LEN = 80};

void PtrSeek(FILE *fptr);

long PtrTell(FILE *fptr);

void DataRead(FILE *fptr);

int ErrorMsg(char *str);

main(void)

{

FILE *fptr;

char filename[]= "haiku.txt";

int reval = SUCCESS;

clrscr();

if ((fptr = fopen(filename, "r")) == NULL){

reval = ErrorMsg(filename);

} else {

PtrSeek(fptr);

fclose(fptr);

background image

193


}

getch();

return reval;

}

void PtrSeek(FILE *fptr)

{

long offset1, offset2, offset3;


offset1 = PtrTell(fptr);

DataRead(fptr);

offset2 = PtrTell(fptr);

/* skok do 3 wiersza haiku */

fseek(fptr, 26L, SEEK_CUR);

offset3 = PtrTell(fptr);

DataRead(fptr);

printf("\nodczyt z haiku:\n");

/* ponowny odczyt 3 wiersza haiku */

fseek(fptr, offset3, SEEK_SET);

DataRead(fptr);

/* odczyt 2 wiersza haiku */

fseek(fptr, offset2, SEEK_SET);

DataRead(fptr);

/* odczyt 1 wiersza haiku */

fseek(fptr, offset1, SEEK_SET);

DataRead(fptr);

background image

194

}

long PtrTell(FILE *fptr)

{

long reval;


reval = ftell(fptr);

printf(" fptr jest w %ld\n", reval);

return reval;

}

void DataRead(FILE *fptr)

{

char buff[MAX_LEN];

fgets(buff, MAX_LEN, fptr);

printf("---%s", buff);

}

int ErrorMsg(char *str)

{

printf("Bł

ą

d otwarcia \n", str);


return FAIL;

}

----------------------



#include <stdio.h>


enum {SUCCESS, FAIL, MAX_LEN = 80};

void PtrSeek(FILE *fptr);

long PtrTell(FILE *fptr);

background image

195


void DataRead(FILE *fptr);

int ErrorMsg(char *str);


main(void)

{

FILE *fptr;

char filename[]= "LaoTzu.txt";

int reval = SUCCESS;

clrscr();

if ((fptr = fopen(filename, "r")) == NULL){

reval = ErrorMsg(filename);

} else {

PtrSeek(fptr);

fclose(fptr);

}

getch();

return reval;

}

void PtrSeek(FILE *fptr)

{

long offset1, offset2, offset3;


offset1 = PtrTell(fptr);

DataRead(fptr);

offset2 = PtrTell(fptr);

DataRead(fptr);

background image

196

offset3 = PtrTell(fptr);

DataRead(fptr);

printf("\nPonowny odczyt paragrafu:\n");

/* 3-ej sentencji */

fseek(fptr, offset3, SEEK_SET);

DataRead(fptr);

/* 2-ej sentencji */

fseek(fptr, offset2, SEEK_SET);

DataRead(fptr);

/* 1-szej sentencji */

fseek(fptr, offset1, SEEK_SET);

DataRead(fptr);

}

long PtrTell(FILE *fptr)

{

long reval;


reval = ftell(fptr);

printf(" fptr jest w %ld\n", reval);

return reval;

}

void DataRead(FILE *fptr)

{

char buff[MAX_LEN];


fgets(buff, MAX_LEN, fptr);

printf("%s", buff);

background image

197


}

int ErrorMsg(char *str)

{

printf("Bł

ą

d otwarcia %s.\n", str);


return FAIL;

}



Funkcja rewind() - cofni

ę

cie znacznika pozycji na pocz

ą

tek

pliku

#include <stdio.h>

void rewind(FILE *stream);

stream - wska

ź

nik plikowy skojarzony z otwartym plikiem






Zatem równowa

ż

ne s

ą

:


rewind(ftpr); i fseek(ftpr, 0L, SEEK_SET);





Odczyt i zapis danych w trybie binarnym.

Otwarcie instniej

ą

cego pliku binarnego w trybie tylko do

odczytu.

fprt = fopen(”test.bin”, ”rb”);



Odczyt i zapis danych binarnych

//p_101

/* Zapis i odczyt danych binarnych */

background image

198

#include <stdio.h>

enum {SUCCESS, FAIL, MAX_NUM = 3};

void DataWrite(FILE *fout);

void DataRead(FILE *fin);

int ErrorMsg(char *str);

main(void)

{

FILE *fptr;

char filename[]= "double.bin";

int reval = SUCCESS;

clrscr();

if ((fptr = fopen(filename, "wb+")) == NULL)

{

reval = ErrorMsg(filename);

} else

{

DataWrite(fptr);

rewind(fptr);

DataRead(fptr);

fclose(fptr);

}

getch();

return reval;

}

void DataWrite(FILE *fout)

{

background image

199


int i;

double buff[MAX_NUM] = {

123.45,

567.89,

100.11};


printf("Wielko

ść

buff: %d-bajty\n", sizeof(buff));


for (i=0; i<MAX_NUM; i++){

printf("%5.2f\n", buff[i]);

fwrite(&buff[i], sizeof(double), 1, fout);

}

}

void DataRead(FILE *fin)

{

int i;

double x;


printf("\nCzytanie z pliku binarnego :\n");

for (i=0; i<MAX_NUM; i++){

fread(&x, sizeof(double), (size_t)1, fin);

printf("%5.2f\n", x);

}

}

int ErrorMsg(char *str)

{

printf("Bł

ą

d otwarcia %s.\n", str);

background image

200

return FAIL;

}

---------------------



#include <stdio.h>


enum {SUCCESS, FAIL, MAX_LEN = 80};

void PtrSeek(FILE *fptr);

long PtrTell(FILE *fptr);

void DataRead(FILE *fptr);

int ErrorMsg(char *str);


main(void)

{

FILE *fptr;

char filename[]= "LaoTzu.txt";

int reval = SUCCESS;

clrscr();

if ((fptr = fopen(filename, "r")) == NULL){

reval = ErrorMsg(filename);

} else {

PtrSeek(fptr);

fclose(fptr);

}

getch();

return reval;

}

background image

201


void PtrSeek(FILE *fptr)

{

long offset1, offset2, offset3;


offset1 = PtrTell(fptr);

DataRead(fptr);

offset2 = PtrTell(fptr);

DataRead(fptr);

offset3 = PtrTell(fptr);

DataRead(fptr);

printf("\nCzytanie paragrafu :\n");

/* 3 sentencja */

fseek(fptr, offset3, SEEK_SET);

DataRead(fptr);

/* 2 sentencja */

fseek(fptr, offset2, SEEK_SET);

DataRead(fptr);

/* 1 sentencja */

rewind(fptr); /* przewini

ę

cie pozycjonera */


DataRead(fptr);

}

long PtrTell(FILE *fptr)

{

long reval;


reval = ftell(fptr);

background image

202

printf(" fptr jest w %ld\n", reval);

return reval;

}

void DataRead(FILE *fptr)

{

char buff[MAX_LEN];


fgets(buff, MAX_LEN, fptr);

printf("%s", buff);

}

int ErrorMsg(char *str)

{

printf("Bł

ą

d otwarcia %s.\n", str);


return FAIL;

}





Funkcje fscanf() i fprintf()

Funkcje printf() i scanf() słu

żą

do zapisu i odczytu

sformatowanych danych do/z strumieni do plików standardowego
urz

ą

dzenia We/Wy (stdout,stdin).


Dla plików dyskowych s

ą

dwa odpowiedniki tych funkcji :

fprintf() i fscanf(), które dodatkowo pozwalaj

ą

wybrac

strumie

ń

danych wej

ś

cia wyj

ś

cia stream.


#include <stdio.h>

int fscanf(FILE *stream, const char *format, ...);

stream - wska

ź

nik plikowy skojarzony z otwartym plikiem, a

zastosowanie pozostałych elementów jest takie jak w finkcji
scanf()

background image

203

Funkcja zwraca liczb

ę

wczytanych argumentów lub EOF jako wynik

negatywny.



#include <stdio.h>

int fprintf(FILE *stream, const char *format, ... );

stream - wskaxnik plikowy skojarzony z otwartym plikiem,
zastosowanie pozostałych argumentów jest takie jak w funkcji
printf().

Funkcja zwraca liczb

ę

sformatowanych wyra

ż

e

ń

lub warto

ść

ujemn

ą

w przypadku negatywnym.


Zastosowanie funkcji fprintf() i fscanf().

//p_102

/* fscanf() i fprintf() */

#include <stdio.h>

enum {SUCCESS, FAIL,

MAX_NUM = 3,

STR_LEN = 23};

void DataWrite(FILE *fout);

void DataRead(FILE *fin);

int ErrorMsg(char *str);

main(void)

{

FILE *fptr;

char filename[]= "strnum.mix";

int reval = SUCCESS;

clrscr();

if ((fptr = fopen(filename, "w+")) == NULL){

reval = ErrorMsg(filename);

background image

204


} else {

DataWrite(fptr);

rewind(fptr);

DataRead(fptr);

fclose(fptr);

}

getch();

return reval;

}

void DataWrite(FILE *fout)

{

int i;

char cities[MAX_NUM][STR_LEN] = {

"St.Louis->Houston:",

"Houston->Dallas:",

"Dallas->Philadelphia:"};

int miles[MAX_NUM] = {

845,

243,

1459};


printf("Zapis danych:\n");

for (i=0; i<MAX_NUM; i++){

printf("%-23s %d\n", cities[i], miles[i]);

fprintf(fout, "%s %d", cities[i], miles[i]);

}

background image

205


}

void DataRead(FILE *fin)

{

int i;

int miles;

char cities[STR_LEN];


printf("\nCzytanie danych:\n");

for (i=0; i<MAX_NUM; i++){

fscanf(fin, "%s%d", cities, &miles);

printf("%-23s %d\n", cities, miles);

}

}

int ErrorMsg(char *str)

{

printf("Bł

ą

d otwarcia %s.\n", str);


return FAIL;

}

------------------



#include <stdio.h>

enum {SUCCESS, FAIL};

void DataWrite(FILE *fout);

void DataRead(FILE *fin);

int ErrorMsg(char *str);

main(void)

background image

206


{

FILE *fptr;

char filename[]= "data.bin";

int reval = SUCCESS;

clrscr();

if ((fptr = fopen(filename, "wb+")) == NULL){

reval = ErrorMsg(filename);

} else {

DataWrite(fptr);

rewind(fptr);

DataRead(fptr);

fclose(fptr);

}

getch();

return reval;

}

void DataWrite(FILE *fout)

{

double dnum;

int inum;



dnum = 123.45;

inum = 10000;


printf("%5.2f\n", dnum);

fwrite(&dnum, sizeof(double), 1, fout);

background image

207


printf("%d\n", inum);

fwrite(&inum, sizeof(int), 1, fout);

}

void DataRead(FILE *fin)

{

double x;

int y;


printf("\nCzytanie z pliku binarnego:\n");

fread(&x, sizeof(double), (size_t)1, fin);

printf("%5.2f\n", x);

fread(&y, sizeof(int), (size_t)1, fin);

printf("%d\n", y);

}

int ErrorMsg(char *str)

{

printf("Bł

ą

d otwarcia %s.\n", str);


return FAIL;

}







Funkcja freopen()

Standardowy przepływ strumieni danych mo

ż

na zmieni

ć

np. tak

aby strumienie stdin i stdout skojarzy

ć

z plikami dyskowymi.

U

ż

ywana do tego celu funkcja freopen().


#include <stdio.h>

background image

208


FILE *freopen(const char *filename, const char *mode, FILE
*stream);

const char *filename - wska

ź

nik do stałego ła

ń

cucha znaków,

nazwy plików

Chodzi tu o ten plik, który nale

ż

y skojarzy

ć

ze standardowym

strumieniem (trzeci argument funkcji)

FILE *stream - wska

ź

nik do standardowego strumienia, który

nale

ż

y skojarzy

ć

z plikiem.


mode - wska

ź

nik typu *char wskazuj

ą

cy ła

ń

cuch znaków

okre

ś

laj

ą

cy tryb otwarcia danego pliku dyskowego; argument ten

mo

ż

e przybiera

ć

tu te same warto

ś

ci, co w przypadku funkcji

fopen();

Funkcja freopen() zwraca pusty wska

ź

nik w przypadku

wyst

ą

pienia bł

ę

du, w przeciwnym przypadku zwraca standardowy

strumie

ń

/wska

ź

nik typu FILE */. Ten standardowy strumie

ń

zostaje skojarzony z plikiem zadanym przez pierwszy argument
funkcji filename.







Skierowanie standardowego strumienia stdout do pliku dyskowego

//p_103

/* Zmiana kierunku przepˆywu standardowego srtumienia danych
*/

#include <stdio.h>

enum {SUCCESS, FAIL,

STR_NUM = 4};


void StrPrint(char **str);

int ErrorMsg(char *str);

main(void)

{

background image

209


char *str[STR_NUM] = {

"Be bent, and you will remain straight.",

"Be vacant, and you will remain full.",

"Be worn, and you will remain new.",

"--- by Lao Tzu"};

char filename[]= "LaoTzu.txt";

int reval = SUCCESS;

clrscr();

StrPrint(str);

if (freopen(filename, "w", stdout) == NULL)

{

reval = ErrorMsg(filename);

} else

{

StrPrint(str);

fclose(stdout);

}

getch();

return reval;

}

void StrPrint(char **str)

{

int i;


for (i=0; i<STR_NUM; i++)

printf("%s\n", str[i]);

background image

210


}

int ErrorMsg(char *str)

{

printf("Bł

ą

d otwarcia %s.\n", str);


return FAIL;

}

------------------



#include <stdio.h>


enum {SUCCESS, FAIL,

MAX_NUM = 3,

STR_LEN = 23};


void DataRead(FILE *fin);

int ErrorMsg(char *str);


main(void)

{

FILE *fptr;

char filename[]= "strnum.mix";

int reval = SUCCESS;

clrscr();

if ((fptr = freopen(filename, "r", stdin)) == NULL){

reval = ErrorMsg(filename);

} else {

DataRead(fptr);

background image

211


fclose(fptr);

}

getch();

return reval;

}

void DataRead(FILE *fin)

{

int i;

int miles;

char cities[STR_LEN];


printf("Czytanie danych :\n");

for (i=0; i<MAX_NUM; i++){

scanf("%s%d", cities, &miles);

printf("%-23s %d\n", cities, miles);

}

}

int ErrorMsg(char *str)

{

printf("Bł

ą

d otwarcia %s.\n", str);


return FAIL;

}







background image

212
























Preprocesor


Preprocesor to specjalny program pozwalaj

ą

cy na definiowanie i

kojarzenie nazw symboli ze stałymi. Preprocesor jest
uruchamiany przed kompilatorem. Przed uruchomieniem
kompilatora preprocesor przetwarza makropolecenia.
makrodefinicj

ę

mo

ż

na umie

ś

cic w dowolnym miejscu programu,

jednak makronazwa musi zosta

ć

zdefiniowana przed jej pierwszym

u

ż

yciem w programie.


Preprocesor pozwala równie

ż

na doł

ą

czanie do kodu

ź

ródłowego

programu innych plików

ź

ródłowych (stdlib.h,

strung.h,stdio.h).

Preprocesor ma własn

ą

składni

ę

.


Rozkazy jego rozpoczynaja si

ę

od znaku # i ko

ń

cz

ą

znakiem

przej

ś

cia do nowego wiersza (nie

ś

rednika jak w j

ę

zyku C);


Preprocesor C pracuje w trybie wiersz-po-wierszu.

Najcz

ęś

ciej u

ż

ywane dyrektywy preprocesora C :


#define - zdefiniuj

#undef - anuluj definicj

ę

background image

213

#if - je

ż

eli


#elif - w przeciwnym razie, je

ś

li...


#else - w przeciwnym razie

#ifdef - je

ś

li zdefiniowane jest...


#ifndef - je

ś

li nie jest zdefiniowane...


#endif - koniec bloku warunkowego

Makrorozkazy /te, które maja by

ć

zast

ą

pione stałymi/ s

ą

zazwyczaj pisane du

ż

ymi literami.










Dyrektywy #define #undef



#define macro_name macro_body

macro_name - identyfikator

macro_body - ła

ń

cuch zło

ż

ony z elementów danych zastepuj

ą

cy

identyfikator przy ka

ż

dym jego wyst

ą

pieniu w programie


np.

#define MY_NAME ‘Artur’

#define SUMA (12+3)

Dla anulowania dyrektywy #define słuzy dyrektywa #undef

#undef macro_name

np.

#undef MY_NAME ‘Artur’

Definiowanie makropolece

ń

na podobie

ń

stwo funkcji przy pomocy

dyrektywy #define

background image

214

W makronazwie definiowanej przy pomocy dyrektywy #define ,
mo

ż

na podobnie jak w przypadku funkcji definiowa

ć

jeden lub

wi

ę

cej argumentów.




#define MULTIPLY (val1,val2) ((val1)*(val2))

rezult = MULTIPLY(2,3) + 10;

Zastosowanie dyrektywy #define

//p_104











Zagnie

ż

d

ż

anie makrodefinicji


Uprzednio zdefiniowane makro mo

ż

e by

ć

zastosowane w nast

ę

pnej

definicji

#define JEDEN 1

#define DWA (JEDEN + JEDEN)

#define TRZY (JEDEN + DWA)

wynik = DWA + TRZY;

#define SUMA 12 + 8

wynik = SUMA * 10; à 92

#define SUMA (12 + 8)

wynik = SUMA * 10; à 200





Kompilacja warunkowa

background image

215

Dyrektywy #infdef i #endif
wyznaczaj

ą

pocz

ą

tek i koniec fragmentu kodu

ź

ródłowego

decyduj

ą

czy w/w fragment kodu zostanie skompilowany


#ifdef macro_name

instr1;

instr2;

instr3;

...

#endif

nacro_name - dowolny ła

ń

cuch zdefiniowany dyrektyw

ą

define


Instrukcje zostan

ą

skompilowane i wejd

ą

w skład kodu, je

ż

eli w

chwili przetwarzania identyfikator macro_name jest
zdefiniowany.



Dyrektywa #ifndef

Dyrektywa ta pozwala na warunkow

ą

kompilacj

ę

feagmentu kodu

ź

ródłowego, je

ż

eli okre

ś

lona makronazwa nie jest zdefiniowana.




#ifndef

instr1;

instr2;

instr3;

...

#endif

Zastosowanie dyrektyw : #ifdef, #ifndef, #endif

//p_105




background image

216

Dyrektywy #if, #elif, #else

Dyrektywa #if okre

ś

la warunki ewentualnej kompilacji i

ą

czenia do kodu wykonywalnego pewnych instrukcji pod

warunkiem,

ż

e wyra

ż

enie warunkowe zwróci warto

ść

niezerow

ą

(warunek spełniony). Wyra

ż

enie warunkowe mo

ż

e by

ć

np.

wyra

ż

eniem arytmetycznym.


#if wyra

ż

enie


instr1;

instr2;

instr3;

...

#endif



Przy wyborze jednej z dwu mozliwo

ś

ci :


#if

instr1;

instr2;

instr3;

...

#else

ins1;

ins2;

ins3;

...

#endif



#ifdef DEBUG

instrukcja1;

background image

217


#else

instrukcja2;

#endif



#if 1

instr1; à zawsze b

ę

dzie kompilowana


#endif

dyrektywa #elif oznacza to samo co else...if



Zastosowanie dyrektyw #if #elif #else



//p_106





Zagnie

ż

d

ż

anie bloków kompilacji warunkowej


/standard ANSI C max 8 poziomów/

#if makro1

#if makro2

#if makro3

instr1;

#else

instr2;

#endif

#else

instr3;

background image

218

#endif

#else

instr4;

#endif











Zagnie

ż

d

ż

anie dyrektywy #if


//p_107












Wyszukiwarka

Podobne podstrony:
plikus pl Programowanie strukturalne, Wyklad z C
Programowanie strukturalne i obiektowe
Programowanie strukturalne i obiektowe Podręcznik do nauki zawodu technik informatyk
dokumentacja, Zasady Programowania Strukturalnego (ZAP)
Zmienne tablicowe, INFORMATYKA, INFORMATYKA sem. III, 2.Prograowanie strukturalne i obiektowe
Programowanie strukturalne i obiektowe Podrecznik do nauki zawodu technik informatyk prstko
BLOKI, Programowanie strukturalne i obiektowe, C ++, Ćwiczenia C++ (skan)
Programowanie opracowanie, Informatyka, Informatyka semestr II, 3.Programowanie strukturalne i obiek
ALGORYTMY-PREZENTACJA, SZKOLNE PLIKI-mega zbiory (od podstawówki do magisterki), Programowanie struk
Programowanie strukturalne i obiektowe Podrecznik do nauki zawodu technik informatyk prstko 2
Systemy obliczania w praktyce, INFORMATYKA, INFORMATYKA sem. III, 2.Prograowanie strukturalne i obie
Typy danych i ich klasyfikacja, INFORMATYKA, Programowanie strukturalne i obiektowe, Semestr 1
STRING - Procedury i funkcje, Szkoła, Klasa 1, Programowanie struktularne i obiektowe

więcej podobnych podstron