Get the Flash Player to see this player.

time2online Joomla Extensions: Simple Video Flash Player Module
Ściąga dla C

W tym artykule postaram się wypisać najważniejsze typy zmiennych, instrukcję warunkowe, pętle i inne ważne funkcje, które przydają się każdemu programiście. Dobrym kursem jest:
https://www.youtube.com/playlist?list=PL_k1YAvuKxVhkY2q5A-_a6niBWRR0_oz7
Oraz mój kurs z wybranymi najważniejszymi rzeczami pod mikroprocesory:
https://www.youtube.com/playlist?list=PLZQKTfr7_vvT7q8fuKLAJn_QN11ffyR3b

Typy zmiennych


int, Liczby całkowite, 4 bajty,
od -2 147 483 648 do 2 147 483 647
float, Liczby rzeczywiste pojedynczej precyzji, 4 bajty,
od 1.5 · 10-45 do 3.4 · 1038
double
Liczby rzeczywiste podwójnej precyzji, 8 bajtów,
od 5.0 · 10-324 do 3.4 · 10308
char Zazwyczaj pojedyncza litera (pojedynczy bajt), 1 bajt,
od -128 do 127
short int Krótsze liczby całkowite niż int, 2 bajty,
od -32 768 do 32 767
long int Dłuższe liczby całkowite niż int, 4 bajty,
od -2 147 483 648 do 2 147 483 647
long long int Bardzo duże liczby całkowite, 8 bajtów,
od -9 223 372 036 854 775 808 do 9 223 372 036 854 775 807
long double Dłuższe liczby rzeczywiste niż double, 12 bajtów,
od 1.9 · 10-4951 do 1.1 · 104932

Każdy typ zmiennych może mieć przedrostek:
• signed – Przedrostek umożliwiający definicję liczb dodatnich oraz ujemnych (standardowo)
• unsigned – Przedrostek umożliwiający definicję liczb tylko dodatnich oraz zera.

Dla przykładu:
unsigned char - 1 bajt, od 0 do 255

Gdy zmienna ma przedrostek const, to jest to zmienna tylko do odczytu. Taką zmienną nie można nadpisywać w programie.

Przypisywanie wartości do zmiennych

Liczby można zapisać w różnych systemach:

Liczba 10.4. Stała zmiennopozycyjna zawierająca kropkę dziesiętną

a=10.4 

Stała zmiennopozycyjna zawierająca wykładnik. Liczba 10.4

a=104E-1 

Liczba 0.00124. Stała zmiennopozycyjna zawierająca kropkę dziesiętną oraz wykładnik.

a=1.24E-3

Liczba 100000. Stała całkowita dziesiętna z wykładnikiem.

a=10E+5 

Liczba 1000. Stała całkowita zapisana w systemie ósemkowym (zero na początku).

a=01750 

Liczba 1000. Stała całkowita zapisana w systemie szesnastkowym (0x, lub OX na początku).

a=0x3E8 

Liczba 3. Stała całkowita zapisana w systemie binarnym(0b).

a=0b00000011 

Operatory

Operatory stosuje się w działaniach na zmiennych. W języku C mam następujące operatory:

+ Dodawanie
- Odejmowanie
* Mnożenie
/ Dzielenie
% Dzielenie modulo (reszta z dzielenia)

Dla przykładu jeśli chcemy dodać dwie liczby to używamy operatora +:

suma=a+b;

Operatory Logiczne

Operatory logiczne to takie, które w wyniku dają nam prawdę lub fałsz. W języku C mam następujące operatory:

> Większy niż
>= Większy lub równy niż
< Mniejszy niż
<= Mniejszy lub równy niż
== Równy
!= Różny

&& Logiczne „i”
|| Logiczne „lub”

Te operatory stosujemy w zapytaniach warunkowych. np w instrukcji if, while, switch. Dla przykładu:


if (a >= min && a <= max) {
printf("Liczba a (%d) zawiera sie w przedziale pomiędzi min i max: ", a);
}

Operatory Zmniejszenia i Zwiększenia, oraz operatory przypisania

Zwiększenia:

n++ Post – inkrementacja
++n Pre – inkrementacja

Zmniejszenia:

n-- Post – dekrementacja
--n Pre – dekrementacja

Dla przykładu jeśli przypiszemy:

a=n++

to wartość a będzie zawierała starą wartość zmiennej n. Dopiero gdy użyjemy a, to zmienna zostanie zwiększona o 1.

Przypisania:

+, -, *, /, %, <<, >>, &, ^, |

np: n += 3.

Wyrażenie, które ma postać n = n + 3 można zapisać w krótszej postaci za pomocą operatora przypisania, definiowanego jako n += 3.

Operatory Bitowe

& Bitowa koniunkcja (AND)
| Bitowa alternatywa (OR)
^ Bitowa różnica symetryczna (XOR)
<< Przesunięcie w lewo
>> Przesunięcie w prawo
~ Dopełnienie jedynkowe

Dla przykładu:

a=0b00000101; //liczba 5
b=0b00000100; //liczba 4
c=a&b;
// w wyniku otrzymamy c = 00000100, czyli liczbę 4;

Funkcje matematyczne

Aby korzystać z funkcji trygonometrycznych, należy dodać bibliotekę math.h

sin(x) - Sinus
cos(x) - Cosinus
tan(x) - Tangens
asin(x) -
Arcus sinus y∈〈−π/2;π/2〉 , x∈〈−1;1〉
acos(x) - Arcus cosinus y∈〈0 ;π 〉 , x∈〈−1;1〉
atan(x) -
Arcus tangensy∈〈−π/2;π/2〉
atan2(y,x) -
Arcus tangens tan(−1) (y/x) ∈〈−π ; π〉
sinh(x) -
Sinus hiperboliczny
cosh(x) - Cosinus hiperboliczny
tanh(x) - Tangens hiperboliczny
exp(x) - Funkcja wykładnicza e x
log(x) - Logarytm naturalny ln(x) , x>0
log10(x) -
Logarytm o podstawie 10, log10(x) , x>0
pow(x,y) -
Potęgowanie x y
sqrt(x) -
Pierwiastkowanie x>=0
ceil(x) -
Najmniejsza liczba całkowita, Nie mniejsza niż x – wynik typu double
floor(x)
- Największa liczba całkowita, Nie większa niż x – wynik typu double
abs(x) -
Wartość bezwzględna, ∣x∣

Instrukcje warunkowe

Instrukcja IF:

if (wyrazenie)
 akcje1
else
 akcje2

wyrażenie musi dawać wartości true lub false i z reguły w tych wyrażeniach stosuje się operatory logiczne. Najprostszy program wygląda następująco:

#include <stdio.h>
main ()
{
int a = 3;
int b = 8;
if (a >= b)
 printf("a wieksze lub rowne b\n");
else
 printf("a mniejsze lub rowne b\n");
}

operator ?:

wyrazenie1 ? akcja1 : akcja2

Operator ten działa w sposób następujący, sprawdzane jest wyrazenie1 i jeśli jest prawdziwe (różne od zera), to wykonana jest akcja1 i ono staje się wartością całego wyrażenia. W przeciwnym wypadku wykonana jest akcja2 i ono jest wartością całego wyrażenia.

Dla przykładu:

#include <stdio.h>
main ()
{
int a = 3, z;
z = (a > 5) ? 5 : (a + 6);
printf("%d\n", z); // 9
}

Instrukcja Switch:

switch (wyrazenie)
{
case wyrazenie1: akcje1;
case wyrazenie2: akcje2;
default: akcje3;
}

Dla przykładu:

switch (n)
{
case 1: printf("Wybrales 1 \n");
 break;
case 2: printf("Wybrales 2 \n");
 break;
case 3: printf("Wybrales 3 \n");
 break;
default: printf("Nie ma takiego dnia\n");
break;
}

Zasada działania jest następująca. Gdy zamiast 'n' wpiszemy liczbę 2, to program będzie sprawdzał kolejne przypadki (case'y), gdy napotka na case == 1, to zostanie wywołany napis "Wybrales 2", a instrukcja break przerwie dalsze sprawdzanie.

Pętle

Pętla FOR:

for (wyrazenie1; wyrazenie2; wyrazenie3)
 akcje

Dla przykładu:

for (i = 0; i <= 12; i++){
 printf("%d ", i);
}
//program wypisze liczby od 0 do 12

Aby uzyskać pętle nieskończoną, należy wykonać następujący kod:

for (;;)
{
 ...
}

Pętlę taką można przerwać za pomocą instrukcji break, oraz return.

Pętla While:

while (warunek)
akcje

Pętla while sprawdza najpierw warunek, a dopiero potem wykonuje akcję.
Dla przykładu:

a=0;
while (a<=5)
{
 printf("%d ", a);
 a++;
}
//kod będzie wię wykonywał dopóki a jest mniejsze od 5

Pętla Do - While:

do
akcje
while (warunek)

Ta pętla najpierw wykonuje kod, a dopiero później sprawdza warunek.

Instrukcje typowe dla pętli:

break - Użycie break w pętlach for, while, do–while  spowoduje natychmiastowe przerwanie pętli i spowoduje przejście do kolejnej (jeśli występują) instrukcji poza pętlą.

continue - Instrukcja continue przerywa aktualnie wykonywaną iterację. Wszystkie akcje pod instrukcją continue są ignorowane. Po wykonaniu instrukcji continue w przypadku pętli "for" zwiększany jest licznik zmiennej sterującej, a w przypadku pętli while oraz do–while sprawdzany jest warunek.

goto - W języku C występuje instrukcja goto, która to w miejscu wywołania robi bezwarunkowy skok do miejsca oznaczonego konkretną etykietą. Składnia tej instrukcji jest następująca.

goto nazwa_etykiety;
 nazwa_etykiety: akcje

#include <stdio.h>
main ()
{
int i = 0;
start: 
 if (i >= 10)
 goto stop;
 else
 {
 printf("%d\n", i);
 goto zwieksz;
 }
zwieksz: 
 i++;
 goto start;
stop: 
 printf("Koniec\n");
}

Tworzenie Funkcji

Funkcje w C wyglądają następująco:

typ_zwracanej_wartosci nazwa_funkcji (parametry funkcji )
{
 cialo funkcji
}

Standardowa funkcja największy wspólny dzielnik wyglądałaby tak:

#include <stdio.h>
int nwd (int liczba1, int liczba2);
main ()
{
 printf("NWD(%d, %d) = %d\n", 10, 14, nwd(10, 14));
 return 0;
}
int nwd (int liczba1, int liczba2)
{
int c;
while (liczba2 != 0)
{
c = liczba1 % liczba2;
liczba1 = liczba2;
liczba2 = c;
}
return liczba1;
}

analogicznie gdy chcemy zwrócić wartość rzeczywistą, to używamy zamiast int double, a gdy nie chcemy zwracać żadnej wartości to używamy void.

Kompilacja Warunkowa

Kompilacja warunkowa sprawdza pewne parametry przy kompilacji i w zależności od tych parametrów kompiluje program. Taką konstrukcję można często spotkać w bibliotekach dla mikrokontrolerów. Wiadomo, że peryferia dla procesora Atmega8 i dla procesora Atmega16 będą na innej nóżce, ale sam program będzie identyczny dla obu procesorów. W takim przypadku należy podczas kompilacji podmienić numer nóżki i wszystko będzie działało.

Poniżej przedstawiłem przykład:

#include <stdio.h>
#if KONTROLA == 1
double z2 = 10.0;
#elif KONTROLA == 2
double z2 = 15.0;
#elif KONTROLA == 3
double z2 = 20.0;
#else
#define X
#endif
main (void)
{
#if !defined(X)
printf("%.1f\n", z2);
#endif
return 0;
}

Podczas kompilacji należy uwzględnić te parametry np. tak:

$ gcc nazwa_pliku.c -o nazwa_pliku -D KONTROLA=2

Słowa kluczowe

extern - używane jest do powiadomienia kompilatora o tym, iż używana będzie zmienna globalna, która nie jest zadeklarowana w pliku z którego będziemy się do niej odwoływać lub zmienna używana w funkcji jest zadeklarowana później.

static - Zmienne statyczne można definiować zarówno globalnie jak i lokalnie. Różnica między statyczną, a zwykłą zmienną globalną jest taka, że statyczne zmienne globalne mają zasięg od miejsca wystąpienia do końca kompilowanego pliku. Czyli jeśli umieścimy pewną zmienną w innym pliku, to będzie ona dostępna tylko dla funkcji znajdujących się w tamtym pliku. Użycie extern nic nie pomoże, do zmiennej nie będziemy mogli się odwołać. Jest to metoda na ukrycie zmiennych przed innymi
funkcjami, które nie potrzebują mieć do niej dostępu. Zmienne statyczne mogą mieć taką samą nazwę jak inne zmienne globalne i nie będzie to kolidować pod warunkiem, że definicje tych dwóch zmiennych nie występują w jednym pliku.

Tablice i Wskaźniki

Tablice jednowymiarowe:

Zadeklarować tablicę można w następujący sposób:

int tab[5];
double axp[7];
int mpx[] = {3, 7, 9, 11};
double kxx[10] = {13.3, 19.0, 19.9, 192.4};

tablice podczas kompilowania muszą mieć określoną długość i jest to warunkiem koniecznym. Jeśli chcemy zadeklarować tablicę o zmiennej długości, to musimy skorzystać z wskaźników.

Zadeklarowanie i wyświetlenie 5 liczb zaprezentowałem poniżej:

#include <stdio.h>
main (void)
{
 int tab[5] = {10, 15, 20, 145, 43};
 int i;
 for (i = 0; i < 5; i++)
 printf("tab[%d] = %d\n", i, tab[i]);
 return 0;
}

Tablice wielowymiarowe:

Deklaracja takiej tablicy jest podobna:

#include <stdio.h>
#define MAX 3
main (void)
{
double tab[MAX][MAX] = {
{0.0, 0.1, 0.2},
{1.0, 1.1, 1.2},
{2.0, 2.1, 2.2},
};
int i, j;
for (i = 0; i < MAX; i++)
 for (j = 0; j < MAX; j++)
 printf("%.1f%c", tab[i][j], (j == MAX - 1) ? '\n' : '\t');
return 0;
}

Wskaźniki:

Wskaźniki są to adresy komórek pamięci. Dzięki wskaźnikom możemy zapisywać zmienne w określony obszar pamięci i tworzyć tablice o zmiennej długości. Wskaźnik możemy zadeklarować w następujący sposób:

int *wsk_i; // wskaznik na typ int
double* wsk_d; // wskaznik na typ double
char * wsk_i; // wskaznik na typ char

W ten sposób zostanie przydzielone miejsce w pamięci o określonym adresie. Aby dostać adres tej komórki wystarczy wyświetlić tę zmienną bez żadnego znaczka:

printf(wsk_i);

Jeśli chcemy wyświetlić wartość, która kryję się pod określonym adresem, to należy użyć operatora wyłuskania, czyli gwiazdki *wsk_i:

printf(*wsk_i);

Jeśli mamy zadeklarowaną zwykłą zmienną int x=5; , to także możemy uzyskać jej adres w pamięci poprzez operator &x:

printf(&x);

Ten adres można przypisywać do wskaźników, ale trzeba sobie zdawać sprawę z konsekwencji płynących z takiego przypisania. W takim przypadku modyfikacja wartości pod tym adresem, będzie miała miejsce dla wszystkich zmienny wskazujących na ten adres.

Znaki specjalne w ASCII

\a Dźwięk (alarm)
\b Backspace
\f Wysunięcie strony
\n Nowa linia
\r Powrót karetki (ang. carriage return)
\t Tabulacja pozioma
\v Tabulacja pionowa
\' Apostrof
\” Cudzysłów
\\ Ukośnik
\? Znak zapytania
\ooo Znak ASCII podany jako liczba ósemkowa
\xhh Znak ASCII podany jako liczba szesnastkowa

Wyświetlanie danych

Do wyświetlania danych używa się funkcji printf(). Dzięki tej funkcji dane wyświetlone są na standardowe urządzenie wyjścia, czyli monitor. Funkcja ma postać:

int printf (char *format, arg1, arg2, ...)

Podobna funkcją jest funkcja sprintf(), lecz w tym przypadku dane nie zostaną wyświetlone na monitorze, ale zostaną zapisane do tablicy. Funkcja ma postać:

int sprintf(char *string, char *format, arg1, arg2, ...);

Poniższy przykład pokazuje zastosowanie dwóch funkcji. Najpierw zostają zapisane dane do tablicy tab za pomocą sprintf, a następnie wyświetlone na monitor za pomocą printf:

#include <stdio.h>
int main (void)
{
 char tab[40];
 int liczba = 10;
 sprintf(tab, "Wyświetlanie liczby: %d ", &liczba);
 printf("%s\n", tab);
 return 0;
}

Widzimy, że zmienne wstawiane są w pola po znaku %. Jest to deskryptor formatu, który mówi kompilatorowi jakiego typu zmienne ma wyświetlać. Do dyspozycji mamy kilka możliwości, dla różnych typów zmiennych:

d, i int Liczba dziesiętna
o int Liczba ósemkowa bez znaku, bez wiodącego zera
x, X int Liczba szesnastkowa bez znaku, bez wiodących 0x, 0X
u int Liczba dziesiętna bez znaku (unsigned)
c int Jeden znak
s char * Ciąg znaków wyświetlany aż do znaku kończącego \0, lub przekroczenie liczby określonej przez precyzję
f double [-]m.dddddd, ilość d określa precyzja, domyślnie 6
e, E double [-]m.dddddde±xx, [-]m.ddddddE±xx
g, G double Liczba wypisana w formacie %e, %E jeśli wykładnik jest mniejszy niż -4 albo większy lub równy precyzji, w przeciwnym wypadku liczba wypisana w formacie %f
p void * Wskaźnik
% - Wypisanie po prostu znaku %

Możemy także wyświetlić dane o określonej precyzji, wyrównać do lewej itp, za pomocą operatorów określonych operatorów wstawianych bezpośrednio za znakiem %. Do dyspozycji mamy następujące operatory:

• – (minus) – Wyrównanie argumentu do lewej strony jego pola
• Liczba określająca minimalny rozmiar pola
• . (kropka) – Oddzielająca rozmiar pola od precyzji
• Prezycja
◦ Maksymalna liczba znaków dla tekstu
◦ Liczba cyfr po kropce dzisiętnej dla liczb rzeczywistych
◦ Minimalna liczba cyfr dla wartości całkowitej
• Jedna z liter: h – jeśli argument całkowity należy wypisać jako short, lub l – jeśli long

Można je użyć np. tak:

printf("%.2e %.10g %.7f %p %%\n", xx, xx, xx, &pi);

Pobieranie danych z klawiatury

Funkcja scanf() pobiera dane z klawiatury. Funkcja ma postać:

int scanf (char *format, arg1, arg2, ...);

Format danych określa się za pomocą operatorów formatowania:

d dla typu int * Liczba całkowita dziesiętna
i dla typu int * Liczba całkowita; może wystąpić w postaci ósemkowej z wiodącym zerem, lub szesnastkowej z wiądącymi 0x, 0X
o dla typu int * Liczba całkowita w postaci ósemkowej z wiodącym zerem lub bez
u dla typu unsigned int * Liczba całkowita dziesiętna bez znaku
x dla typu int * Liczba całkowita w postaci szesnastkowej z wiodącym 0x, 0X lub bez
c dla typu char * Znak
s dla typu char * Tekst
e, f, g dla typu float *Liczba zmiennopozycyjna z opcjonalnym znakiem, opcjonalną kropką dziesiętną i opcjonalnym wykładnikiem
%
- Znak %, nie ma żadnego przypisania

Przykład użycia macie poniżej:

#include <stdio.h>
int main (void)
{
 int x;
 double y;
 printf("Podaj liczbe calkowita: ");
 scanf("%d", &x);
 printf("Podaj liczbe rzeczywista: ");
 scanf("%lf", &y);
 printf("%d %.3f\n", x, y);
 return 0;
}

Funkcja scanf() zapisuje wartości bezpośrednio w pamięci i czasem takie zachowanie prowadzi do nieoczekiwanego działania. Bardziej rozbudowaną funkcją jest funkcja sscanf(), która ma z góry określony typ zmiennych i ma postać:

int sscanf (char *string, char *format, arg1, arg2, ...);