JĘZYKI I METODYKA PROGRAMOWANIA
Podstawy kompilacji programu napisanego w języku C w środowisku UNIX
Temat: Kompilacja GCC, podstawy języka C
GCC – to polecenie służące do kompilacji plików. Aby skompilować kod języka C za pomocą kompilatora GCC, napisany wcześniej w edytorze tekstu (pico), należy użyć polecenia wraz z nazwą pliku. Np.:
W rezultacie otrzymamy plik z domyślną nazwą a.out, który możemy otworzyć w taki sposób:
Używając tej metody, w przypadku, gdy w danym katalogu będziemy chcieli skompilować kilka plików z kodem, zostaną one nadpisane i otrzymamy jeden plik wyjściowy. Aby temu zapobiec możemy użyć polecenia wraz z parametrem –o – co umożliwia nam nadanie własnej nazwy plikowi wyjściowemu.
Który otwieramy w ten sam sposób:
W przypadku, gdy chcemy skompilować program, w którym będziemy korzystać z funkcji matematycznych, musimy dołączyć bibliotekę, w której będą one zdefiniowane. Można to zrobić dodając do wcześniejszego polecenia parametr –lm.
1. Pętla do…while
Program 1(2_do_while_1)
#include
<stdio.h> main() { int
i = 10; do{
printf("Hello %d\n", i ); i
= i -1; }while
( i > 0 ); }
Przepisuję program do edytora Pico i kompiluje za pomocą komendy gcc.
Jak widać program wypisał 10 razy słowo „Hello” z odpowiednim numerem, począwszy od 10 do 1.
P
int
i=10; do{
printf("Hello %d\n", i ); i
= i -1; }while
( i > 0 );}
Pętla:
Zadeklarowana
została na początku wartość i=10.
Pętla wykonuję polecenie
printf("Hello
%d\n", i ); wyświetla
słowo Hello oraz liczbę całkowitą (%d), która jest wartością
zmiennej x.
Zastosowano też \n,
aby każdy kolejny raz był wypisywany
w nowym wierszu. Po
wykonaniu polecenia printf
program zmniejsza wartość i o 1
(
i = i -1).
Następnie
mamy while
( i > 0 ); wg
którego pętla wykonuje się dopóki i jest większe od 0. Wykonuje
się więc 10 razy.
Program 2 (2_do_while_1a)
#include
<stdio.h> /*
Try
following example to understand do...while loop.
You
can put the following code
into
a test.c file and then compile it and then run it. You
can make use of break to come out of for loop at any time. */ main() { int
i = 10; do{
printf("Hello %d\n", i ); i
= i -1; if( i == 6 ) { break; } }while ( i >
0 ); }
Przepisuję program do edytora Pico i kompiluje za pomocą komendy gcc.
Jak widać w odróżnieniu do programu poprzedniego, słowo Hello zostało wypisane tylko 4 razy. Do wartości 7.
W
int
i = 10; do{
printf("Hello %d\n", i ); i
= i -1; if(
i == 6 ) { break; } }while ( i >
0 ); }
Widać
wyraźnie, że program 2 jest modyfikacją programu 1, jednak z
dodanym fragmentem kodu zaznaczonym przeze mnie na zielono.
Instrukcja warunkowa
if(i==6)
{break;}
dla i=6 przerywa wykonywanie pętli do…while. Stąd po wykonaniu
programu widzimy, że ostatnim wypisanym wierszem jest Hello z
numerem 7.
P
#include <stdio.h> #define M 1000 /* makrodefinicja
(preprocesora)*/ /* TO JEST TYLKO ZASTAPIENIE JEDNEGO
NAPISU INNYM! */ int main() { int T[M], a,
i, n, ret; i = 0; do { ret =
scanf(" %d",&a); /* w zmiennej ret bedzie 1,
jezeli poprawnie przeczytamy liczbe */ if (ret!=1) break; /* ret==1 -> liczba
przeczytana */ T[i] = a; i++; } while (i < M);
n = i; printf("%d\n",n);/*
ilosc elementow wcytanych */ for(i=n-1;i>=0;i=i-1/*i--*/)
printf("T[%d]=%d\n",i,T[i]); return 0; }
Kompiluję i wykonuję program.
Na samym początku kodu zmienna M została zadeklarowana makrodefinicją preprocesora #define M 1000.
Program tworzy tablicę o rozmiarze M ze wpisanych przez użytkownika wartości, a następnie wyświetla liczbę wpisanych elementów oraz wszystkie elementy tablicy po kolei. Program składa się z dwóch pętli: do…while oraz for.
P
int T[M], a, i,
n, ret; i = 0; do { ret =
scanf(" %d",&a); if (ret!=1)
break; T[i] = a; i++; } while (i < M);
Na początku zadeklarowana jest tablica T[M] oraz zmienne. Pętla do…while działa od wartości i=0 dopóki i<M.
Wyrażenie ret = scanf(" %d",&a); działa na takiej zasadzie, że do zmiennej a przyporządkowuje wartość całkowitą wpisaną przez użytkownika. Zmienna ret natomiast przyjmuję wartość 1, jeśli wpisana wartość jest liczbą całkowitą, a wartość 0 gdy użytkownik wpisał coś innego niż liczbę całkowitą.
W kolejnym kroku zastosowano instrukcję warunkową: if (ret!=1) break;. Zadaniem tej instrukcji jest przerywanie wykonywania pętli do…while, jeśli użytkownik nie wpisał liczby całkowitej.
N
n = i; printf("%d\n",n);/*
ilosc elementow wcytanych */ for(i=n-1;i>=0;i=i-1/*i--*/)
printf("T[%d]=%d\n",i,T[i]); return 0; }
Po zakończeniu pętli zmiennej n przyporządkowana jest wartość i, tak więc zmienna n określa nam liczbę elementów wpisanych przez użytkownika. Dalej polecenie printf wyświetla nam tą liczbę.
Następnie wykonuje się pętla for, której zadaniem jest wyświetlić wszystkie elementy wpisane przez użytkownika. Pętla ma formę: for(i=n-1;i>=0;i=i-1/*i--*/) printf("T[%d]=%d\n",i,T[i]); tak więc wartości wyświetlają się od ostatniej wpisanej.
2. Pętla for
Program 1 (2_for_1)
#include
<stdio.h> int main() { /* rysowanie trojkata o dlugosci
boku "dl", znakiem "znak" wczytanym
ze standardowego wejscia */ int dl,i,j; char znak; scanf("%c%d",&znak,&dl); printf("znak=%c
liczba=%d\n",znak,dl); for(i=1;i<=dl;i++) { for(j=1;j<=i;j++)
printf("%c",znak); printf("\n"); }
for(i=dl-1;i>=1;i--) { for(j=1;j<=i;j++)
printf("%c",znak); printf("\n"); }
return 0;
}
Kompiluję i wykonuję program dla różnych wartości.
Program rysuje trójkąt za pomocą podanych przez użytkownika znaków i o podanej przez użytkownika wysokości (długości boku).
Nowością jest zadeklarowanie zmiennej char znak; deklarujemy w ten sposób zmienną zawierającą jeden znak tekstu.
Do wprowadzania przez użytkownika wartości wykorzystano ponownie funkcję scanf("%c%d",&znak,&dl); Następnie printf("znak=%c liczba=%d\n",znak,dl); wyświetla podany przez użytkownika znak i liczbę.
N
for(i=1;i<=dl;i++) { for(j=1;j<=i;j++)
printf("%c",znak); printf("\n"); }
for(i=dl-1;i>=1;i--) { for(j=1;j<=i;j++)
printf("%c",znak); printf("\n"); }
Pierwszy „for w forze” wypisuje po kolei znaki w wierszu (w każdym kolejnym o 1 znak więcej., nadrzędny do niego for natomiast przenosi go do kolejnej linijki, aż do osiągnięcia podanej przez użytkownika wysokości.
Kolejne 2 fory natomiast robią to samo, tylko w stronę odwrotną (w każdym kolejnym wierszu o 1 znak mniej) aż do momentu gdy będzie wypisany 1 znak.
P
#include <stdio.h> /* Try following
example to understand for loop.
You can put the
following code
into a test.c file
and then compile it and then run it.*/ main() { int i; int j = 10; for( i = 0; i
<= j; i ++ ) { printf("Hello
%d\n", i ); } }
Po przepisaniu, kompilacji i wykonaniu otrzymałem:
Widzimy, że efekt jest taki sam jak w przypadku programu pierwszego z pętli do…while.
Pętla for( i = 0; i <= j; i ++ ) wykonuje się 11 razy od wartości i=0, dopóki i<=j (j=10), po każdym wykonaniu dodając do i wartość 1.
P
#include
<stdio.h> /*
Try following example to understand for loop.
You
can put the following code
into
a test.c file and then compile it and then run it. You
can make use of break to come out of for loop at any time*/ main() { int
i;
int
j = 10; for
( i = 0; i <= j; i ++ ){
printf("Hello %d\n", i ); if(
i == 6 ) { break; } } }
Program działa analogicznie jak w przypadku pętli do…while. Gdy i=6 break przerywa wykonywanie pętli for. Mamy więc wypisane wiersze tylko do Hello 6.
P
#include
<stdio.h> int
main() { /* program ma
dla podanej wartosci n wyznaczyc wartosc n! = 1
* 2 * ... * n, poprawnie! */ int n, i,
silnia;
/* wczytujemy
wartosc n i sprawdzamy format */ if
(scanf("%d",&n) < 1) {
printf("bledny format!\n"); return 1; }
/* sprawdzamy
czy wartosc miesci sie w zakresie o jaki zakres
chodzi??? - przetestowac! */ if
(n < 0 || n > 13)
{
printf("bledny zakres!\n"); return 1; }
/* wyznaczamy
wartosc n! */
for(i=1,silnia=1 ; i <= n ; i++ /* i = i + 1 */) { silnia =
silnia * i; /*
nowa_wartosc_silni = stara_wartosc_silni * i */ }
/* wyswietlamy
wynik */ printf("%d!=%d\n",n,silnia);
return 0;
}
Program liczący silnię za pomocą pętli for.
Instrukcja if sprawdza nam czy wpisana przez użytkownika wartość jest liczbą. Jeśli tak nie jest, wypisuje „bledny format”. Sprawdziłem to wpisując literę „a”.
Jeżeli wpiszę liczbę program przejdzie do kolejnej instrukcji if:
Działa to tak, że jeżeli liczba będzie mniejsza od 0, lub większa od 13 wyświetli się „bledny zakres!”. Wpisuję więc dla sprawdzenia liczbę 14
Jeżeli podane wcześniej warunki zostały spełnione program przechodzi do pętli, która liczy nam już właściwą silnię.
Pętla wykonuje się tyle razy ile wynosi wartość podanej przez użytkownika liczby n. Liczy silnię po czym wyświetla wynik.
P
#include <stdio.h> int main() { int c, n, fact =
1; printf("Enter
a number to calculate it's factorial\n"); scanf("%d",
&n);
for (c = 1; c <=
n; c++) fact = fact *
c; printf("Factorial
of %d = %d\n", n, fact); return 0; }
Program ponownie liczący silnię, jednak bez podanych jak w poprzednim przypadku warunków.
3. Instrukcja if
Program 1 (2_if_1)
#include
<stdio.h> main() { int
cows = 6; if
(cows > 1) printf("We
have cows\n"); if
(cows > 10) printf("loads
of them!\n"); else
printf("Executing else part...!\n"); if
(cows == 5 { printf("We
have 5 cows\n"); } else
if (cows == 6 ) { printf("We
have 6 cows\n"); } }
Po skompilowaniu i uruchomieniu otrzymałem:
Program w zależności od podanej liczby krów wyświetla nam różne zdania.
Pierwszy
if:
wyświetla napis „We have cows” jeśli liczba krów jest większa
od 1. W tym programie jest z góry zadeklarowana i wynosi 6.
Kolejny
if…else:
dla liczby krów większej od 10 wyświetla nam pierwszy wariant
napisu, jeśli ten warunek jest nie spełniony, wtedy wyświetla
napis określony po wyrażeniu else.
Ostatni
if:
dla liczby krów = 5 wyświetla jeden wariant, natomiast po wyrażeniu
else
mamy kolejny if,
który sprawdza warunek (cows==6),
jeśli ten warunek jest spełniony wyświetla drugi wariant napisu.
Jak
widać dla wartości krów 6 otrzymałem 3 napisy:
Program 2 (2_if_1a)
#include <stdio.h> main() { int a , b; a = 10; printf( "Value
of b is %d\n", (a == 1) ? 20: 30 ); printf( "Value
of b is %d\n", (a == 10) ? 20: 30 ); }
Jest to prosty program, który prezentuje działanie operatora trójargumentowego.
Po
skompilowaniu i uruchomieniu otrzymałem:
Operator zawarty jest wewnątrz wyrażenia printf:
Działa to w następujący sposób: na początku sprawdzany jest warunek (a==1), jeśli jest spełniony wyświetla się 20, jeśli nie, wyświetla się 30.
Analogicznie działa drugi printf, z tym że sprawdza warunek (a==10)
Zmienna
a
była na początku zadeklarowana jako 20, tak więc wynik wygląda
następująco:
P
#include
<stdio.h> int
main() { int a; /*
ustalamy, ze:
legalne
wartosci to: -100 do 100 */ if
(scanf("%d",&a) < 1)
/* funkcja
scanf ZWRACA ilosc przeczytanych liczb */ {
printf("bledny format!\n"); return
1;
} if (a <
-100 || a > 100) { /* a spoza
zakresu */ } /* a z zakresu
*/ printf("liczba
wczytana: %d\n",a); return 0; }
printf("wartosc spoza zakresu!\n");
return
0;
Na początku podobnie jak w jednym z poprzednich programów, sprawdzane jest czy wprowadzona wartość jest liczbą (if (scanf("%d",&a) < 1)). Jeśli nie program wypisuje „bledny format!”.
Dalej
kolejny if (a < -100 || a > 100) sprawdza, czy liczba mieści
się w zakresie od
-100 do 100, jeśli nie, wtedy wypisuje
„wartość spoza zakresu!”. Natomiast gdy warunek jest spełniony
wyświetla „liczba wczytana: a”.
Program 4 (2_instrukcja_if_dochod)
#include
<stdio.h> main
() { float
dochod, podatek; printf ("Jaki
masz dochod?"); scanf ("%f",
&dochod); if (dochod <=
1771) podatek=0;
else if
(dochod<=25252)podatek=dochod*0.19 - 336.6; else if (dochod >
25252)
podatek=4461 +
(dochod - 25252) * 0.3; printf("\nZaplacisz
%0.2f zl podatku.\n",podatek); }
Program liczy wartość podatku dla wartości dochodu podanej przez użytkownika.
Na samym początku zadeklarowane mam dwie zmienne float, czyli liczby zmiennoprzecinkowe.
Ta
instrukcja dla dochodu mniejszego od 1771 wyświetla wartość
podatku równą 0.
Jeśli ten warunek jest niespełniony sprawdzane są kolejne 2 warunki od których zależy procent podatku.
Program 5 (2_instrukcja_if_wyznacznik)
#include
<stdio.h> double
Wyzn (double a1, double a2, double b1, double b2)
{ return
a1*b1-a2*b2; } int
main(void){ double
a1=1, a2=1, a3=2, b1=-1, b2=1, b3=4, W, x, y; W = Wyzn(a1, a3,
b1, b3); if(!W) { if
(!Wyzn(a1, a3, b1, b3))
puts
("\n Uklad rownan zależnych"); else puts("\n
Układ równań sprzecznych"); } else { x = Wyzn(a3, b3,
a2, b2)/W; y = Wyzn(a1, a3,
b1, b3)/W; printf("\n
x=%lf \n y=%lf", x, y); } return 0; }
Program ma na samym początku zdefiniowaną funkcję Wyzn, która operuje na wartościach zmiennoprzecinkowych (a1,a2,b1,b2) i oblicza ich wyznacznik.
W funkcji main za pomocą instrukcji if..else sprawdzane są warunki rozwiązywalności układu równań w zależności od wartości wyznacznika.
Pierwszy if(!W) sprawdza czy wyznacznik jest liczbą ujemną. Jeżeli tak wykonuje instrukcję, która kolejnym warunkiem sprawdza czy układ jest zależny bądź sprzeczny.
Na
samym końcu else
odnoszący się do pierwszego if
oblicza rozwiązania równania
i wyświetla je na monitorze.
Wynik
działania programu dla wartości zadeklarowanych wygląda
następująco:
4. Instrukcja switch
Program 1 (2_switch_1)
#include
<stdio.h> /*
This will produce following result: Excellent Good OK Mmmmm.... You
must do better than this
What
is your grade anyway? */ main( { int
Grade = 'A'; switch(
Grade ) { case
'A' : printf( "Excellent\n" ); case
'B' : printf( "Good\n" ); case
'C' : printf( "OK\n" ); case
'D' : printf( "Mmmmm....\n" ); case
'F' : printf( "You must do better than this\n" );
default
: printf( "What is your grade anyway?\n" ); } }
Switch jest instrukcją warunkową wielokrotnego wyboru.
Na samym początku zdefiniowano, że Grade = ‘A’, a więc wyrażeniu stałemu pierwszego case. Jeżeli po case nie umieścimy wyrażenia break, wtedy automatycznie wykona się kolejny.
Ostatni default realizuje się wtedy gdy wartość w nawiasie przy switchu nie pasuje do żadnego case’a.
Po
wykonaniu tego programu otrzymujemy:
A więc wszystkie możliwe warianty zostały wyświetlone.
Program 2 (2_switch_1a)
#include <stdio.h> main() { int Grade =
'B'; switch( Grade
) { case 'A' :
printf( "Excellent\n" ); break; case 'B' :
printf( "Good\n" ); break; case 'C' :
printf( "OK\n" ); break; case 'D' :
printf( "Mmmmm....\n" ); break; case 'F' :
printf( "You must do better than this\n" ); break; default
: printf( "What is your grade anyway?\n" ); break; } }
Program
jest identyczny jak program opisany poprzednio, jednak tym razem po
każdym case
został dopisany break, a Grade=’B’.
Wynik wygląda następująco:
Jak widać program wyświetlił tylko wariant napisu określony przy case ‘B’.
Program 3 (2_switch_1b)
#include <stdio.h> main() { int Grade =
'L'; switch( Grade
) { case 'A' :
printf( "Excellent\n" ); break; case 'B' :
printf( "Good\n" ); break; case 'C' :
printf( "OK\n" ); break; case 'D' :
printf( "Mmmmm....\n" ); break; case 'F' :
printf( "You must do better than this\n" ); break; default :
printf( "What is your grade anyway?\n" ); break; } }
Jest to kolejny wariant tego samego programu, z tym że Grade=’L’, a więc wyrażenie switch’a nie pasuje do żadnego case’a.
Po skompilowaniu i uruchomieniu otrzymujemy:
Otrzymaliśmy wariant zapisany w default.
5. Pętla while
P
#include
<stdio.h> void
func(void);
static
count=10; /* Global variable - static is the default */
main() { while
(count--)
{ func(); }
}
void
func( void ) { static
i = 5; i++; printf("i
is %d and count is %d\n", i, count); }
Na początku została zadeklarowana funkcja func, która nie zwraca żadnej wartości oraz zmienna statyczna count.
Sama
procedura zawarta w funkcji func
zadeklarowana jest dopiero pod funkcją main
w kodzie źródłowym. Ma ona zadeklarowaną zmienną statyczną i,
dodaje do niej za każdym wykonaniem 1, a ostatecznie printf
wyświetla obie liczby count
oraz i.:
W funkcji main zastosowano pętle while, która wykonuję funkcję func przy warunku (count--)
Ostatecznie po skompilowaniu i uruchomieniu otrzymałem:
Program 2 (2_while_1a)
#include <stdio.h> main() { int i = 10; while ( i >
0 ) { printf("Hello
%d\n", i ); i = i -1; } }
Program, który ponownie wypisuje słowo Hello z odpowiednim numerem, jednak tym razem napisany za pomocą pętli while:
Na początku i=10, pętla na samym początku sprawdza warunek (i>0) i wykonuje się dopóki ten warunek jest spełniony. Po każdym wykonaniu printf od i odejmuje się 1.
Program 3 (2_while_1b)
#include <stdio.h> main() { int i = 10; while ( i >
0 ) { printf("Hello
%d\n", i ); i = i -1; if( i == 6 ) { break; } } }
Kolejna wersja tego samego programu. Przy wartości i=6 break zatrzymuje działanie pętli while.
Ostatnim wyświetlonym wierszem jest „Hello 7” ponieważ zadziałał break.