|
|
1. sor: |
1. sor: |
− | == 4. előadás (2008-03-07) == | + | == 4. előadás (2008-03-14) == |
| | | |
− | === Karakterláncok (sztringek) === | + | === Tömbök átadása paraméterként === |
| | | |
− | * karakterlánc = karakterek tömbje, melyet egy 0-kódú karakter zár. Pl.
| + | ==== Index jelölés ==== |
− | E z \n e g y \" k a r a k t e r l a n c \" \0
| + | |
− |
| + | |
− | 69 122 10 101 ... 32 34 ... 0
| + | |
− | * Karakterlánc deklarálása inicializásással:
| + | |
− | char str[] = "6 betu";
| + | |
− | vele ekvivalens a következő (miért 7?):
| + | |
− | char str[7] = "6 betu";
| + | |
− | * Karakterlánc scanf-fel való beolvasásánál nincs & a tömb neve előtt (miért? ld. később).
| + | |
− | Az alábbi programban összefűzünk két karaketrláncot úgy, hogy az első végéről levesszük a '\0' karaktert, majd odamásoljuk a második karakterláncot, amit '\0'-val zárunk.
| + | |
| | | |
− | ~/info2/osszefuz.c | + | ld a gyakorlaton: ~/info2/mx.c |
| | | |
− | #include <stdio.h>
| + | ==== Típuskényszerítés (casting) ==== |
− |
| + | |
− | int main(void)
| + | |
− | {
| + | |
− | char str1[60]="Ez\negy \"karakterlanc\"";
| + | |
− | // char str1[60]="Ez egy \"karakterlanc\", de nagyon-nagyon hosszu";
| + | |
− | char str2[60]=", ez pedig egy masik, amiben van \\.";
| + | |
− | unsigned sz1 = 0;
| + | |
− | unsigned sz2 = 0;
| + | |
− |
| + | |
− | while (str1[sz1]) sz1++; // az első karakterlánc hossza
| + | |
− | while (str2[sz2]) sz2++; // a második karakterlánc hossza
| + | |
− |
| + | |
− | if(sizeof str1 < sz1 + sz2 + 1)
| + | |
− | printf("\nAz osszefuzes nem fog menni.\n");
| + | |
− | else {
| + | |
− | sz2 = 0;
| + | |
− | while(str2[sz2]) str1[sz1++] = str2[sz2++];
| + | |
− |
| + | |
− | str1[sz1] = '\0'; // 0-val zárjuk a karakterláncot
| + | |
− | printf("\n%s\n", str1);
| + | |
− | }
| + | |
− | return 0;
| + | |
− | }
| + | |
| | | |
− | '''Feladat:''' Olvassuk be valaki nevét és korát vesszővel elválasztva, majd írjuk ki a nevét és a korát, de az utóbbiból tagadjunk le 10 évet! Használjuk a %[...] formátumot és a <code>stdlib.h</code> <code>atoi</code> nevű függvényét!
| + | ~/info2/mx2.c |
| | | |
− | #include <stdio.h>
| |
− | #include <stdlib.h>
| |
− |
| |
− | int main(void)
| |
− | {
| |
− | char nev[60];
| |
− | char kor[4];
| |
− | int sz1 = 0, sz2 = 0, k = 0;
| |
− |
| |
− | scanf("%[^,], %[0123456789]", nev, kor);
| |
− | while (nev[sz1]) sz1++; // az első karakterlánc hossza
| |
− | while (kor[sz2]) sz2++; // a második karakterlánc hossza
| |
− | k=atoi(kor)-10;
| |
− |
| |
− | printf("Neved: %s, korod: %d\n", nev, k);
| |
− |
| |
− | return 0;
| |
− | }
| |
| | | |
− | === Mutató (pointer) ===
| |
| | | |
− | * Mutató deklarálása:
| |
− | int *pn;
| |
− | * NULL egy (több headerfájlban is definiált) konstans cím, mely a memóriában nem mutat sehová.
| |
− | int *pn=NULL;
| |
− | * A NULL cím egyszerűen tesztelhető, vagyis hogy egy mutatónak adtunk-e már valódi címet: az <code>if(pn==NULL)</code> ekvivalens a <code>if(!pn)</code> kóddal.
| |
− | * & a címet adó unér művelet:
| |
− | int n;
| |
− | int *pn=&n;
| |
− | * (*pn)++ nem ugyanaz, mint *pn++ a precedenciaszabályok miatt.
| |
− | * pn++ a *pn típusának megfelelő bájtértékkel növeli a mutató értékét, tehát pl. char esetén 1-gyel, int esetén 4-gyel.
| |
− | * a scanf függvény mutatót vár, ezért a következőképp olvashatunk be egész számot:
| |
− | int n = 0, *pn;
| |
− | pn=&n;
| |
− | scanf("%d",pn);
| |
− | vagy
| |
− | scanf("%d",&n);
| |
| | | |
− | Az alábbi példában az n változóra mutat a pn mutató. Vizsgáljuk meg az értékeiket a (*pn)++; és a pn++; utasítások után!
| + | === Véletlen sorozat generálása === |
| | | |
− | ~/info2/mutato.c | + | Véletlen számok generálása: rand() az stdlib.h betöltése után egy [0,RAND_MAX] = [0,INT_MAX] intervallumba eső egészt generál. '''random seed''': srand( '''<szám>''' ) hívással befolyásolható az elsőnek generált -- és ezzel az összes -- szám, mivel ez csak álvéletlen sorozat. Valódi véletlenség látszatához használjuk a time( NULL ) függvényt. |
| + | |
| + | ~/info2/rand.c |
| #include <stdio.h> | | #include <stdio.h> |
− | int main(void) | + | #include <stdlib.h> |
− | { | + | #include <time.h> |
− | int n, *pn = NULL; // pn egy mutató, mely egy egészre mutat
| + | |
− | n = 5;
| + | |
− | pn = &n;
| + | |
| | | |
− | printf("\nn címe: %p\n", &n);
| + | int main (void) { |
− | printf("n mérete: %d\n", sizeof n);
| + | int i; |
− | printf("n értéke: %d\n", n);
| + | |
− | printf("pn címe: %p\n", &pn);
| + | |
− | printf("pn mérete: %d\n", sizeof pn);
| + | |
− | printf("pn értéke: %p\n", pn);
| + | |
− | printf("*pn értéke: %d\n", *pn); | + | |
| | | |
− | (*pn)++; | + | srand( (unsigned int) time( NULL )); // seed |
− | printf(" (*pn)++;\n");
| + | for (i=0; i<5; ++i) printf("%d ",rand()%64); // [0..RAND_MAX] |
− | printf("pn értéke: %p\n", pn); | + | printf("\n"); |
− | printf("*pn értéke: %d\n", *pn);
| + | |
− |
| + | |
− | pn++;
| + | |
− | printf(" pn++;\n");
| + | |
− | printf("pn értéke: %p\n", pn);
| + | |
− | printf("*pn értéke: %d\n", *pn); | + | |
| | | |
| return 0; | | return 0; |
| } | | } |
| | | |
− | Egy futás eredménye:
| + | === Struktúra === |
| | | |
− | n címe: 0xbfa8d2f0
| + | ==== Struktúra átadása paraméterként ==== |
− | n mérete: 4
| + | |
− | n értéke: 5
| + | |
− | pn címe: 0xbfa8d2ec
| + | |
− | pn mérete: 4
| + | |
− | pn értéke: 0xbfa8d2f0
| + | |
− | *pn értéke: 5
| + | |
− | (*pn)++;
| + | |
− | pn értéke: 0xbfa8d2f0
| + | |
− | *pn értéke: 6
| + | |
− | pn++;
| + | |
− | pn értéke: 0xbfa8d2f4
| + | |
− | *pn értéke: -1079454960
| + | |
− | | + | |
− | * Konstansok:
| + | |
− | int n=5;
| + | |
− | const int *pn = &n;
| + | |
− | esetén *pn értéke konstans, vagyis ez nem változtatható, de n értéke igen.
| + | |
− | int c=5;
| + | |
− | int *const pc=&c;
| + | |
− | esetén pc nem változtatható, de *pc igen.
| + | |
− | | + | |
− | ===Tömb és mutató=== | + | |
− | * A tömb neve önmagában, index nélkül mutatóként viselkedik (ld. scanf karakterlánc beolvasásánál).
| + | |
− | ~/info2/tombmutato.c
| + | |
− | #include <stdio.h>
| + | |
− | int main(void)
| + | |
− | {
| + | |
− | int i=0;
| + | |
− | char t[] = "karakterlanc";
| + | |
− | char *p = &t[0];
| + | |
− | printf("a tömb első elemének címe: %p\n", p);
| + | |
− | printf("a tömb címe : %p\n", t);
| + | |
− | for(; t[i]; i++)
| + | |
− | printf("%p címen: %c\n", p+i, *(p+i) );
| + | |
− |
| + | |
− | return 0;
| + | |
− | }
| + | |
− | ugyanez egészekkel:
| + | |
− | ~/info2/tombmutato1.c
| + | |
− | #include <stdio.h>
| + | |
− | int main(void)
| + | |
− | {
| + | |
− | int i=0, t[3]={11,12,13};
| + | |
− | int *p = &t[0];
| + | |
− | printf("a tömb első elemének címe: %p\n", p);
| + | |
− | printf("a tömb címe : %p\n", t);
| + | |
− | for(; i<3; i++)
| + | |
− | printf("%p címen: %d\n", p+i, *(p+i) );
| + | |
− |
| + | |
− | return 0;
| + | |
− | }
| + | |
− | | + | |
− | * a fenti példák alapján tehát: a t tömb t[i] eleme megegyezik *(p+i) vagy *(t+i) értékével, míg a cím, ahol van, a p+i vagy t+i vagy &t[i].
| + | |
− | * egy többdimenziós (pl. t[3][3]) tömb esetén t, t[0] és &t[0][0] mutatók megegyeznek.
| + | |
− | | + | |
− | #include <stdio.h>
| + | |
− | int main(void)
| + | |
− | {
| + | |
− | int i, j, t[2][2] = { {1,2}, {3,4} };
| + | |
− |
| + | |
− | for(i=0; i<2; i++) {
| + | |
− | for(j=0; j<2; j++) {
| + | |
− | printf(" %d", *(*t + 2*i + j));
| + | |
− | }
| + | |
− | printf("\n");
| + | |
− | }
| + | |
− |
| + | |
− | for(i=0; i<4; i++)
| + | |
− | printf(" %d", *(*t + i));
| + | |
− | printf("\n");
| + | |
− | return 0;
| + | |
− | }
| + | |
− | Az alábbi ábra a t tömb és a t illetve t[0] és t[1] mutatók működését szemlélteti. --> a mutatóból a mutatott helyre mutat, az = az adott címen lévő tartalom ekvivalens megadásait jelenti:
| + | |
− | t --> t[0] --> t[0][0] = *t[0] = **t t[0][1] = *(t[0]+1) = *(*t+1)
| + | |
− | t[1] --> t[1][0] = *(t[0]+2) = *(*t+2) = *t[1] t[1][1] = *(t[0]+3) = *(*t+3) = *(t[1]+1)
| + | |
Véletlen számok generálása: rand() az stdlib.h betöltése után egy [0,RAND_MAX] = [0,INT_MAX] intervallumba eső egészt generál. random seed: srand( <szám> ) hívással befolyásolható az elsőnek generált -- és ezzel az összes -- szám, mivel ez csak álvéletlen sorozat. Valódi véletlenség látszatához használjuk a time( NULL ) függvényt.