background image

 
 
 

Katedra Informatyki Stosowanej 

Politechniki Łódzkiej 

 
 
 

mgr inż. Tomasz Jaworski 

 
 

Programowanie w języku  

ANSI C

 

 
 

 

 

 

Al. Politechniki 11, 90-924 Łódź 

ul. Stefanowskiego 18/22, 90-924 Łódź 

http://tjaworski.kis.p.lodz.pl

 

e-mail: 

tjaworski@kis.p.lodz.pl

 

 
 

background image

Programowanie w języku ANSI C 

 

1. 

 Podstawowe informacje o kodzie źródłowym. 

W C/C++ tworzenie programu odbywa się w dwóch etapach: 

 - opracowanie kodu źródłowego 
 - generowanie kodu wynikowego 

Pierwszy  etap  to  zapisanie  algorytmu  za  pomocą  instrukcji  języka.  W  efekcie 

uzyskujemy kod źródłowy programu, który jest plikiem tekstowym. W drugim etapie zapis w 
języku  wysokiego  poziomu  (C++)  tłumaczony  jest  na  rozkazy  procesora,  a  program 
doprowadzany  jest  do  postaci  wykonywalnej  w  danym  systemie  operacyjnym.  Taki  proces 
tłumaczenia składa się z dwóch faz: kompilacji i łączenia. 

Z  punktu  widzenia  kompilatora  kod  źródłowy  traktowany  jest  jako  ciąg  znaków 

ASCII.  Z punktu  widzenia  programisty  jest  on  podzielony  na  wiersze,  które  zawierają 
różnego  rodzaju  deklaracje,  definicje,  instrukcji  i  inne  elementy  programu.  Podstawowe 
elementy, z których zbudowany jest program, nazywane są jednostkami leksykalnymi. Są one 
porozdzielane znakami spacji, tabulatorów lub sekwencjami końca wiersza. 

Do  podstawowych  jednostek  leksykalnych  języka  C++  zaliczamy:  słowa  kluczowe, 

identyfikatory,  stałe,  literały  łańcuchowe,  operatory  znaki  przestankowe  Identyfikator  może 
składać  się  z  liter  małych  i  wielkich,  cyfr  oraz  znaku  podkreślenia.  Słowa  kluczowe  są 
specjalnymi  identyfikatorami  zarezerwowanymi  dla  ściśle  określonych  celów.  Oto  ich 
zestawienie: 

asm 
auto 
brake 
case 
cdecl 
_cdecl 
__cdecl 
char 
class 
const 
continue 

_cs 
__cs 
default 
delete 
do 
double 
__ds 
else 
enum 
__es 
__export 

extern 
far 
__fastcall 
float 
for 
friend 
goto 
huge 
if 
inline 
int 

interrupt 
__loadds 
long 
near 
new 
operator 
pascal 
private 
protected 
public 
register 

return 
__saveargs 
__seg 
short 
signed 
sizeof 
__ss 
static 
struct 

switch 
template 
this 
typedef 
union 
unsigned 
virtual 
void 
volatile 
while 

Znakami przestankowymi w języku C++ są: [ ] ( ) { } , ; : ... * = #. 

2. 

 

Struktura programu w języku C++ 

Cechą charakterystyczną języka C/C++ jest standardowa możliwość budowy programu 

z  wielu  funkcjonalnych  modułów.  Program  zbudowany  jest  z  funkcji.  Każda  z  nich  może 
przyjmować  dowolną  ilość  parametrów  oraz  zwracać  jedną  wartość.  Aby  można  było 
wygenerować  wykonywalny  kod  wynikowy  programu,  w  jednym  i  tylko  w  jednym 
z modułów musi znajdować się funkcja główna main, od której rozpocznie się wykonywanie 
programu. Najprostszy wykonywalny program w języku C może wyglądać następująco: 

int main(int) 

  return 0; 
}

 

Powyższy program składa się z bezparametrowej funkcji main. Funkcja zwraca wartość typu 
całkowitego.  Ciało  funkcji,  otoczone  nawiasami  {},  zbudowane  jest  z  instrukcji. 
W powyższym przykładzie instrukcja return zwraca wartość 0. 
Poniższy  przykład  demonstruje  podstawowe  funkcje  biblioteczne  obsługujące  standardowe 
wejście  i  wyjście.  Aby  móc  stosować  te  funkcje  należy  włączyć  do  programu  plik  stdio.h 
instrukcją #include.  

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

char imie[20]; 
int i; 

background image

Programowanie w języku ANSI C 

 

 

printf(„\nPodaj swoje imie: „);   

// wypisz na ekranie 

gets(imie); 

 

 

// pobierz wartość łańcuchową 

puts(„Ile masz lat? „); 
scanf(„%d”, &i); 

 

 

// pobierz wartość liczbową 

printf(“\n%s ma %d lat.”, imie, i); 
return 0; 

}

 

3. 

 

Typy danych, deklaracje zmiennych i stałych 

Typy danych dostępne w języku C można podzielić zasadniczo na typy proste i strukturalne. 
Typy  proste  są  niepodzielne  i  wykorzystywane  są  do  tworzenia  typów  strukturalnych.  Typy 
proste to: 
Arytmetyczne: całkowite, zmiennoprzecinkowe i znakowe 

a.  Wskaźnikowe 
b.  Referencyjne 

Natomiast typy strukturalne to: 

•  Tablice 
•  Struktury i unie 
•  Klasy 

Typy i zmienne całkowite 

Słowo kluczowe 

Znaczenie 

char 
int 
long 
signed 
short 
unsigned 

Typ znakowy 
Typ całkowity 
Typ tzw. długich liczb całkowitych 
Liczby ze znakiem 
Typ tzw. krótkich liczb całkowitych 
Liczby bez znaku 

W/w słów kluczowych zwykle używa się w połączeniu. Poniższa tabela demonstruje takie 
połączenia i ich rozmiar w pamięci oraz zakres przyjmowanych wartości. 

Typ 

Rozmiar 
w bitach 

Min 

Max 

unsigned char 
signed char 
unsigned int 
short signed int 
signed int 
long unsigned int 
long signed int 


16 
16 
16 
32 
32 

-128 

-32768 
-32768 

-2 147 483 648 

255 
127 

65535 
32767 
32767 

4 294 967295 
2147 483 647 

 

Typy i zmienne rzeczywiste (zmiennoprzecinkowe) 

Typ 

Rozmiar 
w bitach 

Min 

Max 

float 
double 
long double 

32 
64 
80 

3,4*10

-38

 

1,7*10

308

 

3,4*10

-4932 

3,4*10

38

 

1,7*10

308

 

3,4*10

4932

 

 

background image

Programowanie w języku ANSI C 

 

 

Typy i zmienne wskaźnikowe 
W  języku  C/C++  istnieje  możliwość  definiowania  zmiennych  zawierających  adres  jakiegoś 
obszaru w pamięci, przy czym obszar ten może być interpretowany jako zmienna określonego 
typu.  Są  to  tzw.  zmienne  wskaźnikowe.  Mogą  one  zawierać  adres  zmiennych  należących  do 
typów zarówno prostych jak i strukturalnych. Zmienne takie nazywamy wówczas zmiennymi 
wskazywanymi

. Jak pokazano na rysunku obok. 

Deklaracje zmiennych wskaźnikowych mogą wyglądać następująco: 

char *wsk_znaku; 
int *wsk_liczby_calk; 
double *wsk_liczby_rzecz; 
char (*wsk_tablicy)[10]; 
int **wsk_wsk; 

Inny przykład pokazuje zmienne wskazywane i wskaźnikowe. Dostęp do zmiennych 
wskazywanych: 

void func() 

     char znak = ‘a’, *wsk_znaku = &znak; 
     int liczba = 100, *wsk_liczby_calk = &liczba; 
... 
     *wsk_znaku = ‘b’; 
     *wsk_liczby_calk = ‘222’; 
... 

}

 

W  przykładzie  zamieszczonym  powyżej  zadeklarowano  zmienne  typu  char  i  int  oraz 
zmienne  wskazujące  zmienne  wymienionych  tu  typów.  Zadeklarowanym  zmiennym 
wskaźnikowym  przypisano  adres  (operator  &  służy  do  pobierania  adresu  zmiennej) 
zmiennych typów wskazywanych przez te zmienne. W rezultacie przypisanie takie jak: 

*wsk_znaku = ‘b’; 

operuje  na  zmiennej  wskazywanej  przez  zmienną  wsk_znaku,  a  więc  w  tym  przypadku  na 
zmiennej znak. W tej sytuacji jest ono równoważne przypisaniu: 

znak = ‘n’; 

Wskaźniki w języku C/C++ posiadają ogromne znaczenie, gdyż umożliwiają: 

•  Tworzenie i przetwarzanie dynamicznych struktur danych, 
•  Zarządzanie blokami pamięci, łańcuchami i tablicami, 
•  Przekazywanie parametrów funkcji, w tym także parametrów funkcyjnych. 

 

Typy i zmienne referencyjne (C++) 
Poza typem wskaźnikowym język C++ wprowadza tzw. typ referencyjny. Zmienne tego typu 
służą  do  reprezentowania  innych  zmiennych  w  programie.  Operacje  na  zmiennej  x  są 
równoważne  operacjom  na  zmiennej  referencyjnej  związanej  ze  zmienną.  W  praktyce 
omawiane  typy  są  wykorzystywane  podczas  przekazywania  parametrów  do  funkcji  oraz 
zwracania wartości funkcji. Deklaracja zmiennej referencyjnej przedstawia się następująco: 

typ &identyfikator = identyfikator_zmiennej; 

przy czym znak  może wystąpić zarówno przy identyfikatorze zmiennej, jak i przy nazwie 
typu. Poniżej zademonstrowano przykład wykorzystania zmiennych referencyjnych. 

int n = 10, i, &ri = i;   

 

// zmienna referencyjna ri, związana ze zmienną i 

double pos = 10, &r_pos = pos; 

//zmienna referencyjna r_pos, związana ze zmienną pos 

... 
ri = n; 

 

 

 

//zmiennej referencyjnej ri przypisz wartość zmiennej n, 

 

 

 

 

 

//czyli 10, a nie powiąż ze zmienną n, jakby się mogło  

 

 

 

 

 

//wydawać. 

background image

Programowanie w języku ANSI C 

 

Ponieważ operacje na zmiennej ri są równoważne operacjom na zmiennej i, więc w wyniku 
ostatniego przypisania zmienne i również zyskuje wartość 10.  

Tablice i wskaźniki. Łańcuchy 
Tablica jest złożoną strukturą danych, składającą się z elementów tego samego typu. Zajmuje 
ona ciągły obszar w pamięci o rozmiarze niezbędnym do zapamiętania jej elementów. Dostęp 
do  kolejnych  elementów  jest  możliwy  za  pośrednictwem  indeksów,  liczby  określającej 
położenie  elementu  w  tablicy.  Deklaracja  tablicy  N-wymiarowej  o  wymiarach  wymiar1, 
wymiar2,  ...,  wymiarN

  wygląda  następująco.  Poniżej  zamieszczono  przykładowe  deklaracje 

tablic. 

typ ident_tablicy [wymiar1][wymiar2] ... [wymiarN]; 

char str[30];   

//tablica 30 znaków 

char *t[12]; 

 

//tablica 12 wskaźników znaków 

double tabdbl[30][20]  //dwuwymiarowa tablica liczb rzeczywistych 
int tab1[20] = {10, 20}  //inicjowanie tablicy. Wpisywane parametry muszą być wartościami stałymi 
int tab2[10][10] = { {3.1}, {-10, 90} }; 
 

 

 

//tu zainicjowano tylko pierwsze dwa elementy z pierwszych dwóch kolumn.  

 

 

 

//Pozostałym domyślnie przypisana zostanie wartość 0. 

Najprostszym sposobem dostępu do elementu tablicy jest podanie jego pozycji (od 0 do N-1), 
np. 

tab1[3] = 0; 

 

//element czwarty (0, 1, 2, 3, .., 19) 

tab2[1][1] = 4; 

 

Przydzielanie pamięci 
Zadeklarowano zmienną wskaźnikową oraz przydzielono jej pamięć: 

#include <stdlib.h> 
… 
int n = 20; 
int *ptr = (int *)malloc(n * sizeof(int));  

//rozmiar może być podany jako zmienna 

int ptr2[20]; 

 

 

 

 

//tu rozmiar musi być podawany jako stała 

Odwołania do elementów ptr i ptr2 nie różnią się niczym. 

 

Łańcuchy w języku C++ 
Łańcuch w języku C/C++ jest tablica znaków zakończoną znakiem o kodzie zero – ‘\0’. 
Łańcuch deklarujemy tak samo, jak tablice znaków. Więc np. 

char str[100]; 

Deklarację można połączyć z jego inicjacją: 

char a[10] = ”\nRadek”; 
char str[20] = {’\n’,’R’,’a’,’d’,’e’,’k’,’\0’}; 
char *str1 = ”Radek. Autor skryptu”; 

Znajdowanie długości takiego łańcucha możliwe jest przy zastosowaniu funkcji strlength() i 
tak np. 

int len = strlen(str1);  

 

Struktury 

Jeżeli  wystąpi  potrzeba  zdefiniowania  obiektu  i  opisania  go  kilkoma  parametrami, 

można  zgromadzić  potrzebne  dane  Sw  jednym  miejscu  –  w  strukturze.  Składają  się  one  ze 
składowych różnych typów, umieszczonych w pamięci jedna za drugą. Rozmiar struktury jest 
więc równy sumie rozmiarów jej poszczególnych składowych. Deklaracja struktury wygląda 
następująco: 

background image

Programowanie w języku ANSI C 

 

struct ident_typu_struktury 

 

deklaracje-składowych 

} [ident_struktury[=inicjator], ...]; 

Identyfikator  typu  struktury  może  zostać  pominięty,  podobnie  jak  identyfikatory  struktury 
i inicjatory. Poniżej podano przykłady praktyczne deklarownia struktur. 

struct punkt 

 

double x, y; 


 
struct pracownik 

 

char *nazwisko; 

 

float wyplata; 

 

int czas_pracy; 

 

double efektywnosc; 

 

worker *nastepny; 

} w1 = { „Radek”, 1000, 10, 0.22}, tab[10]; 

W  drugim  przypadku  zdefiniowano  typ  struktury  pracownik’a.  Definicję  typu  struktury 
połączono  z  utworzeniem  zmiennej  strukturalnej  w1  oraz  tablicy  tab.  Zainicjowano  też 
strukturę  w1.  Na  uwagę  może  zwrócić  jedna  składowa  typu  pracownik.  Służy  ona  do 
wskazywania  na  następny  obiekt  typu  pracownik  będący  w  liście  wszystkich  obiektów  typu 
pracownik

.  

Dostęp  do  składowych  struktury  umożliwiają  operatory  .  i  ->.  Pierwszy  wykorzystywany 
w przypadku 

struktur 

reprezentowanych 

przez 

zmienne 

strukturalne, 

drugi 

przez wskaźnikowe. I tak np. 

pracownik pr1, *pr2; 
... 
pr1.wyplata = 1000; 
pr2->wyplata = 2000; 

 

Zasięg deklaracji i widoczność zmiennych 
Zasięg  deklaracji  zmiennych  może  obejmować  albo  określony  blok  programu  (otoczony 
nawiasami klamrowymi), albo cały plik kodu źródłowego, począwszy od miejsca deklaracji. 
Deklaracja  zmiennej  obejmuje  cały  plik,  jeśli  znajduje  się  ona  poza  wszystkimi  blokami 
programu.  Zmienne  takie  nazwami  zmiennymi  globalnymi.  Zmienna  zadeklarowana 
wewnątrz  bloku  programu  jest  zmienna  lokalną  i  nie  jest  widoczna  poza  tym  blokiem. 
Natomiast jest ona widoczna we wszystkich blokach znajdujących się wewnątrz danego bloku 
macierzystego. 

background image

Programowanie w języku ANSI C 

 

4. 

 

Instrukcje 

Jednym z najważniejszym elementów każdego języka programowania sa instrukcje. 

UmożliSwiają  one  zapis  algorytmu,  a  co  za  tym  idzie  –  służą  do  sterowania  przebiegiem 
programu. 

Instrukcje warunkowe 
Gdy  wystąpi  problem  sprawdzenia,  czy  zachodzi  dana  zależność  i  w  zależności  od  tego 
wykonanie takich czy innych czynności. 
Ogólna postać instrukcji warunkowej „jeżeli” przedstawia się następująco: 

if (wyrażenie-warunkowe) 

 

 

instrukcje składowe 


else if (wyrażenie-warunkowe) 

 

instrukcje składowe 


else 

 

instrukcje składowe 

Instrukcja wyboru 
Instrukcja wyboru ma następującą postać: 

switch (wyrażenie-sterujące) 

 

case wyrażenie-stałe-typu-całkowitego: instrukcje składowe; 

 

 

[break]; 

 

default: wyrażenie-stałe-typu-całkowitego: instrukcje składowe; 

Etykieta default jest nazywana domyślną etykietą wyboru. 

Instrukcje iteracyjne 
Pętla „dla” (for). 

for (wyrażenie-inicjujące ; wyrażenie-warunkowe ; wyrażenie-zwiększające) 

 

instrukcje składowe 

Instrukcja „dopóki” (while) 

while (wyrażenie-warunkowe) 

 

instrukcje składowe 

Instrukcja „wykonuj .. dopóki” (do .. while) 

do 

 

instrukcje składowe 

} while (wyrażenie-warunkowe) 

Instrukcje sterujące 

•   „przerwij” (break
•  „kontynuuj” (continue
•  „zwróć wartość i powróć” (return
•  „skok do” (goto

background image

Programowanie w języku ANSI C 

 

5. 

 

Funkcje 

Podczas  zapisu  algorytmu  często  spotykamy  się  z  problemami  wielokrotnego  wykonywania 
tych  samych  operacji,  lecz  dla  różnych  danych,  w  różnych  sytuacjach.  W  celu  ominięcia 
powielania kodu źródłowego można wykorzystać funkcje. W obrębie definicji takiej funkcji 
można zamknąć pewne operacje wykonywane na podstawie parametrów wejściowych. Każda 
funkcja w języku C/C++ posiada określony typ wartości, która jest zwracana po zakończeniu 
jej wykonywania.  
W  praktyce  pisząc  program  buduje  się  go  z  wielu  funkcji  (metod).  Ogólne  działanie  każdej 
z nich jest podobne i zilustrowane na rysunku. 

 

Zmienne globalne 

Parametry 

Wartości 

Modyfikacja zmiennych 

globalnych i inne efekty 

działania funkcji 

Funkcja

 

 

Rys. 1 Ilustracja działania funkcji w programie 

Na  podstawie  parametrów  wejściowych  funkcja  wykonuje  operacje,  których  rezultatem  są 
wartości funkcji. Często zdarza się jednak, że parametry  funkcji nie są jej jedynymi danymi 
wejściowymi,  podobnie  jak  wartości  funkcji  nie  są  jej  jedynymi  rezultatami  wykonania. 
Funkcja może np. pobierać dane z urządzenia wejściowego (plik, klawiatura) i również je tam 
wysyłać  lub  korzystać  ze  zmiennych  globalnych  programu,  których  wartość  może  wpływać 
na jej działanie.  
Zalety stosowania funkcji w konstrukcji programu: 

-  przejrzystość i bardziej czytelna struktura programu 

-  oszczędność czasu – raz napisana i skompilowana funkcja może być używana 

wielokrotnie w różnych programach 

-  oszczędność pamięci – funkcja jest umieszczana w jednym miejscu pamięci, do którego 

następują odwołania w momencie jej wywołania.  

Deklaracja i definicja funkcji 
Deklaracja funkcji w odróżnieniu od definicja funkcji jest pojęciem logicznym, gdyż stanowi 
tylko informację dla kompilatora, że funkcja o nazwie, typie wartości i parametrów może (ale 
nie  musi!)  zostać  użyta  gdzieś  w  danym  module  programu.  Definicja  funkcji  określa 
natomiast, co funkcja właściwie robi. Stanowi ona zapis jakiegoś algorytmu lub jego części. 
Definicja  funkcji  powoduje,  w  odróżnieniu  od  deklaracji,  przydzielenie  obszaru  pamięci, 
w którym znajdzie się kod wynikowy funkcji. 

Deklaracja funkcji zwana też prototypem wygląda zwykle następująco: 

<typ> identyfikator_funkcji (lista_deklaracji_typów_parametrów); 

 
Jeżeli  pominięty  zostanie  typ  wartości  zwracanej,  przyjmowany  jest  on  domyślnie  jako  int
Również lista deklaracji typów parametrów może być pusta. Oznaczać to będzie, że funkcja 
nie przyjmuje żadnych parametrów.  

background image

Programowanie w języku ANSI C 

 

Dopuszczalne jest również użycie specyfikatora funkcji const. Znaczenie użycia jest zwykle 
takie, by zagwarantować niezmienialność zmiennych wskazywanych danym parametrem np.: 

int strlen(const char *s); 

 
Powyższa funkcja nie może zmieniać wartości zmiennej wskazywanej parametrem s.  

Wywołanie funkcji 
Wywołanie funkcji ma postać: 

nazwa_funkcji (lista_parametrów_wywołania); 

 
Na listę parametrów wywołania składają się oddzielone przecinkami wyrażenia typu 
zgodnego z typem parametru funkcji. 
Przeanalizujmy poniższy przykład. Powiedzmy, że mamy zdefiniowaną funkcję następująco: 

int funk(int i, int j, char *str) 

 

... 

}

 

wówczas wywołanie może mieć postać: 

int a = 10, b = 20; 
char *napis = ”Programowanie w C++”; 
 
funk(a, b, napis); 

//wywołanie funkcji

 

Funkcje przeciążone, domyślne wartości parametrów (C++) 
Funkcjami przeciążonymi (ang. overloaded functions) nazywamy rodzinę funkcji o tej samej 
nazwie,  lecz  różniącej  się  parametrami  (typem  i/lub  liczbą)  i  ewentualnie  typem  wartości 
zwracanej.  Dwie  funkcje  przeciążone  nie  mogą  różnić  się  tylko  typem  wartości  zwracanej. 
O tym,  która  funkcja  zostanie  wywołana,  decydują  parametry  wywołania.  Oto  kilka 
przykładów funkcji przeciążonych: 

int funk(int x); 
int funk(); 
double funk(double x); 
double funk(double x, double y); 
 
bool funk(double x); 

//to jest zła deklaracja funkcji przeciążonej. Istnieje już  

//funkcja o takiej nazwie i o takim parametrze wejściowym

 

Domyślną wartość parametrów podajemy w deklaracji funkcji, co ilustruje poniższy przykład: 

int funk(int i, double x = 10.1, double y = 20.2);

 

 
Daje nam to możliwość wywoływania funkcji zarówno w sposób funk(a, b, c) jak i w sposób 
funk(a)

 – reszta parametrów ma wartości domyślne. 

 

Przekazywanie parametrów i zwracane wartości 
Możliwe są trzy rodzaje przekazywania parametrów do funkcji: 

1.  przez wartość 
2.  przez wskaźnik (C) 
3.  przez referencje (C++) 

Ad. 1 
W wyniku przekazania parametru przez wartość funkcja otrzymuje kopię zmiennej na stosie 
procesora.  Przekazywany  parametr  jest  traktowany  tak  samo,  jak  wszystkie  zmienne 
zadeklarowane w ciele funkcji tj. istnieje tylko podczas jej wywołania.  
Demonstruje nam to poniższy przykład: 

background image

Programowanie w języku ANSI C 

10 

 

#include <iostream.h> 

int funk(int x) 

 

x++; 

 

//tu zmieniamy wartość parametru x 

 

return x; 

//i go zwracamy 


 
void main(void) 

 

 

int liczba = 10, wartosc; 

 

 

 

wartosc = funk(liczba); 

 

cout << ”Liczba: ” << liczba << ” Wartość: ” << wartosc; 

}

 

 W wyniku działania programu na ekranie zostanie wyświetlony napis: Liczba: 10  Wartość
11

. Dlaczego? W funkcji funk zmieniliśmy wartość parametru x, do którego przypisana była 

wartość  parametru  liczba.  Ale  ponieważ  x  jest  zmienna  lokalną  w  funkcji  funk,  Wartość 
zmieniona  została  zapomniana  zaraz  po  zakończeniu  działania  funkcji.  Zmienioną  wartość 
mogliśmy tylko otrzymać jako wynik działania (wartość zwracaną) funkcji.  

Ad. 2 
Przekazywanie  parametrów  funkcji  przez  wskaźnik  jest  w  zasadzie  odmianą  przekazywania 
przez  wartość.  Tu  funkcja  otrzymuje  kopię  wskaźnika.  Ale  ma  to  jednak  głębszy  sens. 
Wskaźnik przekazywany do funkcji może identyfikować zmienną należącą do innej funkcji. 
Przypisanie  wartości  zmiennej  wskazywanej  przez  parametr  wskaźnikowy  pozwala  więc 
zmienić  wartość  zmiennych  utworzonych  w  innych  funkcjach  programu.  Takie 
przekazywanie parametru jest używane zasadniczo w dwóch celach: 

-  do przekazywania struktur danych o dużych rozmiarach, takich jak tablice czy łańcuchy,  
-  w celu umożliwienia zwrócenia więcej niż jednej wartości. 

Przykład: 

#include <sting.h> 
#include <iostream.h> 
 
char *funk(char *str) 

 

strcat(str, „ dobry“); 

 

return str; 


 
void main(void) 

 

char *napis = ”Dzień”; 

 
 

cout << napis << endl;   

//napis nie zmodyfikowany 

 

cout << funk(napis) << endl; 

//wyświetlona wartość zwracana 

 

cout << napis << endl;   

//wyświetlona zmodyfikowana zmienna  
//przekazana przez wskaźnik do funkcji  

}

 

W wyniku działania programu otrzymamy wyświetlony na ekranie tekst: 
Dzień 
Dzie
ń dobry 
Dzie
ń dobry 
Podsumowując można powiedzieć, że takie rozwiązanie pozwala na ingerencję w zawartość 
zmiennych  i  struktur  danych  utworzonych  poza  funkcją,  do  której  parametr  wskaźnikowy 
został  przekazany.  Z  możliwości  tej  należy  korzystać  roztropnie,  gdyż  niezauważone  lub 
zakamuflowane  oddziaływanie  funkcji  na  wartość  zmiennych  należących  do  innych  funkcji 
programu może doprowadzić do trudnych do wykrycia błędów. 

 

background image

Programowanie w języku ANSI C 

11 

 

Ad. 3 
W  języku  C++  dodatkowo  występuje  typ  referencyjny,  który  umożliwia  deklarowani 
zmiennych  reprezentujące  inne  zmienne.  Ogólnie  rzecz  ujmując  to  zmienne  referencyjne  są 
wykorzystywane przy przekazywaniu parametrów do i z funkcji. Operacje są przeprowadzane 
bezpośrednio na zmiennej, której referencję przekazano do funkcji. 

6. 

 

 Wypisywanie danych na ekran 

Po załadowaniu biblioteki  

#include <iostream.h>

 

możliwe  jest  wypisywanie  danych  na  ekranie.  Do  tego  celu  służy  funkcja  cout.  Jest  to 
specyficzne funkcja, które ma zmienną liczbę parametrów wejściowych, które oddzielone są 
znakami „<<” i nie są zebrane w nawiasy „()”. Parametrami funkcji mogą być: zwykły tekst 

cout << “Witam na kursie”;

 

zmienne

 

int val = 1; 
double val_d = 1.5; 
char *str = “Napis”; 
cout << val << str << val_d << endl;

 

Wartość każdej ze zmiennych zostanie wyświetlona kolejno na ekranie. Ostatni parametr  
endl
 jest znakiem nowej linii. 

7. 

 

Pobieranie danych od użytkownika 

Po załadowaniu biblioteki  

#include <iostream.h>

 

możliwe  jest  wczytywanie  danych  od  użytkownika.  Do  tego  celu  służy  funkcja  cin.  Jest  to 
specyficzne funkcja, które ma zmienną liczbę parametrów wejściowych, które oddzielone są 
znakami „>>” i nie są zebrane w nawiasy „()”. 

 

int val; 
double val_d; 
char *str; 
cout <<”Podaj liczbe: ”; 
cin >> val; 
cout >> “Podaj liczbę i napis oddzielając znakiem entera:”; 
cin >> str >> val_d;

 

Zostaną wczytane kolejno wartości do zmiennych odpowiednich typów.

 

8. 

 

Operacje na plikach 

Niezależnie  od  wykonywanych  operacji  na  plikach,  korzystamy  zawsze  z  typu  plikowego 
FILE*. Aby był one widoczny w programie należy dołaczyć następującą bibliotekę: 

#include <stdio.h> 

Wczytywanie danych z pliku 
Poniżej zamieszczono przykładowy kod programu. Program odczytuje dane z pliku. 

#include <stdio.h> 
#include <iostream.h> 

main() 

 

char *NazwaPliku; 

//pytamy użytkownika o nazwę pliku 
 

cout << “Podaj nazwę pliku, z którego dane mam przeczytać: “; 

 

cin >> NazwaPliku; 

//otwieramy plik w trybie binarnym do odczytu i zapamiętujemy uchwyt do pliku w zmiennej plik 
 

FILE *plik = fopen(NazwaPliku, „rb”); 

//możemy pobierać dane do bufora o określonej wielkości, ale nie więcej niż całą linię 
 

char word[100]; 

background image

Programowanie w języku ANSI C 

12 

 

 

fgets(word, 100, plik); 

//lub czytać dane liczbowe bądź łańcuchowe oddzielone określonym separatorem 
 

int zmienna; 

 

fscanf(plik, „%d”, &zmienna); 

// %d – oczekiwana liczba całkowita 
// %f – oczekiwana liczba rzeczywista 
// %s – oczekiwana wartość łańcuchowa 
 
//funkcja sprawdzająca koniec pliku  
 

feof(plik); 

//która zwraca 1, gdy napotkano już na koniec pliku i 0, gdy końca pliku jeszcze nie było 
//na koniec zamykamy plik 
 

fclose(plik); 

Zapisywanie danych do pliku 

#include <stdio.h> 
#include <iostream.h> 

main() 

 

char *NazwaPliku; 

//pytamy użytkownika o nazwę pliku 
 

cout << “Podaj nazwę pliku, gdzie mam dane zapisać: “; 

 

cin >> NazwaPliku; 

//otwieramy plik w trybie binarnym do zapisu i zapamiętujemy uchwyt do pliku w zmiennej plik 
//jak pliku nie było, to zostanie taki stworzony 
 

FILE *plik = fopen(NazwaPliku, „wb”); 

//zapis 
 

char word[100] = „krotkie slowo”; 

 

fputs(word, plik); 

//lub 
 

int zmienna = 2; 

 

fprintf(plik, “%d”, zmienna); 

//i również zamykamy plik, gdu niepotrzebny 
 

fclose(plik); 

}