background image

PODSTAWY INFORMATYKI

PODSTAWY INFORMATYKI

Wykład 3

background image

Instrukcja 

if

• Ogólna postać 

   if (wyrażenie)
       instrukcja

1

   else
       instrukcja

2

• Wykonywana jest dokładnie jedna z dwóch 

instrukcji związanych z  if-else.

• Jeśli wyrazenie jest prawdą (nie 0), to 

wykonywana jest instrukcja

1

; jeśli nie, 

wykonywana jest  instrukcja

2

.

• Każda instrukcja może być pojedynczą 

instrukcją lub ciągiem instrukcji ujętą w 
nawiasy klamrowe. 

background image

Warunki - przykłady

• if (a>b) printf(”tak!\n”);
• if (a>b && b>c) ...
• if (2+a == 3*b) ...
• if ((a>4) == (b<10)) ...
• Wartościowanie:

– od lewej do prawej
– wstrzymywane, gdy znany jest wynik:

• if (4>9 && a>n++) ...
  /* czy n będzie zwiększone? */

background image

Operatory inkrementacji

i dekrementacji

• ++
• --

• mogą być używane jako operatory prefiksowe 

(przed zmienną, np. ++n) albo postfiksowe (po 

zmiennej, np. n++)

• Przykład: jeśli n jest równe 5, to

x = n++;

ustawia x na 5, ale 

x = ++n;

ustawia x na 6; obydwa przypisania ustawiają n na 

6.

background image

Operatory bitowe

&

bitwise AND

|

bitwise inclusive OR

^

bitwise exclusive OR

<<   left shift

>> right shift

~

one's complement (unary)

background image

Operator bitowy AND

• Działa na wartościach całkowitych
• Przykład:

108

0

1

1

0

1

1

0

0

& 217

1

1

0

1

1

0

0

1

= 72

0

1

0

0

1

0

0

0

background image

Operatory bitowe - 

przykłady

• 6 & 11 = 
• 4 | 1  =
• 7 ^ 2  =
• 5 >> 2 

=

• 3 << 2=
• ~0

=


5
5
1
12
-1

(por. z !0)

background image

Ujemne liczby 

całkowite:

dlaczego ~0 jest równe 

-1

• Unsigned

0: 0000
1: 0001
2: 0010
...

  15:

1111

• Signed
  -8: 1000
  -2: 1110
  -1: 1111

0: 0000
1: 0001
2: 0010
7: 0111

...

...

background image

Strumienie wejściowe i 

wyjściowe

krótki przegląd

• Standardowe wejście:  stdin
• Standardowe wyjście:  stdout
• Stand. strumień błędów:

stderr

• Szczegóły zostaną omówione później
• Normalnie strumienie te są związane z 

konsolą:

– stdin z klawiaturą
– stdout i stderr z terminalem tekstowym

• Strumienie mogą być przekierowywane

testapp.exe <dane.txt >wyniki.txt

background image

Wejście znakowe

• Odczytanie pojedynczego znaku lub 

EOF:

int getc(FILE *stream);

powyższa deklaracja nazywana jest

 prototypem

• Przykład:

int c;
c = getc(stdin);

• Czytanie jednego znaku z stdin:

int getchar(void);

• getchar() 

działa jak 

getc(stdin)

background image

Wyjście znakowe

• Zapis pojedynczego znaku do 

strumienia:

int putc(int c, FILE *stream);

• Przykład:

putc(’A’,stdout);

• Zapis pojedynczego znaku do stdout:

int putchar(int c);

• putchar(’A’) 

działa jak 

putc(’A’,stdout)

• Zwracana wartość: wypisany znak

background image

Kopiowanie plików

#include <stdio.h>
   

/* kopiowanie wejścia na wyjście:

    pierwsza wersja  */

   main()
   {
       int c;
       c = getchar();
       while (c != ‘q
) {
           putchar(c);
           c = getchar();
       }
       return 0;
   }

background image

Kopiowanie plików - druga 

wersja

 

#include <stdio.h>

   

/* copy input to output; 2nd version  */

   main()
   {
       int c;

       while ((c = getchar()) != ‘q)
           putchar(c);
   
       return 0;
   }

background image

Liczenie znaków

 

#include <stdio.h>

   

/* count characters in input; 1st version */

   main()
   {
       long nc;

       nc = 0;
       while (getchar() != ‘q’)
           ++nc;
       printf("%ld\n", nc);
       
       return 0;
   }

background image

Liczenie znaków - druga 

wersja

  #include <stdio.h>

   

/* count characters in input; 2nd version */

   main()
   {
       double nc;
       for (nc = 0; getchar() != ‘q
; ++nc)
           ;
       printf("%.0f\n", nc);
       return 0;
   }

background image

Liczenie wierszy

 #include <stdio.h>

   

/* count lines in input */

   main()
   {
       int c, nl;

       nl = 0;  

/* the number of lines so far */

       while ((c = getchar()) != ‘q)
           if (c == '\n')  

/* new line found */

               ++nl;
       printf("%d\n", nl);
       return 0;
   }

background image

Zmienne w pamięci

• Każda zmienna pamiętana jest w 

pewnym miejscu pamięci ... lub w 

rejestrze procesora

•  

Adres

 zmiennej jest 

indeksem

 tej 

komórki pamięci, w której znajduje się 

pierwszy bajt zmiennej

• Liczba bajtów zajmowanych przez 

zmienną zależy od jej typu; operator 

sizeof informuje o tym rozmiarze: 

sizeof(type)

background image

Wskaźniki

• Wskaźnik jest adresem, pod którym 

znajduje się zwykle coś użytecznego

• Definiowanie zmiennej przechowującej 

adres:

<type> *<variable>

• Przykład:

int *pti;  

• Pobieranie adresu, pod którym 

przechowywana jest zmienna: operator &

int x;
pti = &x;

background image

Wskaźniki - dostęp do 

pamięci

int x;
pti = &x;
x = 5;
*pti = *pti + 1; 

/* teraz x = 6 

*/

x++;
printf(”%d”,x);   

/* 7 */

background image

Wskaźniki przykład

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

int main(void)
{
char*p[3]={
"tak","nie",
"byc moze.Zmien postac 

pytania„

};
char nap[80];
printf("wprowadz pytanie\n");
gets(nap);
printf(p[strlen(nap)%3]);
return 0;}

/*WYNIK:
wprowadz pytanie
tak
tak
wprowadz pytanie
Nnnnn
byc moze.Zmien postac 
pytania*/
 

background image

 scanf

• ...aby przeczytać z wejścia coś bardziej 

złożonego niż pojedynczy znak

• scanf

 jest odpowiednikiem  

printf

 

dla 

strumienia wejściowego

• udostępnia wiele podobnych konwersji 

jak 

printf

, ale w przeciwnym kierunku

• Prototyp:

int scanf(char *format, ...)

• scanf

 wymaga wskaźników do 

zmiennych 

background image

Przykład 

scanf

#include <stdio.h>

main() {

int x;
printf(” Podaj liczbę: ”);
scanf(”%d”, &x);
printf(”Kwadrat %d wynosi %d\n”, x, x*x);
return 0;

}

/*WYNIK:
Podaj liczbę:5
Kwadrat 5 wynosi 
25*/

 

background image

Tablice

• Definiują więcej “zmiennych” jedną 

definicją

• Składnia:

<typ> <zmienna>[liczba_elementów]

• Przykład:

int a[10];

• Indeksowanie: od 0 - jaki jest ostatni 

indeks?

• Dostęp:

a[5] = 17;

background image

Tablice przykład 1

#include<stdio.h>
#include<stdlib.h>

int main(void)
{
int a1[10],a2[10];
int i;
for(i=1;i<11;i++)a1[i-1]=i;
for(i=0;i<10;i++)a2[i]=a1[i];
for(i=0;i<10;i++)printf("%d\n",a2[i]);
return 0;
}

WYNI
K
1
2
3
4
5
6
7
8
9
10 

background image

Łańcuchy znakowe jako 

Łańcuchy znakowe jako 

tablice

tablice

• Definiowanie zmiennej 

przechowującej łańcuchy (teksty): 
jako tablicy znaków:

char nazwa[długość]

na przykład:

char s[20];

• Na końcu łańcucha jest znak ’\0’

• Uwaga na długość!
• Funkcje operujące na łańcuchach

background image

Operacje na 

Operacje na 

wskaźnikach

wskaźnikach

• Wskaźniki mogą być:

– porównywane
– odejmowane
– powiększane o wartość całkowitą 

(skalowaną!)

– pomniejszane o wartość całkowitą 

(skalowaną!)

• Dodanie 1 do wskaźnika powiększa 

adres

rozmiar wskazywanego typu

background image

Dodawanie liczby 

Dodawanie liczby 

całkowitej

całkowitej

do wskaźnika

do wskaźnika

double *pd;
double t[10];
pd = &(t[5]); 
printf(”%p\n”,pd); 

/* 0065FB60 */

pd = pd + 3; 
printf(”%p\n”,pd); 

/* 0065FB78 */

/* teraz pd wskazuje na t[8] */

 

0x18 = 24 
=
= 3*8

background image

Wskaźniki i tablice

Wskaźniki i tablice

• Nazwa tablicy jest synonimem 

adresu jej początkowego elementu

• Przykład:

double x[5];
double *p;
p = x;  

/* tak jak p = &(x[0]); */

*p = 12;
p++;    

/* teraz p wskazuje na x[1] */

*p = 13;

     

/* tutaj x[0]=12, x[1]=13 */

background image

Wyprowadzenie łańcucha

Wyprowadzenie łańcucha

bez użycia 

bez użycia 

printf

printf

#include <stdio.h>

main()
{
   char s[]="Hello again!\n";
   char *p;
   p=s;
   while (*p)
     putchar (*p++);

   return 0;
}

WYNIKI:
Hello again!

 

background image

Nasza pamięć

Nasza pamięć

• Człowiek dysponuje (co najmniej) 

dwoma rodzajami pamięci:

– dużą

: trwałą, ale trudną w zapisie 

(czas zapisu jest długi)

– małą

: zanikającą w ciągu kilku 

sekund, ale łatwą do zapisania

background image

Funkcje

Funkcje

• Człowiek potrafi analizować jednocześnie 

około 7 obiektów

• Co stanie się, jeśli program ma więcej niż

7 linii?

• Program należy podzielić na funkcje:

– Zapisać kilka linii kodu i nadać im nazwę
– Uruchamiać je stosując nazwę

• Oczywiście, nie jest to jedyny powód, dla 

którego należy stosować funkcje...

background image

Funkcje w języku C

Funkcje w języku C

Definicja funkcji ma następującą postać:

typ_wyniku nazwa_funkcji(opcjonalne 

deklaracje_parametrów)

{
   deklaracje
   instrukcje
}

background image

Przykład Funkcji podnoszenia do 

potęgi

 #include <stdio.h>
/* power:  podnoszenie base to n-tej potęgi;
            n >= 0 */
    int power(int base, int n)
    {
        int i, p;   /* zmienne lokalne */
        p = 1;
        for (i = 1; i <= n; ++i)
            p = p * base;
        return p;
    }
 main(){
        int i;
        for (i = 0; i < 10; ++i)
            printf("%d %d %d\n",
            i, power(2,i), power(-3,i));
        return 0;}

background image

Wyniki programu

0 1 1
1 2 –3
2 4 9
3 8 –27
4 16 81
5 32 –243
6 64 729
7 128 –2187
8 256 6561
9 512 -19683 

background image

Sterowanie - 

Sterowanie - 

dokończenie

dokończenie

• Konstrukcje poznane do tej pory:

– if
– if-else
– while
– for

• Inne:

– do-while
– switch
– break
– continue

background image

Pętla 

do-while

• Składnia:

  do

  

 instrukcja

  while (wyrazenie);

• Przyklad:

  int n;

    do {
      printf(”Podaj liczbę dodatnią: ”);
      scanf(”%d”,&n);
    } while (n<=0);

background image

do-while

 Przykład

#include<stdio.h>
main()
{

  int n;

     do {
     printf("Podaj liczbę dodatnia: ");
     scanf("%d",&n);
    } while (n<=0);
    }

background image

do-while

 Wyniki 

programu

Podaj liczbę dodatnia: -4
Podaj liczbę dodatnia: -4
Podaj liczbę dodatnia: -3
Podaj liczbę dodatnia: -2
Podaj liczbę dodatnia: -1
Podaj liczbę dodatnia: 0
Podaj liczbę dodatnia: 1 

background image

Instrukcja 

switch

Składnia:

 

switch (wyrażenie) {

  

case wyrazenie-staleinstrukcje

      

case wyrazenie-staleinstrukcje

       

default: instrukcje

 

}

Przykład:

 

switch (c=getchar()) {

   

case ’+’: 

printf("Plus");

break;

       

case ’-’: 

printf("Minus");

break;

       

default:  printf("Inny znak");

  }

background image

Przerywanie pętli

Przerywanie pętli

•Czasem potrzebne okazuje się 
przerwanie pętli w inny sposób niż 
przy testowaniu warunku

•Instrukcja 

break

 daje możliwość 

wyjścia z pętli 

forwhile

 i 

do

, tak 

jak ze 

switch

break

 powoduje, że przerywana 

jest najbardziej wewnętrzna pętla 
lub 

switch

 

 

background image

kalkulator Przykład 

switch, 

break

 

#include<stdio.h>
#include<stdlib.h>

int main(void){
int i,j;
char dz;
printf("wprowadz dzialanie\n");
scanf("%d%c%d",&i,&dz,&j);
switch(dz){
case '+':printf("%d",i+j);
break;
case'-':printf("%d",i-j);
break;
case'/':if(j)printf("%d",i/j);
break;
case'*':printf("%d",i*j);}
return 0;}

/*WYNIKI
wprowadz dzialanie
3-2
1
wprowadz dzialanie
4*5
20
wprowadz dzialanie
4+5
9
wprowadz dzialanie
4/2

*/

background image

Pomijanie iteracji:

Pomijanie iteracji:

 

 

continue

continue

• Instrukcja 

continue

 jest podobna do 

break

, jest stosowana rzadziej

• Powoduje rozpoczęcie kolejnej iteracji 

for

while

, lub 

do

 bez dokańczania 

bieżącej

• W pętli 

while

 i 

do

 oznacza to 

natychmiastowe przejście do 

testowania warunku

• W pętli 

for

, sterowanie przechodzi do 

części „inkrementującej”

• Instrukcja 

continue

 nie dotyczy 

switch

. Zastosowana w tej instrukcji 

pomija iterację pętli, w której 

umieszczono 

switch 

background image

continue

continue

: przykład

: przykład

• Przetwarzanie 

tylko 

nieujemnych 

elementów tablicy a

• Ujemne wartości są pomijane

 

 

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

 {  
    if (a[i] < 0) 

/* skip negative elements */ 

      continue;

    ...           /* do positive elements   */

 }

background image

g

g

oto

oto

 i etykiety

 i etykiety

 

 

• W  C  dostępna  jest  instrukcja 

goto

  i  etykiety  do 

opisywania celu skoku

• Formalnie, instrukcję 

goto

 można zastąpić innymi

• W praktyce łatwo jest pisać kod bez 

goto

• Sytuacja, 

której 

goto

 

jest 

przydatne: 

przerywanie  zagnieżdżonych  pętli  w  sytuacji 

wystąpienia błędu:

       

for ( 

...

 )

           for ( 

...

 ) {

               

...

               if (katastrofa)
                   goto error;
           }
       

...

   error:

       /* clean up the mess */

background image

g

g

oto

oto

: inny przykład

: inny przykład

 

 

• Ustalenie,  czy  dwie  tablice  a  i  b  mają 

wspólny element:

    for (i = 0; i < n; i++)
        for (j = 0; j < m; j++)
            if (a[i] == b[j])
                goto found;

    /* nie znaleziono wsp. elem. */

      ...
    found:

    /* znaleziono: a[i] == b[j] */

      ...

background image

Unikanie 

Unikanie 

g

g

oto

oto

 

 

• Kod  zawierający 

goto

  może  zawsze  zostać 

zapisany  bez  tej  instrukcji,  choć  czasem  wymaga 

to  wprowadzenia  dodatkowych  zmiennych  i 

wydłużenia kodu:

  found = 0;
  for (i = 0; i < n && !found; i++)
     for (j = 0; j < m && !found; j++)
         if (a[i] == b[j])
             found = 1;
  if (found)

      /* znaleziono: a[i-1] == b[j-1] */

       ...
  else

      /* nie znaleziono el. wsp. */

       ...


Document Outline