Jeśli zaistaniała by taka potrzeba to po uprzednim kontakcie mailowym. Raczej nie do południa.
Zakładam, że program wraz z ewentualnym makefile`em jest w kataolgu \(prog1\)
tar -cf program1.tar prog1
Uwaga! Przed spakowaniem katalogu należy usunąć z niego plik wykonywalny (skompilowany program).
Można dodatkowo spakować:
bzip2 program1.tar
Dopiero tak spakowaną paczkę należy przesłać jako rozwiązanie.
Ze względu na szereg przesunięc w zajęciach i dopasowanie się do poziomu uśrednionego poziomu problemów na ćwiczeniach, code-review zostanie zmieniony na projekty czyli po prostu większe prace domowe.
Aby zaliczyć projekt (warunki konieczne):
Aby otrzymać lepszą ocenę (warunki dodatkowe):
-W -Wall --ansi
)Po prostu należy być przyzwoitym i je pisać.
Minimalny program w języku C wygląda dość skromnie: ## Minimalny, program
main()
{
}
Jest tylko jeden obowiązkowy element programu:
Z dodatków zamieniających programy w coś przydatnego:
#include<stdio.h>
int main()
{
printf("Witaj szary Świecie!\n");
return 0;
}
W C (konkretniej dla współczesnych kompilatorów C) mamy trzy możliwość:
//wszystko za slashami jest komentarzem
/* wszystko pomiędzy jest komentarzem */
/* mogą być
wieloliniowe */
/* ale nie mogą być zagnieżdżone */
#if 0
//można tak wyłączyć szybko duży blok kodu wraz z komentarzami
int a;
int b;
a=2;
for(b=0;b<10;b++) printf("Bezsensowna pętla\n");
//nie można ich zagnieżdżać
#endif
gcc -o <nazwa_programu_po_kompilacji> <nazwa_pliku_źródłowego>
Przykładowy Makefile kompilujący kod.c do programu exe
all:
gcc -o exe kod.c
Teraz wystarczy wpisać make i zostanie wykonana kompilacja.
if( <warunek> )
{
//blok instrukcji
}
if( <warunek> )
{
}
else
{
//ten blok instrukcji zostanie wykonany gdy <warunek> jest fałszem.
}
if( <warunek1> )
{
//jeśli warunek1 jest prawdą wykonaj
}
else if ( <warunek2> ) //jeśli warunek1 nie jest prawdą sprawdź warunek2
{
}
else if ( <warunek3> ) //jeśli warunek2 nie jest prawdą sprawdź warunek3
{
}
else
{
//jeśli warunek3 nie jest prawdą wykonaj ten blok
}
for( <instrukcjaPrzedFor> ; <warunekIstnieniaPętli> ; <instrukcjaPoZakończeniuBloku> )
{
//blok instrukcji
}
while( <warunkeIstnieniaPętli> )
{
//blok instrukcji
}
do
{
//blok instrukcji
}
while( <warunekIstnieniaPętli> );
/*Deklaracja funkcji*/
int Funkcja(int a);
/*Definicja funkcji*/
int Funkcja(int a)
{
return a*a;
}
Obowiązkową cześć jest definicja funkcji (pełni ona również rolę deklaracji jeśli taka nie wystąpiła).
Deklaracja (lub cała treść (definicja)) funkcji musi wystąpić PRZED użyciem tej funkcji.
#include<stdio.h>
int Funkcja(int a)
{
return a*a;
}
int main()
{
printf( "%d\n", Funkcja(16) );
return 0;
}
lub:
#include<stdio.h>
//Deklaracja
int Funkcja(int a);
int main()
{
printf( "%d\n", Funkcja(16) );
return 0;
}
//Definicja
int Funkcja(int a)
{
return a*a;
}
Jaki błąd zwróci komilator jeśli w tym wypadku pominiemy deklarację a jaki jeśli pominiemy definicję?
Jeśli kompilator nie zwraca żadnych, błędów skompiluj program z następującymi flagami:
> gcc -o exe funkcje.c -W -Wall -ansi
Deklaracja:
<typ> nazwa[rozmiar];
Przykłady:
char znaki[256];
int liczby[100];
Zapisanie liczby w pierwszym elemencie tablicy i wypisanie go na ekran:
int tab[10];
tab[0]=178;
printf("%d\n",tab[0]);
Wczytanie ze standardowego wejścia do piątego elementu tablicy:
int tab[19];
scanf("%d", &(tab[4]) );
Napisz funkcję o następującej deklaracji:
int CzyParzysta(int Liczba);
która sprawdza czy liczba całkowita Liczba jest parzysta.
Jeśli jest zwróć wynik 1. A 0 w przeciwnym wypadku.
Napisz funkcję o następującej deklaracji:
int CzyPodzielna(int Liczba, int Przez);
która sprawdza czy liczba całkowita Liczba jest podzielna przez liczbę całkowitą Przez.
Napisz funkcję o następującej deklaracji:
int Fibonacci(int Numer);
która oblicza i zwraca liczbę Fibonacciego o zadanym numerze.
Jaka jest maksymalna liczba Fibonacciego którą można zapisać przy użyciu typu int? Jak wykazać to empirycznie?
Wykorzystaj kawałek kodu
#include<stdio.h>
int main()
{
char litera;
while(scanf("%c",&litera) == 1)
{
printf("%c",litera);
}
return 0;
}
Napisz dwa programy jeden do zaszyfrowania a drugi do odszyfrowywania.
Program ma wykorzystywać funkcję Przesun o następującej deklaracji:
char Przesun(char Litera, int Przesuniecie);
Która przesuwa znak z następującymi regułami (jeśli na przykład Przesuniecie==1
):
Podpowiedź: wykorzystaj dzielenie modulo aby poruszać wewnątrz podzbiorów (małe litery, duże litery, liczby).
Aby zaszyfrować plik list.txt i zapisać wynik w zaszyfrowany_list.txt można użyć przekierowania w powłoce (bash, tcsh, ...):
> ./program < list.txt > zaszyfrowany_list.txt
Gdy testujemy program z klawiatury, aby przerwać jego działanie można użyć kombinacji klawiczy ctrl + c
.
Wykorzystaj wiedzę zdobytą przy okazji zadania 3.5 i napisz program który zlicza biłe znaki.
Białe znaki to:
' '
- spacje'\n'
- znaki końca linii'\t'
- tabulatoryNapisz program który wczytuje liczby całkowite ze standardowego wejścia, sprawdza ich podzielność przez 2,3,4,...,9 i komunikuje ten fakt na standardowe wyjście.
Przykładowa treść wejścia to:
1
2
15
-16
Wyjście w tym wypadku powinno być mniej więcej takie:
Liczba 1 Podzielna przez
Liczba 2 Podzielna przez 2
Liczba 15 Podzielna przez 3 5
Liczba -16 Podzielna prze 2 4 8
Zdeklaruj statyczną tablicę liczb całkowitych o rozmiarze 10. Wypełnij ją w pętli liczbami od 5 do 14. Wypisz na standardowe wyjście elementy tablicy.
W programie z 4.1 wyodręnij funkcje o następujących deklaracjach:
int Wypelnij(int *tab, int rozmiar, int ndanych);
Która wypełnia, przekazaną przez wskaźnik tab
, tablicę (o rozmiarze rozmiar
) i zwraca 0
jeśli wszystko przebiegło w poprawnie a 1
gdy ndanych
było więcej niż rozmiar
tablicy. Wypełniane jest pierwsze ndanych
elementów.
void Wypisz(int *tab, int ndanych);
Która wypisuje na standardowe wyjście elementy tablicy.
Dodaj do programu kolejną funkcję:
int Wczytaj(int *tab, int rozmiar, int ndanych);
Która w odróżnieniu od Wypelnij
wczytuje dane ze standardowego wejścia. Obsługa błędu tak samo jak w Wypelnij
.
Dopisz funkcję sprawdzającą podzielność przez 5. I napisz program który sprawdzi podzielność danych (wczyta je ze standardowego wejścia i wypisze podzelności na wyjście).
Format wejścia ma być następujący:
n
a1
a2
(...)
an
Gdzie n to liczba danych do wczytania (liczba całkowita od 0 do 100) a a1,..,an to dane (liczby całkowite).
Przykładowe wejście:
3
5
15
14
I wyjście dla tych danych:
1
1
0
Napisz funkcję obliczającą ilocz skalarny wektorów.
float Skalarny(float *A, float *B);
Użyj jej w programie który wczyta dwa wektory ze standardowego wejścia
1.3 1.5 0.
0. 2. 1.
i zwróci na standardowe wyjście wynik:
3.
Napisz funkcję obliczającą iloczyn wektorowy wektorów.
void Wektorowy(float *A, float *B, float *Wynik);
Użyj jej w programie. Przykłądowe wejście:
1. 0. 0.
0. 1. 0.
Wyjście:
0. 0. 1.
Napisz funkcję:
void Normalizacja(float *A);
normalizującą wektor.
Użyj jej w programie.
Przykładowe wejście:
2. 0. 0.
Wyjście:
1. 0. 0.
Napisz funkcję:
void Swap(float *a, float *b);
zamieniającą miejscami wartości zmiennych.
Napisz funkcję:
void Srotuj(float *A);
która posortuje tablicę danych. Wykorzystaj funkcję swap.
Napisz program który sortuje dane.
Wejście
n
a1
a2
...
an
Przykład wejścia
3
4.5
1.2
-4
Wyjście
-4
1.2
4.5
UWAGA W programie warto napisać bardzo dokładne komentarze (wręcz przekleić treść)! Program stanie się swego rodzaju ściągawką podczas dalszej nauki c/c++.
Napisz program pointers, który robi następujące rzeczy (w kolejności):
a
i b
)a_ptr
i b_ptr
)a_ptr
obszar pamięci a
. "Wskazuje a_ptr na a."b
, b_ptr
a
wartość (wedle fanaberii).b
wartość przy użyciu b_ptr
a
i b
(używając zmiennych a
i b
).a
i b
(używając zmiennych a
i b
).a
i b
(używając wskaźników a_ptr
i b_ptr
).a
i b
(używając zmiennych a_ptr
i b_ptr
).a_ptr
i b_ptr
.c
odpowiedniego typu i zapisuje w niej wartość a przy pomocy wskaźnika a_ptr
d_ptr
odpowiedniego typu, który wskazuje na zmienną b
d_ptr
podwaja wartość zmiennej b
c
i b
Aby ćwiczenie stało się uniwersalne w skali c/c++ należy uzupełnić je o referencję. Np. tworząc referencję do c
i podglądając jej wartość/adres. Oczywiście to wymaga skorzystania z innego kompilatora... ;)
Napisz program morepointers a w nim:
size
o wartości 8.tab
o wielkości size
zmiennych typu inttab
przemnażając go przez 4.p
i q
) na typ inttab
Używając deklaracji struktury i typu:
struct SZespolona
{
float Re;
float Im;
};
typedef struct SZespolona TZespolona;
Zaimplementuj funkcje operujące na liczbach zespolonych:
Funkcję obliczającą moduł:
float Modul(TZespolona A);
Funkcje zwracające część rzeczywistą/urojoną:
float Im(TZespolona A);
float Re(TZespolona A);
Funkcje dodające/odejmujące i mnożące dwie liczby zespolone:
TZespolona Dodaj(TZespolona A, TZespolona B);
TZespolona Odejmij(TZespolona A, TZespolona B);
TZespolona Pomnoz(TZespolona A, TZespolona B);
Do zaalokowania (zarezerwowania) służy komenda (między innymi - patrz strona 336 podręcznika) malloc
. Używamy jej następująco:
Najpierw tworzymy wskaźnik do którego będzie dopięta nasza tablica:
double *pfDane; //liczby zmienno przecinkowe
int *pnLiczby; //albo może liczby całkowite
Następnie prosimy komputer o zarezerwowanie pamięci na, powiedzmy, n
= 100 obiektów odpowiedniego typu. W celu dowiedzenia się ile bajtów zajmuje dany typ, możemy posłużyć się np. naszą wiedzą albo funkcją sizeof
. Do trzymania długości tablicy "kanonicznie" używa się typu size_t
- zazwyczaj jest to long long int
.
int n = 100;
size_t nRozmiarDane = n*sizeof(double); //zamiast typu, argumentem sizeof może też być zmienna
size_t nRozmiarLiczby = n*sizeof(int);
pfDane = (double*)malloc(nRozmiarDane);
pnLiczby = (int*)malloc(nRozmiarLiczby);
Gdyby nie udało się zaalokować danego obszaru pamięci (powodów może być bardzo dużo), funkcja malloc
zwróci aders NULL
. Czyli sprawdzenie polegało by na:
if((pfDane == NULL) || (pnLiczby == NULL))
{
printf("nie udalo zarazerowac sie pamieci ktoregos z obszarow\n");
exit(EXIT_FAILURE);
}
Po zakończeniu używania dynamicznych tablic, należy zwolnić obszar przez nie zajmowany:
free(pfDane);
free(pnLiczby);
Zadanie polega na posortowaniu n liczb podanych następująco:
n
a1
a2
a3
...
an
Używając tablicy dynamicznej.
Wynikiem powinno być lista posortowanych liczb.
Przykład. In:
3
2
5
2
Out:
2
2
3
Napisz program który posortuje n liczb zespolonych po ich module, części rzeczywistej lub urojonej. Wejście:
t
n
re1 im1
re2 im2
...
ren imn
gdzie t to typ sortowania (0
- po module, 1
- po części rzeczywistej, 2
- poczęści urojonej), n to liczba danych.
Danych może być dużo także należy użyć dynamicznej alokacji pamięci.
Program ma wykorzystywać strukturę podobną do tej z zadania 8.1
Napisz program który posortuje n wektorów po ich długości. Program powinien (pełna ocena) wykorzystywać funkje takie jak w 5-tej serii ćwiczeń.
Wejście:
n
x1 y1 z1
...
xn yn zn
n liczba całkowita - ilość wektorów (nie większa niż 20).
xi yi zi liczby zmienno przecinkowe - współrzędne wektora.
Wyjście:
wx1 wy1 wz1
...
wxn wyn wzn
Przykładowe wejście:
4
1. 3. 5.
1. 3. 8.
0. 5. 0.
1. 0. 0.
Przykładowe wyjście:
1. 0. 0.
0. 5. 0.
1. 3. 5.
1. 3. 8.
Jeśli zastanawiacie się jak można zapisać wiele wektorw w jednowymiarowej tablicy - proponuję następującą podpowiedź... Zapisać je jeden za drugim. ;]
//pojemnik dla 4 wektorów
float Dane[12];
Czyli kolejne komórki pamięci wyglądały by ta
Dane[0] - to x0
Dane[1] - to y0
Dane[2] - to z0
Dane[3] - to x1
Dane[4] - to y1
Dane[5] - to z1
itd.
Jeśli mięliśmy dowolną funkcję wykorszystującą wektor jako tablicę o długości 3. Np.:
float ZwrocXWektora(float *Wektor)
{
return Wektor[0];
}
To przesuwając wskaźnik początku tablicy, możemy dostarczy do funkcji kolejne wektory:
float Dane[6] = {0. , 2. , 5.,
7. , 3. , 4. };
printf("Xowa wspolrzedna %d-go wektora to %f\n", 0, ZwrocXWektora(Dane));
printf("Xowa wspolrzedna %d-go wektora to %f\n", 1, ZwrocXWektora(Dane+3));
Korzystając z takiego układu wektórw w pamięci, proponuję następującą podpowiedź do zadania:
//Funkcja dlugosc oblicza dlugosc wektora
//Wejsciem jest tablica o co najmniej rozmiarze [3]
//Wykorzystuje funkcje obliczajaca iloczyn skalarny
float Dlugosc(float *Wektor)
{
return sqrt(Skalarny(Wektor,Wektor));
}
//Funkcja ktora wypelnia tablice dlugosci
void ObliczDlugosci(float *Wektory, float *IchDlugosci, int IchLiczba)
{
int i;
for(i=0; i<IchLiczba; ++i)
{
IchDLugosci[i] = Dlugosc(Wektor+3*i);
}
}
//Funkcja ktora zamienia miejscami DlugoscA-DlugoscB i WektorA-WektorB
//Wektory są tablicami o co najmniej trzech wspolrzednych. Tzn. i tak
//interesuja nas tylko pierwsze trzy
void Swap(float *DlugoscA, float *DlugoscB, float *WektorA, float *WektorB)
{
float TempDlugosc;
float TempWektor[3];
//zamiana danych miejscami
//bla bla bla
}
void Posortuj(float *Wektory, float *IchDlugosci, int IchLiczba)
{
//blablabla
//gdizes wewnatrz jakis petli w sortowaniu bombelkowym
if(IchDlugosci[i] > IchDlugosci[i+1])
{
//moza przekazac tak:
Swap( IchDlugosci+i, IchDlugosc+i+1, Wektory+(3*i), Wektory+((i+1)*3) );
//albo tak:
//Swap(&(IchDlugosci[i]), &(IchDlugosc[i+1]), &(Wektory[3*i]), &(Wektory[3*(i+1)]);
IloscSwapniec++;
}
}
int main()
{
float DaneWektorow[60];
float DlugosciWektorow[20];
int nLiczba;
//czytanie danych
//bla bla bla
ObliczDlugosci(DaneWektorow,DlugosciWektorow,nLiczba);
Posortuj(DaneWektorow,DlugosciWektorow,nLiczba);
//wypisywanie
//szmery/bajery
return 0;
}
Należy rozwiązać następujące problemy:
Dane wejściowe
N
x1
x2
(...)
xN
Gdzie \(N\) jest liczbą całkowitą określającą ilość danych wejściowych. \(N\) jest zakresu od 1 do 100. \(x_i\) to liczby zmiennoprzecinkowe.
Oblicz średnią \[ \mu = \frac{1}{N}\sum _{i=1}^{N}x_i \] i sigmę \[ \sigma = \sqrt{\frac{1}{N} \sum_{i=1}^{N}(x_i - \mu)^2 } \]
i podaj je na stadardowe wyjście:
mu
sigma
Zarówno \(\mu\) i \(\sigma\) to, z bardzo oczywistych powodów, liczby zmienno przecinkowe.
Wejście:
10
0.
1.
2.
3.
4.
5.
6.
7.
8.
9.
Wyjście:
4.500000
2.872281
Program powinien spełniać warunki konieczne (50%) i dodatkowe 2, 3 (50%).
Dane wejściowe
N
a1
a2
(...)
aN
Gdzie \(N\) jest liczbą całkowitą określającą ilość danych wejściowych. \(a_i\) to liczby całkowite z zakresu od 3 do 100.
Program ma sprawdzać czy dana liczba ma następujące cechy:
Wynik programu (standardowe wyjście)
a1 fib parz mapierw
(...)
aN fib parz mapierw
Gdzie fib, parz i mapierw to liczby całkowite 0 lub 1 określające daną cechę.
Wejście:
3
5
8
27
Wyjście:
5 1 0 0
8 1 1 1
27 0 0 1
Program powinien spełniać warunki konieczne (50%), dodatkowe 1, 2, 3 (50%).
Ma | Pa | Pi | Ry |
* | * | * | * |
1 | * | 0.5 | 0 |
1 | 0 | 0 | 0 |
0 | 0 | 0 | 0 |
1 | 0 | 0 | 0 |
1 | 0 | 1 | 0 |
1 | 1 | 1 | 0 |
0 | 0 | 0 | 0 |
1 | 0 | 1 | 0 |
Ma | Pa | Pi | Ry |
1 | 0.5 | 0 | 0 |
1 |