Info2/2008tavasz/kuka

A MathWikiből
(Változatok közti eltérés)
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)
+

A lap 2008. március 14., 06:57-kori változata

Tartalomjegyzék

4. előadás (2008-03-14)

Tömbök átadása paraméterként

Index jelölés

ld a gyakorlaton: ~/info2/mx.c

Típuskényszerítés (casting)

~/info2/mx2.c



Véletlen sorozat generálása

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 <stdlib.h>
#include <time.h>

int main (void) {
  int i;

  srand( (unsigned int) time( NULL ));         // seed
  for (i=0; i<5; ++i) printf("%d ",rand()%64); // [0..RAND_MAX]
  printf("\n");

  return 0;
}

Struktúra

Struktúra átadása paraméterként

Személyes eszközök