F: Készíts egy pointert, ami egy konstans értékre mutat.
F: Készíts egy konstans pointert, ami egy nem konstans értékre mutat.
F: Készíts egy pointert, ami egy tömbre mutat.
==============================================================================
#include <stdio.h>
int main()
{
const int *p = NULL; // pointer, ami egy konstans értékre mutat
int * const c = NULL; // konstans pointer, ami egy nem konstans értékre mutat
int (*t)[20]; // pointer, ami egy tömbre mutat
p = malloc(sizeof(int));
*p = 2007; /* HIBÁS - mivel konstans értékét nem tudjuk megváltoztatni */
free(p);
c = malloc(sizeof(int)); /* HIBÁS */
*c = 2007;
free(c);
return 0;
}
Tárolási osztályokat bemutató program
==============================================================================
#include <stdio.h>
#define MAX_NUM 5
/* A static tárolási osztály azt jelenti, hogy az adott változó megmarad a
* blokkból kilépés után is, és a következő belépéskor elérhető lesz a
* legutóbbi tartalom.
*
* Használhatjuk arra, hogy megszámoljuk, hányszor hívtuk az adott függvényt.
*/
int* counter()
{
static int count = 0;
count++;
printf("Count : %d\n",count);
return &count;
}
int* kell()
{
return counter();
}
int main()
{
/* Az auto tárolási osztály az alapértelmezett, ki sem szükséges tenni.
*/
auto int valami = 10;
/* A register tárolási osztály arra szolgál, hogy jelezzük a fordítónak,
* hogy olyan gépi kódot PRÓBÁLJON meg csinálni, amely során ez a változó
* folyamatosan a CPU egy regiszterében van. -> Gyorsabb elérésű, mint a
* memória, de sokkal kevesebb ilyen változó létezhet. Gyakran változó
* változót érdemes.
*
* A fordító figyelmen kívül hagyhatja!
*/
register int i;
/* A volatile módosító azt mondja a fordítónak, hogy:
* "Vigyázat, ez a változó értéke úgy is módosulhat, hogy a kódban nincsen
* annak módosítására szolgáló utasítás!"
* Pl. a változó egy porthoz csatlakozik, ahová az adott eszköz írhat!
*/
volatile unsigned short int device = (unsigned short int)0;
/* A const módosító azt mondja a fordítónak, hogy az érték nem
* megváltoztatható. Ez viszont csak annyit jelent, hogy az adott
* változóhivatkozás nem szerepelhet értékadás bal oldalán.
*/
const long int nemvaltozo = 2007;
int *p;
p=&i; /* EZ HIBÁS */
p=counter();
printf("*%p = %d\n", p, *p);
p=kell();
printf("*%p = %d\n", p, *p);
*p = 100;
counter();
return 0;
}
Több feladat közül futási időben döntöm el, hogy melyiket hajtom végre. A függvényre mutató pointer a függvény kódjának a címére mutat, azon keresztül meghívhatom a függvényt. A pointernek tudnia kell a függvény típusát (paraméterek és visszatérési érték típusa). Pl.:
double fgv(double, double); /* függvény deklarációja */ double (*fptr)(double, double); /* ilyen típusú függvényre mutató pointer deklarációja */ fptr = fgv; /* a függvény nevét adom kezdőértékül, a fordító persze ebből címet állít elő */ fptr(x, y); /* meghívom a függvényt a pointeren keresztül */
F: Egy tömbben soroljunk fel függvényeket, és hívjuk meg valahányadikat.
==============================================================================
#include <stdio.h>
#include <math.h>
/* sinus négyzet - beépített függvénnyel */
double sin2(double x) {
double sinx = sin(x);
return sinx*sinx;
}
/* kettes alapú logaritmus - beépített függvénnyel */
double log2(double x) {
return log(x) / log(2);
}
/* cosinus négyzet - beépített függvénnyel */
double cos2(double x) {
double cosx = cos(x);
return cosx*cosx;
}
typedef double (*fgvtip)(double); /* függvényre mutató pointer típusa */
/* melynek double a visszatérési értéke és double típust vár a paraméterlistában */
fgvtip tabla[] = { /* ilyen pointerek tömbje */
sin2, /* a függvény neve értékül adható függvényre mutató pointernek */
log2,
cos2
};
int main() {
int f, x;
char* valasztek = "{ 1: sin2x }\n{ 2: log2x }\n{ 3: cos2x }\n"; /* karakterekre mutató pointer, lényegileg egy string */
printf("Melyik fuggveny legyen?:\n%s?:\t", valasztek);
scanf("%d", &f);
printf("Argumentum erteke?:\t");
scanf("%d", &x);
printf("A fuggveny erteke az adott pontban:\t%lf\n", tabla[f-1](x) );
/* a tömbben lévő pointeren keresztül hívom a függvényt */
/* 1-től 3-ig várt bemenetet a program.
0-tól való indexelés miatt levon 1-et [f-1]
és paraméterként átadódik az úgyszint beolvasott érték (x) */
return 0;
}
F: Egy tömbbe olvassunk be, majd írassuk ki az elemeket úgy, hogy a tömb
bejárását egy függvény végezze, ami megkapja a műveletet.
==============================================================================
#include <stdio.h>
#define N 10
typedef void (*muvelettipus)(int*); /* függvényre mutató pointer típusa */
/* melynek nincs visszatérési értéke (void) és int-re mutató pointert vár a paraméterlistában */
/* egy tömböt vár illetve a bejar függvény alatt található művelet függvények egyikét */
void bejar(int* tomb, muvelettipus muvelet) {
int i;
for(i=0; i<N; i++) {
(*muvelet)(tomb+i); // ide kerül behelyettesítésre a paraméterként kapott művelet-függvény, mely saját bemeneti paraméterét is megkapja.
// azért kerül 'tomb+i' a paraméterlistába, mert a 'tomb' alapjáraton a paraméterként kapott tömb kezdőpozíciójára mutat,
// így a for ciklusban végig haladva, mindig i-t hazzáadva mindig a tömb rákövetkező elemét kapjuk
}
}
void beolvas(int* v) {
scanf("%d", v);
}
void kiir(int* v) {
printf("%d\n", *v);
}
void duplaz(int* v) {
(*v) *= 2;
}
int main()
{
int t[N];
bejar(t, beolvas);
bejar(t, kiir);
bejar(t, duplaz);
bejar(t, kiir);
return 0;
}
Egy egyszerűbb példa:
#include <stdio.h>
#include <time.h>
/* Csinálunk 4 fuggvenyt, ahol mindegyiknek megegyező lesz a tipusa es a bemeneti parametereknek a tipusa illetve szama is */
/* Egyszeru pelda reven legyen ez a 4 fuggveny a 4 alapmuvelet */
int osszead (int a, int b){
return a+b;
}
int kivon (int a, int b){
return a-b;
}
int szoroz (int a, int b){
return a*b;
}
int oszt (int a, int b){
if (b > 0) // mivel 0-val nem osztunk!
return a/b;
else
return 0;
}
/* hozzuk letre az ilyen fuggvenyekre mutato pointer tipust */
typedef int (*muveletekPointer)(int, int);
/* hozzunk letre egy tombot, mely az elozoleg definialt tipusu legyen,
es a 4 eleme a 4 fuggvenyunk neve legyen */
muveletekPointer muveletekTomb[] = {osszead, kivon, szoroz, oszt};
int main(){
srand(time(NULL));
int a, b, eredmeny, // 3 segedvaltozo a 2 bemeneti paramterhez es a visszaadott ertekhez
random = rand()%4; // random szam sorsolasa 0 es 3 kozott [0,3]
printf("Add meg az elso parametert: ");
scanf("%d",&a);
printf("Add meg a masodik parametert: ");
scanf("%d",&b);
/* a radnom elem alapjan kivalasztott eleme a tombnek az adott sorszamu fuggveny,
mely megkapja az elozoleg beolvasott ket erteket bemeneti parameternek.
Mint latszik a fuggvenyek hasonlosagabol adodoan az osszes fuggvenyre raillik ez a hivasmod */
eredmeny = muveletekTomb[random](a, b);
/* csak hogy legyen egy kis regen latott vezerlesi szerkezet,
az alapjan, hogy melyik muveletet sorsoltuk,
az alapjan valtozik az eredmeny kiiratasa */
switch(random){
case 0: printf("A ket szam osszege: "); break;
case 1: printf("A ket szam kulonbsege: "); break;
case 2: printf("A ket szam szorzata: "); break;
case 3: printf("A ket szam hanyadosa: "); break;
}
printf("%d\n\n", eredmeny);
return 0;
}
A main függvénynek három paramétere lehet. Az első egy int, a parancssorban kapott argumentumok száma + 1 (a program neve maga is egy argumentum). A második egy olyan pointer-tömb, mely azokra a memóriaterületekre mutatnak, ahol sztringként vannak letárolva a parancssori argumentumok. A harmadik hasonló a másodikhoz, csak ez a környezeti változók címeit tartalmazza.
Írjuk ki a parancssorban lévő argumentumokat:
#include <stdio.h>
main(int argc, char **argv)
// vagy így is lehet az argv-t deklarálni:
// main(int argc, char *argv[])
{
int i;
printf("argc = %d\n\n",argc);
for (i=0; i<argc; ++i) {
printf("argv[%d]: %s\n", i, argv[i]);
}
}
Mentsük el a fenti programot arg.c néven és fordítsuk le!
$ gcc -o arg arg.c $ ./arg alma korte szilva barack palinka argc = 6 argv[0]: ./arg argv[1]: alma argv[2]: korte argv[3]: szilva argv[4]: barack argv[5]: palinka
F: Írj egy programot, ami összeadja a parancssori paramétereket.
==============================================================================
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[])
{
int i;
int arg = 0;
printf("Osszesen %d programargumentumot kaptam!\n",argc);
for(i = 0; i< argc; i++)
printf("%d : %s\n",i, argv[i]);
if(argc > 1)
{
for(i = 1; i< argc; i++)
arg += atoi(argv[i]);
}
printf("Az argumentumok osszege : %d\n", arg);
return 0;
}
F: Írj egy programot, amely n-szer egymás után fűzi ugyanazt az s sztringet,
ahol n és s is parancssori paraméter.
==============================================================================
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char* argv[])
{
int i;
char *er;
if(argc < 3)
{
printf("Használat: %s <valami szám> <valami sztring>\n", argv[0]);
return 1;
}
er = (char*) calloc ( atoi(argv[1]) + 1 , strlen(argv[2]) );
strcpy(er,argv[2]);
for(i=0;i<atoi(argv[1])-1;i++){
strcat(er,argv[2]);
}
printf("%s\n",er);
free(er);
return 0;
}
Készíts egy programot, amely bekér egy magasságot illetve egy karaktert, majd kirajzol egy ilyen magas piramist, az így megadott karakterből.
Példa:
Add meg, hogy milyen magas legyen a piramis: 5 Add meg milyen karakterbol epuljon fel a piramis: A A AAA AAAAA AAAAAAA AAAAAAAAA
Fejlesszük tovább úgy, hogy egy rombuszt rajzoljunk ki.
Példa:
Add meg, hogy milyen magas legyen a piramis: 5 Add meg milyen karakterbol epuljon fel a piramis: A A AAA AAAAA AAAAAAA AAAAAAAAA AAAAAAA AAAAA AAA A
Egy lehetséges megoldás elérhető itt .
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ó.
A házi feladat és további gyakorló példák elérhetőek a PUB-ban ( /n/pub/ProgramozasAlapjai/Gyakorlat/ )
Bárkinek bármi kérdése adódik a feladatokkal kapcsolatban írjon nyugodtan! ( Gyakoroljatok sokat! )
Téma:
3. - 10. gyakorlat anyaga.
Gyakorlásra:
A honlapomon a 3. - 10. 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ó:
Előreláthatóan 45 percetek lesz a feladatok megoldására és beadására (tehát 8:55-ig/12:45-ig). A feladatokat 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, mivel 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.