background image

WYKŁADY cz.2 v.3 (2008)          Podstawy programowania 1           

(dr.inŜ Marcin Głowacki)

  1 

 

 

 

PODSTAWY 

PROGRAMOWANIA

 

 

 

 

 

kurs I - część 2 

 

 

 

 

 

PROWADZĄCY: dr inŜ. Marcin Głowacki

 

E-Mail: 

Marcin.Glowacki@pwr.wroc.pl

 

Pok.907 C-5  

 

Wrocław 2008 

background image

WYKŁADY cz.2 v.3 (2008)          Podstawy programowania 1           

(dr.inŜ Marcin Głowacki)

  2 

3.

INSTRUKCJE WEJŚCIA – WYJŚCIA 

 
Operacje wejścia-wyjścia słuŜą do bezpośredniej komunikacji uŜytkownika z programem 
poprzez ekran i klawiaturę oraz do zapisu i odczytu danych z plików a takŜe urządzeń 
peryferyjnych. 
 
W języku C występują funkcje

 standardowe wejścia-wyjścia 

zdefiniowane w pliku 

nagłówkowym (ang. header) 

<stdio.h> 

 

 
W C++ uŜywane są obiekty klas 

istream 

i

 ostream

 tzw. strumienie wejścia – wyjścia (ang. 

streams). 

 

INSTRUKCJE WYJŚCIA

 

 
Funkcja

 printf 

 

int 

printf 

( const char *format [, argumenty]... ); 

 
Inne funkcje z rodziny printf to: 
fprintf, sprintf i snprintf 

 
Parametry: 

format

 – ciąg znaków definiujący format, w jakim zostaną wypisane kolejne argumenty  

 

%

[

flagi

] [

szerokość

] [.

precyzja

] [{h | l | I | I32 | I64}]

typ 

• 

określenie 

typu

 formatu.  

opcjonalne uŜycie dowolnej liczby flag,  

opcjonalne określenie minimalnej szerokości pola, 

opcjonalne określenie precyzji – dokładności wyświetlanych liczb,  

opcjonalne określenie rozmiaru argumentu, 

Typ 

Funkcje z rodziny 

printf

 obsługują następujące typy formatów: 

• 

di

 - argument typu int jest przedstawiany jako liczba całkowita ze znakiem w postaci  

[-]ddd

.  

• 

ouxX

 - argument typu unsigned int jest przedstawiany jako nieujemna liczba 

całkowita zapisana w systemie oktalnym (

o

), dziesiętnym (

u

) lub heksadecymalnym (

x

 i 

X

).  

• 

fF

 - argument typu double jest przedstawiany w postaci 

[-]ddd.ddd

.  

background image

WYKŁADY cz.2 v.3 (2008)          Podstawy programowania 1           

(dr.inŜ Marcin Głowacki)

  3 

• 

eE

 - argument typu double jest reprezentowany w postaci 

[i]d.ddde+dd

, gdzie liczba 

przed kropką dziesiętną jest róŜna od zera, jeŜeli liczba jest róŜna od zera, a + oznacza 
znak wykładnika. Format E uŜywa wielkiej litery E zamiast małej.  

• 

gG

 - argument typu double jest reprezentowany w formacie takim jak f lub e 

(odpowiednio F lub E) zaleŜnie od liczby znaczących cyfr w liczbie oraz określonej 
precyzji.  

• 

aA

 - argument typu double przedstawiany jest w formacie [-]0xh.hhhp+d czyli 

analogicznie jak dla e i E, tyle Ŝe liczba zapisana jest w systemie heksadecymalnym.  

• 

c

 - argument typu int jest konwertowany do unsigned char i wynikowy znak jest 

wypisywany. JeŜeli podano modyfikator rozmiaru l argument typu wint_t konwertowany 
jest do wielobajtowej sekwencji i wypisywany.  

• 

s

 - argument powinien być typu wskaźnik na char (lub wchar_t). Wszystkie znaki z 

podanej tablicy, aŜ do i z wyłączeniem znaku null są wypisywane.  

• 

p

 - argument powinien być typu wskaźnik na void. Jest to konwertowany na serię 

drukowalnych znaków w sposób zaleŜny od implementacji.  

• 

n

 - argument powinien być wskaźnikiem na liczbę całkowitą ze znakiem, do którego 

zapisana jest liczba zapisanych znaków.  

 

Flagi 

W sekwencji moŜliwe są następujące flagi: 

• 

-

 (minus) oznacza, Ŝe pole ma być wyrównane do lewej, a nie do prawej.  

• 

+

 (plus) oznacza, Ŝe dane liczbowe zawsze poprzedzone są znakiem (plusem dla liczb 

nieujemnych lub minusem dla ujemnych).  

• 

spacja

 oznacza, Ŝe liczby nieujemne poprzedzone są dodatkową spacją; jeŜeli flaga plus i 

spacja są uŜyte jednocześnie to spacja jest ignorowana.  

• 

#

 (

hash

) powoduje, Ŝe wynik jest przedstawiony w alternatywnej postaci:  

dla formatu 

o

 powoduje to zwiększenie precyzji, jeŜeli jest to konieczne, aby na 

początku wyniku było zero;  

dla formatów 

x

 i 

X

 niezerowa liczba poprzedzona jest ciągiem 

0x

 lub 

0X

;  

dla formatów 

aAeEfFg, G

 wynik zawsze zawiera kropkę nawet jeŜeli nie 

ma za nią Ŝadnych cyfr;  

dla formatów 

g

 i 

G

 końcowe zera nie są usuwane.  

• 

0

 (

zero

) dla formatów 

diouxXaAeEfFgG

 do wyrównania pola 

wykorzystywane są zera zamiast spacji za wyjątkiem wypisywania wartości 
nieskończoność i NaN. JeŜeli obie flagi 

0

 i 

-

 są obecne to flaga zero jest ignorowana. Dla 

formatów 

diouxX

 jeŜeli określona jest precyzja flaga ta jest ignorowana.  

background image

WYKŁADY cz.2 v.3 (2008)          Podstawy programowania 1           

(dr.inŜ Marcin Głowacki)

  4 

Szerokość pola i precyzja 

Minimalna szerokość pola oznacza ile najmniej znaków ma zająć dane pole. JeŜeli wartość po 

formatowaniu zajmuje mniej miejsca jest ona wyrównywana spacjami z lewej strony (chyba, Ŝe 
podano flagi, które modyfikują to zachowanie). Domyślna wartość tego pola to 0. 
Precyzja dla typów formatów określa: 

• 

dioux, X

 - minimalną liczbę cyfr, które mają być wyświetlone i ma domyślną 

wartość 1;  

• 

aAeEf , F

 - liczbę cyfr, które mają być wyświetlone po kropce i ma domyślną 

wartość 6; 

• 

gG

 - liczbę cyfr znaczących i ma domyślną wartość 1;  

• 

s

 - maksymalną liczbę znaków, które mają być wypisane.  

Szerokość pola moŜe być albo dodatnią liczbą zaczynającą się od cyfry róŜnej od zera albo 

gwiazdką. Podobnie precyzja z tą róŜnicą, Ŝe jest jeszcze poprzedzona kropką. Gwiazdka 
oznacza, Ŝe brany jest kolejny z argumentów, który musi być typu int. Wartość ujemna przy 
określeniu szerokości jest traktowana tak jakby podano flagę - (minus). 

 
Rozmiar argumentów: 

[{h | l | I | I32 | I64}]

 

Dla formatów 

oraz 

i

 moŜna uŜyć jednego z przykładowych modyfikatorów rozmiaru: 

• 

h

 - oznacza, Ŝe format odnosi się do argumentu typu 

short

,  

• 

l

 (małe L) - oznacza, Ŝe format odnosi się do argumentu typu 

long

,  

• 

I32

 – oznacza, Ŝe format odnosi się do argumentu typu 

_int32

 

• 

I64

 – oznacza, Ŝe format odnosi się do argumentu typu 

_int32

 

• 

I

 - oznacza, Ŝe format odnosi się do argumentu typu 

ptrdiff_t

, który jest 

__int32

 na 

platformach 32-bitowych oraz 

__int64

 na 64-bitowych 

Dla formatów typu 

o, u, x, X

 moŜna uŜyć takich samych modyfikatorów rozmiaru jak dla 

formatu 

d

 i oznaczają one, Ŝe format odnosi się do argumentu odpowiedniego typu bez znaku, a 

dla rozmiaru I oznacza, Ŝe format odnosi się do argumentu typu 

size_t

, który jest 

unsigned 

__int32

 na platformach 32-bitowych oraz 

unsigned __int64

 na 64-bitowych 

Dla formatu typu 

n

 moŜna uŜyć takich samych modyfikatorów rozmiaru jak dla formatu 

d

 i 

oznaczają one, Ŝe format odnosi się do argumentu będącego wskaźnikiem na dany typ. 
 

Wartość zwracana 

 

JeŜeli funkcje zakończą się sukcesem zwracają 

liczbę znaków

 w tekście 

wypisanym na 

standardowe wyjście

, do podanego strumienia lub tablicy znaków, nie wliczając kończącego '\0'. 

W przeciwnym wypadku zwracana jest liczba ujemna. 
 

Znaki specjalne 

 

Aby wydrukować znaki specjalne naleŜy je poprzedzić znakiem backslash: 

printf("Procent: %% Backslash: \\");

 

 

Efekt:  

Procent: % Backslash: \ 

background image

WYKŁADY cz.2 v.3 (2008)          Podstawy programowania 1           

(dr.inŜ Marcin Głowacki)

  5 

Dygresja: 

Funkcja 

wprintf

 jest wersją z szerokimi znakami (ang.wide-character) funkcji printf; format jest 

wtedy ciągiem wchar_t . Funkcje wprintf and printf zachowują się identycznie.  

API (ang. Application Programming Interface) z „wąskimi” znakami nadaje się tylko do 
kodowań, w których jeden znak zajmuje jeden bajt.  

API z „szerokimi” znakami nadaje się do dowolnych kodowań obsługiwanych przez system, przy 
czym programista musi podawać ciągi wchar_t (jeden cchar_t moŜe zawierać kilka wchar_t, jeśli 
to jest znak z osobno kodowanymi akcentami)

 

Przykład:

 [msdn.microsoft.com

 

// crt_printf.c 
/* This program uses the printf function 
 * to produce formatted output. 
 */ 
 
#include <stdio.h> 
 
int main(void){ 
char   ch = 'h', *string = "computer"; 
int    count = -9234; 
double fp = 251.7366; 
wchar_t wch = L'w', *wstring = L"Unicode"; 
 
/* Display integers. */ 
   printf( "Integer formats:\n" 
           "   Decimal: %d  Justified: %.6d  Unsigned: %u\n", 
           count, count, count ); 
   printf( "Decimal %d as:\n   Hex: %Xh  C hex: 0x%x  Octal: %o\n", 
            count, count, count, count ); 
   /* Display in different radixes. */ 
   printf( "Digits 10 equal:\n   Hex: %i  Octal: %i  Decimal: %i\n", 
            0x10, 010, 10 ); 
   /* Display characters. */ 
 
   printf("Characters in field (1):\n%10c%5hc%5C%5lc\n", ch, ch, wch, wch); 
   wprintf(L"Characters in field (2):\n%10C%5hc%5c%5lc\n", ch, ch, wch, wch); 
 
   /* Display strings. */ 
   printf("Strings in field (1):\n%25s\n%25.4hs\n   %S%25.3ls\n", 
   string, string, wstring, wstring); 
   wprintf(L"Strings in field (2):\n%25S\n%25.4hs\n   %s%25.3ls\n", 
       string, string, wstring, wstring); 

background image

WYKŁADY cz.2 v.3 (2008)          Podstawy programowania 1           

(dr.inŜ Marcin Głowacki)

  6 

 
   /* Display real numbers. */ 
   printf( "Real numbers:\n   %f %.2f %e %E\n", fp, fp, fp, fp ); 
 
   /* Display pointer. */ 
   printf( "\nAddress as:   %p\n", &count); 
 
   /* Count characters printed. */ 
   printf( "\nDisplay to here:\n" ); 
   printf( "1234567890123456%n78901234567890\n", &count ); 
   printf( "   Number displayed: %d\n\n", count ); 

Efekt: 

Integer formats: 
   Decimal: -9234  Justified: -009234  Unsigned: 4294958062 
Decimal -9234 as: 
   Hex: FFFFDBEEh  C hex: 0xffffdbee  Octal: 37777755756 
Digits 10 equal: 
   Hex: 16  Octal: 8  Decimal: 10 
Characters in field (1): 
         h    h    w    w 
Characters in field (2): 
         h    h    w    w 
Strings in field (1): 
                 computer 
                     comp 
   Unicode                      Uni 
Strings in field (2): 
                 computer 
                     comp 
   Unicode                      Uni 
Real numbers: 
   251.736600 251.74 2.517366e+002 2.517366E+002 
 
Address as:   0022FF6C 
 
Display to here: 
123456789012345678901234567890 
   Number displayed: 16

 

background image

WYKŁADY cz.2 v.3 (2008)          Podstawy programowania 1           

(dr.inŜ Marcin Głowacki)

  7 

Funkcja

 puts 

 

Identyczna w działaniu do wywołania: printf("%s\n", argument); moŜe jednak działać szybciej. 
Zawsze na końcu wysyłany jest znak przejścia do nowej linii. 

 

Przykład:

 

 

#include <stdio.h> 
 
int main(void){ 
  puts("Hello world!"); 
  return 0; 

Efekt: 
Hello world! 
 

Funkcja

 fputs 

 
Podobnie jak puts, z argumentem określającym strumień wyjścia, np. stdout lub pliku, który 
został wcześniej otwarty do zapisu. Działa bez wypisania na końcu znaku przejścia do nowej 
linii. 
 

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

  fputs("Hello world!\n", stdout); // lub stderr 
  return 0; 

 
Efekt: 
Hello world! 
 

Funkcja

 putchar 

 
SłuŜy do wypisywania pojedynczych znaków. Przykładowo jeŜeli chcielibyśmy napisać program 
wypisujący w prostej tabelce wszystkie liczby od 0 do 99 moglibyśmy to zrobić tak:  
 

include <stdio.h> 
 
int main(void) { 
  int i = 0; 
  for (; i<100; ++i) { 
    /* Nie jest to pierwsza liczba w wierszu */ 
    if (i % 10) { 

background image

WYKŁADY cz.2 v.3 (2008)          Podstawy programowania 1           

(dr.inŜ Marcin Głowacki)

  8 

      putchar(' '); 
    } 
    printf("%2d", i); 
    /* Jest to ostatnia liczba w wierszu */ 
    if ((i % 10)==9) { 
      putchar('\n'); 
    } 
  } 
  return 0; 

 

INSTRUKCJE WEJŚCIA 

 

Funkcja

 scanf 

 

Funkcja wczytuje dane ze standardowego strumienia wejścia stdin, które zwykle podłączone 

jest do klawiatury, ale moŜe równieŜ być dołączone w systemie operacyjnym do innego 
strumienia wyjścia niŜ bufor obsługi klawiatury. WaŜny jest nowy operator: 

&

, gdyŜ bez niego 

funkcja scanf() nie skopiuje odczytanej wartości liczby do odpowiedniej zmiennej. Operator 

oznacza przekazanie do funkcji 

adresu do zmiennej - wskaźnika

, aby funkcja mogła 

zmodyfikować jej wartość. Dzięki temu funkcja scanf moŜe zapamiętać odczytane z wejścia 
wartości. Bez znajomości adresu (wskaźnika) do zmiennej funkcja otrzymałaby jedynie obecną 
wartość zmiennej bez moŜliwości jej zmiany. 
 

#include <stdio.h> 
 
int main (void){ 
  int liczba = 0; 
  printf ("Podaj liczbę: "); 
  scanf ("%d", 

&

liczba); 

  printf ("%d*%d=%d\n", liczba, liczba, liczba*liczba);  
  return 0; 

Wczytanie ciągu znaków (tekstu) do tablicy znakowej. 

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

  char tablica[100];     /* 1 */ 
  scanf("%s", tablica);  /* 2 */ 
  return 0; 

Bezpieczna wersja programu z ograniczeniem na wczytywanie danych do 99 znaków 

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

background image

WYKŁADY cz.2 v.3 (2008)          Podstawy programowania 1           

(dr.inŜ Marcin Głowacki)

  9 

  char tablica[100]; 
  scanf("%99s", tablica); 
  return 0; 

Wczytanie liczby: 
 

#include <stdio.h> 
 
int main(void){ 
  int n; 
  while (scanf("%d", &n)==1) { 
    printf("%d\n", n*n*n); 
  } 
  return 0; 

Wczytanie kolejno dwóch liczb: 
 

#include <stdio.h> 
 
int main(void){ 
  int a, b; 
  while (scanf("%d %d", &a, &b)==2) { 
    printf("%d\n", a+b); 
  } 
  return 0; 

Trochę bardziej skomplikowany przykład. Podobnie jak poprzednio program będzie wypisywał 3 
potęgę podanej liczby, ale tym razem musi ignorować błędne dane (tzn. pomijać ciągi znaków, 
które nie są liczbami) i kończyć działanie w momencie, gdy nastąpi błąd odczytu lub koniec 
pliku: 
 

#include <stdio.h> 
 
int main(void){ 
  int result, n; 
  do { 
    result = scanf("%d", &n); 
    if (result==1) { 
      printf("%d\n", n*n*n); 
    } else if (!result) { /* !result to to samo co result==0 */ 
      result = scanf("%*s"); //ignorowanie zawartości bufora 
    } 
  } while (result!=EOF); 
  return 0; 

 
 

background image

WYKŁADY cz.2 v.3 (2008)          Podstawy programowania 1           

(dr.inŜ Marcin Głowacki)

  10 

Analiza: 
Najpierw wywoływana jest funkcja scanf() i następuje próba odczytu liczby typu int. JeŜeli 
funkcja zwróciła 1 to liczba została poprawnie odczytana i następuje wypisanie jej trzeciej 
potęgi. JeŜeli funkcja zwróciła 0 to na wejściu były jakieś dane, które nie wyglądały jak liczba. 
W tej sytuacji wywołujemy funkcję scanf() z formatem odczytującym dowolny ciąg znaków nie 
będący białymi znakami z jednoczesnym określeniem, Ŝeby nie zapisywała nigdzie wyniku. W 
ten sposób niepoprawnie wpisana dana jest omijana. Pętla główna wykonuje się tak długo jak 
długo funkcja scanf() nie zwróci wartości EOF.  
 

Funkcja

 gets - 

nie naleŜy jej uŜywać ! 

 
Przyjmuje jeden argument - adres pierwszego elementu tablicy, do którego naleŜy zapisać 
odczytaną linię - i nic poza tym. Z tego powodu nie ma Ŝadnej moŜliwości przekazania do tej 
funkcji rozmiaru bufora podanego jako argument. Podobnie jak w przypadku scanf() moŜe to 
doprowadzić do przepełnienia bufora, co moŜe mieć tragiczne skutki. Zamiast tej funkcji naleŜy 
uŜywać funkcji fgets().  
 

Funkcja

 fgets 

 

 

fgets

(

tablica_znaków, rozmiar_tablicy_znaków, stdin

); 

 
Funkcja czyta tekst aŜ do napotkania znaku przejścia do nowej linii, który takŜe zapisuje w 
wynikowej tablicy (funkcja gets() tego nie robi). JeŜeli brakuje miejsca w tablicy to funkcja 
przerywa czytanie, w ten sposób, aby sprawdzić czy została wczytana cała linia czy tylko jej 
część naleŜy sprawdzić czy ostatnim znakiem nie jest znak przejścia do nowej linii. JeŜeli 
nastąpił jakiś błąd lub na wejściu nie ma juŜ danych funkcja zwraca wartość NULL.  

 

#include <stdio.h> 

 

int main(void) { 
  char buffer[128], whole_line = 1, *ch; 
  while (fgets(buffer, sizeof buffer, stdin)) { /* 1 */ 
    if (whole_line) {                           /* 2 */ 
      putchar('>'); 
      if (buffer[0]!='>') { 
        putchar(' '); 
      } 
    } 
    fputs(buffer, stdout);                      /* 3 */ 
    for (ch = buffer; *ch && *ch!='\n'; ++ch);  /* 4 */ 
    whole_line = *ch == '\n'; 
  } 
  if (!whole_line) { 
    putchar('\n'); 
  } 
  return 0; 

background image

WYKŁADY cz.2 v.3 (2008)          Podstawy programowania 1           

(dr.inŜ Marcin Głowacki)

  11 

Analiza: 
PowyŜszy kod wczytuje dane ze standardowego wejścia - linia po linii - i dodaje na początku 
kaŜdej linii znak większości, po którym dodaje spację jeŜeli pierwszym znakiem na linii nie jest 
znak większości. W linijce 1 następuje odczytywanie linii. JeŜeli nie ma juŜ więcej danych lub 
nastąpił błąd wejścia funkcja zwraca wartość NULL, która ma logiczną wartość 0 i wówczas 
pętla kończy działanie. W przeciwnym wypadku funkcja zwraca po prostu pierwszy argument, 
który ma wartość logiczną 1. W linijce 2 sprawdzamy, czy poprzednie wywołanie funkcji 
wczytało całą linię, czy tylko jej część - jeŜeli całą to teraz jesteśmy na początku linii i naleŜy 
dodać znak większości. W linii 3 najzwyczajniej w świecie wypisujemy linię. W linii 4 
przeszukujemy tablicę znak po znaku, aŜ do momentu, gdy znajdziemy znak o kodzie 0 
kończącym 

ciąg znaków

 albo znak przejścia do nowej linii. Ten drugi przypadek oznacza, Ŝe 

funkcja fgets() wczytała całą linię.  
 

Funkcja

 getchar()

 

Jest to bardzo prosta funkcja, wczytująca 1 znak z klawiatury. W wielu przypadkach dane mogą 
być buforowane przez co wysyłane są do programu dopiero, gdy bufor zostaje przepełniony lub 
na wejściu jest znak przejścia do nowej linii. Z tego powodu wpisaniu danego naleŜy nacisnąć 
klawisz Enter, aczkolwiek trzeba pamiętać, Ŝe w następnym wywołaniu zostanie zwrócony znak 
przejścia do nowej linii. Gdy nastąpił błąd lub nie ma juŜ więcej danych funkcja zwraca wartość 
EOF (która ma jednak wartość logiczną 1 toteŜ zwykła pętla 

while (getchar())

 nie da 

oczekiwanego rezultatu):  

#include <stdio.h> 
 
int main(void){ 
  int c; 
  while ((c = getchar())!=EOF) { 

 

//koniec gdy Ctrl-Z 

    if (c==' ') {   

//zamiana spacji na podkreślenie 

      c = '_'; 
    } 
    putchar(c); 
  } 
  return 0; 

Ten prosty program wczytuje dane znak po znaku i zamienia wszystkie spacje na znaki 
podkreślenia. MoŜe wydać się dziwne, Ŝe zmienną c zdefiniowaliśmy jako trzymającą typ int, a 
nie char. Właśnie taki typ (tj. int) zwraca funkcja getchar() i jest to konieczne poniewaŜ wartość 
EOF wykracza poza zakres wartości typu char (gdyby tak nie było to nie byłoby moŜliwości 
rozróŜnienia wartości EOF od poprawnie wczytanego znaku).  

background image

WYKŁADY cz.2 v.3 (2008)          Podstawy programowania 1           

(dr.inŜ Marcin Głowacki)

  12 

STOSOWANIE FUNKCJI z rodziny 

printf

 i 

scanf

Argumenty za: 

są bardzo wygodne  

cały szablon jest w jednym miejscu  

umoŜliwiają łatwe dodawanie informacji nt. formatu  

Przeciw: 

trudno je rozszerzyć o nowe typy  

kompilator nie zawsze moŜe sprawdzić ich poprawność 

mogą wystąpić problemy z bezpieczeństwem  

konieczna znajomość typu kaŜdego przetwarzanego wyraŜenia

  

 

background image

WYKŁADY cz.2 v.3 (2008)          Podstawy programowania 1           

(dr.inŜ Marcin Głowacki)

  13 

W języku 

C++

 w pliku nagłówkowym 

<iostream>

 predefiniowane są strumienie standardowe: 

 

cout

 – strumień standardowego wyjścia domyślnie skierowany na ekran; 

cin

 – strumień standardowego wejścia domyślnie dołączony do klawiatury 

cerr

 - strumień standardowego wyjścia komunikatów o błędach (errors) domyślnie skierowany na 

ekran. Strumień niebuforowany – natychmiastowe powiadomienie o błędach. 

clog

 - strumień standardowego wyjścia komunikatów do dziennika (logu) domyślnie skierowany 

na ekran. Strumień buforowany – moŜe gromadzić komunikaty, a gdy zbierze się kilka wysłać do 
dziennika co powoduje większą optymalizację pracy dziennika. 
 
Do związania danych ze strumieniami słuŜą operatory: 

<<

 i 

>>

 

 

int k; 

cin 

>>

 k; 

//kierunek informacji ze strumienia cin do zmiennej k 

cout

 

<<

 ”Wartość k: ”<<k;  //kierunek informacji do strumienia cout ze zmiennej k 

 
 

background image

WYKŁADY cz.2 v.3 (2008)          Podstawy programowania 1           

(dr.inŜ Marcin Głowacki)

  14 

FLAGI STANU FORMATOWANIA 

 
Są to zasady formatowania zapisane w słowie typu 

long

 

 
 

enum { 
 

skipws  

= 0x0001 

//ignoruje białe znaki (spacje, tabulacje)

 

 

left  

 

= 0x0002 

//justowanie lewe 

 

right   

= 0x0004 

//justowanie prawe

 

 

internal 

= 0x0008 

//justowanie ”wewnętrzne” 

 

dec 

 

= 0x0010 

//konwersja dziesiętna

 

 

oct 

 

= 0x0020 

//konwersja ósemkowa

 

 

hex 

 

= 0x0040 

//konwersja hexadecymalna

 

 

showbase 

= 0x0080 

//pokaŜ podstawę konwersji

 

 

showpoint 

= 0x0100 

//pokaŜ kropkę dziesiętną

 

 

uppercase 

= 0x0200 

//wielkie litery w liczbach

 

 

showpos 

= 0x0400 

//znak + w liczbach dodatnich

 

 

scientific 

= 0x0800 

//notacja wykładnicza (naukowa) 

 

fixed   

= 0x1000 

//notacja zwykła

 

 

unitbuf 

= 0x2000 

//buforowanie

 

 

stdio   

= 0x4000 

//współpraca z stdio

 

}; 

 

background image

WYKŁADY cz.2 v.3 (2008)          Podstawy programowania 1           

(dr.inŜ Marcin Głowacki)

  15 

Modyfikacje stanu flag formatowania mogą być wprowadzone przy uŜyciu trzech metod: 

• 

przy uŜyciu elementarnych funkcji składowych klasy ios o nazwach: 

setf

unsetf

 

• 

złoŜonych funkcji składowych klasy ios, których nazwy przypominają to co robią: 

width

precision

 i 

fill

• 

manipulatorów – wpuszczania do strumienia specjalnych kodów zmieniających 
formatowanie 

 
Przykład uŜycia elementarnych funkcji składowych klasy ios o nazwach: 

setf

unsetf

 

#include <iostream>

 

 

int main() { 
      using std::cout; using std::endl; using std::cin; 
      float x=1175; 
      long stare_flagi; 
      cout << x <<endl; //domniemane ustawienia formatowania 
      cout<<"Zapamietanie flag formatowania\n"; 
      stare_flagi=cout.flags(); 
      cout.setf(ios::showpoint); 
      cout<<x<<endl; 
      cout.setf(ios::scientific, ios::floatfield); 
      cout<<x<<endl; 
      cout.setf(ios::uppercase); 
      cout<<x<<endl; 
      cout.unsetf(ios::showpoint);   //wyłączenie flagi showpoint 
      cout<<x<<endl; 
      cout<<"Powrót do starych flag formatowania\n"; 
      cout.flags(stare_flagi); 
      cout<<x<<endl; 
      return 0; 

 
Funkcja 

int width(int)

 ustala rozmiar pola, na którym będzie wydrukowana liczba.  

float x=1175; 
cout.width(8);

 

 

//liczba będzie wyświetlana na ośmiu polach

 

lub 
 

char napis[7]; 

 

//tekst o rozmiarze 6 znaków

 

 

cin.width(sizeof(napis)); 

 

cin>>napis; 

 
Funkcja 

char fill(char)

 wypełnienie dla pustych miejsc, jeśli przewidziane pole jest dłuŜsze niŜ 

zawartość zmiennej. 
 

int saldo = 2573; 

 

cout<<”stan konta: ”; 

 

cout.width(9); 

 

cout.fill(‘*’);   

//dopelnienie gwiazdami pustych miejsc

 

 

cout << saldo<<”,-\n”; 

background image

WYKŁADY cz.2 v.3 (2008)          Podstawy programowania 1           

(dr.inŜ Marcin Głowacki)

  16 

Funkcja 

int precision(int)

 ustala poziom dokładności. 

 

float x=72.435672591143; 

 

Y = 10.55; 

 

Z = 2; 

 
 

cout << ”Domyślna dokładność to: ”<<( cout.precision() )<<endl; 

 

cout <<”x: ”<<x<<” y: ”<<y<<” z: ”<<z<<endl; 

 

cout.precision(8); 

 

cout << ”Teraz dokładność to: ”<<( cout.precision() )<<endl; 

 

cout <<”x: ”<<x<<” y: ”<<y<<” z: ”<<z<<endl

 
 

Manipulatory

 umoŜliwiają wysyłanie do strumieni informacji o formatowaniu. 

Występuje zestaw manipulatorów predefiniowanych w klasie ios: 

• 

bezargumentowe: 

dec

hex

oct, flush, endl, ends i ws

 

int i=30; 
cout<<i<<endl; 

//postać dziesiętna

 

cout<<i<<” ,”<<hex<<i<<endl; 

 

• 

parametryzowane zdefiniowane w bibliotece 

<iomanip>

.  

setw(int)

 – ustawia szerokość 

#include <iomanip> 
cout<<setw(5)<<m<<setw(9)<<m<<setw(7)<<m<<endl; 
char slowo[6]; 

//deklaracja na slowo o rozmiarze do 5 znaków 

cin>>setw(sizeof(slowo))>>slowo; 

setfill(int)

 – ustawia wypełnienie wolnej przestrzeni 

int kwota=3200; 
cout<<”Stan konta: ”<<setfill(‘*’)<<setw(9)<<kwota<<”-,”<<endl;
 

setprecision(int)

 – ustawia dokładność 

double x=99.123456789; 
cout<<x<<”, ”<<setprecision(2)<<x<<”, “<<setprecision(8)<<x<<endl; 

setiosflags(long)

 oraz 

resetiosflags(long)

 - ustawia i kasuje wskazane flagi 

int liczba=242; 
cout <<hex<<liczba<<”, ”<<setiosflags(ios::uppercase)<<liczba 
<<resetiosflags(ios::uppercase)<<liczba<<endl;
 

setbase(int)

 – określa podstawę dla konwersji liczb, czyli to samo co manipulatory 

dec

hex

 i 

oct

 

int liczba=100; 
cout<<dec<<liczba<<hex<<liczba<<oct<<liczba; 
 

 

to samo co 

cout<<setbase(10)<<liczba<<setbase(16)<<liczba<<setbase(8)<<liczba; 

 

background image

WYKŁADY cz.2 v.3 (2008)          Podstawy programowania 1           

(dr.inŜ Marcin Głowacki)

  17 

NIEFORMATOWANE OPERACJE WEJŚCIA / WYJŚCIA 

 
W klasie 

istream

 zdefiniowane są funkcje:  

 

• 

get

 – wczytanie jednego znaku (bajtu), Funkcja jest przeciąŜona i moŜe wczytywać 

zadaną liczbę znaków lub do chwili napotkania wzorca. 

 

istream& 

get

(

char &

); 

int 

get

();  

 

 

//funkcja zwraca kod znaku w postaci int 

istream& 

get

(

char

 ); 

istream& 

get

(

char *, int

 ); 

//drugi argument to długość wczytywanych znaków 

istream& 

get

(

char *, int , int =’\n’

); 

//domyślny wzorzec to znak nowej linii 

 

Przykłady: 

char 

znak

cin.get

(

znak

);   

//wczytanie bajtu ze strumienia cin 

 

 

 

//wczytywane są takŜe białe znaki (spacje i tabulacje) 

 

 

 

 

 

 

//- w odróŜnieniu od 

cin

>>

znak

;  

 

 

//------------------- WCZYTANIE ZNAKU ------------------------ 

 

 

char 

znak

 

 

cout<<”Wciskaj klawisze (^Z-konczy)”<<endl; 

 

 

 

while((

cin.get

(

znak

))!=0) 

 

 

 

 

cout<<”Znak : ”<<

znak

<<” ma kod ”<<int(

znak

)<<endl; 

 

 

//------------ WCZYTANIE ZNAKU INACZEJ – A MOśE TAK SAMO ? -------- 

 

 

char 

znak

 

 

cout<<”Wciskaj klawisze (^Z-konczy)”<<endl; 

 

 

 

while((char(znak)=

cin.get

())!=EOF ) //EOF – znak końca pliku tekstowego 

//funkcja zwraca kod znaku w postaci int 

 

 

 

 

cout<<”Znak : ”<<

znak

<<” ma kod ”<<int(

znak

)<<endl; 

 

 

//----------------------- WCZYTANIE ZNAKÓW DO TABLICY --------------------- 

 

 

char 

zdanie

[

80

]; 

 

 

cout<<”Wpisz zdanie:”<<endl; 

 

 

 

cin.get

(

zdanie, 

sizeof

(zdanie)

);

 

// 

cin.get

(

zdanie,

80

); 

cout<<”Twoje zdanie to: ”<<

zdanie

<<endl; 

 

 

//----------- WCZYTANIE ZNAKÓW DO WYSTĄPIENIA WZORCA ------------ 

 

 

char 

zdanie

[

80

]; 

 

 

cout<<”Wpisz zdanie:”<<endl; 

 

 

 

cin.get

(

zdanie,

sizeof

(zdanie),’

,

);

 

// wczytuj do wystąpienia przecinka 

cout<<”Twoje zdanie to : ”<<

zdanie

<<endl; 

 

UWAGA:

 Nie wczytane dane z powodu limitu długości lub napotkania wzorca pozostają 

w buforze strumienia i mogą być czytane następnymi instrukcjami. Napotkany znak 
wzorca zostaje zwrócony do strumienia.

background image

WYKŁADY cz.2 v.3 (2008)          Podstawy programowania 1           

(dr.inŜ Marcin Głowacki)

  18 

 

• 

getline

 – wczytanie zadanej liczby bajtów lub do napotkania wskazanego znaku 

 

istream& 

getline

(

char *, int , int=’\n’

);    //domyślny wzorzec to znak nowej linii 

 

 

Działa podobnie do 

get

(

char *, int , int=’\n’

) z tą róŜnicą, Ŝe zabiera i usuwa ze 

strumienia napotkany wzorzec. Funkcja zwraca referencję do strumienia, na którym 
pracuje. UmoŜliwia to kaskadowe łączenie takich funkcji, np. cin.getline(...).getline(...) 
 

• 

read

 – wczytanie określonej liczby bajtów w trybie binarnym. Nie dołącza znaku ‘\0’ na 

końcu jak to robią poprzednie funkcje 

 

istream& 

read

(

char *, int

); 

Funkcja zwraca referencję do strumienia, na którym pracuje. UmoŜliwia to kaskadowe 
łączenie takich funkcji, np. cin.read(...).read(...) 

• 

ignore

 – wczytuje i ignoruje grupę bajtów ze strumienia 

 

istream& 

ignore

(

int , int

); 

 

• 

gcount 

– pozwala dowiedzieć się ile znaków zostało wczytanych za pomocą 

nieformatowanej operacji wejścia/ wyjścia 

 

int 

gcount

(); 

Przykład: 

char 

zdanie

[

80

]; 

 

 

cout<<”Wpisz zdanie:”<<endl; 

 

 

 

cin.get

(

zdanie,

sizeof

(zdanie),’

,

’); 

// wczytuj do wystąpienia przecinka 

cout<<”Zdanie: ”<<

zdanie

<<”. ma : ”<<

cin.gcount() 

<<” znakow”<<endl; 

 

• 

peek 

– słuŜy do sprawdzenia jaki bajt czeka w strumieniu, nie wyjmuje bajtu 

 

int 

peek

(); 

Przykład: 

char 

zdanie

[

80

]; 

float 

liczba

int 

test

cout<<”Wprowadz dane (tekst lub liczbe):”;  
test =

cin.peek()

if(isdidgit(

test

)) {  

cin>>liczba;  
cout<<”Wprowadziłeś liczbę: “<<

liczba

<<endl; 

} else { 

cin.getline(

zdanie,

sizeof

(zdanie)

); 

cout<<”Wprowadziłeś tekst: “<<

zdanie

<<endl; 

background image

WYKŁADY cz.2 v.3 (2008)          Podstawy programowania 1           

(dr.inŜ Marcin Głowacki)

  19 

 

• 

putback 

– umoŜliwia zwrócenie do strumienia wyjętego bajtu. Bajt ten wraca do 

strumienia i moŜe następnie być wyjęty operacją wyjmowania. 

 
istream & 

putback

(

char

); 

 
W klasie 

ostream

 zdefiniowane są funkcje:  

 

• 

put 

– wkłada do strumienia jeden bajt 

 

ostream & 

put

(char)  

Przykład: 

char 

zdanie

[]={”I do Love You”}; 

 

 

int i=0; 

do { 
cout.put(zdanie[i]).put(”_”); 
} while(zdanie[++i]); 

Efekt: I_ _d_o_ _ L_o_v_e_ _Y_o_u. 

 

• 

write 

– wkłada do strumienia zadaną liczbę bajtów 

 

ostream & 

write

(char *, int)  

 
Przykład: 

char zdanie[]={”I do Love You”}; 

cout.write(zdanie,2)
cout<<”hate”; 
cout.write(zdanie+10,4); 

Efekt: 

I hate You.

 

 

background image

WYKŁADY cz.2 v.3 (2008)          Podstawy programowania 1           

(dr.inŜ Marcin Głowacki)

  20 

OPERATORY ARYTMETYCZNE 

Operator

 

Działanie

 

Postać matematyczna

 

=

 

instrukcja przypisania

 

 

 

z = x;

 

dodawanie 

z = x + y; 

odejmowanie 

z = x – y; 

mnoŜenie 

z = x * y; 

dzielenie 

z = x / y; 

dzielenie modulo = reszta z dzielenia 

z = x % y; 

-- 

zmniejszanie o jeden (dekrementacja) 

z = z – 1; 

++ 

zwiększanie o jeden (inkrementacja) 

z = z + 1; 

+= 

skrót przypisania 

z += x; 

to samo co:

 z = z + x; 

-= 

skrót odejmowania 

z -= x; 

to samo co:

 z = z – x; 

*= 

skrót mnoŜenia 

z *= x; 

to samo co:

 z = z * x; 

/= 

skrót dzielenia 

z /= x; 

to samo co:

 z = z / x; 

 
Ogólna postać instrukcji przypisania wygląda następująco: 

zmienna = wyraŜenie; 

MoŜna teŜ stosować wielokrotnie takie instrukcje, np.: 

z = x = y = 0; 

 
Program realizujący operację dodawania dwóch liczb typu float. 

#include <iostream> 
#include <conio.h> 
int main() 
{  
float x, y, z; // deklaracja zmiennych 
using std::cout; using std::endl; using std::cin; 
cout << endl << "Podaj dwie liczby " << endl; 
cin >> x >> y; 
z = x + y; 
cout << x << " + " << y <<" = " << z<<endl; 
return 0; 

 
W przykładzie wykorzystano operatory 

dodawania

 

+

 

oraz 

przypisania

 

=

 
 

background image

WYKŁADY cz.2 v.3 (2008)          Podstawy programowania 1           

(dr.inŜ Marcin Głowacki)

  21 

OPERATORY RELACYJNE i LOGICZNE 

KaŜda róŜna od zera liczba, z którą spotykamy się w C, posiada wartość 

TRUE

 

(prawda) , 

natomiast liczba 0 posiada wartość 

FALSE

 

(nieprawda). WyraŜenia, w których występują 

operatory relacyjne bądź logiczne, zwracają wartość 

1

 (

TRUE

) lub 

(

FALSE

). W zaleŜności 

od potrzeb posługujemy się następującymi operatorami: 
 

Operatory relacyjne 

 

Operator 

Działanie 

większy 

mniejszy 

>= 

większy lub równy 

<= 

mniejszy bądź równy 

== 

równy 

!= 

róŜny 

 

Operatory logiczne 

 

Operator 

Działanie 

&& 

koniunkcja AND (i) 

|| 

alternatywa OR (lub) 

negacja NOT (nie) 

 
Posługując się przedstawionymi operatorami naleŜy zawsze pamiętać, Ŝe posiadają one róŜny 
priorytet wykonywania kolejnych działań. Rozpatrzmy to na przykładzie wyraŜenia 

5-4 != 0

Jego wartość obliczana jest w taki sposób, Ŝe najpierw zostanie wykonana operacja odejmowania 
liczb, a dopiero potem sprawdzony warunek, czy rezultat odejmowania jest róŜny od zera, tzn.: 

(5-4) != 0

. NaleŜy teŜ pamiętać, Ŝe operator 

()

 

ma największy priorytet. JeŜeli nie jesteśmy 

pewni priorytetów stosowanych operatorów zawsze w wątpliwych sytuacjach moŜemy posłuŜyć 
się właśnie operatorem 

()

 

OPERATORY BITOWE 

 

Operator 

Działanie 

bitowa koniunkcja AND (i) 

bitowa alternatywa OR (lub) 

bitowa negacja NOT (nie) 

bitowa róŜnica symetryczna XOR 

<< 

przesuniecie bitów w lewo (mnoŜenie przez 2) 

>> 

przesuniecie bitów w prawo (dzielenie przez 2) 

 

MoŜliwe jest w pewnych szczególnych zastosowaniach wykonywanie operacji na liczbach w 
logice bitowej.  

background image

WYKŁADY cz.2 v.3 (2008)          Podstawy programowania 1           

(dr.inŜ Marcin Głowacki)

  22 

PRZEDROSTKI I PRZYROSTKI 

Zarówno operator inkrementacji (

++

), jak i dekrementacji (

--

) występuje w dwóch odmianach: 

• 

przedrostkowej (np. 

++x

) jest obliczany przed przypisaniem (zwiększ wartość zmiennej i 

zapamiętaj ją) 

x=5;  
int y = ++x; 
cout <<x<<”\t”<<y;

  //po wykonaniu: x jest równe 6, y jest równe 6 

• 

przyrostkowej (np. x++) jest obliczany po przypisaniu (pamiętaj pierwotną wartość 
zmiennej, po czym zwiększ wartość) 

x=5;  
int y = x++; 
cout <<x<<”\t”<<y;

 

//po wykonaniu: x jest równe 6, y jest równe 5

 

 
Przykład działania operatora przedrostkowego i przyrostkowego 

1: #include <iostream> 
2: int main() { 
3: using std::cout; 
4: int mojWiek = 39; // inicjalizujemy dwie zmienne całkowite 
5: int twojWiek = 39; 
6: cout << "Ja mam: " << mojWiek << " lat.\n"; 
7: cout << "Ty masz: " << twojWiek << " lat\n"; 
8: mojWiek++; // inkrementacja przyrostkowa 
9: ++twojWiek; // inkrementacja przedrostkowa 
10: cout << "Minal rok...\n"; 
11: cout << "Ja mam: " << mojWiek << " lat.\n"; 
12: cout << "Ty masz: " << twojWiek << " lat\n"; 
13: cout << "Minal kolejny rok\n"; 
14: cout << "Ja mam: " << mojWiek++ << " lat.\n"; 
15: cout << "Ty masz: " << ++twojWiek << " lat\n"; 
16: cout << "Wypiszmy to jeszcze raz.\n"; 
17: cout << "Ja mam: " << mojWiek << " lat.\n"; 
18: cout << "Ty masz: " << twojWiek << " lat\n"; 
19: return 0; 
20: } 

 
 

Efekt: 

Ja mam: 39 lat. 
Ty masz: 39 lat 
Minal rok... 
Ja mam: 40 lat. 
Ty masz: 40 lat 
Minal kolejny rok 
Ja mam: 40 lat. 
Ty masz: 41 lat 
Wypiszmy to jeszcze raz. 
Ja mam: 41 lat. 
Ty masz: 41 lat

 

background image

WYKŁADY cz.2 v.3 (2008)          Podstawy programowania 1           

(dr.inŜ Marcin Głowacki)

  23 

INSTRUKCJA DECYZYJNA

   

if  

Instrukcja 

if

 jest pytaniem czy jest spełniony 

warunek

, który moŜe być wyraŜeniem logicznym 

TRUE/ FALSE lub wprost wartością odpowiednio róŜną od zera (!=0) lub równą zero (==0). 

 
if

 (

warunek

) {  

 

//jeśli warunek spełniony TRUE (!=0) 

 

instrukcja; 

 

instrukcja; 

 

... 

}; 
lub 

if

 (

warunek

)  

 

instrukcja; 

//jeśli jedna instrukcja to moŜe być bez klamry 

 
 

if (warunek)

TAK

NIE

instrukcja;
instrukcja;

...

 

MoŜna teŜ stosować wielobok zamiast rombu. 
 

if (warunek)

TAK

NIE

 

 
 

background image

WYKŁADY cz.2 v.3 (2008)          Podstawy programowania 1           

(dr.inŜ Marcin Głowacki)

  24 

INSTRUKCJA DECYZYJNA

   

if ... else 

 

Instrukcja 

if ... else

 jest pytaniem czy jest spełniony 

warunek

, który moŜe być wyraŜeniem 

logicznym TRUE/ FALSE lub wprost wartością odpowiednio róŜną od zera (!=0) lub równą zero 
(==0). W przypadku nie spełnienia 

warunku

 następuje wykonanie instrukcji występujących po 

else

. Dopiero wtedy wykonywane są następne instrukcje w programie. W przypadku spełnienia 

warunku

 instrukcje po 

else

 są omijane. 

 

if

 (

warunek

) {  

 

//jeśli warunek spełniony TRUE (!=0) 

 

instrukcja; 

 

instrukcja; 

 

... 

else

 {   

 

 

//jeśli warunek nie jest spełniony FALSE (0) 

 

instrukcja; 

 

instrukcja; 

 

... 

}; 
lub 

if

 (

warunek

)  

 

instrukcja; 

//jeśli jedna instrukcja to moŜe być bez klamry 

else 

 

instrukcja; 

if (warunek)

TAK

NIE

instrukcja;
instrukcja;

...

instrukcja;
instrukcja;

...

else

background image

WYKŁADY cz.2 v.3 (2008)          Podstawy programowania 1           

(dr.inŜ Marcin Głowacki)

  25 

Program – ilustracja złoŜonych warunków logicznych dla 

if ... else

 

 

#include <iostream> 
 
int main() 

using std::cout; using std::endl; using std::cerr; 
enum KOLORY {bialy=1, czerwony, zielony, zolty, niebieski, fioletowy}; 
KOLORY kolor=zielony; 
int liczba=2; 

//liczba musi być w zakresie koloru i nieparzysta to kolor teŜ musi być nieparzysty lub 
// gdy parzysta to kolor teŜ parzysty 

if

(((liczba<=6)&&(liczba>=1))&&(((!(kolor%2))&&(!(liczba%2)))||((kolor%2)&&(liczba%2))))

 

cout<<"Liczba: "<<liczba<<"\tKolor: "<<kolor<<endl; 

else 

cerr<<"Bledna kombinacja liczb i kolorow"<<endl; 

      return 0; 

UWAGA: Przy niespełnionym warunku przy 

if

 nie wiemy, które z kryteriów nie było spełnione 

 

Program – Ten sam program i te same warunki logiczne rozbite na kaskadę wielu 

if ... else

  

 
#include <iostream> 
 
int main() 

using std::cout; using std::endl; using std::cerr; 
enum KOLORY {bialy=1, czerwony, zielony, zolty, niebieski, fioletowy}; 
KOLORY kolor=bialy; 
int liczba=4; 
//jesli liczba jest w zakresie koloru i parzysta to kolor tez parzysty 

if

((liczba<=6)&&(liczba>=1))

//sprawdzanie zakresu liczby 

if

((!(kolor%2))&&(!(liczba%2)))

 

//sprawdzanie parzystej liczby i koloru

 

        cout<<"Liczba parzysta: "<<liczba<<"\tKolor parzysty: "<<kolor<<endl; 

else  
if

 

((kolor%2)&&(liczba%2))

 

//sprawdzanie nieparzystej liczby i koloru 

        cout<<"Liczba nieparzysta: "<<liczba<<"\tKolor nieparzysty: "<<kolor<<endl; 

else 

          cerr<<"Liczba w zakresie, ale nie pasuje do koloru"<<endl; 

else

 

cerr<<"Liczba poza zakresem"<<endl; 

return 0; 

Sprawdzane są poszczególne kryteria i wiadomo jakie występują kombinacje liczby i koloru. W 
ten sposób uŜytkownik jest dokładnie informowany o szczegółach zarówno wyników 
sprawdzania oraz występujących błędów.

background image

WYKŁADY cz.2 v.3 (2008)          Podstawy programowania 1           

(dr.inŜ Marcin Głowacki)

  26 

INSTRUKCJA DECYZYJNA

   

switch 

 
Instrukcja

 switch

 porównuje wyraŜenie z wartością dla wybranych przypadków (

case

). Przy 

zgodności wartości wykonane zostaną instrukcje zawarte po 

case

 oraz wszystkie instrukcje po 

case

 umieszczonych poniŜej oraz po 

default

, chyba Ŝe pojawi się rozkaz wyjścia z instrukcji: 

break

. W przypadku braku zgodności ze wszystkimi wartościami po 

case

 moŜe być wykonany 

ciąg instrukcji dla przypadku domyślnego 

default

 

switch

 (

wyraŜenie

) { 

 

case

 

wartość_1:

 

instrukcja; 
instrukcja; 
... 

break; 

 

case

 

wartość_2:

 

 

 

instrukcja; 

 

 

instrukcja; 

 

 

... 

 

 

break; 

 

... 

 

case

 

wartość_n:

 

 

 

instrukcja; 

 

 

instrukcja; 

 

 

... 

 

 

break; 

default

//fragment wykonywany domyślnie dla braku zgodności 
//wartości wyraŜenia w sprawdzanych przypadkach 

case

 

 

 

instrukcja; 

 

 

instrukcja; 

}; 
lub 

switch

 (

wyraŜenie

) { 

 

case

 

wartość_1: 

 

//moŜna łączyć wartości, które posiadają wspólne instrukcje 

 

case

 

wartość_2:

 

 

 

instrukcja; 

 

 

instrukcja; 

 

 

... 

 

 

break; 

 

... 

 

background image

WYKŁADY cz.2 v.3 (2008)          Podstawy programowania 1           

(dr.inŜ Marcin Głowacki)

  27 

if (wyra

Ŝ

enie==warto

ść

_1)

TAK

NIE

instrukcja;
instrukcja;

...

switch (wyra

Ŝ

enie)

case warto

ść

_1:

if (wyra

Ŝ

enie==warto

ść

_2)

NIE

case warto

ść

_2:

TAK

instrukcja;
instrukcja;

...

if (wyra

Ŝ

enie==warto

ść

_n)

NIE

case warto

ść

_n:

TAK

instrukcja;
instrukcja;

...

instrukcja;
instrukcja;

...

default:

.  .  .

.  .  .

break;

break;

break;

break;

 

background image

WYKŁADY cz.2 v.3 (2008)          Podstawy programowania 1           

(dr.inŜ Marcin Głowacki)

  28 

Program – przykład uŜycia instrukcji 

switch

 

 
#include <iostream> 
int main() 

using std::cout; using std::endl; using std::cerr; 
      enum OCENA {mierny=1,ndst,dst,db,bdb,celujacy}; 
      OCENA zaliczenie=mierny; 
      

switch

 (

zaliczenie

) { 

             

case

 

mierny

             

case

 

ndst

: cout <<"Ocena: "<<int(zaliczenie)<<"\tBrak zaliczenia."<<endl; 

                  break; 
             

case

 

dst

             

case

 

db

             

case

 

bdb

             

case

 

celujacy

: cout <<"Ocena: "<<int(zaliczenie)<<"\tZaliczenie."<<endl; 

                  break; 
             

default

: cerr<<"Błędna ocena"<<endl; 

             };      return 0; 

background image

WYKŁADY cz.2 v.3 (2008)          Podstawy programowania 1           

(dr.inŜ Marcin Głowacki)

  29 

INSTRUKCJA CYKLICZNA

   

while 

 
Instrukcje cykliczne nazywane w Ŝargonie pętlami. 
Instrukcja 

while

 sprawdza czy zachodzi 

warunek

 i jeśłi tak (ang. 

while

 = podczas gdy 

warunek

 

spełniony) wykonuje instrukcje zawarte w klamrze. Następnie ponownie sprawdza 

warunek

. Po 

pierwszym wejściu w cykl instrukcja 

while

 moŜe zakończyć działanie jeśli instrukcje wewnątrz 

while

 lub zdarzenia wejścia/wyjścia wpłyną na dane w taki sposób, Ŝe 

warunek

 przestanie być 

spełniany lub zostanie wykonana instrukcja 

break

 przerywająca pętlę 

while

 w dowolnym 

momencie. W dowolnym momencie podczas wykonywania pętli moŜe być wydana komenda 

continue

, która spowoduje przejście do ponownego sprawdzenia 

warunku

 

while

(

warunek

) { 

 

instrukcja; 

 

instrukcja; 

 

... 

}; 
lub 

while

(

warunek

) instrukcja;  //jeśli jedna instrukcja to moŜe być bez klamry 

 
 

if (warunek)

TAK

NIE

instrukcja;
instrukcja;

...

break;

continue;

continue;

while (warunek)

 

 
 

background image

WYKŁADY cz.2 v.3 (2008)          Podstawy programowania 1           

(dr.inŜ Marcin Głowacki)

  30 

Program – demonstruje działanie 

while

 

 

#include <iostream> 
 
int main() 

using std::cout; using std::cin; 
long int iSuma=0,iIloczyn=1,iLiczba=0; //lepiej dać long int 
cout<<"Podaj liczby (0 - konczy): "; 
cin>>

iLiczba

while

(

iLiczba

) { 

//zero kończy program – warunek: iLiczba!=0 

 

iSuma+=

iLiczba

 

iIloczyn*=iLiczba; 

 

cout<<"Suma liczb = "<<iSuma<<'\t'; 

 

cout<<"Iloczyn liczb = "<<iIloczyn<<endl; 

 

cout<<"Nastepna liczba (0 - konczy): "; 

 

cin>>

iLiczba

 

    return 0; 

 

background image

WYKŁADY cz.2 v.3 (2008)          Podstawy programowania 1           

(dr.inŜ Marcin Głowacki)

  31 

INSTRUKCJA CYKLICZNA

   

do ... while 

 
Instrukcja 

do ... while

 działa podobnie do 

while

 z tą róŜnicą, Ŝe najpierw są wykonywane 

instrukcje a potem sprawdzany 

warunek

. Powoduje to przynajmniej jednokrotne wykonanie 

cyklu instrukcji w pętli. Po pierwszym wejściu w cykl instrukcja 

do ... while

 moŜe zakończyć 

działanie jeśli warunek nie jest spełniony. Przy kolejnych wykonaniach jedynie instrukcje 
wewnątrz 

do ...

 

while

 lub zdarzenia wejścia/wyjścia wpłyną na dane w taki sposób, Ŝe 

warunek

 

przestanie być spełniany lub zostanie wykonana instrukcja 

break

 przerywająca pętlę 

do ... while

 

w dowolnym momencie. W dowolnym momencie podczas wykonywania pętli moŜe być wydana 
komenda 

continue

, która spowoduje przejście do ponownego sprawdzenia 

warunku

 

do

 { 

 

instrukcja; 

 

instrukcja; 

 

... 

while

(

warunek

); 

 
lub 

do

 instrukcja

 

while

(

warunek

); 

//jeśli jedna instrukcja to moŜe być bez klamry 

 

if (warunek)

TAK

NIE

instrukcja;
instrukcja;

...

break;

continue;

while (warunek)

do

 

background image

WYKŁADY cz.2 v.3 (2008)          Podstawy programowania 1           

(dr.inŜ Marcin Głowacki)

  32 

Program – demonstruje działanie 

do ... while

 

 

#include <iostream> 
int main()//Program oblicza dlugość szeregu wprowadzanych liczb 

using std::cout; using std::cin; 
int iDlugosc=0, iLiczba; 

do

 { 

   cout<<"Podaj liczbe z szeregu (0 - konczy): "; 
   cin >>iLiczba; 
   iDlugosc++; 

while

 (

liczba

); 

iDlugosc--;     //korekta dlugosci o liczbe 0, która jest sygnalem do wyjscia 
cout<<"Dlugosc szeregu liczb wynosi  " <<iDlugosc<<endl; 
return 0; 

 

background image

WYKŁADY cz.2 v.3 (2008)          Podstawy programowania 1           

(dr.inŜ Marcin Głowacki)

  33 

INSTRUKCJA CYKLICZNA

   

for 

 
Instrukcja cykliczna for słuŜy do wykonywania zadań na skończonym zbiorze danych. Dzięki 
wykorzystaniu dodawania (inkrementacji) lub odejmowania (dekrementacji) moŜliwe jest 
iteracyjne (krokowe) ze zdefiniowanym krokiem przetwarzanie lub dostęp do danych, np. 
operacje na tablicach, obliczenia dla ciągu argumentów itp. 
 

for

 (instrukcje_1;

warunek

iteracje

) { 

instrukcja; 
instrukcja; 
... 

}; 
 
lub  

for

 (instrukcje_1;

warunek

iteracje

)   

//jeśli jedna instrukcja to moŜe być bez klamry 

instrukcja; 

 

if (warunek)

TAK

NIE

instrukcja;
instrukcja;

...

break;

continue;

for(instrukcje_1; warunek; iteracje)

iteracje

instrukcje_1

 

background image

WYKŁADY cz.2 v.3 (2008)          Podstawy programowania 1           

(dr.inŜ Marcin Głowacki)

  34 

Przykłady: 
 

 

for(int i=1;i<11;i++)  

//dziesięć cykli dla i=1,2,3,4,5,6,7,8,9,10 

 

 

 

cout<<”Liczby rosnąco: ”<<i<<endl; 

 
a teraz w odwrotnej kolejności: 
 

 

for(int i=10;i>0;i--)   

//dziesięć cykli dla i=10,9,8,7,6,5,4,3,2,1 

 

 

 

cout<<”Liczby malejąco: ”<<i<<endl; 

 
Jaka jest róŜnica ? 

 

for

(int i=1; 

i<11

 ;

i++

 

 

for

(int j=1;

j<11

;

j++

 

 

 

instrukcja1; 

 

for

(int i=1; 

i<11

 ;

i++

 

 

for

(int j=i;

j<11

;

j++

 

 

 

instrukcja2; 

//Pytanie: ile cykli ? 

//Pytanie: ile cykli ? 

//Odpowiedź

:                   100

<- 

// 

//Odpowiedź:           

55

<-            

// ?dlaczego: 10+9+8+7+6+5+4+3+2+1 <- 

 

for

(int i=1,j=100; 

i<11

 ;

i++,j++

 

 

instrukcja3; 

 

 

for

(int i=1,j=100; 

j<101

 ;

i++,j++

 

 

instrukcja4; 

 

//Pytanie: ile cykli ? 

//Pytanie: ile cykli ? 

//Odpowiedź:                  

10

<- 

// 

//Odpowiedź:                       

1

<- 

// 

for

(int i=1,j=1; 

(i<11)&&(j<101)

;

i++,j++

 

 

instrukcja5; 

 

for

(int i=1,j=1; 

(i<11)||(j<101)

;

i++,j++

 

 

instrukcja6; 

 

//Pytanie: ile cykli ? 

//Pytanie: ile cykli ? 

//Odpowiedź:                      

10

<- 

// 

//Odpowiedź:                        

100

<- 

// 

 
Program – demonstruje działanie 

for

 

#include <iostream> 
int main() { 
const unsigned int SZEROKOSC=4; 
using std::cout; using std::endl; 
          

for

(int i=1;

i<11

;

i++

) { 

              if (i>1) cout<<endl; 
              

for

(int j=1;

j<11

;

j++

) { 

              cout.width(SZEROKOSC); 

cout<<i*j; 

              } 
          } 
          cout<<endl; 
      return 0; 

Jaki będzie rezultat wykonania programu ? 

background image

WYKŁADY cz.2 v.3 (2008)          Podstawy programowania 1           

(dr.inŜ Marcin Głowacki)

  35 

 

i*j 

Ekran 

1    

1   2    

1   2   3 

... 

... 

... 

... 

 

2    

... 

... 

 

... 

10 

10 

100 

1   2   3   4   5   6   7   8   9   10 
2   4   6   8  10  ... 

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

10  20  30 40  50  60  70  80  90  100 

 
 

background image

WYKŁADY cz.2 v.3 (2008)          Podstawy programowania 1           

(dr.inŜ Marcin Głowacki)

  36 

INSRUKCJE CYKLICZNE – ZAGADKA 

 

To samo ? 

for

 (instrukcje_1;

warunek

iteracje

) { 

instrukcja; 
instrukcja; 
... 
if (warunek) continue; 
... 
instrukcja; 
instrukcja; 
... 
if (warunek) break; 
... 
instrukcja; 
instrukcja; 

}; 

instrukcje_1;

 

while

(

warunek

) { 

 

instrukcja; 

 

instrukcja; 

 

... 

if (warunek) { 

iteracja;

 continue;} 

... 
instrukcja; 
instrukcja; 
... 

if (warunek) break; 

... 
instrukcja; 
instrukcja; 

 
iteracje;

 

}; 
 

A moŜe są róŜnice ?: 

sprawdź działanie break lub continue

<- 

Odpowiedź – 

róŜnica jest w działaniu: continue

 <- 

 
 

background image

WYKŁADY cz.2 v.3 (2008)          Podstawy programowania 1           

(dr.inŜ Marcin Głowacki)

  37 

4.

F

UNKCJE

      1.

 

 
 
MoŜna podzielić program na fragmenty - podprogramy, które realizują ściśle określone zadania. 
 
Dlaczego stosować funkcje ? 

• 

Powtarzające się fragmenty lub realizujące ściśle określone operacje mogą być wyodrębnione 
i zapisane w postaci funkcji 

• 

Bezpośrednia odpowiedniość pomiędzy algorytmem i kodem programu MoŜna pisać i 
uruchamiać fragmenty programu niezaleŜnie – struktura modułów funkcjonalnych – 
„skrzyneczki” 

• 

MoŜna je wywoływać z dowolnego punktu programu  

• 

Skrócenie programu powoduje jego większą czytelność 

 
 
Forma zapisu: 
 
 
 
 
 
 
 

typ

 

fnNazwa

 (

typ argument1, typ argument2

) { 

 
def. zmiennych lokalnych 
instrukcja; 
... 
 

return

(

wartość zwracana

); 

... 

 
 
 
 
Funkcja moŜe zwracać wartość (lub nie) poprzez instrukcję: 

return(wartość); 

 lub samo:  

return; 

do miejsca w którym funkcja została wywołana 

np. wynik = 

fnSumaKwadratow

(

n

); 

Przykłady: (ang. void - znaczy nieokreślona) 
void 

fnFunkcja1

(

int m

//nie zwraca wartości – argument: int m 

int 

fnFunkcja2

(

void

)   

//zwraca wartość int – nie posiada argumentów 

void 

fnFunkcja3

(

void

//nie zwraca wartości – nie posiada argumentów

Typ wartości zwracanej 

Parametry wywołania ze 

wskazaniem typów 

zmiennych 

Zmienne tworzone dla 

potrzeb wewnątrz funkcji 

Powrót z funkcji wraz z 

wartością zwracaną 

Operacje funkcji 

background image

WYKŁADY cz.2 v.3 (2008)          Podstawy programowania 1           

(dr.inŜ Marcin Głowacki)

  38 

F

UNKCJE

      2.

 

 

Kolejność definicji funkcji:

 

 
Definicje i deklaracje globalne 
Definicja funkcji 1 
Definicja funkcji 2 
... 
Definicja funkcji głównej main 

 

lub 

 

Definicje i deklaracje globalne 
Prototyp funkcji 1 
Prototyp funkcji 2 
... 
Definicja funkcji głównej main 
Definicja funkcji 1 
Definicja funkcji 2 
 
Program liczy sumę kwadratów liczb n zadana z klawiatury 

#include <iostream> 
 
int 

fnSumaKwadratow

(

int k

);        //definicja prototypu 

 
int main(){ 
using std::cout; using std::cin; using std::endl; 
int n, iWynik; 
cout<<"Podaj wartosc zmiennej n: ";cin>>n; 
iWynik = 

fnSumaKwadratow(

n

)

;   //wywolanie funkcji 

cout << "Suma kwadratow dla n = "<<n<<" wynosi "<<iWynik<<endl; 
return 0; 

/////////////////////////////////////// FUNKCJE ///////////////////////////////////////////////// 
int 

fnSumaKwadratow

(

int k

) {   // czy moŜe być k zamiast n ? 

int i, iSuma = 0; 
for (i=1; i<=

k

;i++) 

 

// czy moŜe być k zamiast n ? 

 

iSuma+=i*i; 

return

(iSuma); 

 
Co się stanie gdy zadeklaruje się jako parametr wywołania funkcji zmienną 

k

 zamiast 

n

 ? 

}

 

podobnie jak w plikach nagłówkowych 

(ang. headers) , np. plik.h 

background image

WYKŁADY cz.2 v.3 (2008)          Podstawy programowania 1           

(dr.inŜ Marcin Głowacki)

  39 

iWynik=fnSumaKwadratow(n);

int n, iWynik;

...

int main(){

}

Adres

powrotu

n

STOS

iWynik

...

...

Adres

wyjścia z main()

WYWOŁANIE FUNKCJI

RAM

zrz

ut

skok

n

...

...

fnSumaKwadratow(n){
int i, iSuma = 0;

}

return (iSuma);

for (i=1; i<=n;i++)  iSuma+=i*i;

 

 
Podczas wywołania funkcji następuje zapamiętanie na stosie (zrzut na stos) adresu powrotu 
(segment i offset) do miejsca następnej instrukcji następującej po wywoływanej funkcji. 
Na stos zostaje odłoŜona wartość argumentu wywołania funkcji, która będzie funkcjonować jak 
zmienna lokalna w obszarze funkcji. 

 

background image

WYKŁADY cz.2 v.3 (2008)          Podstawy programowania 1           

(dr.inŜ Marcin Głowacki)

  40 

Adres

powrotu

n

STOS

iWynik

...

Adres

wyjścia z main()

DZIAŁANIE FUNKCJI

ob

lic

ze

ni

a

i

iSuma

...

n

...

iWynik=fnSumaKwadratow(n);

int n, iWynik;

...

int main(){

}

RAM

...

fnSumaKwadratow(n){
int i, iSuma = 0;

}

return (iSuma);

for (i=1; i<=n;i++)  iSuma+=i*i;

 

 
Zostają powołane do Ŝycia nowe zmienne lokalne: i oraz iSuma w postaci komórek pamięci na 
stosie. Na tych zmiennych odbywa się przetwarzanie, czyli obliczenia sumy kwadratów liczb od 
1 do n. Zmienna i jest liczbą podnoszoną do kwadratu w pętli for. 
 

 

background image

WYKŁADY cz.2 v.3 (2008)          Podstawy programowania 1           

(dr.inŜ Marcin Głowacki)

  41 

Adres

powrotu

n

STOS

iWynik

...

Adres

wyjścia z main()

POWRÓT Z FUNKCJI

i

iSuma

...

n

...

przepisuje
wynik

pow

rót

iWynik

Adres

wyjścia z main()

...

n

...

STOS

zwalnia

stos

...

iWynik=fnSumaKwadratow(n);

int n, iWynik;

...

int main(){

}

RAM

...

fnSumaKwadratow(n){
int i, iSuma = 0;

}

return (iSuma);

for (i=1; i<=n;i++)  iSuma+=i*i;

 

 
Powrót z funkcji następuje po napotkaniu instrukcji return lub po dotarciu do klamry zamykającej 
‘}’. W tym przypadku funkcja zwraca wartość typu int i przepisuje ją do zmiennej lokalnej 
funkcji main o nazwie iWynik. Musi nastąpić zatem przepisanie wartości zmiennej iSuma pod 
adres zmiennej iWynik na stosie. Wszystkie zmienne lokalne w funkcji fnSumaKwadratow, czyli 
iSuma, i oraz n przestają być potrzebne i zostają usunięte (zciągnięte ze stosu). Wtedy na stosie 
odkryty zostanie adres powrotu, który jest wczytywany do rejestru instrukcji procesora. To 
spowoduje przekazanie sterowania pod ten adres, czyli wykonana będzie instrukcja następująca 
po wywołaniu funkcji. W ten sposób poza zmienioną wartością iWynik zmiennej lokalnej funkcji 
main nie pozostanie Ŝaden ślad działalności funkcji fnSumaKwadratów. Obszar stosu uŜywany 
przez tą funkcję zostanie zwolniony i moŜe być wykorzystany do innych celów. 
 

background image

WYKŁADY cz.2 v.3 (2008)          Podstawy programowania 1           

(dr.inŜ Marcin Głowacki)

  42 

F

UNKCJE

      3.

 

 

ZASIĘG DOSTĘPNOŚCI ZMIENNYCH: 

 
Zmienne: 

• 

Globalne

 – mają zasięg ogólny – dostępne wszędzie w programie, posiadają rezerwację w 

pamięci operacyjnej i swój stały adres 

• 

Lokalne

 – powoływane do Ŝycia wewnątrz funkcji, znikają po zakończeniu funkcji 

(tworzone tymczasowo na stosie w pamięci operacyjnej). Przesłaniają inne zmienne o tych 
samych nazwach (patrz przykład) 

• 

Statyczne

 – definiowane wewnątrz funkcji – zachowują wartość do następnego wywołania 

tej samej funkcji 

 
PRZESŁANIANIE ZMIENNYCH GLOBALNYCH

Nazewnictwo zmiennych lokalnych nie jest dowolne, poniewaŜ zmienne globalne o tych 

samych nazwach zostają 

przesłonięte

 przez nowe definicje, ale ich czas Ŝycia jest ograniczony 

do wnętrza funkcji. Po zakończeniu funkcji zmienne lokalne znikają bezpowrotnie. Bierze się to 
stąd, Ŝe są one tworzone tymczasowe na strukturze stosu w pamięci operacyjnej komputera. 
 
Przykładowy program: 

 
#include <iostream> 
 
int 

k

=50, 

j

=10; 

//zmienne globalne z nadaną wartością początkową 

 
int 

fnFunkcja

(

void

) { 

return (

k

+100);  

//obszar zasięgu zmiennej globalnej 

k

=150 

 

 
int main() { 
using std::cout; using std::endl; 
int 

k

=3; 

 

//zmienna lokalna 

k

 w funkcji main 

cout<< ”Dla lokalnego k: ”<<

k

+100+

j

<<” Dla globalnego k: „<<

fnFunkcja()

+

j

<<endl; 

Wynik : ? >

113, 160

< 

 

background image

WYKŁADY cz.2 v.3 (2008)          Podstawy programowania 1           

(dr.inŜ Marcin Głowacki)

  43 

Przykładowy program: 

#include <iostream> 

 

int 

i

=10, 

j

=200, 

k

=300; 

//zmienne globalne 

 

void

 

fnFun

(

void

) { 

using std::cout; using std::endl; 
int 

i

 =4;  

 

 

 

//przesłonięcie nazwy globalnej 

static

 int 

j

=0;   

 

 

//przesłonięcie nazwy globalnej – zmienna 

static

  

i

++; 

j

++;

k

++; 

cout<<"W fnFun(): I= "<<

i

<<"  J= "<<

j

<<"  K= "<<

k

<<endl; 


int main() { 
int 

i

k

=0; 

for (

i

=0; 

i

<3; 

i

++) 

fnFun

(); 

cout<<"W main():  I= "<<

i

<<"  J= "<<

j

<<"  K= "<<

k

<<endl; 

return 0; 

Wynik:  

 

W fnFun(): I= 5  J= 1  K= 301 
W fnFun(): I= 5  J= 2  K= 302 
W fnFun(): I= 5  J= 3  K= 303 
W main():  I= 3  J= 200  K= 0 

 

int main() {
int i, k=0;
for (i=0; i<3; i++) fnFun();
cout<<"W main():  I= "<<i
<<"  J= "<<j<<"  K= "<<k<<endl;
return 0;
}

STOS

...

i

Adres

wyjścia z main()

RAM

powrót

k

...

i=10
j=200
k=300

zmienne
globalne

void fnFun(void) {
using std::cout; using std::endl;
int i =4; 
static int j=0;
i++; j++;k++;
cout<<"W fnFun(): I= "<<i
<<"  J= "<<j<<"  K= "<<k<<endl;
}

Adres

powrotu z fnFun()

i

STOS

...

i

Adres

wyjścia z main()

k

...

j

j

i

i

k

skok

powrót

skok

zmienne
lokalne

zmienne
lokalne

static j=10

 

background image

WYKŁADY cz.2 v.3 (2008)          Podstawy programowania 1           

(dr.inŜ Marcin Głowacki)

  44 

A

RGUMENTY 

F

UNKCJI

     1. 

 

To co było do tej pory w przykładach to 

przekazywanie argumentów przez wartość

 

 

Funkcja nie moŜe wpływać na wartości zmiennych przekazywanych do funkcji jako 

argumenty, poniewaŜ w trakcie wywołanie funkcji powoływane są do Ŝycia zmienna w sensie 
lokalnym o typie i nazwie argumentu wywołania oraz z wartością początkową wywołania. 
Po opuszczeniu funkcji nie pozostanie ślad po argumentach i operacjach na nich wykonanych. 
Funkcja moŜe zwrócić wartość w postaci jawnej (instrukcja return) do uŜycia w dalszej części 
programu. 
 
Przykładowy program: 

#include <iostream> 
void 

fnZwieksz

(

int a, int b

) { 

using std::cout; using std::endl; 
a+=100; 
b+=200; 
cout << " a: "<<a<<" b: "<<b<<endl; 

int main(){ 
using std::cout; using std::endl; 
int 

x

=10, 

y

=10; 

fnZwieksz

(

x,y

);  //nie spowoduje zmiany wartości 

x

 i 

w funkcji main() 

cout << ” x: ”<<

x

<<” y: ”<<

y

return 0; 

UWAGA

: MoŜna to obejść uŜywając wewnątrz funkcji zmiennych globalnych, ale nie podając 

ich jako argument wywołania, lecz wykonując jedynie operacje na nich. 

#include <iostream> 
int 

x

=10, 

y

=10; 

//zmienne globalne 

void 

fnZwieksz

(

int a, int b

) { 

using std::cout; using std::endl; 
x=a+100; 
y=b+200; 
cout << " a: "<<a<<" b: "<<b<<endl; 

int main(){ 
using std::cout; using std::endl; 
int x=10,y=10; 

fnZwieksz

(

x,y

);  //nie spowoduje zmiany wartości 

x

 i 

w funkcji main() 

cout << ” x: ”<<

x

<<” y: ”<<

y

return 0; 

ODPOWIEDNIE METODY: 

referencja

 i 

wskaźniki

  

– omawiane w dalszej części kursu 

Wynik:  

a: 110 b: 210 

  

 

x: 10 y: 10 

 

Wynik:  

a: 10 b: 10 

  

x: 110 y: 210 

 

background image

WYKŁADY cz.2 v.3 (2008)          Podstawy programowania 1           

(dr.inŜ Marcin Głowacki)

  45 

A

RGUMENTY 

F

UNKCJI

     2. 

 

Argumenty funkcji 

main()

 są skojarzone z 

parametrami

 wywołania 

programu

nazywanymi 

linią komend

 lub 

wierszem polecenia

 

 
int 

main

 () lub int 

main

 (

void

) – bez parametrów, 

int 

main

(

int argc, char *argv[]

) – dwa parametry:  

• 

argc

 – liczba argumentów wywołania programu (>=1) 

• 

argv

 – tablica wskaźników do tekstów argumentów 

 
//Program wypisze liczbę oraz zawartość wszystkich argumentów funkcji main() 

#include <iostream> 
 
int 

main

(

int argc, char *argv[]

) { 

using std::cout; using std::endl; 
cout<<”Program ”<<

argv[0]

<<” ma ”<<

argc

-1<<” argumentów.”<<endl; 

for(int i=1;i<

argc

;i++) 

 

cout<<” Argument\t”<<i<<”\tto\t”<<

argv[i]

<<endl; 

return 0; 

 
Wywołanie programu: funkcje_5.exe argument1 argument2 argument3 
Wynik: 
Program ścieŜka\ funkcje_5.exe ma 3 argumentów. 
 Argument       1       to      argument1 
 Argument       2       to      argument2 
 Argument       3       to      argument3 
Aby kontynuować, naciśnij dowolny klawisz . . . 
 
UWAGA: Trzeba pamiętać, Ŝeby dokonać ustawień dla linii komend w kompilatorze, np. w Dev-
C++ w okienku Compilation przycisk Parameters. 
 

background image

WYKŁADY cz.2 v.3 (2008)          Podstawy programowania 1           

(dr.inŜ Marcin Głowacki)

  46 

D

OMYŚLNE 

A

RGUMENTY 

F

UNKCJI

 

 
Podczas definicji funkcji moŜna przypisać domyślne (początkowe) wartości argumentów funkcji 
 

void 

fnSuma

(

int a=10, int b=20, int c=30, int d=40

){ 

.... 

 
Wywołanie tej funkcji moŜe się odbyć z niepełną liczbą parametrów: 
 

fnSuma

(

1,2

); //a=1, b=2 i domyślnie c=30 i d=40 

 
= równowaŜne = 
 

fnSuma

(

1,2,30,40

); 

 

UWAGA:

 MoŜemy pominąć tylko 

wszystkie

 argumenty począwszy od tego, 

którego pominiemy jako pierwszy. 

 

background image

WYKŁADY cz.2 v.3 (2008)          Podstawy programowania 1           

(dr.inŜ Marcin Głowacki)

  47 

5.

P

RZECIĄśANIE 

F

UNKCJI

 

 

Nadajemy te same nazwy funkcjom, które realizują analogiczne operacje,  

ale 

róŜniące się typem lub liczbą parametrów

 - dzięki tym róŜnicom kompilator 

rozpoznaje, którą z funkcji ma być uŜyta w zaleŜności od typu wywołania. 
 

Przykład: 

//prototypy funkcji 
int 

polePowierzchni

(

int bokX,int bokY

); 

double 

polePowierzchni

(

double bokX,double bokY

); 

double 

polePowierzchni

(

double promien

); 

int main(){ 
int a=5,b=4; 
double c=5.8,d=3.2, r=2.11; 
cout<<"Pole powierzchni z argumentami całkowitymi "<<

polePowierzchni

(

a,b

)<<'\n'; 

cout<<"Pole powierzchni z argumentami rzeczywistymi "<<

polePowierzchni

(

c,d

)<<endl; 

cout<<"Pole powierzchni koła z argumentem rzeczywistym "<<

polePowierzchni

(

r

)<<endl; 

return 0; 

//definicja funkcji 
int 

polePowierzchni

(

int bokX,int bokY

){ 

return (bokX*bokY);  

double 

polePowierzchni

(

double bokX,double bokY

){ 

return (bokX*bokY); 

double 

polePowierzchni

(

double promien

){  //promień kola 

return (promien*promien*3.1415); 

 

background image

WYKŁADY cz.2 v.3 (2008)          Podstawy programowania 1           

(dr.inŜ Marcin Głowacki)

  48 

T

ABLICE

      1. 

 

Struktura danych zawierająca uporządkowany zbiór obiektów tego samego typu i 

odpowiada matematycznemu pojęciu wektora, macierzy. 
Mogą być tablice wielowymiarowe, ale pamiętajmy, Ŝe w pamięci i tak ułoŜone są sekwencyjnie. 
 
Dla miłośników motoryzacji: tablica iMoto o rozmiarze 

4x4

:  

int iMoto[

4

] [

4

]; 

 
 
 
 

[0][0] 

[0][1] 

[0][2] 

[0][3] 

[1][0] 

[1][1] 

[1][2] 

[1][3] 

[2][0] 

[2][1] 

[2][2] 

[2][3] 

10 

11 

12 

[3][0] 

[3][1] 

[3][2] 

[3][3] 

13 

14 

15 

16 

 
MoŜna wpisać wartości początkowe:  
 
tak: (bardziej czytelne) 

lub tak: 

 
int iMoto[4] [4] = { 
 

{1,2,3,4}, 

 

{5,6,7,8}, 

 

{9,10,11,12}, 

 

{13,14,15,16} 

}; 

 
int iMoto[4] [4] ={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}; 
 

 

TABLICE SĄ INDEKSOWANE OD ZERA [0] !!! 

 
Przykład: Wpisujemy wartość 2 do wszystkich elementów pewnej tablicy: 

Czy jest róŜnica ?

 

int iTab[

10

][

5

]; 

for (int i=0;i<

10

;i++) 

 

for(int j=0;j<

5

;j++) 

 

 

iTab[i][j] = 2; 

 

int iTab[

50

]; 

for (int i=0;i<

50

;i++) 

 

iTab[i] = 2; 

 

Jeśli wpisujemy wszystkie wartości początkowe do tablicy to moŜemy nie podawać liczby 
elementów - komputer poradzi sobie z policzeniem: 

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

 

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

 

Indeks 

Wartość 

background image

WYKŁADY cz.2 v.3 (2008)          Podstawy programowania 1           

(dr.inŜ Marcin Głowacki)

  49 

T

ABLICE

      2. 

 

RAM

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

int iMoto[4][4] = 
{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};

int iMoto[4][4] = { {1,2,3,4},
                               {5,6,7,8},
                               {9,10,11,12},
                               {13,14,15,16} };

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

(toŜsame)

[0]

[1]

[2]
[3]

[4]

[5]

[6]
[7]

[8]

[9]
[10]

[11]

[12]
[13]

[14]

[15]

indeks

[0]

[0]

[0]
[0]

[1]

[1]

[1]
[1]

[2]

[2]
[2]

[2]

[3]
[3]

[3]

[3]

[0]

[1]

[2]
[3]

[0]

[1]

[2]
[3]

[0]

[1]
[2]

[3]

[0]
[0]

[0]

[0]

indeks

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

 

 

background image

WYKŁADY cz.2 v.3 (2008)          Podstawy programowania 1           

(dr.inŜ Marcin Głowacki)

  50 

Przykładowy program 

//Program wynajduje element min i max w tablicy jednowymiarowej (wektorze) 
#include <iostream> 
const int MAXTAB 100 
 
int main(){ 
using std::cout; using std::cin; using std::endl; 
int n,i,iMin,iMinIndx,iMax,iMaxIndx; //n - aktualny rozmiar wektora 
int 

iTab

[MAXTAB]; 

cout<<"Podaj liczbe elementow: (w zakresie od 1 do  ”<<MAXTAB; cin>>n; 
for(i=0;i<n;i++){ 

 

//wprowadzenie danych do tablicy 

 

cout<<"Podaj "<<i<<" element: "; cin>>

iTab

[i]; 

 

iMin=iMax=

iTab

[0]; 

iMinIndx=iMaxIndx=0; 

//inicjalizacja parametrów do poszukiwania 

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

//wyszukaj min i max 

 

if(

iTab

[i]<iMin) { 

 

 

iMin=

iTab

[i]; iMinIndx=i; 

 

 

 

if(

iTab

[i]>iMax) { 

 

 

iMax=

iTab

[i]; iMaxIndx=i; 

 

 

 

cout<<"Minimum to: "<<iMin<<" na pozycji "<<iMinIndx<<endl; 
cout<<"Maximum to: "<<iMax<<" na pozycji "<<iMaxIndx<<endl; 
cout<<"Index\t"<<"Wartosc"<<endl; 
for(i=0;i<n;i++) { //wyswietl minima i maxima 
 

cout<<i<<"\t"<<

iTab

[i]; 

 

if(

iTab

[i]==iMax) cout<<"\tMAXIMUM"; 

 

if(

iTab

[i]==iMin) cout<<"\tMINIMUM"; 

 

cout<<endl; 

 

return 0; 

Rezultat: 
Podaj liczbe elementow: 7 
Podaj 0 element: 2 
Podaj 1 element: 5 
Podaj 2 element: 6 
Podaj 3 element: 4 
Podaj 4 element: 2 
Podaj 5 element: 6 
Podaj 6 element: 3 
Minimum to: 2 na pozycji 0 
Maximum to: 6 na pozycji 2 
Index  Wartosc 

2          

MINIMUM 

6          

MAXIMUM 

2          

MINIMUM 

6          

MAXIMUM 

background image

WYKŁADY cz.2 v.3 (2008)          Podstawy programowania 1           

(dr.inŜ Marcin Głowacki)

  51 

T

ABLICE I 

W

SKAŹNIKI

 

 

WPROWADZENIE do WSKAŹNIKÓW

 

 

Nazwa tablicy

 podaje adres - 

jest wskaźnikiem

 na pierwszy element 

tablicy – o indeksie 

0

 

RAM

wskaznik iMoto

wskaznik
iMoto + 3

wskaznik
iMoto + 15

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

[0]

[1]

[2]
[3]

[4]

[5]
[6]
[7]

[8]
[9]

[10]

[11]
[12]

[13]
[14]

[15]

indeks

[0]

[0]

[0]
[0]

[1]

[1]
[1]
[1]

[2]
[2]

[2]

[2]
[3]

[3]
[3]

[3]

[0]

[1]

[2]
[3]

[0]

[1]
[2]
[3]

[0]
[1]

[2]

[3]
[0]

[0]
[0]

[0]

indeks

 

 
 
int 

iTab

[10]; 

 

iTab

[0] to jest to samo co: *

iTab

 (wartość spod adresu 

iTab

 

iTab

[i] to jest to samo co: *(

iTab

+i) (zwiększamy adres o i) 

 

iTab

 

nie powinno

 być zmieniany pod Ŝadnym pozorem 

 

Błąd: 

iTab

+=i Błąd 

background image

WYKŁADY cz.2 v.3 (2008)          Podstawy programowania 1           

(dr.inŜ Marcin Głowacki)

  52 

W

SKAŹNIKI

      1. 

 

Zmienne wskaźnikowe

 

– wartościami są adresy wskazujące na miejsce w 

pamięci operacyjnej pewnego obiektu (segment + offset). 

 

int *wa

; //deklaracja zmiennej wskaźnikowej wa na obiekt int  

 

int *wa

, a=10, b=20; 

 

wa=&a

; // wa zaczyna wskazywać na zmienna ‘a’ 

 

Dostęp do wartości zmiennej ‘a’: 

 

cout<<a<<”,”; 

lub 
 

cout<<*wa;

   //przez 

operator

 

wyłuskania

 

//(nie mylić z wyłuzdaniem) 

Efekt: 10,10 
 
MoŜna teraz 

*wskaźnik

 traktować jak zmienną na którą obecnie wskazuje (w przykładzie na a), 

np.  

*wa = 100

; zapisze wartość 100 do zmiennej ‘a’ 

b=*wa+1; 
c=(*wa)++;

 //operatory działają od prawej do lewej to trzeba nawiasy 

c=++*wa;

 //to samo 

ale nie: 

c=*wa++;

  

//spowoduje zwiększenie adresu wskazania wa o jeden i dopiero przypisanie do c 

 

 

//zwykle NIEUśYWANE 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
Adres a składa się z adresu Segmentu i Offset fizycznego adresu RAM w komputerze. 
Wskaźnik zatem zajmuje 2 bajty adresu segmentu i 2 bajty adresu offsetu = 4 bajty. 
 

wa 

int *wa 

?

 

10 

20 

int a=10, b=20; 

wa 

wa=&a 

wskazanie na a 
(zaadresowanie a) 

adres a 

background image

WYKŁADY cz.2 v.3 (2008)          Podstawy programowania 1           

(dr.inŜ Marcin Głowacki)

  53 

W

SKAŹNIKI

      2. 

 

PRZEKAZYWANIE PARAMETRÓW DO FUNKCJI: 

 

Poprzednio poznaliśmy przekazywanie parametrów funkcji przez wartość. Były na to 

przykłady, które pokazywały, Ŝe zmienne nawet o tej samej nazwie nie mają ze sobą nic 
wspólnego – jedynie ich wartość przekazywana jest do wnętrza funkcji. 
 
Przykład: 

void 

fnZwieksz

(

int a, int b

) { 

 

a +=100; 

 

b+=200; 

Wywołanie: 

int x = 10, y = 10; 

fnZwieksz

(

x,y

);

 //nie zmienia wartości x i y 

Efekt: //bez zmian: x = 10, y=10 
 

Jak to zmienić ? 

 
1.  Nie zmieniać – 

uŜywać zmiennych globalnych

2.  Wykorzystać 

wskaźniki

 (C, C++) – przekazywanie przez wskaźniki 

3.  Wykorzystać 

referencję

 (C++) – przekazywanie adresu 

 
Ad.2 

Wskaźniki

 – przekazanie przez wskaźniki 

void 

fnZwiekszInny

 (

int *a, int *b

) { 

*a+=100; 
*b+=200; 

Wywołanie: 

int x=10, y =10; 

fnZwiekszInny

(

&x,&y

); //zmienia wartość x i y 

Efekt: x=110, y=210 
 
Ad.3 

Referencja

 - przekazywanie adresu 

void 

fnZwiekszRef

(

int &a, int &b

){ // Zmienia się jedynie deklaracja funkcji 

a+=100; 
b+=200; 

Wywołanie: 

int x = 10, y = 10; 

fnZwiekszRef

(

x,y

); // zmienia wartość x i y 

Efekt: x=110, y=210 

background image

WYKŁADY cz.2 v.3 (2008)          Podstawy programowania 1           

(dr.inŜ Marcin Głowacki)

  54 

W

SKAŹNIKI

      3. 

 
Przykład - zamiana wartości argumentów: 

void 

fnZmien

(

int &a, int &b

){ 

int pom=b; 
b=a; 
a=pom; 

 
Wywołanie: 

int x=10, y=30; 

fnZmien

(

x,y

); 

 
Efekt: x=30, y=10 
 

TABLICE i FUNKCJE

 

 

Nazwa tablicy jest wskaźnikiem na zerowy element tablicy

, zatem przekazanie 

tablicy poprzez nazwę jest jednocześnie 

przekazywaniem przez adres

UWAGA:

 Rozmiar tablic moŜe być róŜny, zatem naleŜy pamiętać o przekazaniu do funkcji 

rozmiaru tablicy przez wartość poprzez inny argument wywołania. 
 
Przykłady: 

//Program liczy sumę wszystkich elementów tablicy 
int 

fnSumaWekt(

int t[], int m

){ //m – rozmiar tablicy 

int sum=0; 
for(int i=0;i<m;i++) 
 

sum+=t[i]; 

return sum; 

 
Wywołanie: 

int x[20],iWynik; 
iWynik=

fnSumaWekt

(

x,20

); 

 
lub: dla określonego wiersza tablicy dwuwymiarowej 
 

int y[20][20],iWynik; 
iWynik=

fnSumaWekt

(

y[1],20

); //obliczy sumę drugiego wiersza y[1] tablicy y 

 

background image

WYKŁADY cz.2 v.3 (2008)          Podstawy programowania 1           

(dr.inŜ Marcin Głowacki)

  55 

Przykład: 

wyświetla wynik funkcji przeciąŜonych suma wektora i tablic dwuwymiarowych

 

#include <iostream> 
#define MMAX 3 
#define NMAX 3 
using namespace std; 
int 

fnSuma

(

int iTab[][NMAX], int m, int n

){ 

  int iSuma=0; 
  for (int i=0;i<m;i++){ 
 

  cout<<endl; 

 

  for(int j=0;j<n;j++){ 

 

 

 iSuma+=iTab[i][j]; 

 

 

 cout<<'\t'<<iTab[i][j]; 

 

  } 

  } 
  cout<<"\nSuma tablicy naturalnej: "<<iSuma<<endl; 
  

return

 iSuma; 


double 

fnSuma

(

double dTab[][NMAX], int m, int n

){ 

  double dSuma=0; 
  for (int i=0;i<m;i++){ 
 

  cout<<endl; 

 

  for(int j=0;j<n;j++){ 

 

 

 dSuma+=dTab[i][j]; 

 

 

 cout<<'\t'<<dTab[i][j]; 

 

  } 

  } 
  cout<<"\nSuma tablicy zmiennoprzecinkowej: "<<dSuma<<endl; 
  

return

 dSuma; 


int 

fnSuma

(

int iTab[], int m

){ 

  int iSuma=0; 
  for (int i=0;i<m;i++){ 
 

 

 iSuma+=iTab[i]; 

 

 

 cout<<'\t'<<iTab[i]; 

  } 
  cout<<"\nSuma wektora naturalnego: "<<iSuma<<endl; 
  

return

 iSuma; 


int 

main

(){ 

int 

iTablica

[MMAX][NMAX] = {1,2,3,4,5,6,7,8,9}; 

double 

dTablica

[MMAX][NMAX] =  

{ {1.1,2.2,3.3},{4.4,5.5,6.6},{7.7,8.8,9.9}}; 

fnSuma

(

iTablica,MMAX,NMAX

); 

fnSuma

(

dTablica,MMAX,NMAX

); 

fnSuma

(

iTablica[1],NMAX

);  

return

 0; } 

Efekt: 
 
        1       2       3 
        4       5       6 
        7       8       9 
Suma tablicy naturalnej: 45 
 
        1.1     2.2     3.3 
        4.4     5.5     6.6 
        7.7     8.8     9.9 
Suma tablicy 
zmiennoprzecinkowej: 49.5 
        4       5       6 
Suma wektora naturalnego: 15