Język C, C++.

Transkrypt

Język C, C++.
Język C, C++.
Wprowadzenie do programowania w języku C/C++:
struktura programu,
nazwy i słowa zastrzeżone,
podstawowe typy danych,
struktura funkcji,
stałe, zmienne,
deklaracje,
wyrażenia,
instrukcje we/wy,
operatory,
instrukcje sterujące,
preprocesor,
tablice,
wskaźniki.
Wejście, wyjście w c/C++.
Język C został zdefiniowany w 1972 r. przez Dennisa M Ritchie z Bell Laboratories w New Jersey.
Język C jest językiem ogólnego zastosowania. Język w miarę prostoty, niezbyt obszerny, szerokiego
zastosowania. Charakteryzuje się także nowoczesnymi strukturami danych i bogatym zestawem
operatorów.
C nie jest językiem "bardzo wysokiego poziomu", nie jest nawet "duży", i nie został opracowany dla
jakiejś szczególnej dziedziny zastosowao. Brak ograniczeo oraz ogólnośd powodują, że w wielu
przypadkach jest wygodniejszy i bardziej sprawny od innych języków oprogramowania o pozornie
większych możliwościach. Można zrobid w nim w miarę wszystko.
Ścisły związek z UNIX - ci sami twórcy.
Tysiące funkcji bibliotecznych. Język C opracował i zrealizował Dennis Ritchie dla systemu
operacyjnego UNIX działającego na minikomputerze DEC PDP-11. S
System operacyjny, kompilator C i niemal wszystkie programy usługowe systemu UNIX są napisane w
C. Kompilatory języka C tworzy się dla różnych maszyn, łącznie z IMB/370, jednak C nie jest związany
z żadnym konkretnym systemem czy sprzętem i łatwo w nim pisad programy, które można
uruchamiad bez zmian na dowolnej maszynie, na której język C jest zrealizowany.
Język C funkcjonuje do dziś jako ANSI C.
W latach 80 rozszerzenie - C++ (struktury obiektowe, sprawdzanie wszystkiego).
Można w nim tworzyd małe programy jak i stosowad do komercyjnych zastosowao.
Najbardziej popularny język na świecie (łącznie z C++). Cechuje go elastycznośd, nie jest rygorystyczny
pod względem sprawdzania - można popełnid wiele nadużyd, wskazana ostrożnośd (programy ciężko
się uruchamia gdy duża elastycznośd). Pascal jako język dydaktyczny jest bardzo hermetyczny i
sztywny.
Z punktu widzenia programisty:


języki niskiego poziomu
języki wyższego poziomu
W językach wyższego poziomu abstrahujemy od rozkazów wewnętrznych i komórek pamięci
Języki wewnętrzne, maszynowe, algorytmiczne (Pascal, częściowo C), języki czwartej
generacji (w tym niektóre języki do tworzenia aplikacji na bazie danych np. SQL)
Więcej operacji elementarnych za pomocą jednej konstrukcji języka wyższej generacji.
W SQL przełożenie o wysokim współczynniku np. 1:10
Program w języku źródłowym (Pascal, C, 4GL Informix...)  Translator  program w
innym języku wynikowym (niższego poziomu, np. w języku wewnętrznym)
Strategie tłumaczenia:


1. Program źródłowy -> Kompilator -> Program wynikowy -> SO (system
operacyjny) -> PaO (pamięć) i wykonanie
2. Program źródłowy <--> Interpretator -> Jakieś operacje
Cechy języków programowania:





Języki niskiego bądź wysokiego poziomu (jak złożone operacje można zakodować za
pomocą pojedynczych. instrukcji)
Języki dedykowane dla określonych zastosowań: obliczenia inżynierskie (np.
Fortrran), symulacja (np. Smaltalk), przetwarzanie danych (bazy danych), zagadnienia
sztucznej inteligencji (program może się sam zmieniać w trakcie wykonywania) np.
LISP, PROLOG, sterowanie
Ułatwienia dla tworzenia programów - programy małe lub duże - jak zapanować nad
złożonością, poszczególni ludzie lub firmy tworzą fragmenty programu
Modularyzacja, kompilacja oddzielna, scalanie modułów
Techniki obiektowe np. C++
Język C
Język C pierwotnie miał ułatwiać tworzenie oprogramowania systemowego - UNIX.
UNIX z definicji wyposażony w kompilator C.
Język C można zakwalifikować jako język wysokiego poziomu (1:10 - źródło wynik).
Można również wykonać operacje zastrzeżone dla niskiego poziomu - elementy
programowania niskiego poziomu.
Możliwość operowania adresami - operacje na adresach (np. wsk, *wsk, *(wsk+7)). Pozwala
to wyeliminować wstawki w języku Asemblera.
Wersje języka C:


Wersja 1 - zgodna ze standardem pierwotnym K & R
Wersja 2 - zgodna z ANSI 1989
Borland C oparty na ANSI C, Microsoft C, Watcom C, Unix C, C++
W języku C podprogramami są funkcje. Zmienne lokalne i globalne.
Łączy cechy wysokiego z możliwościami języka niskiego poziomu.
Język w wysokim stopniu przenośny.
Elastyczność - łagodniej kontroluje zgodność typów - kontrowersyjne, niebezpieczne.
Zwięzłość - w Pascalu np. 10 linii, w C - kilka linii.
Ze zwięzłością nie należy przesadzać - trudniej wykryć błąd.
Ogólna struktura programu w języku C
Cechą języka C/C+ jest możliwość budowy programu z wielu modułów.
Modułem może być każdy zbiór zawierający poprawny kod źródłowy.
W pełni poprawny moduł, którego kompilacja zakończy się sukcesem:
int n;
Program w C zbudowany jest z funkcji.
Każda z nich może posiadać parametry oraz określony typ wartości.
Aby można było wygenerować kod wynikowy programu (w DOS, Windows plik .EXE),
w jednym i tylko w jednym z modułów musi się znaleźć funkcja main, od której rozpocznie
się wykonywanie programu. Moduł zawierający funkcję main nazywa się modułem
głównym.
Najprostszy wykonywalny program C:
int main(void)
{
return 0;
}
Po uruchomieniu TC.EXE
Program ten składa się tylko z bezparametrowej funkcji main, której wartość jest typu
całkowitego (int).
Ciało funkcji zbudowane jest z instrukcji, które powinny znaleźć się w bloku wyznaczonym
nawiasami kwadratowymi.
Funkcja ta zwraca za pomocą instrukcji return wartość zero.
Program TC.EXE – Turbo C
Katalogi Turbo C
Katalog: c:\Tc
2011-10-15 15:22 <DIR>
BGI
2011-11-12 15:03 <DIR>
BIN – tu są program, m.in. TC.EXE – środowisko
programistyczne, , TCC.EXE – kompilator
2011-10-15 15:22 <DIR>
CLASSLIB
2011-10-15 15:22 <DIR>
DOC
2011-10-15 15:22 <DIR>
EXAMPLES
2011-10-15 15:22 <DIR>
INCLUDE
2011-10-15 15:22 <DIR>
LIB - biblioteki
2011-11-08 10:43 <DIR>
Programy
Menu programu TC.EXE
MenuFile – Plik: opcje: New – Nowy, Open – Otwórz, Save – Zapisz, Save as – Zapisz jako,
Save All – zapisz wszystko, Change dir – zmień katalog,
DOS Shell – okno DOS (exit – wyjście), Quit – wyjście
Menu Edit
Search – szukaj
Run - Uruchom
Compile – Kompiluj
Compile Alt F9 – kompiluj, Make – utwórz, Link – linkuj, Build All – zbuduj wszystko,
Information – informacja, Remove messages – usuń komunikaty (wiadomości)
Debug - debugowanie
Project – Projekt
Options – Opcje
Window – Okno
Help
Ustawienia programu - przykładowe: Options, Directories
Kompilacja programu:
Po kompilacji programu: Alt C, Compile lub Alt F9 lub F9
utworzy się plik wynikowy P1.EXE w katalogu Output Directory
Uruchomienie programu: Alt R lub Ctrl F9
Skompiluje się również program w postaci:
main() { },
ewentualnie w postaci
void main() { }
lub
void main(void) { }
Przykład z Turbo C
// Borland C++ - (C) Copyright 1991 by Borland International
/*
HELLO.C -- Hello, world */
#include <stdio.h>
int main()
{
printf("Hello, world\n");
return 0;
}
Po uruchomieniu i naciśnięciu Alt F5 – wynik
Pomoc w programie:
Help, Index, wpisujemy szukane słowo, np. void i naciskamy Enter
Ogólna struktura programu w C/C++
Nagłówek programu
#include (włączenia tekstowe)
#define stałe makroinstrukcje
Zmienne globalne
Prototypy funkcji
Funkcja main()
Funkcje pozostałe
W profesjonalnych programach w nagłówku powinna być podana nazwa programu,
dane o autorze, prawa autorskie, przeznaczenie programu, data ostatniej aktualizacji
programu, nazwa kompilatora, uwagi odnośnie kompilowania, linkowania, wykonania.
Sekcja #include zawiera specyfikację włączanych plików bibliotecznych oraz własnych
Sekcja #define zawiera definicje stałych i makroinstrukcji
Następne sekcje to zmienne globalne oraz prototypy funkcji.
Muszą wystąpić przed ciałami funkcji, aby w dalszej części programu nie było odwołań do
obiektów nieznanych kompilatorowi.
Jeżeli funkcje pozostałe umieszczone byłyby przed funkcją main to specyfikowanie
prototypów byłoby zbyteczne.
Włączenia tekstowe #include mogą w zasadzie wystąpić w dowolnym miejscu programu.
Zaleca się aby dłuższe funkcje lub grupy funkcji były umieszczane w osobnych plikach.
Podstawowy fragment (element) programu w języku C
main()
begin w Pascalu)*/
{
/* treść */
}
/* klamra otwierająca - początek funkcji głównej (jak
/* tu zaczyna się treść programu - w funkcji main()
/* klamra zamykająca - jak end w Pascalu*/
/* - rozpoczęcie komentarza, */ - koniec komentarza
W pisaniu programów rozróżniane są duże i małe litery - np. w main()
Język C/C++ nie ma instrukcji realizujących operacje we/wy.
Do tego celu służą funkcje bibliotek standardowych.
Użycie ich jest niezbędne, gdy trzeba pobrać dane od użytkownika i wysłać je na ekran.
#include <stdio.h>
int main(void) // funkcja glowna, brak argumentow, zwraca typ calkowity int
{
char imie[20]; // deklaracja tablicy znakow
int i; // deklaracja zmiennej calkowitej
printf("\nPodaj swoje imie "); // wydruk na ekran,\n – nowa linia
gets(imie);
// pobranie zmiennej imie
puts("Ile masz lat? ");
// wydruk
scanf("%d",&i);
// pobranie zmiennej typu calkowitego
printf("\n%s ma %d lat.",imie, i); //wydruk napisu i liczby calkow.
return 0; // funkcja glowna zwraca 0 – pomyślny koniec
}
Przykłady prostych programów
Przykład prostego programu: prog1.c
Wydruk na ekranie napisu: Dzień dobry (z przejściem kursora do nowej linii)
/* Prog1.c - Program napisany
#include <stdio.h>
/* preprocesor - załącz pliku
main()
{
printf("Dzień dobry\n"); /*
/*
}
w pliku żródłowym Prog1.c */
bibliot. standard. stdio.h
*/
printf - drukuj-fragment bibliot. standard */
\n - znak nowego wiersza */
Komentarz w języku C stanowi tekst ograniczony znakami /* i */
Inne wersje tego programu:
#include <stdio.h>
void main()
{
printf("Dzień dobry\n");
}
#include <stdio.h>
int main()
{
printf("Dzień dobry\n");
return 0;
}
# - preprocesor - wstępny przetwarzacz - uwzględnia dodatkowe rzeczy
#include <stdio.h> - dołączenie nagłówków z biblioteki standardowej (ścieżka domyślnych
przeszukowań)
#include "program.h" - dołączenie programu z katalogu aktualnego - podwójne cudzysłowy
Język C/C++ wymaga kompilacji, w wyniku czego tworzy sie plik wykonywalny, binarny, z
rozszerzeniem EXE. Nie ma interpreterów do języka C. Skompilować wystarczy raz.
Nie są ważne odstępy w programie. Muszą być całe słowa. Mogą być znaki spacji, nowego
wiersza, tabulacji - nieważne ile.
#inlcude musi być w jednej linii.
Ważne jest projektowanie.
Jedna godzina poświęcona na projektowanie pozwala zaoszczędzić kilka godzin
programowania.
Prosty przykład obliczeniowy - obliczenie objętości walca
/********************************************************/
/* Program p1a.c
*/
/* Obliczanie objetosci walca
(wariant startowy)
*/
/*------------------------------------------------------*/
#include <stdio.h>
void main()
{
float promien, wysokosc, objetosc;
promien = 3.3;
wysokosc = 44.4;
objetosc = 3.1415926 * promien * promien * wysokosc;
printf("Objetosc walca = %f", objetosc);
}
/********************************************************/
Efektem wykonania będzie wydruk na ekranie: Objętość walca=1519.010254
Następny program zawiera za dużo komentarzy
/* poczatek tekstu programu */
/********************************************************/
/* Program p1b.c
*/
/* Obliczanie objetosci walca (nadmiar komentarzy)
*/
/*------------------------------------------------------*/
#include <stdio.h>
main()
{
/* wlaczenie biblioteki */
/* poczatek modulu glownego */
/* poczatek bloku */
/* deklaracje zmiennych */
float promien, wysokosc, objetosc;
/* nadanie wartosci poczatkowych zmiennym */
promien = 3.3;
wysokosc = 44.4;
/* obliczenie podstawowe */
objetosc = 3.1415926 * promien * promien * wysokosc;
/* wyprowadzenie wyniku */
printf("Objetosc walca = %f", objetosc);
}
/* koniec bloku */
/********************************************************/
/* koniec tekstu programu */
Następny przykład pozbawiony komentarzy ale czytelny:
/* p1c.c */
#include <stdio.h>
main()
{
float promien, wysokosc, objetosc;
promien = 3.3;
wysokosc = 44.4;
objetosc = 3.1415926 * promien * promien * wysokosc;
printf("Objetosc walca = %f", objetosc);
Następny przykład jest bardzo zwięzły w zapisie ale mało czytelny:
/*p1d.c*/#include<stdio.h>
main(){float r,h,v;r=3.3;h=44.4;v=3.1415926*r*r*h;printf("V=%f",v);}
Wniosek - brak jak i nadmiar komentarzy nie słuzy czytelnosci programu.
W praktyce stosowane są 2 sposoby umiejscowiana klamer { },
ograniczających sekwencje instrukcji.
1)
main()
{
/* sekwencja instrukcji */
}
2)
main() {
/* sekwencja instrukcji */
}
Na czytelność programu wpływa stosowanie wcięć.
Przykłady.
Przeliczenie stopni Fahrenheita na Celsjusza
Wersja 1
/* Program sz2.cpp - komentarz
Przelicza stopnie Fahrenheita na Celsjusza
*/
#include <stdio.h>
void main() /* Poczatek funkcji glownej main - nic nie zwraca*/
{
/* Definicje zmiennych */
int tf=0;
/* typ integer - temp. Fahrenheita*/
float tc;
/* typ float
- temp Celsjusza */
while (tf <=100) /* petla - iteracja
przebiegiem petli */
{
tc=(5*(tf-32))/9.0;
printf("%4d %6.1f \n",tf,tc);
tf=tf+10;
}; /* while */
}
/* main */
tf używana też do sterowania
Wersja 2
/* Program sz2a.cpp - bez zmiennej tc
Przelicza stopnie Fahrenheita na Celsjusza
*/
#include <stdio.h>
void main() /* Poczatek funkcji glownej main - nic nie zwraca*/
{
/* Definicje zmiennych */
int tf=0;
/* typ integer - temp. Fahrenheita*/
while (tf <=100) /* petla - iteracja */
{
printf("%4d %6.1f \n",tf,
5*(tf-32)/9.0);
tf=tf+10;
}; /* while */
}
/* main */
Uwaga! We wzorze (tf-32)*(5/9) - zaokrąglenie 5/9 do liczb całkowitych!. Bezpieczne
mnożenie, niebezpieczne dzielenie.
Wersja 3
/* sz2b.c */
#include <stdio.h>
#include <conio.h>
main()
{
float fahr, celsius;
int lower, upper, step;
lower =0; /*dolna granica temp*/
upper=300;
step=20;
celsius=lower;
clrscr();
printf("Zamiana stopni Celsiusza na Fahrenheita\n");
printf(" Celsjusz
Fahr\n");
while (celsius<=upper) {
fahr=(9.0/5.0*celsius+32.0);
printf("%3.0f %20.1f\n",celsius,fahr);
celsius=celsius+step;
}
getch();
return 0;
}
Formaty wydruku:
%d, %i
liczba całkowita
%x
w formacie 16 bez znaku
%f, %e, %g zmiennopozycyjny
%s
string (łańcuch znaków)
%c
znak
%o
ósemkowo
Deklaracja a definicja
Deklaracja - informuje kompilator, że dana nazwa reprezentuje obiekt jakiegoś typu ale nie
rezerwuje dla niej miejsca w pamięci. Mówi, że zmienna jest ale nie powołuje jej do życia.
Definicja - wprowadza do programu zmienną i przydziela jej pamięć, powołuje obiekt do
życia.
Przykłady deklaracji, które nie są definicjami:
extern int a; int f(int); struct s; typedef int Int;
Zmienna - komórka lub grupa komórek
Podstawowe elementy języka C (każdego praktycznie języka programowania)








zestaw znaków
nazwy i słowa zastrzeżone
typy danych
stałe
zmienne i tablice
deklaracje
wyrażenia
instrukcje
Zestaw znaków C:



litery małe i duże języka łacińskiego (angielskiego)
cyfry 0..9
znaki specjalne: ! * + \ " < # ( = | { > % ) ~ ; } / ^ - [ : , ? & _ ] ' . oraz znak odstępu
(spacja)
Nazwy i słowa zastrzeżone (kluczowe, zarezerwowane)
Nazwy służą do identyfikowania elementów programu
(stałych, zmiennych, funkcji, typów danych, itd.).
Nazwa składa się z ciągu liter i cyfr, z tym, że pierwszym znakiem musi być litera.
Znak podkreślenia traktowany jest jako litera.
W języku C rozróżniane są duże i małe litery w identyfikatorach.
Przykład użycia różnych nazw:
/********************************************************/
/* Program p6.c
*/
/* Obliczanie objetosci walca (rozroznianie nazwy /1)
/*------------------------------------------------------*/
*/
#include <stdio.h>
main()
{
float promien, wysokosc, objetosc;
float PROMIEN, WYSOKOSC, OBJETOSC;
promien = 3.3;
wysokosc = 44.4;
PROMIEN = 10.;
WYSOKOSC = 20.;
objetosc = 3.1415926 * promien * promien * wysokosc;
printf("\nObjetosc walca = %f", objetosc);
OBJETOSC = 3.1415926 * PROMIEN * PROMIEN * WYSOKOSC;
printf("\nOBJETOSC WALCA = %f", OBJETOSC);
}
/********************************************************/
Efektem wykonania programu są 2 wydruki:
Objetosc walca = 1519.010254
OBJETOSC WALCA = 6283.185059
Użycie odstępu w nazwie jest niedozwolone.
Niektóre implementacje rozpoznają w nazwie do 8 znaków, inne więcej (do 32).
Słowa zastrzeżone
Są to słowa o szczególnym znaczeniu dla języka, których nie wolno używać programiście np.
jako nazw zmiennych.
Standardowy zestaw znaków zastrzeżonych języka C:
auto
break case
char const
goto
if
long register return
unsigned void
int
continue default do
short
double else
signed sizeof
enum extern float
static struct switch typedef union
volatile while
Niektóre kompilatory mają niektóre lub cześć z następujących słów kluczowych
ada asm entry far fortran huge near pascal
for
Podstawowe typy danych i rozmiary danych
W języku C występuje tylko kilka podstawowych typów danych:




char - jeden bajt, zdolny pomieścić 1 znak
int - typ całkowity
float - typ zmiennopozycyjne pojedynczej precyzji
double - typ zmiennopozycyjny podwójnej precyzji
Dodatkowo występuje kilka kwalifikatorów stosowanych z tymi podstawowymi typami.
Kwalifikatory short i long odnoszą się do obiektów całkowitych
Typ
Opis
Zakres wartości
Reprezentacja
char (signed char)
pojedynczy znak
(np. litera)
-128...127
1 bajt
unsigned char
znak (bez znaku dodatni)
0...255
1 bajt
short
liczba całkowita
krótka
-32768...32767
2 bajty
unsigned short
liczba krótka bez
znaku
0...65535
2 bajty
int (signed int)
liczba całkowita
-32768...32767
2 bajty
unsigned int
całkowita bez
znaku
0...65535
2 bajty
long (long signed
int)
liczba całkowita
długa
-2147483648...2147483647
4 bajty
0...4294967295
4 bajty
unsigned long (long
j.w. bez znaku
unsigned int)
float
l. rzeczywista
-3.4E-38..-3.4E-38,0,3.4E38..3..3.4E38
4 bajty
double
l. rzeczywista
podwójna
-1.7E308..-1.7E-308,0,1.7E308..1.7E308
8 bajtów
long double
l. rzecz. długa
podwójna
-1E4932..-3.4E-4932,0,3.4E4932..1.1E4932
10 bajtów
Szczegóły zależne są od konkretnej implementacji kompilatora języka C.
Są jeszcze inne typy danych jak:
void (typ funkcji nie zwracającej wartości),
enum (typ wyliczeniowy) oraz typ wskaźnikowy.
Typ wyliczeniowy (enum) reprezentowany jest na 2 bajtach,
wskaźnikowy na 2 lub 4 (w zależności od modelu pamięci),
void nie jest reprezentowany.
Typy, operatory, wyrażenia
Zmienne i stałe są podstawowymi obiektami danych, jakimi posługuje się program.
Deklaracje wprowadzają potrzebne zmienne oraz ustalają ich typy i ewentualnie wartości
początkowe.
Operatory określają co należy z nimi zrobić.
Wyrażenia wiążą zmienne i stałe, tworząc nowe wartości.
Stałe
W C występują 4 rodzaje stałych:
stałe całkowitoliczbowe,
stałe rzeczywiste,
stałe znakowe oraz
łańcuchy znaków.
Wartość stałej numerycznej nie może wykraczać poza dopuszczalne granice.
Stałe całkowitoliczbowe
Nazwa
Dozwolony zestaw
Uwagi
znaków
Przykłady
Stałe dziesiętne 0..9 + -
Jeśli więcej niż 1 znak,
pierwszym nie może być 0
0 1 876 -122 +909
Stałe ósemkowe 0..7 + -
Pierwszą cyfrą musi być 0
0 0111 0777 -0777
+0222
Stałe
szesnastkowe
Pierwszymi znakami muszą być 0x 0X1234
0x lub 0X
0XAFDEC 0xffff
0..9 a..f A..F + -
W celu zainicjowania zmiennych typów int i long po znaku równości podajemy całkowitą
stałą liczbową. Przykłady:
int l=100;
unsigned k=121;
int la = 0x2ffa;
long i = 25L; /* long */
long unsigned z = 1000lu; /* lub 1000UL */
Stała całkowita, jak np. 1234 jest obiektem typu int.
W stałej typu long na końcu występuje litera l lub L, jak 123456789L.
Stała całkowita nie mieszcząca się w zakresie int jest traktowana jako stała typu long.
W stałych typu unsigned na końcu występuje u lub U,
a końcówka ul lub UL oznacza stałą typu unsigned long.
Stałe rzeczywiste, zwane zmiennoprzecinkowymi reprezentują liczby dziesiętne.
Dozwolony zestaw znaków: 0..9 . + - E e (E lub e reprezentuje podstawę systemu tj. 10)
Uwagi: 1.2*10^-3 można zapisać 1.2E-3 lub 1.2e-3.
Stałe zmiennopozycyjne zawierają albo kropkę dziesiętną (np. 123.4), albo wykładnik e (np.
1e-2) albo jedno i drugie.
Typem stałej zmiennopozycyjnej jest double, chyba, że końcówka stanowi inaczej.
Występująca na końcu litera f lub F oznacza obiekt typu float,
a litera l lu L - typu long double.
Przykłady: 0. 2. 0.2 876.543 13.13E13 2.4e-5 2e8
Deklaracja i inicjalizacja zmiennych rzeczywistych - przykłady::
float s=123.16e10; /* 123.16*10^16 */
double x=10.;
long double x=.12398;
double xy=-123.45
Stałe znakowe
Stała znakowa jest liczbą całkowitą; taką stałą tworzy jeden znak ujęty w apostrofy, np. 'x'.
Są to więc pojedyncze znaki zamknięte dwoma apostrofami.
Zestaw dowolnych widocznych znaków ASCII. Wartością jest wartość kodu znaku w
maszynowym zbiorze znaków. Np. wartością stałej '0' jest liczba 48 - liczba nie mająca nic
wspólnego z numeryczną wartością 0.
Pewne znaki niegraficzne mogą być reprezentowane w stałych znakowych i napisowych
przez sekwencje specjalne, takie jak \n (znak nowego wiersza).
Przykłady: 'A' '#' ' '
char a='a';
Znaki z zestawu ASCII o kodach 0 do 31 są znakami sterującymi, niewidocznymi na
wydrukach.
Znaki o kodach 0...127 są jednakowe dla wszystkich komputerów bazujących na kodzie
ASCII.
Znaki o kodach 128...255 (kod rozszerzony ASCII) mogą się różnić na różnych komputerach.
Escape-sekwencje - sekwencje specjalne
Niektóre znaki "niedrukowalne" mogą być przedstawione w postaci tzw. escape-sekwencji,
np. znak nowej linii jako sekwencja \n.
Pierwszym znakiem tej sekwencji jest backslash (\).
Sekwencja specjalna wygląda jak 2 znaki, ale reprezentuje tylko jeden znak
Sekwencja
znaków
Wartość
ASCII
Znaczenie
\a
7
Sygnał dźwiękowy (BEL)
\b
8
Cofniecie o 1 znak (BS)
\t
9
Tabulacja pozioma (HT)
\v
11
Tabulacja pionowa (VT)
\n
10
Nowa lina (LF)
\f
12
Nowa strona (FF)
\r
13
Powrót karetki (CR)
\"
34
Cudzysłów
\'
39
Apostrof
\?
63
Znak zapytania
\\
92
Backslash
\0
0
Znak pusty (null) - nie jest równoważne stałej znakowej
'0'
Stałe napisowe - napisy, łaocuchy znaków (stałe łaocuchowe)
Stała napisowa lub napis jest ciągiem złożonym z zera lub wiecej znaków, zawartym między
znakami cudzysłowu, np. "Jestem napisem".
Stała łańcuchowa składa się z ciągu o dowolnej liczbie znaków.
Ciąg ten musi być ograniczony znakami cudzysłowu.
Przykłady:
"Wynik = "
" + 2 mln $"
"Linia nr 1\nLinia nr2"
""
Łańcuchy mogą zawierać escape-sekwencje.
Łańcuchem pustym są same cudzysłowy.
Łańcuch w sposób niejawny jest zakończony znakiem null czyli \0.
Dlatego np. stała znakowa 'K' nie jest równoważna łańcuchowi "K".
Łańcuch znaków (napis) można traktować jako tablicę złożoną ze znaków, uzupełnioną na
końcu znakiem '\0'
Taka reprezentacja oznacza, że praktycznie nie ma ograniczenia dotyczącego długości
tekstów.
Programy muszą jednak badać cały tekst, by określić jego długość, np. strlen(s) ze
standardowej biblioteki.
Przykład:
Napis "Katowice" , który może być zadeklarowany jako tablica jednowymiarowa, której
elementami są znaki, np.
char napis[] = "Katowice"
Nr elementu
1 2345 6789
Napis
K a t o w i c e \0
Wartość indeksu 0 1 2 3 4 5 6 7 8
Deklaracja i inicjalizacja łańcuchów - przykłady:
char s[10]="\n\fAndrzeh\x60";
char str[20]={'\n','\f', 'A', 'n', 'd', 'r', 'z', 'e', 'j', '\x60', '\0'};
"A + B =
"
Stałe wyliczeniowe (enumeration constant)
Stałe wyliczeniowe tworzą zbiór stałych o określonym zakresie wartości. Wyliczenie jest listą
wartosci całkowitych, np.
enum boolean {NO, YES};
Pierwsza nazwa na liście wyliczenia ma wartość 0, następna 1 itd., chyba że nastąpi jawnie
podana wartość.
Przykłady:
enum KOLOR {CZERWONY, NIEBIESKI, ZIELONY, BIAŁY, CZARNY}
KOLOR staje się nazwą wyliczenia, powstaje nowy typ. Do CZERWONY zostaje przypisana
wartośc 0, do niebieski 1, zielony 2 itd. Każda stała wyliczeniowa ma wartość całkowitą. Jeśli
specjalnie się nie określi, to pierwsza stała przyjmie wartość 0, druga 1 itd.
enum KOLOR {red=100, blue, green=500, white, black=700};
red przyjmie wartość 100, blue 101, green 500, white 501, black 700
enum escapes{BELL='\a', BACKSPACE='\b', TAB='\t', NEWLINE='\n', VTAB='\v',
RETURN='\r'};
enum months {JAN=1, FEB, MAR, APR , MAY, JUL, AUG, SEP, OCT, NOV, DEC};
(luty jest 2-gi itd.)
Stałe symboliczne - makrodefinicje
Stała symboliczna jest nazwą przedstawiającą inną stałą - numeryczną, znakową lub tekstową.
Definicję stałej symbolicznej umożliwia instrukcja #define:
#define NAZWA tekst
gdzie NAZWA jest nazwą stałej symbolicznej, a tekst jest związanym z tą nazwą łańcuchem
znaków
Przykłady:
Makrodefinicje proste:
#define identyfikator <ciąg-jednostek-leksykalnych>
#define PI 3.14159
#define TRUE 1
#define FALSE 0
#define NAPIS1 Siemianowice
#define IMIE "Andrzej"
(puts(IMIE) rozwija w tekst puts("Andrzej")
#define IMIE_I_NAZWISKO IMIE+"Zalewski"
rozwinięcie daje tekst
"Andrzej + Zaleski"
#define WCZYTAJ_IOSTREAM_H #include <iostream.h>
Makrodefinicje parametryczne
#define identyfikator(idPar1, idPar2,...) ciąg_jedn_leksykalnych
#define ILORAZ(a,b) ((a)/(b)) - makrodefinicja ILORAZ - parametry w
nawiasach!
#define SUMA(a,b) ((a)+(b))
W trakcie kompilacji nazwy stałych symbolicznych są zastąpione przez odpowiadające im
łańcuchy znaków.
Ułatwia to parametryzację programu, a także umożliwia zastępowanie często niewygodnych
w pisaniu sekwencji programu, tworzenie makrodefinicji, tworzenie własnych dialektów
języka, czy nawet języków bezkompilatorowych (na bazie kompilatora C).
Przykład z walcem, z zastosowaniem pseudoinstrukcji #define
/********************************************************/
/* Program p8.c
*/
/* Obliczanie objetosci walca
( #define )
*/
/*------------------------------------------------------*/
#include <stdio.h>
#define
#define
#define
#define
PI
3.1415926
PROMIEN
3.3
WYSOKOSC 44.4
WYNIK
printf("Objetosc walca = %f", objetosc)
main()
{
float promien, wysokosc, objetosc;
promien = PROMIEN;
wysokosc = WYSOKOSC;
objetosc = PI * promien * promien * wysokosc;
WYNIK;
}
/********************************************************/
Wynik programu:
Objętość walca = 1519.010254
Dzięki #define program jest bardziej czytelny.
Stała PI może być użyta wielokrotnie, wartości danych są widoczne na początku.
Użycie dużych liter jako nazwy stałej symbolicznej nie jest obowiązkowe ale zalecane.
Zmienne
Zmienną nazywamy nazwę (identyfikator) reprezentującą określony typ danych.
W chwili rozpoczęcia pracy programu zmienna powinna posiadać nadaną wartość
początkową (nie powinna być przypadkowa).
W trakcie pracy programu wartości zmiennych ulegają zwykle zmianom.
Należy przewidzieć zakres zmienności tych zmiennych.
W języku C wszystkie zmienne muszą być zadeklarowane przed ich użyciem, zwykle na
początku funkcji przed pierwszą wykonywaną instrukcją.
Deklaracja zapowiada właściwości zmiennych.
Składa się ona z nazwy typu i listy zmiennych, jak np.
int fahr, celsius;
W języku C oprócz podstawowych typów: char, short, int, long, float, double
występują także
tablice, struktury, unie, wskaźniki do tych obiektów oraz funkcje zwracające ich wartości.
W przypadku zmiennych nalezy zwrócić uwagę na 2 zasadnicze rzeczy:


nadanie wartości początkowej
oszacowanie zakresu zmienności
Przykład ilustrujacy ten problem
/********************************************************/
/* Program p9.c
*/
/* Obliczanie objetosci walca
( zmienne )
*/
/*------------------------------------------------------*/
#include <stdio.h>
#define PI
#define PROMIEN
#define WYNIK
3.1415926
3.3
printf("Objetosc walca = %f", objetosc)
main()
{
float promien, wysokosc, objetosc;
int i;
promien = PROMIEN;
objetosc = PI * promien * promien * wysokosc;
/* uwaga */
WYNIK;
i=40000;
/* uwaga */
printf("\ni = %i ", i);
}
/********************************************************/
Efekt wykonania:
Objetosc walca = 0.000000
i = -25536
Objętość walca jest równa 0, bo nie została zainicjalizowana zmienna 'wysokosc' - przez
domniemanie kompilator przyjął 0. Na wydruku i widać, że nastąpiło przekroczenie
dopuszczalnego zakresu zmiennej 'i' typu int.
Zmienne mogą być automatyczne oraz zmienne zewnętrzne.
Zmienne automatyczne pojawiają się i znikają razem z wywołaniem funkcji.
Zmienne zewnętrzne to zmienne globalne, dostępne przez nazwę w dowolnej funkcji
programu.
Zmienna zewnętrzna musi być zdefiniowana dokładnie jeden raz na zewnątrz wszystkich
funkcji - definicja przydziela jej pamięć. Taka zmienna musi być też zadeklarowana w każdej
funkcji, która chce mieć do niej dostęp. Można to zrobić albo przez jawną deklarację extern,
albo niejawnie przez kontekst.
Jeśli definicja zmiennej zewnętrznej pojawia się w pliku źródłowym przed użyciem zmiennej
w konkretnej funkcji, to nie ma potrzeby umieszczania w tej funkcji deklaracji extern.
Deklaracje
Deklaracje umożliwiają wyspecyfikowanie grup zmiennych określonego typu.
Większość kompilatorów dopuszcza nadanie wartości początkowej zmiennej w deklaracji
(inicjalizację).
Wszystkie zmienne muszą być zadeklarowane przed użyciem.
W deklaracji określa się typ, a następnie wymienia jedną lub kilka zmiennych tego typu, np.
int lower, upper;
char c, line[1000];
W deklaracjach można nadawać zmiennym wartości początkowe, np.
char esc='\';
int i=0;
float eps=1.0e-5;
int limit=MAXLINE+1;
Jeśli zmienna nie jest automatyczna, to jej wartość początkową nadaje się tylko raz - jakby
przed rozpoczęciem programu; jej inicjatorem musi być wyrażenie stałe.
Zmiennym automatycznym jawnie określone wartości początkowe nadaje się za każdym
razem przy wywołaniu funkcji lub przy wejściu do zawierającego je bloku.
Zmiennym zewnętrznym i statycznym przez domniemanie nadaje się wartość pocz. zero.
Zmienne automat. bez jawnie określonej wartości pocz. mają wartości przypadkowe
(śmiecie).
Kwalifikator const mówi, że wartość zmiennej będzie stała.
const double e=2.71828182;
const char mas[]="Uwaga:";
Deklarację const można stosować również do tablicowych paramentów funkcji, by wskazać,
że funkcja nie może zmieniać tablicy:
int strlen(const char[]);
Przykład programu z deklaracjami zmiennych. Niektórym nadano wartości początkowe.
Przykład programu z deklaracjami zmiennych. Niektórym nadano wartości początkowe.
/********************************************************/
/* Fragment p10.c
Turbo C 2.0
*/
/*
(dozwolone deklaracje elementarne) */
/*------------------------------------------------------*/
main()
{
/* Komentarz
(znaczenie slow kluczowych)
typy danych:
char
int
float
double
- znak (bajt),
- liczba calkowita,
- liczba rzeczywista,
- liczba rzeczywista podwojna,
modyfikatory: short
- krotki,
long
- dlugi,
signed
- ze znakiem,
unsigned - bez znaku
*/
/* --- typy znakowe --------------------------------- */
char
c1 ='k';
signed char
c2 ='\123';
unsigned char
c3 ='\xAB';
/* --- tablice znakow ------------------------------- */
char
tekst[]
= "Katowice";
unsigned char
teKst[30] = "Taki sobie teKst to jest!";
/* --- typy liczb calkowitych ----------------------- */
int
i1 = 0;
signed int
i2 =-32767;
unsigned int
i3;
signed
i4 = 32767;
unsigned
i5 = 32767;
short
i6 = 3;
signed short
i7 =-3;
unsigned short
i8 = 44;
short int
i9 = 22;
signed short int
i10 =-555;
unsigned short int
i11 = 1;
long
i12 = 11111;
signed long
i13 =-1;
unsigned long
i14;
long int
i15 = 22222;
signed long int
i16;
unsigned long int
i17;
/* --- typy liczb rzeczywistych --------------------- */
float
r1 =-3.4E38;
signed float
r2 = 3.4E38;
unsigned float
r3 = 5.5E38;
long float
r4 = 1.7E308;
double
r5 = 1.7e308;
long double
r6 = 1.1e4932;
float
r7 = 1234.56789;
/* dalsza ( robocza ) czesc programu ... */
}
/********************************************************/
W deklaracji typu text[]="... " kompilator sam sobie dobiera długość pola tablicy, dbając też,
by ostatnim znakiem był null (\0).
W przypadku deklaracji explicite, np. text[20]="...", gdy łańcuch będzie dłuższy od 20 to
nastąpi jego obcięcie, a gdy będzie krótszy, to niewykorzystane miejsca zostaną wypełnione
albo znakami pustymi albo po znaku \0 będą wartości przypadkowe (nieistotne).
Operatory arytmetyczne
Wyrażenia 2-argumentowe: +, -, *, / oraz operator dzielenia modulo %
Dzielenie całkowite obcina cześć ułamkową wyniku.
Przykład:
int x,y, a=5, b=2;
x=a/b;
/* w wyniku x otrzyma wartość 2 */
y=a%b;
/* y => 1 - reszta z dzielenia */
x % y daje w wyniku resztę dzielenia x przez y.
Operatora % nie można stosować do danych typu float i double.
Operatory jednoargumentowe:
+, -.
Dwuargumentowe operatory + i - mają ten sam priorytet, niższy od *, /, %, który z kolei jest
niższy od priorytetu jednoargumentowych. operatorów + i -.
Operatory arytmetyczne są lewostronnie łączne.
Relacje i operatory logiczne
Operatory relacji: > >=
< <= (mają ten sam priorytet)
Operatory przyrównania: == (równe)
!= (różne) (priorytet niższy)
Operatory logiczne: && (and) i || (or)
Wyrażenia
Wszystko co zwraca wartość jest wyrażeniem.
Wyrażeniem może być samodzielny element, np. liczba, stała, zmienna.
Może to być też kombinacja w/w elementów połączonych znakami operatorów, np.
arytmetycznych lub logicznych.
Przykłady:









3.2
PI
a=a+b;
x=y;
x<LAFA;
k == m;
y = x = a+b;
x != y
b[i-2] = a[j+1];
Instrukcje
Instrukcje są to fragmenty tekstu programu (zwykle linie), które powodują jakąś czynność
komputera w trakcie wykonywania programu.
Instrukcje można podzielić na grupy:
Instrukcje obliczające wartości wyrażeń, np. a=b+c;
Każda taka instrukcja musi być zakończona średnikiem;
Instrukcje grupujące (złożone) - ograniczone klamrami { },


np.
{
a=3;
b=2.2;
p=a*b;
printf("Pole=%f",p);
}


Instrukcje sterujące, np. while, if...
Instrukcje wywołania funkcji
Przykład instrukcji złożonej (grupującej)
/********************************************************/
/* Program p11.c
*/
/* Obliczanie objetosci walca
( instrukcja bloku )
*/
/*------------------------------------------------------*/
#include <stdio.h>
#define
#define
#define
#define
#define
#define
PI
3.1415926
PROMIEN
3.3
WYSOKOSC
44.4
KRYTERIUM 1500.0
WSP
2.2
WZOR_OBJETOSC PI * promien * promien * wysokosc
main()
{
float promien, wysokosc, objetosc;
promien = PROMIEN;
wysokosc = WYSOKOSC;
objetosc = WZOR_OBJETOSC;
printf("Objetosc walca = %f", objetosc);
if (objetosc > KRYTERIUM)
{
float objetosc, promien = PROMIEN * WSP;
objetosc = WZOR_OBJETOSC;
printf("\nObjetosc walca = %f
(lokalna)", objetosc);
}
printf("\nObjetosc walca = %f", objetosc);
}
/********************************************************/
Efekt wykonania programu:
Objetosc walca = 1519.010254
Objetosc walca = 7352.010742
Objetosc walca = 1519.010254
(lokalna)
Wejście i wyjście programu
Do podstawowych funkcji języka C, umożliwiających komunikację z otoczeniem należą:
dla operacji wejścia: getchar, gets, scanf;
dla operacji wyjścia: putchar, puts, printf;
W DOS, wyniki wysyłane na ekran mogą być przy pomocy znaku potoku wysłane do pliku
lub na drukarkę.
Np. p11 > Wynik.txt (do pliku)
p11 > PRN (na drukarkę)
Funkcja putchar: int putchar(int)
Funkcja wysyła na zewnątrz (do standardowego strumienia wyjściowego stdout, standardowo
na ekran0 pojedynczy znak
Funkcja (makro) zwraca wartość wypisanego znaku lub EOF (jako sygnał błędu).
Przykład:
/********************************************************/
/* Program p12.c
*/
/*
( putchar )
*/
/*------------------------------------------------------*/
#include <stdio.h>
#define SPACJA 32
main()
{
char napis[] = "ABCDEFGHIJKLMNOPQRS...";
int znak = 73;
/* wyprowadzanie pojedynczych znakow
przy pomocy funkcji putchar
*/
putchar('\n');
putchar(znak);
putchar(55);
putchar(SPACJA);
putchar(SPACJA);
putchar('\066');
putchar('\x3A');
putchar('\n');
putchar(SPACJA);
putchar(napis[4]);
putchar(znak+'\066'-52);
putchar(SPACJA);
putchar('Z');
putchar(SPACJA);
putchar(napis[0]);
putchar(SPACJA);
putchar('\n');
}
/********************************************************/
Wynik:
I 7 Z 6 :
A E K
Funkcja puts: int puts(const char *s);
Wysyła łańcuch s do standardowego strumienia wyjściowego (stdout) i dołącza znak końca
wiersza.
W przypadku powodzenia operacji wartość jest nieujemna, w przeciwnym wypadku EOF.
/********************************************************/
/* Program p13.c
*/
/*
( puts )
*/
/*------------------------------------------------------*/
#include <stdio.h>
#define NOWA_LINIA putchar('\n')
main()
{
char napis[] = "ABCDEFGHIJKLMNOPQRS...";
/* wyprowadzanie pojedynczych linii tekstu
przy pomocy funkcji puts
*/
NOWA_LINIA; puts(napis); NOWA_LINIA;
puts("To jest praktyczna funkcja");
puts("\066\067\x2B\x2A itd.");
}
/********************************************************/
Wynik:
ABCDEFGHIJKLMNOPQRS...
To jest praktyczna funkcja
67+* itd.
Funkcja printf
Wyprowadza wynik przetwarzania w różnych formatach.
printf (łańcuch, lista argumentów)
int printf(const char *format,...)
Przykład:
/********************************************************/
/* Program p14.c
*/
/*
( printf /1/ )
*/
/*------------------------------------------------------*/
#include <stdio.h>
main()
{
int
k = 21101;
/* liczba dziesietna */
printf("\nk(_10) = %i
k(_8) = %o
k(_16) = %X", k, k, k);
}
/********************************************************/
Wynik:
k(_10) = 21101
k(_8) = 51155
k(_16) = 526D
Formaty realizowane przez funkcję printf (znaki typu w łańcuchach formatujących)
Typ danych - znak Argument
typu w formacie
wejściowy
Format wyjściowy
Liczba
%d, %i
int
liczba całkowita ze znakiem
%u
unsigned int
l. całk. ze bez znaku
%o
int
ósemkowa
%x
int
szestnastkowa bez znaku, małe litery a..f
%X
int
j.w. będą duże litery A..F
%f
float/double
l. zmiennoprzecinkowa: [-]nnnn.mmmmm
%e
float/double
j.w. w postaci [-].nnnne[+-]mmm
%E
-"-
j.w. ze znakiem E
%G
-"-
jak %f lub %E, mniejsza liczba znaków
%c
char (znak)
pojedynczy znak
%s
char * wskaźnik
łańcucha
łańcuch znaków, aż do napotkania bajtu
zerowego \0
%n
int *
Liczba dotychczas wysłanych znaków
%p
pointer wskaźnik
argument w postaci wskaźnika, co zależy
od modelu pamięci (segm:offs lub offs)liczba 16-wa
ZNAK lub
ŁAŃCUCH
WSKAŹNIK
Przykłady:
/********************************************************/
/* Program p15.c
*/
/*
( printf /2/ )
*/
/*------------------------------------------------------*/
#include <stdio.h>
Przykład
main()
{
float
a,b,c;
a=153.67789;
b=2.33E-2;
c = a * b;
printf(" %f razy %E wynosi: %f ", a,b,c);
}
/********************************************************/
Wynik:
153.677887 razy 2.330000E-02 wynosi: 3.580695
/********************************************************/
/* Program p16.c
*/
/*
( printf /3/ )
*/
/*------------------------------------------------------*/
#include <stdio.h>
main()
{
char napis[] = "ABCDEFGHIJKLMNOPQRS...";
int znak = 73;
/* wykonanie tego samego co w przykladach
p12.c i p13.c przy pomocy funkcji printf
*/
/* p12.c */
printf("\n%c %c %c %c %c \n%c %c %c\n",
znak,55,'Z','\066','\x3A',napis[0],napis[4],znak+'\066'-52);
/* p13.c */
printf("\n%s\nTo jest praktyczna funkcja\n%c%c%c%c itd.",
napis,'\066','\067','\x2B','\x2A');
}
/********************************************************/
Wynik:
I 7 Z 6 :
A E K
ABCDEFGHIJKLMNOPQRS...
To jest praktyczna funkcja
67+* itd.
/********************************************************/
/* Program p17.c
( Turbo C 2.0 )
*/
/*
( printf /4/ )
*/
/*------------------------------------------------------*/
#include <stdio.h>
main() /* zagadnienie dokladnosci */
{
double a=153.67789;
int
k=22799;
int
m=-500;
int
*p;
/* wskaznik */
char
c='M';
char
napis[]="Lepsze C od B lub P
p=&k;
printf("\n format
%%d
%d", k);
";
printf("\n
printf("\n
printf("\n
printf("\n
printf("\n
printf("\n
printf("\n
printf("\n
printf("\n
printf("\n
printf("\n
printf("\n
printf("\n
printf("\n
printf("\n
format %%i
%i", m);
format %%u
%u", k);
format %%o
%o", k);
format %%x
%x", k);
format %%X
%X", k);
format %%f
%f", a);
format %%e
%e", a);
format %%E
%E", a);
format %%g
%g", a);
format %%G
%G", a);
format %%c
%c", c);
format %%s
%s", napis);
format %%p
%p", *p);
------------------------");
"); printf(napis);
}
/********************************************************/
Wynik:
format %d
22799
format %i
-500
format %u
22799
format %o
54417
format %x
590f
format %X
590F
format %f
153.677890
format %e
1.536779e+02
format %E
1.536779E+02
format %g
153.678
format %G
153.678
format %c
M
format %s
Lepsze C od B lub P
format %p
654C:590F
-----------------------Lepsze C od B lub P
Użyty w łańcuchach formatu zapis %% reprezentuje pojedynczy "widzialny" znak procentu.
Pełny zapis instrukcji formatu printf:
% [Pole znaku] [Szerokość] [.Dokładność] [Modyfikator] Typ danych
%[flagi][szerokość][.precyzja][F|N|h\l|L]znak-typu
Wszystkie sekwencje formatujące zaczynają się od znaku %. Kolejne elementy określają:





Znaki flag - dodatkowe możliwości (np. wyrównanie lewostronne)
Szerokość - liczba wysyłanych znaków -całkowita szerokość pola na zapis liczby
Precyzja (dokładność) - liczba cyfr znaczących - określa ilość miejsc dziesiętnych po
kropce dziesiętnej.
Może wystąpić *.
Specyfikator precyzji - rozpoczyna się znakiem kropki, który oddziela go od
pozostałych elementów sekwencji formatującej.
Modyfikator rozmiaru argumentów - zawierają dodatkową informację nt. rozmiaru
argumentu i są wykorzystywane w połączeniu ze znakami typu w celu wskazania
faktycznego typu argumentu.
Znaki typu - określają typ argumentów
Zapisy w nawiasach kwadratowych są opcjonalne i nie muszą wystąpić
Pole znaku (znaki flag):
'+'
'-'
'#'
' ' (spacja)
0 (zero)
- wyprowadzony ciąg znaków będzie wyrównany lewostronnie
+ znak ma być wydrukowany (- lub +)
Flagi w sekwencjach formatujących
Flaga Co określa
Justuje lewostronnie wartość, umieszczając z prawej strony odpowiednią ilość spacji
+
Jeśli wyświetlana jest liczba ze znakiem, wówczas zostanie przed nią umieszczony
znak + lub -, w zależności od wartości
spacja
Jeśli wartość jest nieujemna, zamiast plus wyświetlana będzie spacja, w przypadku
wartości ujemnych -
#
Wpływ tego znaku zależy od tego, z jakim znakiem typu jest związany - tabela poniżej
Typ
danych
c, s, d, i, u
Reakcja, gdy występuje znak #
%o
Przy wartościach dodatnich na początku zostanie dopisany znako 0
%x, %X
Wszystkie liczby będą przedstawione z 0x lub 0X
%e, %E,
%f
Również w przypadku braku miejsc znaczacych dziesiętnych, po przecinku
będzie kropka dzies.
%g, %G
Odpowiednio jak dla %e i %E, ale będą widoczne nieznaczące zera
Nie wpływa
Specyfikator precyzji rozpoczyna się znakiem kropki, który oddziela go od pozostałych
elementów sekwencji formatującej
Specyfikatory precyzji (dokładności) - zagadnienie dokładności obliczeń
Specyfikator
Precyzja - znaczenie
dokładności
Domyslne precyzje:
- 1 dla znaków typu d, i, o, u, x, X
nie podano
- 6 dla typu e, E, f
- wszystkie znaczące cyfry dla typu g i G
.0
Dla znaków typu d, i, o, u, x, X przyjmowana jest precyzja d domysla. Dla
e, E, f nie jest drukowana kropka dziesiętna. Liczby całkowite o wartosci
zero nie będą drukowane
.n
Drukowane będzie n znaków lub cyfr dziesiętnych. Może nastąpić
obcięcie lub zaokrąglenie
*
Lista argumentów zawiera wartość określającą precyzję.
Specyfikator szerokości - określa minimalną szerokość dla wartości wyjściowej.
Specyfikatory szerokości pola
Specyfikator
szerokości pola
Wpływ na formatowane dane
n
Drukowanych jest przynajmniej n znaków. Jeśli wartość zajmuje mniej
niż n znaków, umieszczone będą dodatkowe spacje, z lewej lub prawej
strony (jeśli ustawiono odpowiednią flagę)
0n
Drukowanych jest przynajmniej n znaków. Jeśli znaków drukowanych
jest mniej niż n to nastąpi wypełnienie zerami z lewej strony
*
Szerokość pola znajdzie się w argumencie poprzedzającym argument, z
którym związana jest dana sekwencja
Modyfikatory rozmiaru argumentów - zawierają dodatkową informację o typie argumenów
wejściowych. Jedna z liter: F, N, h, I
Modyfikator Działanie
Przekazanie wskaźnika typu far. Argument zostanie potraktowany jako daleki
F
wskażnik - używany ze znakami typu p, s, n
N
Przekazanie wskaźnika typu near. Argument będzie traktowany jako wskaźnik
bliski. Nie stosować w modelu huge.
h
Oznacza przekazanie danej typu short int. Argument traktuje się jako short int
dla znaków typu d, i, o, u, x, X
l
Oznacza przekazanie danej typu long int względnie double.
L
Argument traktowany jako long double dla znaków typu e, E, f, g, G
Przykłady:
/********************************************************/
/* Program p18.c ( Turbo C 2.0 ) */
/* ( printf /5/ ) */
/*------------------------------------------------------*/
#include <stdio.h>
main() /* wybrane formaty */
{
double a=153.67789, b=153. ;
int k=22799;
int m=-500;
int *p; /* wskaznik */
char c='M';
char napis[]="Lepsze C od B lub P ";
p=&k;
printf("\n format %%#-+8d %#-+8d", k);
printf("\n format %%#-+8i %#-+8i", m);
printf("\n format %%#- 8u %#- 8u", k);
printf("\n format %%#-+8o %#-+8o", k);
printf("\n format %%#-+8x %#-+8x", k);
printf("\n format %%#-+8X %#-+8X", k);
printf("\n format %%#020.8f %#020.8f", a);
printf("\n format %%# 20.8e %# 20.8e", a);
printf("\n format %% +20.8E % +20.8E", b);
printf("\n format %% +20.8g % +20.8g", a);
printf("\n format %% +20.8G % +20.8G", b);
printf("\n format %% +20.8c % +20.8c", c);
printf("\n format %%.20s %.20s", napis);
printf("\n format %%24p %24p", *p);
printf("\n ---------------------------------------");
printf("\n%44.*s",30,napis);
m=printf("\n\n123456789 123456789 123456789 123456789 1\n");
printf("\n\"Wynik\" poprzednio wykonanej instrukcji");
printf("\np r i n t f wynosi %i znaki \n", m);
}
/********************************************************/
Wynik:
format %#-+8d
+22799
format %#-+8i
-500
format %#- 8u
22799
format %#-+8o
054417
format %#-+8x
0x590f
format %#-+8X
0X590F
format %#020.8f
00000000153.67789000
format %# 20.8e
1.53677890e+02
format % +20.8E
+1.53000000E+02
format % +20.8g
+153.67789
format % +20.8G
+153
format % +20.8c
M
format %.20s
Lepsze C od B lub P
format %24p
10B4:590F
--------------------------------------Lepsze C od B lub P
123456789 123456789 123456789 123456789 1
"Wynik" poprzednio wykonanej instrukcji
p r i n t f
wynosi 44 znaki
/********************************************************/
/* Program p19.c
( Turbo C 2.0 )
*/
/*
( printf /6/ )
*/
/*------------------------------------------------------*/
#include <stdio.h>
main() /* zapisy rownowazne, dynamiczny format */
{
double a=153.22;
char
napis[]="Wszystko dobre co nie jest niedobre ";
int
i,j;
printf("\n%.9s", napis);
printf("\n%.*s", 9, napis);
i=9;
i=14;
i=21;
printf("\n%.*s", i, napis);
printf("\n%.*s", i, napis);
printf("\n%.*s", i, napis);
printf("\n
printf("\n
printf("\n
i=9; j=3;
printf("\n
i=20; j=8;
printf("\n
a = %#09.3f", a);
a = %#0*.3f", 9, a);
a = %#0*.*f", 9, 3, a);
a = %#0*.*f", i, j, a);
a = %#0*.*f", i, j, a);
}
/********************************************************/
Wynik:
Wszystko
Wszystko
Wszystko
Wszystko dobre
Wszystko dobre co nie
a = 00153.220
a = 00153.220
a = 00153.220
a = 00153.220
a = 00000000153.22000000
/********************************************************/
/* Program p20.c
*/
/* Obliczanie objetosci walca
( wieksza dokladnosc ) */
/*------------------------------------------------------*/
#include <stdio.h>
#define PI
#define PROMIEN
#define WYSOKOSC
3.1415926
3.3
44.4
main()
{
{ float promien, wysokosc, objetosc;
promien = PROMIEN; wysokosc = WYSOKOSC;
objetosc = PI * promien * promien * wysokosc;
printf("\nObjetosc walca = %f", objetosc);
}
{ double promien, wysokosc, objetosc;
promien = PROMIEN; wysokosc = WYSOKOSC;
objetosc = PI * promien * promien * wysokosc;
printf("\nObjetosc walca = %f", objetosc);
}
}
/********************************************************/
Wynik:
Objetosc walca = 1519.010254
Objetosc walca = 1519.010288
/********************************************************/
/* Program p21.c
*/
/* Obliczanie objetosci walca
( wieksza dokladnosc ) */
/*------------------------------------------------------*/
#include <stdio.h>
#define PI
#define PROMIEN
#define WYSOKOSC
3.1415926
3.3
44.4
main()
{
double promien, wysokosc, objetosc;
promien = PROMIEN;
wysokosc = WYSOKOSC;
objetosc = PI * promien * promien * wysokosc;
printf("\nObjetosc walca = %f", objetosc);
printf("\nObjetosc walca = %E", objetosc);
printf("\nObjetosc walca = %g", objetosc);
printf("\nObjetosc walca = %15.10f", objetosc);
printf("\nObjetosc walca = %25.20f", objetosc);
}
/********************************************************/
Wynik:
Objetosc walca = 1519.010288
Objetosc walca = 1.519010E+03
Objetosc walca = 1519.01
Objetosc walca = 1519.0102875816
Objetosc walca = 1519.01028758159987000000
Funkcja getchar
int getchar(void)
Funkcja odczytuje znak ze standardowego strumienia wejściowego (stdin) i zwraca go po
dokonaniu konwersji bez rozszerzenia znakowego. Funckja przy każdym wywołaniu podaje
następny znak z wejścia lub EOF, gdy napotkała koniec pliku. W przypadku błędu lub końca
zbioru wartością funkcji jest EOF. Stała symboliczna EOF jest zdefiniowana w nagłówku
<stdio.h.. Jej wartoscią jest na ogół -1, ale e testach należy używać EOF.
Zadaniem funkcji jest wprowadzenie pojedynczego znaku do pamięci komputera.
Syntaktycznie postać funkcji jest następująca:
c = getchar(); gdzie c jest typu char.
Po każdym wywołaniu funkcja getchar pobiera ze strumienia znaków następny znak i wraca z
jego zawartością. Zawartością zmiennej jest następny znak z wejścia.
Przykłady:
#include <stdio.h>
/* przepisz wejscie na wyjście, wersja 1 */
main()
{
int c;
c = getchar(); /* przeczytaj znak */
while (c != EOF) /* dopóki znak nie jest znakiem konca pliku (Ctrl Z) */
{
putchar(c); /* wypisz przeczytany znak */
c=getchar(); /* przeczytaj nastepny znak */
}
}
Funkcja scanf
int scanf(const char * format, ...)
Funkcja scanf jest wejściowym odpowiednikiem funkcji printf . Wczytuje znaki ze
standardowego wejścia, interpretuje zgodnie ze specyfikacjami w argumencie format i
zapamiętuje wyniki w miejscach określonych przez argumenty, np.
int i, j;
scanf("%d%d", &i, &h);
spowoduje, ze ze standardowego wejścia zostaną pobrane 2 liczby całkowite (sekwencje
formatujące %d i %d), których wartość zostanie umieszczona w zmiennych "i" i "j".
Syntaktycznie funkcja scanf ma definicję:
scanf(łańcuch formatu, lista argumentów)
Przykład: Obliczenie objętości walca:
/************************************************************/
/* Program p24.c
*/
/* Obliczanie objetosci walca
( scanf /1/ )
*/
/*----------------------------------------------------------*/
#include <stdio.h>
#define PI
3.1415926
main()
{
float promien, wysokosc, objetosc;
printf("\n----- Program oblicza objetosc walca -----");
printf("\n----- Podaj dane wejsciowe: \n");
printf("\npromien = ");
scanf("%f", &promien);
printf("wysokosc = ");
scanf("%f", &wysokosc);
objetosc = PI * promien * promien * wysokosc ;
printf("\nObjetosc walca = %f", objetosc);
}
/************************************************************/
Wyniki:
----- Program oblicza objetosc wal
----- Podaj dane wejsciowe:
promien = 3.3
wysokosc = 44.4
Objetosc walca = 1519.010254
Liczby 3.3 i 44.4 zostały wprowadzone z klawiatury. Każdy łańcuch znaków reprezentujacy
liczbę, musi być zakoczony ENTER.
Uproszczona wersja w.w. programu - brak zmiennej objętość:
/************************************************************/
/* Program p24b.c
*/
/* Obliczanie objetosci walca
( printf /8/ )
*/
/*----------------------------------------------------------*/
#include <stdio.h>
#define PI
3.1415926
main()
{
float promien, wysokosc;
printf("\n----- Program oblicza objetosc walca -----");
printf("\n----- Podaj dane wejsciowe: \n");
printf("\npromien = ");
scanf("%f", &promien);
printf("wysokosc = ");
scanf("%f", &wysokosc);
printf("\nObjetosc walca = %f",PI*promien*promien*wysokosc);
}
/************************************************************/
Instrukcja formatu dla funkcji scanf:
% [*] [Szerokość] [Modyfikator1] [Modyfikator2] Typ danych
Znaczenie opcji:





* (gwiazdka) - zignorowanie pola wejściowego
szerokość - maks. liczba wczytanych znaków (przerwanie wprowadzania po spacji lub
innym nieodpowiednim znaku dla formatu we)
Modyfikator1 - F dla wskaźnika far, N dla near
Modyfikator2 - h dla short int, l dla long int lub double
Znaki typu łańcuchów formatujacych dla funkcji scanf - formaty realizowane przez
funkcję scanf
Typ danych (znak
formatu)
Typ
argumentu
Format wejściowy - dana wprowadzana
%d
int *
liczba całkowita dziesiętna, całkowita ze znakiem
%D
long *
liczba całkowita dzies. ze znakiem
%i
int *
liczba dzies., ósemkowa, 16-wa, całkowita, ze
znakiem
LICZBA
%l
long *
j.w.
%u
unsigned *
liczba całkowita, dziesiętna, bez znaku
%U
unsigned
long *
liczba całk. dziesiętna, bez znaku
%o
int *
liczba ósemkowa ze znakiem
%O
long *
j.w.
%x
int *
liczba 16-wa całkowita
%X
long *
j.w.
%f
float *
liczba zmiennoprzecinkowa
%e
float *
j.w.
%E
float *
j.w.
%c
char *
pojedynczy znak
%s
char tab[n]
łańcuch aż do bajtu zerowego
%n
brak
liczba już wczytanych znaków zapamiętana we
wskaźniku typu (int *)
%p
far * / near *
wskaźnik do dowolnego obiektu, jako liczba 16-wa,
bliski (ofs) lub daleki (seg:ofs)
ZNAKI (znak lub
łańcuch znaków)
WSKAŹNIK

Na liście argumentów funkcji scanf używany jest operator &. Jego wystąpienie przed
nazwą zmiennej oznacza adres tej zmiennej.























/********************************************************/
/* Program p25.c
*/
/*
( & )
*/
/*------------------------------------------------------*/
#include <stdio.h>
main()
/* operator
& */
{
int
*p, k=13;
printf("\n%i",k);
p=k;
/* wartosc */
printf("\n%i",p);
printf("\n%p",p);
p=&k;
/* adres k */
printf("\n%p",p);
}
/********************************************************/
Wynik:
13
(wartość k)
13
(wartość *p)

























0000:000D
137F:21E8
(wartość *p w formacie 16-wym)
(adres zmiennej k)
Przykład na obliczenie objętości walca - wprowadzenie 2 liczb w jednej linii:
/************************************************************/
/* Program p26.c
( Turbo C 2.0 )
*/
/* Obliczanie objetosci walca
( scanf /2/ )
*/
/*----------------------------------------------------------*/
#include <stdio.h>
#define PI
3.1415926
main()
{
float promien, wysokosc, objetosc;
printf("\n----- Program oblicza objetosc walca -----");
printf("\nPodaj dane wejsciowe (2 liczby)");
printf("\npromien i wysokosc
(format: xxx.xx xxx.xx)\n");
scanf("%6f %6f", &promien, &wysokosc);
objetosc = PI * promien * promien * wysokosc ;
printf("\nObjetosc walca = %f", objetosc);
}
/************************************************************/
----- Program oblicza objetosc walca ----Podaj dane wejsciowe (2 liczby)
promien i wysokosc (format: xxx.xx xxx.xx)
3.3 44.4

Objetosc walca = 1519.010254
Znakiem separacji danych może być tu znak spacji, znak nowej linii (ENTER) lub
znak tabulacji. W przypadku błędnych formalnie danych (np. litera k zamiast liczby)
program nie zawiesza się tylko przyjmowane jest zero jako wartość zmiennej. Dobrym
nawykiem jest oddrukowywanie danych wejściowych.
/********************************************************/
/* Program p27.c
*/
/*
( scanf /3/ )
*/
/*------------------------------------------------------*/
#include <stdio.h>
main() /* to samo co w przyk. p22.c i p23.c
{
char znak, linia[80];
scanf("%c",
&znak);
printf("%c\n", znak);
scanf("%s",
linia);
printf("%s", linia);
*/
/* p22.c */
/* p23.c */
}
/********************************************************/
Program poniższy pokazuje możliwość filtrowania znaków:
/********************************************************/
/* Program p28.c
*/
/*
( scanf /4/ )
*/
/*------------------------------------------------------*/
#include <stdio.h>
main() /* filtrowanie znakow */
{
char linia[80];
scanf("%[a-zABC]",linia);
printf("%s", linia);
}
/********************************************************/
Przykładowy wynik:
alinaABOLa
alinaAB
Instrukcja scanf pozwala tu na wprowadzenie wszystkich małych liter a-z oraz wybranych
liter A, B, C. Wprowadzony łańcuch zostanie obcięty przed znakiem nie należacym do zbioru
podanego.
Inne możliwe filtry:




%[A-Z] - duże litery dozwolone
%[^A-Z] - duże litery wykluczone
%[AaBb+-.:K] - wybrane znaki dozwolone
%[^XYZxyz] - wybrane znaki wykluczone
Operatory i wyrażenia
Do wykonania obliczeń zmieniających dane w informacje, niezbędne są operatory. Operator
to symbol mówiący komputerowi, jak ma przetwarzać dane.
Operatory, z punktu widzenia liczby argumentów dzielimy na dwuargumentowe i
jednoargumentowe.
a op b - op jest operatorem 2-argumentowym, np. a+b; a*b; a/b; a%b;
op a - op jest operatorem jednoargumentowym, np. -a; -(a+b); !a
Można je pogrupować wg cech funkcjonalnych na grupy:





operatory arytmetyczne
operatory porównania - relacyjne
operatory logiczne
operatory bitowe
operatory przypisania






operatory unarne
operatory rozmiaru
operatory konwersji
operator warunkowy
operator przecinkowy
operatory wskazywania
Operatory arytmetyczne
Operatory arytmetyczne można podzielić na 3 grupy:
operatory inkrementacji i dekrementacji: --Op, ++Op, Op--, Op++
operatory addytywne: "+" i "-"
operatory multiplikatywne: "*', "/", "%"
Operatory te używane są do wykonywania działań matematycznych.
Operatory addytywne i multiplikatywne:
Operator Funkcja
+
Dodawanie
Wyrażenie Operandy
Op1 i Op2 są typu
arytmetycznego
Op1 typu całk, Op2
Op1+Op2
wskaźnik
Op1 wskaźn, Op2
całkowity
Przykład
Wynik
int a=9; int
b=2, c;
c=a+b;
c=11
-
Odejmowanie
Op1-Op2
Op1 i Op2 są typu
arytmet.
Op1 i Op2 są
int a=9; int
wskaźnikami tego
c=7
b=2, c; c=a-b;
samego typu
Op1 jest wskaźnikiem,
Op2 typu całkowitego
*
Mnożenie
Op1*Op2
Op1 i Op2 typów
arytmet.
/
Dzielenie
Op1 / Op2 -"-
%
Reszta z dzielenia
liczb całkowitych modulo
Op1 %
Op2
Op1 i Op2 typów
całkowitych
Brak jest operatora potęgowania (realizuje to funkcja biblioteczna pow)
int a=9; int
b=2, c;
c=a*b;
c=18
int a=9; int
c=4
b=2, c; c=a/b;
int a=9; int
b=2, c;
c=a%b;
c=1
Jeżeli dzielimy zmienne lub liczby całkowite przy pomocy operatora /, to wynik zawsze
bedzie liczbą całkowitą. Z operatora % korzystamy do obliczenia reszty z dzielenia liczb
całkowitych.
Przykład wykorzystujący operatory arytmetyczne:
/********************************************************/
/* Program p29.c
*/
/*
( operatory arytmetyczne )
/*------------------------------------------------------*/
#include <stdio.h>
main()
{
int
float
k = 20, m = 3,
x = 7.5, y = 1.5,
i;
z;
printf("\n k=20, m=3
(int)");
printf("\n---------------------------");
i = k + m;
printf("\n k + m = %i ", i);
i = k - m;
printf("\n k - m = %i ", i);
i = k * m;
printf("\n k * m = %i ", i);
i = k / m;
printf("\n k / m = %i ", i);
i = k % m;
printf("\n k %% m = %i ", i);
printf("\n");
printf("\n x=7.5, y=1.5
(float)");
printf("\n---------------------------");
z = x + y;
printf("\n x + y = %6.2f ", z);
z = x - y;
printf("\n x - y = %6.2f ", z);
z = x * y;
printf("\n x * y = %6.2f ", z);
z = x / y;
printf("\n x / y = %6.2f ", z);
printf("\n---------------------------");
i = k*x + (m+k+1)/y ;
printf("\n k*x + (m+k+1)/y = %i
(int)", i);
z = k*y + (x+k+1.)/m ;
printf("\n k*y + (x+k+1.)/m = %6.2f (float)", z);
}
/********************************************************/
Wynik wykonania:
k=20, m=3
(int)
--------------------------k + m = 23
k - m = 17
k * m = 60
k / m = 6
k % m = 2
x=7.5, y=1.5
(float)
--------------------------x + y =
9.00
*/
x - y =
6.00
x * y = 11.25
x / y =
5.00
--------------------------k*x + (m+k+1)/y = 166
(int)
k*y + (x+k+1.)/m = 39.50 (float)
Operatory porównania - relacyjne
Operatory relacyjne pozwalają stwierdzić, czy między operandami zachodzi dana relacja.
Jeżeli relacja jest prawdziwa, to jej wartością jest true (prawda, wartość 1), a jeżeli fałszywa,
to jej wartością jest false (wartość 0). Operator sprawdzenia róności to "==" (operator
przypisania to "=").
Operator Znaczenie
Relacja
Opis
Przykład
<
Mniejszy
Op1<Op2
int a,b,wyn;
Op1 mniejsze niż a=10; b=3;
Op2
wyn = a<b; // zostanie przypisana
wartość 0 (false)
<=
Mniejszy lub
równy
Op1 <=
Op2
Op1 mniejsze
równe Op2
wyn = a<=b; // 0
>
Większy
Op1 > Op2
Op1 większe niż
Op2
wyn = a>b; // 1 (true)
>=
Większy lub
równy
Op1 >=
Op2
==
Równy - równe
Op1 ==
Op2
Op1 równe Op2
!=
Nierówny różne
Op1 !=
Op2
Op1 różne od Op2 wyn = a != b; //1
wyn = a>= b; //1
wyn = a == b; // 0
Operandy Op1 i Op2 w powyższych relacjach muszą spełniać jedną z 2 reguł:


Op1 i Op2 są typu arytmetycznego
Op1 i Op2 są wskaźnikami zgodnych typów
Operandy wyrażeń z operatorem równości == lub różnosci powinny spełnaić w.w.
właściwości lub jedną z poniższych:


Jeden z operandów jest wskaźnikiem, drugi zaś jest typu void
Jeden z operandów jest wskaźnikiem, natomiast drugi stałą oznaczającą adres pusty
(NULL)
Uwaga! Operator równości jest często mylony z operatorem przypisania =
if (a=1) - przypisanie, wartością wyrażenia jest 1, czyli prawda, zamiast
if (a==1) - porównanie, wartością wyrażenia jest prawda, jeśli a równa się 1 lub fałsz gdy nie.
Kilka przykładów:
int k=1; m=2; n=3;
Wyrażenie
Interpretacja Wartość
m<n
prawda
1
(k+m)>=n
prawda
1
(m-k)>n
fałsz
0
n>=3
prawda
1
k != m
prawda
1
k == 2
fałsz
0
(m+2) <= k
fałsz
0
Operatory logiczne
W języku C/C++ wartość logiczna prawda to liczba całkowita różna od zera, zaś fałsz to zero
(całkowite)
Wyrażenie
Operator Znaczenie
Opis
Przykład
&&
Koniunkcja - logiczne AND Op1 &&
(i) /iloczyn
Op2
int k=1, m=2, n=3;
Koniunkcja Op1 i
((k+m)>=n) &&
Op2
(m==1) // 0
||
Alternatywa - logiczne OR
(lub) /suma log.
Op1 || Op2
Alternatywa Op1 ((m-k)>n) || (m==2)
i Op2
//1
!
Negacja - logiczne NOT
(nie)
!Op1
Negacja Op1
!(k>n) //1
Operandy Op1 i Op2 muszą być skalarami, zaś wartość wyrazenia logicznego jest zawsze
typu int.
Wartości wyrażeń logicznych (f - fałsz/ false, t - prawda/false)
Op1 Op2 Op1 && Op2 Op1 || Op2 !Op1
f
f
f
t
t
f
t
f
t
t
t
f
f
t
f
t
t
t
t
f
if (x != 0) to samo co if (x)
if (y == 0) równoważne if (!y)
Przykład (Zalewski, Programowanie w C i C++ ..., str 131):
#include <stdio.h>
#define TRUE 1
#define FALSE 0
typedef int BOOL;
BOOL czy_w_przedziale(double x, double s, double t, BOOL domkniety)
{
if ((x<t && x>s && !domkniety) || (x<=t && x>=s && domkniety))
return TRUE;
else return FALSE;
}
int main(void)
{
double x, s=5, t=20;
printf("\nPodaj liczbe: ");
scanf("%lf",&x);
if (czy_w_przedziale(x,s,t,TRUE))
printf("\nLiczba %lf nalezy do przedzialu <%lf, %lf>",x,s,t);
else
printf("\nLiczba %lf nie nalezy do przedzialu <%lf, %lf>",x,s,t);
return 0;
}
Przykładowy wynik :
Podaj liczbe: 3
Liczba 3.000000 nie nalezy do przedzialu <5.000000, 20.000000>
Przykład z walcem - promień ma być w przedziale (2, 3.3), a wysokosć w przedziale (4.50,
5.50), dodatkowo H/r ma być w przedziale [2.11,2.42] lub w [2.58, 2.95], objętość walca C
<= 100 - walec jest DOBRY
/*************************************************************/
/* Program p30.c
*/
/* Ocena jakosci walca
( operatory logiczne )
*/
/*-----------------------------------------------------------*/
#include <stdio.h>
#define PI
3.1415926
/* parametry narzucone przez kryterium:
P1 - promien minimalny
P2 - promien maksymalny
H1 - wysokosc minimalna
H2 - wysokosc maksymalna
hp - stosunek wysokosci do promienia
HP1 - dolna granica hp (zakres pierwszy)
HP2 - gorna granica hp (zakres pierwszy)
HP3 - dolna granica hp (zakres drugi)
HP4 - gorna granica hp (zakres drugi)
V
- objetosc maksymalna
#define
#define
#define
#define
P1
P2
H1
H2
2.00
3.30
4.50
5.50
*/
#define
#define
#define
#define
#define
HP1
2.11
HP2
2.42
HP3
2.58
HP4
2.95
V
100.00
main() /* kryterium jakosci walca */
{
float promien, wysokosc, hp, objetosc;
scanf("%f %f", &promien, &wysokosc);
hp = wysokosc / promien;
objetosc = PI * promien * promien * wysokosc;
if
(((promien > P1) && (promien < P2)) &&
((wysokosc >= H1) && (wysokosc <= H2)) &&
(((hp>=HP1) && (hp<=HP2)) || ((hp>=HP3) && (hp<=HP4))) &&
( objetosc <= V ))
{
printf("\n------ Walec jest DOBRY dla:");
printf("\npromien= %5.2f, wysokosc=%5.2f",promien,wysokosc);
}
printf("\nobjetosc=%6.2f, hp=
%6.2f",objetosc,hp);
}
/**************************************************************/
2.30
5.40
------ Walec jest DOBRY dla:
promien=
2.30, wysokosc= 5.40
objetosc= 89.74, hp=
2.35
Operatory bitowe
Bitowe operatory logiczne działają na uporządkowanym ciągu bitów (0,1) i pozwalają na
manipulowanie bitami. Za pomocą tych operatorów można realizować funkcje logiczne OR,
AND, EXOR, NOT.
Operator Znaczenie
&
Bitowa koniunkcja (AND)
Wyrażenia
Przykłady
Op1 & Op2
0&0=0
0&1=0
1&0=0
1&1=1
Op1 | Op2
0|0=0
0|1=1
1|0=1
1|1=1
|
Bitowa alternatywa (OR)
^
Bitowa różnica symetryczna
(XOR)
Suma modulo 2
Op1 ^ Op2
0^0=0
0^1=1
1^0=0
1^1=1
~
Bitowa negacja
~Op1
~0 = 1
~1 = 0
<<
Przesunięcie w lewo
Op1 <<
Op2
Przesuń Op1 w lewo o Op2
bitów
>>
Przesunięcie w prawo
Op1 >>
Op2
Przesuń Op1 w prawo o
Op2 bitów
Operandy Op1 i Op2 muszą być typu całkowitego. Użycie operatorów bitowych powoduje
wykonanie operacji logicznych na wszystkich parach odpowiadających sobie bitów.
Przykład:
/********************************************************/
/* Program p31.c
*/
/*
( operatory bitowe )
*/
/*------------------------------------------------------*/
#include <stdio.h>
main()
{
unsigned int
k = 0x5555,
m = 0x3333,
i;
printf("\n k = %#x
m = %#x ", k, m);
printf("\n------------------------------");
i = k & m;
printf("\n k & m
= %#x ", i); /* wydruk z początkowym )x */
i = k | m;
printf("\n k | m
= %#x ", i);
i = k ^ m;
printf("\n k ^ m
= %#x ", i);
i = ~ m;
printf("\n
~ m
= %#x ", i);
i = k << 3;
printf("\n k << 3 = %#x ", i);
i = k >> 2;
printf("\n k >> 2 = %#x ", i);
printf("\n------------------------------");
}
/********************************************************/
Wydruk wyników:
k = 0x5555
m = 0x3333
-----------------------------k & m
= 0x1111
k | m
= 0x7777
k ^ m
= 0x6666
~ m
= 0xcccc
k << 3 = 0xaaa8
k >> 2 = 0x1555
------------------------------
Operatory przypisania
Instrukcją przypisania jest trójka elementów zapisana jako:
identyfikator operator_przypisnia wyrażenie
Operator Przykład zapisu Zapis równoważny
=
a=b
a=b
+=
a += b
a=a+b
-=
a -= b
a=a-b
*=
a *= b
a=a*b
/=
a /= b
a=a/b
%=
a %= b
a=a%b
<<=
a <<= b
a = a << b
>>=
a >>=b
a = a>>b
&=
a &= b
a=a&b
^=
a ^= b
a=a^b
|=
a |= b
a=a|b
Przykłady:
double x, y, x;
x = y = z = 1.01;
c += d + e; // równoważne: c = c + d + e;
Przykłady:
double x, y, x;
x = y = z = 1.01;
c += d + e; // równoważne: c = c + d + e;
Przykład programu wykorzystującego operatory przypisania:
/********************************************************/
/* Program p32.c
*/
/*
( operatory przypisania )
/*------------------------------------------------------*/
#include <stdio.h>
main()
{
int
k = 5,
m = 3,
i;
printf("\n wartosci poczatkowe: k=%i, m=%i, i=?",k,m);
printf("\n------------------------------------------");
printf("\n operacja
wynik ");
printf("\n------------------------------------------");
i = m;
printf("\n ( i = m
)
i = %i ", i);
i += k;
printf("\n ( i += k )
i = %i ", i);
i -= k;
printf("\n ( i -= k )
i = %i ", i);
*/
i *= k;
printf("\n ( i *= k )
i = %i ", i);
i /= k;
printf("\n ( i /= k )
i = %i ", i);
i <<= 3;
printf("\n ( i <<= 3 )
i = %i ", i);
i >>= 2;
printf("\n ( i >>= 2 )
i = %i ", i);
i &= k;
printf("\n ( i &= k )
i = %i ", i);
i ^= k;
printf("\n ( i ^= k )
i = %i ", i);
i |= k;
printf("\n ( i |= k )
i = %i ", i);
i %= k;
printf("\n ( i %%= k )
i = %i ", i);
printf("\n-----------------------------------------");
}
/********************************************************/
Wydruk wyników:
wartosci poczatkowe: k=5, m=3, i=?
-----------------------------------------operacja
wynik
-----------------------------------------( i = m
)
i = 3
( i += k )
i = 8
( i -= k )
i = 3
( i *= k )
i = 15
( i /= k )
i = 3
( i <<= 3 )
i = 24
( i >>= 2 )
i = 6
( i &= k )
i = 4
( i ^= k )
i = 1
( i |= k )
i = 5
( i %= k )
i = 0
-----------------------------------------
Operatory unarne (jednoargumentowe)
W grupie tej wystepują 3 operatory:



++ zwany operatorem inkrementacji (zwiększania)
-- zwany operatorem dekrementacji (zmniejszania)
- zwany minusem jednoargumentowym oraz +
Operatory ++ i -- są szczególnie charakterystyczne dla języka C. Przykładami zapisu mogą
być: ++i, --i, i++, i--.
Zapisowi i++ lub ++i odpowiada równoważny zapis i = i + 1. Zapisowi i-- lub --i odpowiada i
= i-1. Należy pamiętać, że wyrażenia ++i oraz i++ są różne. Operacja: ++i zwiększa wartość
zmiennej i o 1 przed jej użyciem, natomiast i++ zwiększa wartość zmiennej i o 1 po uzyciu jej
poprzedniej wartości.
Operatory zwiększania lub zmniejszania o 1 jest wykonywana przez większość procesoró w
jednym rozkazie, dlatego w języku C są oddzielne operatory pozwalajace na wykonanie tych
operacji.
Operator
Dekrementacja Inkrementacja
przedrostkowy --Op
++Op
przyrostkowy Op-Op++
Operand Op musi być typu arytmetycznego lub wskaźnikowego i jednocześnie musi stanowić
l-wartość (zmieniana jest więc wartość zmiennej).
Przykład przed- i przyrostkowych operatorów inkrementacji::
int m=3; n=1; r;
r=(m++) + (++n)
/* r=3+(1+1) = 5; m=m+1=4; */
r = (++m) + (++n) /* m=m+1=4; n=n+1=2; r=(3+1) + (1+1) = 6; */
Istotę różnicy między ++i a i++ oraz --i a i-- ilustruje też poniższy program:
/********************************************************/
/* Program p33.c
*/
/*
( operatory unarne )
*/
/*------------------------------------------------------*/
#include <stdio.h>
main()
{
int
i=5 ;
printf("\n----------------");
printf("\n i = %i ",
i );
printf("\n i = %i ", ++i );
printf("\n i = %i ",
i );
printf("\n i = %i ",
i++);
printf("\n i = %i ",
i );
printf("\n i = %i ", --i );
printf("\n i = %i ",
i );
printf("\n i = %i ",
i--);
printf("\n i = %i ",
i );
printf("\n i = %i ", -i );
printf("\n----------------");
}
/********************************************************/
Wydruk wyników:
---------------i=5
i=6
i=6
i=6
i=7
i=6
i=6
i=6
i=5
i = -5
---------------Instrukcja printf("\n i = %i", ++i) jest równoważna sekwencji instrukcji: i=i+1; printf("\n i =
%i",i);
natomiast instrukcja printf("\n = %%i", i++); jest równoważna sekwencji instrukcji: printf("\n
i =%i",i); i=i+1;.
Jeszcze 2 zapisy: a =-b; oraz a -= b;
Pierwszy zapis dotyczy minusa unarnego (zmiany znaku liczby: a= (-b)), zapis drugi operacji odejmowania: a = a-b;
Operator rozmiaru - sizeof
Operator sizeof może być używany w jeden ze sposobów:


sizeof wyrażenie (albo sizeof Op) - rozmiar pamięci zajmowany przez operand Op
(wyrażenie)
sizeof (identyfikator-typu) - rozmiar w bajtach typu określonego przez podany
identyfikator
Rezultatem jest liczba całkowita, określająca rozmiar argumentu w bajtach.
Jeśli Op jest tablicą, to zwracany jest całkowity rozmiar pamięci zajmowany przez wszystkie
jej elementy. W związku z tym liczba elementów tablicy równa się sizeof (tab) / sizeof
(tab[0]). Jeśli Op jest strukturą lub unią, zwracana jest całkowita wielkość obszaru pamięci
przez nią zajmowanego.
Typ wartosci pobrania rozmiaru nosi nazwę size_t i jest zdefiniowany m.in. w stdio.h jako
unsigned int.
Przykład programu z użyciem sizeof:
/********************************************************/
/* Program p34.c
Turbo C 2.0
*/
/*
( operator sizeof )
*/
/*------------------------------------------------------*/
#include <stdio.h>
main()
{
char
c1;
char
tekst[] = "Turbo C jak Turbo-Jetta",
napis[80]= "Jaki komputer taki pan ";
int
i1;
short int
i2;
long int
i3;
float
r1;
long float
r2;
double
r3;
long double
int
r4;
*p;
printf("\n Turbo C 2.0 (reprezentacja) ");
printf("\n============================= ");
printf("\n Typ
Liczba bajtow
");
printf("\n----------------------------- ");
printf("\n char
: %2i ", sizeof(char));
printf("\n int
: %2i ", sizeof(int));
printf("\n short int
: %2i ", sizeof(short int));
printf("\n long int
: %2i ", sizeof(long int));
printf("\n float
: %2i ", sizeof(float));
printf("\n long float : %2i ", sizeof(long float));
printf("\n double
: %2i ", sizeof(double));
printf("\n long double : %2i ", sizeof(long double));
printf("\n pointer
: %2i ", sizeof p);
printf("\n----------------------------- ");
printf("\n tekst
: %i ", sizeof tekst);
printf("\n napis
: %i ", sizeof napis);
printf("\n zmienna r4 : %i ", sizeof r4);
printf("\n============================= ");
}
/********************************************************/
Wydruk:
Turbo C 2.0 (reprezentacja)
=============================
Typ
Liczba bajtow
----------------------------char
:
1
int
:
2
short int
:
2
long int
:
4
float
:
4
long float :
8
double
:
8
long double : 10
pointer
:
2
----------------------------tekst
: 24
napis
: 80
zmienna r4 : 10
=============================
Dla deklaracji tekst[] kompilator zadeklarował tyle miejsca, ile potrzeba so zmieszczenia
napisu. Dla deklaracji tab[80] kompilator zarezerwował dokładnie 80 bajtów, mimo, że
faktycznie łańcuch jest krótszy.
Operator sizeof jest szczególnie pożyteczny przy dynamicznie określanych rozmiarach
pamięci dla różnych typach danych.
Przykład 2 (Zalewski str. 139):
#include <stdio.h>
struct PUNKT
{
double x,y; /* 2 * 8 bajtów = 16 bajtów */
int t[10];
};
/* 10 * 2 bajty = 20 bajtów */
int main(void)
{
double tab[10];
printf("\nRozmiary:\nTablicy: %d\nTypu float: %d\nStruktury PUNKT: %d",
sizeof tab,
sizeof (float),
sizeof (struct PUNKT));
printf("\nPrzypadek szczególny: rozmiar = %d",sizeof puts("Andrzej"));
return 0;
}
Wynik:
Rozmiary:
Tablicy: 80
Typu float: 4
Struktury PUNKT: 36
Przypadek szczególny: rozmiar = 2
Rozmiar tablicy tab wynosi 80, co odpowiada 10 elementom po 8 bajtów, rozmiar typu float 4, rozmiar struktury PUNKT - 36. Interesującą ciekawostką jest ostatnie użycie operatora
sizeof, które daje wartość 2. Wynika to z faktu, że wartości standardowej funkcji puts są typu
int. Ponieważ wyrażenie nie jest obliczane, więc funkcja puts nie zostanie wywołana.
Operator konwersji - jednoargumentowy operator rzutowania (cast)
Operator konwersji, zwany również operatorem rzutowania pozwala na jawne przekształcenie
typów danych.
Zapis operatora rzutowania: (nazwa typu) wyrażenie
Wyrażenie jest przekształcane wg reguł dla typu określonego przez nazwę typu.
Przykład:
int a;
a=2;
(double)a; /* typ operandu zmienia się na typ podany w nawiasie - tu double */
Przykład programu z operatorami konwersji:
/********************************************************/
/* Program p35.c
*/
/*
( operator konwersji )
*/
/*------------------------------------------------------*/
#include <stdio.h>
#include <math.h>
main()
{
char
int
float
c = 'k';
i = 70;
f = 345.6789;
printf("\n Wartosci poczatkowe: ");
printf("\n c = \'%c\'; i = %i; f = %8.4f;", c ,i, f);
printf("\n-------------------------------------");
printf("\n Konwersja
Wynik
");
printf("\n-------------------------------------");
printf("\n (int)
c
%i ", (int)
c
);
printf("\n (float) c
%f ", (float) c
);
printf("\n (double) i
%f ", (double) i
);
printf("\n (char)
i
%c ", (char)
i
);
printf("\n (double) i+2000
%f ", (double) i+2000 );
printf("\n (int)
f
%i ", (int)
f
);
printf("\n sqrt((double) c)
%f ", sqrt((double) c));
printf("\n-------------------------------------");
}
/********************************************************/
Wydruk wyników:
Wartosci poczatkowe:
c = 'k'; i = 70; f = 345.6789;
------------------------------------Konwersja
Wynik
------------------------------------(int)
c
107
(float) c
107.000000
(double) i
70.000000
(char)
i
F
(double) i+2000
2070.000000
(int)
f
345
sqrt((double) c)
10.344080
-------------------------------------
Operator konwersji daje możliwośc doraźnego przekształcenia wartości zmiennej określonego
typu dla potrzeb bieżących bez naruszania rzeczywistej wartosci tej zmiennej. Argumentem
funckcji sqrt jest liczba typu double uzyskana do dokonaniu konwersji kodu
całkowitoliczbowego litery k
Wyciąg (skrócona wersja) ww. programu:
#include <stdio.h>
main()
{
char c='k';
int i=70;
printf("k= %d, i= %d\n",c,i);
printf("k= %c
%%d = %d
(int) c = %d\n",c,c,(int) c);
printf("i= %d
%%c = %c
(char) i = %c\n",i,i, (char) i);
getchar();
}
Wydruk:
k= 107, i= 70
k= k
%d = 107
(int) c = 107
i= 70
%c = F
(char) i = F
Operator warunkowy ?
Wyrażenie z użyciem operatora warunkowego:
Op1 ? Op2: Op3;
wyrażenie_warunkowe ? wyrażenie_na_tak: wyrażenie_na_nie;
Operator warunkowy (?:) pozwala zapisać w bardziej zwartej formie pewne konstrukcje
programowe wymagające użycia instrukcji if.
Np.
z = (a>b)? a:b; /* z=max(a,b) */
Równoważny zapis:
Dla C:
if (a>b) z=a; else z=b;
Dla Pascala:
if a>b then z:=a else z:=b;
W operatorze warunkowym operand Op1 musi być skalarem, zaś operatory Op2 i Op3 muszą
spełniać jedną z zasad:






oba są typu arytmetycznego
oba są zgodnymi strukturami lub uniami
oba są typu void
oba są wskaźnikami zgodnych typów
jeden jest wskaźnikiem, a drugi stałą oznaczającą adres pusty (NULL)
jeden jest wskaźnikiem obiektu lub niekompletnego typu a drugi typu void.
W pierwszej kolejności obliczna jest wartość Op1. Jeśli jest niezerowa (prawda), obliczana
jest wartość Op2, a Op3 ignorowane; w przeciwnym razie (Op1 = 0) obliczna jest wartość
Op3 a Op2 pomijane. Uzyskana wartość operandu Op2 lub Op3 staje się wartością wyrażenia
warunkowego.
Przykłady:
1) Typowe zastosowanie - funkcja max
/* C++ - Operator warunkowy - funkacja max */
#include <iostream.h>
void main()
{
int max(int, int);
int a, b, m;
char c;
cout << "Program wyznacza max 2 liczb\n";
cout << "Podaj 2 liczby calkowite oddzielone spacja: ";
cin >> a >> b;
m=max(a,b);
cout << "Max liczb " << a << " i " << b << " wynosi " << m;
cout << "\nNacisnij cos";
cin >> c;
}
int max(int i, int j)
{
return i > j? i: j;
}
Wynik:
Program wyznacza max 2 liczb
Podaj 2 liczby calkowite oddzielone spacja: 4 7
Max liczb 4 i 7 wynosi 7
Nacisnij cos
2) Użycie operatora warunkowego zamiast instrukcji warunkowej:
if (a<10)
d=b=20;
else
d=c=30;
To samo działanie z operatorem warunkowym:
d = a<10? b=20: c=30;
3) W przypadku większej liczby przypisań można użyć operatora warunkowego w połączeniu
z wyliczeniowym (przecinek), np.
if (a<10)
{
x=12; y=13;
}
else
{
a=1; x=14; y=15;
}
Można napisać:
a<10? x=12, y=13: a=1, x=14, y=15;
4) Przykład: Ustalenie ceny walca w zależności od objętości:
/*************************************************************/
/* Program p36.c
*/
/* Ustalenie ceny walca
( operator warunkowy )
*/
/*-----------------------------------------------------------*/
#include <stdio.h>
#define PI
/*
C1
C2
C3
3.1415926
- cena dla objetosci mniejszej od V1
- cena dla objetosci miedzy V1 a V2
- cena dla objetosci wiekszej od V2
*/
#define
#define
#define
#define
#define
V1
V2
C1
C2
C3
300.0
500.0
1000
2500
1200
main()
{
float promien, wysokosc, objetosc;
int
cena;
scanf("%f %f", &promien, &wysokosc);
objetosc = PI * promien * promien * wysokosc;
cena = (objetosc < V1) ? C1 : (objetosc > V2 ? C3 : C2 ) ;
printf("\nobjetosc=%6.2f, cena=%4i ",objetosc,cena);
}
/*************************************************************/
Wydruk:
1.22 3.50
objetosc= 16.37,
cena=1000
Operator przecinkowy/wyliczeniowy , (koma)
Wyrażenie wyliczeniowe ma postać:
Op1, Op2, ..., Opn
gdzie Opi, (i=1..n) są operandami dowolnych typów.
Opracowanie tego wyrażenia polega na obliczeniu wartości kolejnych operandów, począwszy
od Op1, a skończywszy na Opn. Typ i wartość całego wyrażenia określa operand Opn.
W C++ wynik wyrażenia wyliczeniowego jest l-wartością. Poprawne jest więc wyrażenie:
(a+=b, c-=d, c*=a)++.
Przykład:
int n=10, i=2, k=4, wynik;
wynik=(n-=i, k+=2, i*=5):
W wyniku obliczenia powyższego wyrażenia zmienne uzyskają następujące wartości:
n = n-i = 10-2=8
k = k+2 = 4+2=6
i = i*5 = 2*5=10 (ostatni operand)
wynik = wartość ostatniego operandu, czyli 10
Operator przecinkowy stosowany jest m.in. w instrukcjach for, np. do sterowania
równoległego 2 indeksami, a także w wywołaniach funkcji. Stosując wyrażenia wyliczeniowe
w wywołaniach funkcji należy pamiętać o użyciu nawiasów, np.:
func(i, (i+=k, k++), j); - funkcja otrzymuje tylko 3 parametry.
Przykład programu z operatorem przecinkowym:
/*************************************************************/
/* Program p37.c
*/
/*
( operator przecinkowy )
*/
/*-----------------------------------------------------------*/
#include <stdio.h>
#include <math.h>
main()
{
int
i, j;
printf("\n
i
j
sqrt(i)
sin(j)");
printf("\n----------------------------------- ");
for (i=0, j=10; j>=0; i++, j--)
printf("\n
%2i
%2i
%6.3f
%6.3f",i,j,
sqrt((double) i), sin((double) j) );
/* argument w
radianach */
printf("\n----------------------------------- ");
}
/*************************************************************/
Wydruk:
i
j
sqrt(i)
sin(j)
----------------------------------0
10
0.000
-0.544
1
9
1.000
0.412
2
8
1.414
0.989
3
7
1.732
0.657
4
6
2.000
-0.279
5
5
2.236
-0.959
6
4
2.449
-0.757
7
3
2.646
0.141
8
2
2.828
0.909
9
1
3.000
0.841
10
0
3.162
0.000
-----------------------------------
Operatory wskazywania
Operator adresu & i odwołania do zmiennej wskazywanej *


&Op - pobranie adresu l-wartości Op
*Op - odwołanie do zmiennej wskazywanej przez Op
Operator pobrania adresu &
W przypadku &Op - operand Op musi być identyfikatorem funkcji lub l-wartością, która nie
jest polem bitowym i nie została zadeklarowana ze specyfikatorem register (nie można pobrać
adresu zmiennej przechowywanej w rejestrze). Użycie operatora pobrania adresu w
odniesieniu do funkcji jest zbędne.
Operator odwołania do zmiennej wskazywanej * (operator adresowania pośredniego)
W wyrażeniu *Op, operand Op musi być wskaźnikiem. Wartością wyrażenia jest zmienna
wskazywana przez Op (czyli l-wartość), zaś jego typ zgodny z typem wskazywanym
operandu. Jeśli Op jest wskaźnikiem funkcji, wartość wyrażenia określa wskazywaną funkcję.
Wartość wyrażenia jest nieokreślona w 2 przypadkach:


wyrażenie Op zawiera adres pusty (NULL)
wyrażenie Op jest wskaźnikiem zmiennej automatycznej, zadeklarowanej w bloku,
którego wykonanie zostało już zakończone.
Przykład:
#include <stdio.h>
void main()
{
int i=10, *pi;
pi = &i;
printf("Adres pi=&i = %p
*pi=20;
printf("Adres pi=&i = %p
getchar();
}
*pi= %d
i= %d\n",pi, *pi, i);
*pi= %d
i= %d",pi, *pi, i);
Wydruk:
Adres pi=&i = 4A27:2222
Adres pi=&i = 4A27:2222
*pi= 10
*pi= 20
Przykład na operatory & i * oraz tablice
#include <stdio.h>
int main(void)
{
int tab[3], *ptr=tab;
int (*p)[]=&tab, i;
ptr[0]=5;
*(ptr+1)=10;
(*p)[2]=2;
for (i=0; i<3; i++)
printf("\nTab[%d]=%d",i,tab[i]);
return 0;
}
Wydruk:
Tab[0]=5
Tab[1]=10
Tab[2]=2
Przykład na operatory & i * z funkcjami
i= 10
i= 20
Wersja 1
#include <stdio.h>
int func(int i);
int main(void)
{
int (*pf1)(int)=func, (*pf2)(int);
// int i;
pf2=*pf1;
printf("%d\n",pf1(10));
printf("%d\n",(*pf2)(20));
return 0;
}
int func(int i)
{
return i*i;
}
Wersja 2 - z typedef
#include <stdio.h>
int func(int i);
typedef int (*PFUNC)(int);
void main(void)
{
PFUNC pf1=func, pf2;
pf2=*pf1;
printf("%d\n",pf1(10));
printf("%d\n",(*pf2)(20));
}
int func(int i)
{
return i*i;
}
Wydruk:
100
Operatory wyboru składowej . ->
W celu odwołania się do skłądowych struktury, unii lub klasy (w C++) należy posłużyć się
jednym z operatorów wyboru skłądowej:
Op.identyfikator_składowej
Op->identyfikator_składowej
Operator . (kropka) umożliwia odwołanie do składowej struktury, unii lub klasy (C++)
określonej przez operand Op, operator -> (minus, większe) zaś odwołanie do skłądowej
struktury, unii lub klasy (C++) wskazywanej przez operand Op.
Wartość i typ wyrażenia są określone typem i wartością składowej, do której nastąpiło
odwołanie. Wartość wyrazeń jest l-wartością, jeśli l-wartością jest operand Op.
Przykład:
#include <iostream.h>
struct PUNKT
{
double x,y;
};
void main()
{
struct PUNKT P, *pPt;
P.x=P.y=10.5;
cout << "P.x= " << P.x << " P.y=" << P.y << '\n';
pPt= &P;
pPt->x=12.5;
pPt->y=13.5;
cout << "P.x= " << P.x << " P.y=" << P.y << '\n';
cout << "pPt->x=" << pPt->x << " pPty->y=" << pPt->y;
}
Wydruk:
P.x= 10.5 P.y=10.5
P.x= 12.5 P.y=13.5
pPt->x=12.5 pPty->y=13.5
W językach tych powstają aplikacje dla różnych systemów operacyjnych, w tym m.in. dla Windows,
Unix, Linux, MacOS, BeoS.
Do pisania programów można wykorzystywad edytory narzędzi programistycznych jak:
Borlanda: Turbo C, Borland C, Borland C++ Builder
Microsoft Visual C++,
Dev C++, CodeBlocks
Można użyd dowolnego edytora tekstowego zapisującego pliki w postaci czystego kodu ASCII, typu
Notatnik, Edit lub np. Notepad, który pozwala sprawdzad składnię i podkolorowuje odpowiednio
tekst po wybraniu języka.
Do kompilacji można użyd środowiska programistycznego Borland C++ Compiler 5.5.
Kompilator ten jest darmowy, generuje 32-bitowy kod dla Windows, zawiera tylko niezbędne
narzędzia uruchamiane z linii poleceo, jest prosty w instalacji i konfiguracji.
Najlepiej zainstalowad w C:\BCC55. W katalogu tym są podkatalogi: BIN, INCLUDE, LIB, HELP,
EXAMPLES.
Pliki konfiguracyjne w katalogu C:\BCC55\BIN
Zawartośd plików
Plik BCC32.cfg
-I"c:\Bcc55\include"
-L"c:\Bcc55\lib"
Plik ILINK32.cfg - składa się z jednej linii
-L"c:\Bcc55\lib"
Można też dodad katalog C:\BCC%%\BIN do ścieżki wyszukiwania – dopisad w wierszu poleceo
PATH=%PATH%;C:\BCC55\BIN
Kompilacja programów przy pomocy BCC32:
Bcc32 program.c lub bcc32 program cpp
Program Turbo C – TC.EXE, kompilator TCC.exe
-IC:\TC\INCLUDE
-LC:\TC\LIB
Objaśnienia:
Instrukcja #include poleca kompilatorowi dołączyć do programu plik stdio.h (tzw.
pseudonagłówkowy),
w którym zawarta jest m.in. definicja funkcji printf.
Bardzo często używa się też innych plików pseudonagłówkowych, np. conio.h, math.h itp.
Wszystkie pliki *.h zawarte w nawiasach <> znajdują się w podkatalogu INCLUDE.
Druga linijka z main zawiera rozpoczęcie funkcji głównej programu czyli main().
Nagłówek void main() to inaczej void main(void)
void przed mian oznacza, że funkcja nie zwraca żadnego wyniku. (void )w nawiasie po main oznacza
brak parametrów programu.
Deklaracja funkcji main może mieć inne formy, np.
int main() - funkcja w wyniku swojego działania zwróci wartość typu int i nie pobiera żadnych
parametrów przy rozpoczęciu działania.
int main(void) - inny zapis, ale znaczenie takie samo jak wyżej
main() - jeszcze inny zapis, ale znaczenie takie samo jak wyżej
float main() - w tym przypadku wynikiem działania funkcji będzie typ float.
int main(int argc, char *argv[])
Po linii z main zaczyna się nawiasem klamrowym otwierającym {
ciało (treść) funkcji głównej i kończy na końcu nawiasem zamykającym }
Wewnątrz funkcji głównej jest instrukcja printf, powodująca wyświetlenie na ekranie tekstu,
będącego jej parametrem (tekst w nawiasach w cudzysłowie).
Instrukcje kończymy średnikiem.
Po skompilowaniu czarny ekran i zaraz znika i dlatego trzeba dokonać modyfikacji programu.
Uruchamiamy edytor Edit lub notatnik, zapisujemy plik pod inną nazwą, np. p1a.c i modyfikujemy
// program p1a.c
// to jest komentarz w jednej linii
/* to jest też komentarz, może mied kilka linii, dłuższy, ograniczony */
#include <stdio.h> // dołączenie pliku nagłówkowego z biblioteki systemowej
// potrzebny do wywołania instrukcji printf
#include <conio.h>
// dołączenie pliku conio.h do funkcji getch() i clrscr()
int main()
//funkcja główna main
{ // początek main
clrscr();
// kasowanie ekranu
printf("Nazwisko Imie: Pierwszy program w C – zmodyfikowany ");
printf("\nNacisnij jakis klawisz ");
getch();
// czeka na jakiś klawisz
return 0;
// funkcja główna zwraca 0 przy pomyślnym wyniku zakooczenia
}
// koniec funkcji głównej main
Kompilacja: BCC32 p1a.c – w wyniku program skompilowany p1a.exe
Po uruchomieniu: p1a
W programie wprowadzono funkcje clrscr() – kasowanie ekranu oraz getch() – program czeka na
naciśnięcie dowolnego klawisza. Definicje tych funkcji są w pliku conio.h, dlatego jest on dopisany w
dyrektywie #include <conio.h>/
Zamiast getch() , można zastosowad getchar() lub while(!kbhit())
\n to znak specjalny – powoduje przejście do nowej linii.
Podobnie \t – tabulacja, \a – sygnał dźwiękowy.
Komentarze – oznaczone // - jednolinijkowy
oraz oznaczone /* komentarz */ - dłuższe, mogą zawierad wiele linii
Kompilator nie czyta komentarzy, stosuje się dla wyjaśnienia programu.
Podsumowanie
// program p1d.c
#include <stdio.h>
#include <conio.h>
int main()
{
clrscr();
printf("Program p1d.c - podsumowanie\n");
printf("\nProgramy w C i C++ maja rozszerzenie c oraz cpp\n");
printf("Na poczatku programu #include i pliki z definicjami instrukcji\n");
printf("np. #include <stdio.h> do funkcji printf(), conio.h do clrscr()\n");
printf("\nDeklarujemy funkcje main(), np. int main() \n");
printf("Cialo funkcji main() jest w nawiasach { }\n");
printf("W ciele funkcji glownej wypisujemy wszystkie instrukcje (zakonczone srednikiem) \n");
printf("Mamy 2 rodzaje komentarzy: // - jednoliniowy oraz /* wieloliniowy */\n");
printf("\nAby zatrzymac pracc programu, uzywamy funkcji getch(); lub getchar(); \n");
printf("Do czyszczenia ekranu szuzy funkcja clrscr();. \n");
printf("Na koncu funkcji main jest return 0; - co funkcja zwraca\n");
printf("W programie mozemy uzywac tzw. znakow specjalnych, np. \\n - nowa linia. \n");
printf("\nNacisnij cos ");
getchar();
return 0;
TYPY ZMIENNYCH I WZORCE KONWERSJI
Zmienne służą do tego, aby zapamiętać sobie tymczasową wartość (którą potem można zmienić w
każdej chwili według potrzeby).
Typy zmiennych:







char - typ znakowy
int - liczba całkowita
float - liczba zmiennoprzecinkowa (rzeczywista)
short - liczby całkowite krótkie
long - liczby całkowite długie
double - liczby zmiennoprzecinkowe podwójnej precyzji
long double - liczby zmiennoprzecinkowe podwójnej precyzji długie
Operatory
Operacje arytmetyczne przypominają konwencjonalny matematyczny zapis. Również kolejność
działań jest identyczna jak w matematyce.
Najczęściej używane operatory:
+, -, *, /, =
%
++, -!
<, >
<=, >=
dodawanie, odejmowanie, mnożenie, dzielenie, operator przypisania
reszta z dzielenia (odpowiada operacji modulo)
inkrementacja i dekrementacja
negacja
mniejsze, większe
nie większe, nie mniejsze
&&, ||
==
+=, -=, *=, /=
i, lub (logicznie)
równe
połączenie operatorów przypisania i innych
Inkrementacja jest to proces zwiększenia zmiennej o 1,
a dekrementacja zmniejszenia o 1.
Zmienną a możemy inkrementować na dwa sposoby:
a=a+1;
a++;
- sposób tradycyjny
- sposób krótszy, w języku C/C++
Język C/C++ Sposób tradycyjny (też w C/C++)
a+=10;
a=a+10;
b-=30;
b=b-30;
a*=20;
a=a*20;
b/=5;
b=b/5;
Programy przy zastosowaniu typów zmiennych i operacji matematycznych. możemy zabrać się za
pisanie następnego programu.
Najprostszym przykładem użycia zmiennych jest prosty kalkulator.
Program, który poprosi nas o wpisanie dwóch liczb i wykona na nich podstawowe działania
matematyczne: zsumuje je, odejmie, pomnoży i podzieli.
Na początku program musi wczytać dwie liczby:
//Program p2a.c
// Wczytuje 2 liczby całkowite I wyświetla na ekranie
#include <stdio.h>
#include <conio.h>
Int main ()
{
int a,b; //deklaracja zmiennych a i b
clrscr();
printf("Podaj liczbe a: ");
scanf("%d",&a); // wczytanie liczby a
printf("Podaj liczbe b: ");
scanf("%d",&b); // wczytanie liczby b
printf("Wpisane liczby a i b : %d, %d.\n",a,b);
printf("\nNacisnij Enter ");
getch(); // czekanie na Enter
return 0 ;
}
Typ int (integer) oznacza, że zmienna może przyjmować wartości całkowite z zakresu +/- 32767.
Jeżeli zamierzamy używać w programie dużych liczb wtedy zamiast typu int używamy typu long.
Kompilator już wie, że w kodzie programu będą pojawiać się zmienne a i b i wie ile pamięci musi
zarezerwować na ich przechowanie.
Następnie wypisujemy na ekranie komunikat, który prosi nas o wpisanie liczby.
Program zatrzyma się w tym miejscu i będzie czekał dotąd, aż napiszemy liczbę i zatwierdzimy je
ENTERem.
Funkcja scanf() służy do odczytu wprowadzonych danych z klawiatury
Wzorzec konwersji określa typ zmiennej, którą wpiszemy z klawiatury lub wypiszemy na ekranie.
Poniższa tabela przedstawia deklaracje zmiennych określonego typu, odpowiednie dla nich wzorce
konwersji oraz przykłady ich użycia:
Deklaracja Wzorzec Postać funkcji scanf() Postać funkcji printf()
printf("Liczba A wynosi:
liczba całkowita int A
%d
scanf("%d",&A);
%d",A);
liczba
printf("Liczba B wynosi:
float B
%f
scanf("%f",&B);
%f",B);
rzeczywista
Typ zmiennej
ciąg znaków
char *C
pojedynczy znak char D
%s
scanf("%s",&C);
printf("Łańcuch ma postać:
%s",C);
%c
scanf("%c",&D);
printf("Znak D to: %c",D);
Program zmodyfikowany, wykonujacy podstawowe obliczenia matematyczne
//Program p2b.c
#include <stdio.h>
#include <conio.h>
int main()
{
int a,b; //deklaracja zmiennych całkowitych a i b
int suma,roznica,iloczyn;
float iloraz;
clrscr();
printf("Prosty kalkulator\n");
printf("\nPodaj liczbe a: ");
scanf("%d",&a);
printf("Podaj liczbe b: ");
scanf("%d",&b);
suma=a+b;
roznica=a-b;
iloczyn=a*b;
iloraz=(float)a/(float)b; // operator rzutowania w dzieleniu
printf("\nWyniki dzialan:\n");
printf("\nSuma:
%d ",suma);
printf("\nRoznica: %d ",roznica);
printf("\nIloczyn: %d ",iloczyn);
printf("\nIloraz: %f ",iloraz);
getch();
return 0 ;
}

Podobne dokumenty