Programozás alapjai gyakorlat 2014-2015/1

5. gyakorlat


    Előző heti plusz pontos házi:

Egy lehetséges megoldás letöltése .


    Mit is tanultunk a 4. gyakorlaton?

Ismétlő feladat:

    (a) Kérj be 1 és 10 között egy számot az alapjan, hogy mennyit gyakorolja az adott hallgató hetente a progalapot.

          Ha a szám >=5, akkor eleget tanul a hallgató, <5 esetén többet kellene, ha > 10 akkor írjuk ki, hogy helytelen adat vagy csak nagyon jó a hallgató.

    (b) Kérdezz rá feltételes kifejezéssel, hogy szeretné-e a hallgató megváltoztatni a megadott számot.

    (c) Kezdőfeltételes ismétléses vezérléssel kérj be 5 számot, majd írasd ki.

    (d) Számlálásos ismétléses vezérléssel oldd meg egy 5*5-ös táblázat kiíratását.

    (e) Majd egy végfeltételes ismétléses vezérlést addig futtass, amíg nem kap a program egy SPACE karaktert.

Megoldás letöltése .




    Konstansok

A konstansdefiniálás általános alakja:

#define NÉV érték

Az érték bármi lehet, később a fordítás első menetében a preprocesszor a név összes előfordulását szövegesen a megadott értékkel helyettesíti, majd folytatódik a fordítás. Így a konstans értéke akár programrészlet is lehet.

Feladat: Írj egy programot, ami 1-től 10-ig kiírja a számokat, majd minden második, majd minden negyedik számot.

#include <stdio.h>

int main() {
	int i;
	for(i=1; i<=10; i++) {
		printf(" %d", i);
	}
	putchar('\n');
	for(i=1; i<=10; i+=2) {
		printf(" %d", i);
	}
	putchar('\n');
	for(i=1; i<=10; i+=4) {
		printf(" %d", i);
	}
	putchar('\n');
	return 0;
}

Feladat: Módosítsuk úgy a programot, hogy 21-től 144-ig írjon ki. Hány helyen kellett átírnunk számokat?

Feladat: Csináljuk meg ugyanezt konstansokkal. Így hány helyen kellene módosítani?

#include <stdio.h>

#define A 1
#define B 10

int main() {
	int i;
	for(i=A; i<=B; i++) {
		printf(" %d", i);
	}
	putchar('\n');
	for(i=A; i<=B; i+=2) {
		printf(" %d", i);
	}
	putchar('\n');
	for(i=A; i<=B; i+=4) {
		printf(" %d", i);
	}
	putchar('\n');
	return 0;
}
Az ilyen konstansokat a preprocesszor kezeli, ugyanaz, aki a #include -ot is.

$ gcc -E konstans.c >konstans.i
$ gcc konstans.i -o konstans

Nézzük meg a konstans.i végét! Felismerjük a saját kódunkat? Ami előtte van, az az #include <stdio.h> -ból jön.

Elmélkedjünk: Mi lesz az eredménye az alábbinak:

#define int 100.0

int main() {
	float f=int;
	printf("%f\n", f);
	return 0;
}


    Tömbök

Több azonos típusú adat egyben való tárolására és kezelésére alkalmazhatók a tömbök.

Általános alakja:

típus név[méret];

pl.: 10 darab egész érték tárolására egy tömb létrehozása:

int tomb[10];

A tömbök egyes elemeire egy úgynevezett index-szel lehet hivatkozni. Ez maga a tömben lévő elemek sorszáma. A tömbben az elemek sorszámozása 0-tól kezdődik. Tehát a tömben lévő első elem indexe 0. Ennek megfelelően egy N méretű tömb utolsó eleme az N-1. indexen érhető el. Ha végig szeretnénk haladni a tömb elemein egy ciklussal, akkor az indexek helyes kezelésére nagy figyelmet kell fordítani.

Feladat: Készíts egy 10 egész szám tárolására alkalmas tömböt. Töltsd fel az 1..10 értékekkel, majd írasd ki az elemeit.

#include <stdio.h>

#define N 10
#define M 10

int main()
{
	int tomb[N];
	int i;
	for(i=0; i<M; i++) {
		tomb[i]=i+1;
	}
	for(i=0; i<M; i++) {
		printf(" %d", tomb[i]);
	}
	return 0;
}
 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
		
1 2 3 4 5 6 7 8 9 10

Az első sor prezentálná a tömb elemek indexeit, a második sor pedig az adott indexhez tartozó tömb elem által tárolt értéket.

Kérdés: Mi történik, ha M<N? És ha N<M?

Feladat: Készíts egy 3x3-as mátrixot, töltsd fel elemekkel, majd írasd ki az elemeit sor illetve oszlopfolytonosan is!

#include <stdio.h>

#define N 3

int main()
{
	int tomb[N][N];
	int i, j;
	for(i=0; i<N; i++) {
		for(j=0; j<N; j++) {
			scanf("%d", &(tomb[i][j]));
		}
	}
	for(i=0; i<N; i++) {
		for(j=0; j<N; j++) {
			printf("%d", tomb[i][j]);
		}
	}
	for(i=0; i<N; i++) {
		for(j=0; j<N; j++) {
			printf("%d", tomb[j][i]);
		}
	}
	return 0;
}


    Karaktertömbök - "stringek"

Mivel C-ben nincs külön string típus, ezért karaktertömbök megvalósításával helyettesíthetjük őket. Lényegileg ugyanolyan, mint egy sima tömb, csak egy karaktersorozatot fogunk benne letárolni, és az előzőekhez hasonlóan hivatkozhatunk minden egyes karakterre a megadott szövegünkben, külön-külön is akár, részekre bontva.
A szöveg végét egy 0 ascii kódú karakter (a NUL karakter) jelzi. Ez a karakter a tömbön belül bárhol lehet, az utána levő tömbelemeket a sztringeket feldolgozó függvények figyelmen kívül hagyják, így egy tömbben bármilyen hosszúságú szöveg tárolható, ami rövidebb a tömb méreténél. A záró 0 karakternek mindenképpen szerepelnie kell, mivel a tömb mérete nem állapítható meg, így nem lehetne tudni meddig tart a szöveg a memóriában. Emiatt eggyel nagyobb méretű tömböt kell deklarálni szöveg tárolására, hogy a záró 0 elférjen

Tehát, hogy is nézne ez ki a létrehozás:

char karaktertomb[10];	// 10 karakter tárolására elegendő karaktertömb

Tételezzük fel, hogy feltöltöttük a tömbünket, mi van most benne? Mondjuk benne van a "PROGALAP" szó:

0 1 2 3 4 5 6 7 8 9
P R O G A L A P 0 ?

Ahol a kérdőjelek definiálatlan, véletlenszerű adatot jelentenek.

Feladat: Deklarálj egy megfelelő hosszúságú karaktertömböt, majd írd bele a "Hello Vilag!" szöveget! Írasd ki az str értékét kétféleképpen!

#include <stdio.h>

int main()
{
	char str[20];
	str="Hello Vilag!";
	printf("%s", str);
	return 0;
}

Ez így fordítási hiba. A baj az, hogy str egy karaktertömb, tehát lehet egyesével feltölteni az elemeit. Vagy használhatjuk az strcpy() függvényt.

#include <stdio.h>
#include <string.h>

int main()
{
	char str[20];
	strcpy(str, "Hello Vilag!");
	printf("%s", str);
	printf(str);
	return 0;
}

Feladat: Módosítsd a programot úgy, hogy a következő sorba csak a "Hello" szöveget írja ki!

Feladat: Írj egy függvényt, ami egy egész tömböt kap paraméterül és lecseréli benne az elemeket az abszolútértékükre. A tömb kiírását szintén függvény végezze!

#include <stdio.h>

#define N 10

void tombabs(int tomb[], int meret) {
	int i;
	for(i=0; i<meret; i++) {
		if(tomb[i<0) {
			tomb[i] = -tomb[i];
		}
	}
}

void kiir(int tomb[], int meret) {
	int i;
	for(i=0; i<meret; i++) {
		printf(" %d", tomb[i]);
	}
	putchar('\n');
}


int main()
{
	int i, T[N], e=1;
	for(i=0; i<N; i++) {
		T[i]=e;
		e *= -2;
	}
	kiir(T, N);
	tombabs(T, N);
	kiir(T, N);
	return 0;
}



Nézzünk néhány érdekesebb példát:

Feladat:

    Buborék rendezés. Vegyünk egy 1D tömböt, amelybe 10 számjegyet olvasunk be, tetszőleges sorrendben.
    A buborék rendezés elve, hogy haladunk végig a tömbön és egyesével hasonlítgatjuk össze
    az egymás mellett lévő tömb elemeket. Ha az alacsonyabb indexű elem nagyobb, mint a mellette levő,
    magasabb indexű, akkor cseréljük ki őket. Így járjunk el egészen addig, amíg nagyság szerinti
    sorrendbe nem lesz rendezve a tömbünk.

Megoldás letöltése .

Feladat:

    Fibonacci sorozat. A rákövetkező szám mindig az őt megelőző kettő összege.
    0,1,1,2,3,5,8,13,21,34,55,89,...

Megoldás letöltése .

Feladat:

    (a) FIFO (First In First Out) algoritmus megvalósítása 1D tömbbel.
    Töltsünk fel egy 10 méretű, 1D tömböt 1..10 elemekkel.
    Majd olvassunk be egy értéket egy változóba. Ha az az érték már szerepel
    a tömbben, akkor ne tegyünk semmit, mivel nincs szükség cserére.
    Ha viszont nincs benne az érték a tömbben, akkor töröljük a tömbből
    a legrégebben betöltött elemet és tegyük a tömb végére a beolvasott értéket.

    (b) Módosítsuk, hogy ciklussal olvassunk be bizonyos mennyiségű elemet.
    
    (c) Módosítsuk a feladatot LRU (Least Recently Used)-ra. A feladat hasonló,
    csak most ne a legrégebben betöltöttet cseréljük az új értékre, hanem
    a legrégebben használtat. (Természetesen valamilyen módon a program futása
    során fel kell jegyezni valahogy, hogy a tömb mely értékét mikor használtuk)

(a)+(b) FIFO megvalósításának letöltése .

(c) LRU megvalósításának letöltése .




Házi feladat

A házi feladatot megoldani nem kötelező és bemutatni sem kell, viszont a következő gyakorlaton visszakérhető (kikérdezés, táblához hívás, stb. formájában)! Ha a hallgató megoldása ötletes, szép kivitelezésű, plusz pont adható. Amennyiben viszont nem tudja megoldani gyakorlaton a házi feladatban szereplő példákat vagy nem tud válaszolni az azzal kapcsolatban feltett kérdésekre, mínusz pont adható. Plusz és mínusz pontból is egyaránt maximum 10 pontot gyűjthet össze egy-egy hallgató.

Házi feladat letöltése .

Gyakorló feladatok letöltése .

További gyakorlásra a PUB-ban lévő további házi feladatok és az órán nem megoldott feladatok megoldása.




    Jövő héten 3. miniZH (2014.10.06.)

Téma:

  4. gyakorlat anyaga. (De tudni kell az előző - 3. - gyakorlat anyagát is!)

  Gyakorlásra:

    A honlapomon a 3. és 4. gyakorlathoz tartozó anyag, magyarázatokkal, példákkal.

    A gyakorlatok végén lévő házi feladat és gyakorló feladatok megoldása.

    A honlapom mellet további feladatok találhatóak a PUB-ban. (/n/pub/ProgramozasAlapjai/Gyakorlat/ - erős átfedés van az "itt" és "ott" található feladatok között).

Egyéb infó:

  A gyakorlat 8:10-kor kezdődik és a ZH-t 8:15-kor kezdhetitek írni. Előreláthatóan 30 percetek lesz a feladat megoldására és beadására (tehát 8:45-ig). A feladatot a bíró rendszeren keresztül fogjátok megkapni és beadni is, és az értékelést is a bíró fogja csinálni ott helyben. Tehát egyből látni fogjátok a pontszámokat amiket a bíró adott. Aki késik, az is csak a fenti időintervallum alatt írhatja a ZH-t (a bíró rendszer nyit, majd automatikusan zár is). Hiányozni csak igazolással lehet, de a ZH akkor sem pótolható!


     Vissza a lap tetejére.