background image

 

 

Programowanie

w języku C

Programowanie

w języku C

© 2009

Grzegorz Łukawski & Maciej Lasota
Politechnika Świętokrzyska w Kielcach

Wykład nr 3:

Niejawna i jawna konwersja typów

Instrukcja warunkowa if, switch

Pętle while, do..while, for

Pętle „nieskończone”

Generowanie liczb pseudolosowych

background image

 

 

Niejawna i jawna konwersja typów

Konwersja  typów  następuje,  gdy  operacja  ma  zostać  wykonana  na 

zmiennych różnego typu (np. dodawanie liczb 

int

 i 

float

). Występuje w dwóch 

postaciach:

Konwersja  niejawna  –  wykonywana  automatycznie  przez 

kompilator gdy występuje niezgodność typów danych.

Konwersja jawna (rzutowanie) – wymuszana przez programistę 

w dowolnym miejscu programu.

background image

 

 

Konwersja niejawna

Ponieważ procesor może wykonywać bezpośrednie operacje tylko na danych 

tego  samego  typu  (z  małymi  wyjątkami),  w  przypadku  niezgodności  typów 
zawsze następuje konwersja niejawna na większy z nich.

double

float

long long

long

short

char

K

ie

ru

n

ek

 k

o

n

w

er

sj

i

int a, wynik;
float suma;
(…)
wynik   =  suma   *   a;

(int)   = (float) * (int);

(int)   = (float) * (float);

(float) = (float) * (float);

(int)

background image

 

 

int n1, n2;

// Np. n1=10, n2=1

double wynik;
(…)
wynik = n1 / 100 + n2;

// Wynik nieprawidłowy!

Konwersja niejawna

Umiejętne  stosowanie  stałych  zmiennoprzecinkowych  pozwala  „skierować” 

konwersję we właściwą stronę:

1.01

// double

5.99f

// float

wynik = n1 / 100.0 + n2;

// Wynik prawidłowy

Np.:

background image

 

 

Konwersja jawna – rzutowanie

Konwersja jawna może być wymuszona w dowolnym kierunku.

int n1, n2;
double wynik;
(…)
wynik = n1 / n2;

// Wynik nieprawidłowy!

wynik = 1.0 * n1 / n2;
wynik = (double)n1 / n2;

// Wynik prawidłowy

unsigned char m;
m = (unsigned char)(n1 / (float)n2);

(nowy_typ)zmienna

Przy konwersji typów większych na mniejsze może dojść do utraty danych!

background image

 

 

Konwersja jawna – rzutowanie

Rzutowanie  może  dotyczyć  nie  tylko  liczb,  ma  zastosowanie  również  do 

typów złożonych: 

tablic, struktur, wskaźników, funkcji...

Częste  zastosowanie  konwersji  jawnej  –  zamiana  liczb  ułamkowych  na 
całkowite:

float w1 = 7.99;

int w2 = (int)w1;

// 7 – źle

int w3 = (int)(w1 + 0.5);

// 8 – lepiej

background image

 

 

Instrukcja warunkowa if

if(war)  instrukcja;

if(war)  instrukcja1;
else     instrukcja2;

Pojedyncza „instrukcja” może być zastąpiona blokiem {}.

W  języku  C  nie  istnieje  typ  boolean  –  stwierdzenie  prawdziwości  warunku 
następuje na drodze porównania z wartością 0:

war <> 0

(Prawda)

war = 0

(Fałsz)

background image

 

 

Operatory porównania

==

Równe

!=

Różne

int liczba;
scanf(„%d”, &liczba);
if(liczba < 0)

liczba = -liczba;

float wynik;
if(a == 0) wynik = b*100;
else

wynik = b*100 / a;

>

Większe

>=

Większe lub równe

<

Mniejsze

<=

Mniejsze lub równe

UWAGA!
Jednym  z  najczęstszych  błędów  programistów  języka  C  jest  zastąpienie 

operatora porównania == operatorem przypisania =.
Błąd taki zazwyczaj nie jest sygnalizowany przez kompilator!

background image

 

 

Łączenie warunków

||

Operator lub (or)

&&

Operator i (and)

!

Operator zaprzeczenia (not)

if(a==0 && b==0) puts(„ZERO”);

if(suma>0 && (c==1 || d==1)) {

suma = suma*2;
printf(„Suma = %d\n”, suma);

}
else

puts(„Niewłaściwe wartości”);

Ponieważ operatory porównania mają wyższy priorytet niż operatory logiczne, 

nie trzeba stosować dodatkowych nawiasów.

if(!(a==1 && b==10))

puts(„ERR”);

background image

 

 

Operator przypisania w instrukcji if()

int x, y, z;

scanf(„%d”, &x);

// Wczytanie x

scanf(„%d”, &y);

// Wczytanie y

if(

z = x+y

)

printf(„%d\n”, 100 / z);

else

printf(„Nie dziel przez zero!\n”);

int n;

scanf(„%d”, &n);

// Wczytanie n

if(

n = 0

) {

puts(„Należy podać liczbę różną od 0!”);

exit(0);

}

background image

 

 

Instrukcja warunkowa switch – decyzja wielowariantowa

Instrukcja  switch  zastępuje  serię  instrukcji  if,  pozwala  porównać  wartość 
zmiennej do wielu wartości stałych.

switch(zmienna) {

case W1:

instr1;

break;

case W2:

instr2;

break;

default:

instr3;

}

if(zmienna == W1)

instr1;

else if(zmienna == W2)

instr2;

else

instr3;

background image

 

 

Operator przypisania warunkowego

Jeśli  warunek  jest  spełniony,  zwracana  jest  wartość1,  w przeciwnym 
wypadku wartość2.

warunek ? wartość1 : wartość2

int a, b;

(…)

int max = (a>b) ? a : b;

int x, y, w;

w = (y!=0) ? (x/y) : INT_MAX;

int a, b;

(…)

int max;

if(a>b) 

max = a;

else

max = b;

puts((ocena >= 3.0) ? "Zaliczenie" : "Nie zaliczone");

background image

 

 

Instrukcje pętli w języku C

W języku C istnieją 4 rodzaje pętli:

while() - standardowa pętla z warunkiem na początku;

do..while() - pętla z warunkiem na końcu;

for() - rozszerzenie pętli while() z iteratorem.

background image

 

 

Pętla while()

Typowa  pętla  z  warunkiem  na  początku.  Zasady  dotyczące  warunku  są 

identyczne jak dla instrukcji if().

while(warunek) instrukcja;

while(warunek) {

instr1;
instr2;
(…)

}

background image

 

 

Pętla do...while()

Typowa pętla while() z warunkiem na końcu:

do

instrukcja

while(warunek);

do {

instr1;
instr2;
(…)

} while(warunek);

UWAGA!
Wszystkie  pętle  w  języku  C  wykonują  się  tak  długo  jak  warunek  pętli 

jest spełniony! Dotyczy to także pętli typu do...while().

background image

 

 

Typowe użycie pętli for():

int n;

for(n=0;n < 10;n=n+1)

instr;

/* n = 0..9 */

Pętla for()

Rozszerzenie  pętli  typu  while()  z  iteratorem,  wykorzystuje  zmienną 

licznikową:

for(start;warunek;koniec)

instrukcja;

start

- instrukcja wykonywana raz przed pierwszą iteracją (opcja);

warunek - warunek wykonywania pętli – jak dla while();

koniec

- instrukcja wykonywana po każdym przejściu pętli (opcja).

Zgodnie ze standardem C99 możliwe jest definiowanie zmiennej licznikowej 

wewnątrz instrukcji for():

for(

int

 n=0;n < 10;n=n+1)

instr;

background image

 

 

Pętla for() - przykłady

Mniej typowe użycie:

for(int n=1000;n != 0;n=n/10)

instr;

/* n = 1000, 100, 10, 1 */

Fraza początkowa i końcowa może składać się z kilku instrukcji:

for(m=0,n=100;m < 10;m=m+1,n=n-10)

instr;

/* Pętla z dwoma licznikami */

/* m = 0..9, n = 100,90,80..10 */

Licznikiem  pętli  może  być  dowolna  zmienna,  również  liczba 

zmiennoprzecinkowa:

float kat;

for(kat=0;kat < 2*M_PI;kat = kat+M_PI/6)

/* kat w zakresie <0 , 2Pi) */

Uwaga! W tym wypadku należy unikać operatorów porównania == oraz !=.

background image

 

 

Pętle zagnieżdżone

int szer=640, wys=480;
int kolor;

for(int x=0;x < szer;x++)

 {

for(int y=0;y < wys;y++)

 {

kolor = 

GetPixel

(x, y);

kolor = kolor + 33;
if(kolor > 255) kolor = 255;

PutPixel

(x, y, kolor);

}

}

background image

 

 

Operatory inkrementacji ++ i dekrementacji --

Jednoargumentowe  operatory  ++  (inkrementacja)  i  --  (dekrementacja) 

działają tylko na pojedynczych zmiennych.

int wynik, liczba = 5;
wynik = (

liczba++

)+3;

// Zwiększenie po użyciu

// wynik = 8, liczba = 6

int wynik, liczba = 5;
wynik = (

++liczba

)+3;

// Zwiększenie przed użyciem

// wynik = 9, liczba = 6

int wynik, liczba = 5;
wynik = (

liczba--

)+3;

// Zmniejszenie po użyciu, itd.

// wynik = 8, liczba = 4

zmienna++;  zmienna--;

background image

 

 

Pętle „nieskończone”

while(1) {…}

for(;;) {…}

Instrukcja break przerywa najciaśniej otaczającą pętlę.

Instrukcja continue wymusza kolejną iterację pętli.

int liczba;long suma = 0;

printf(„Podawaj liczby dodatnie, zero na koniec:”);
while(1) {

scanf(„%d”,&liczba);

suma = suma + liczba;

}
printf(„Suma = %ld”,suma);

if(liczba == 0)

break;

if(liczba < 0)

continue;

background image

 

 

Generowanie liczb pseudolosowych

Funkcja generująca liczby:

rand()

Zakres generowanych liczb:

0..RAND_MAX   (co najmniej 32767)

Inicjalizacja generatora:

srand(seed)

Z użyciem czasu:

srand(time(NULL))

Może być konieczne dołączenie nagłówka <time.h>

Generator  należy  zainicjować  tylko  raz  na  początku  programu. 

Niezainicjowany  generator  może  generować  identyczne  ciągu  liczb  po 
każdym uruchomieniu programu.

Najprostszy (prymitywny) sposób na zawężenie zakresu generowanych liczb 

to użycie operatora modulo:

x = rand() % 10 ;

// 0..9

y = 100 + rand() % 101;

// 100..200

z = -5 + rand() % 11;

// -5..5


Document Outline