Bevezetés a C/C++ programozási nyelvbe

A C/C++ programozási nyelv elemi adattípusai

Változók deklarálása

Dinamikus memóriahasználat

Konverziós előírások (printf - formátumsztring)

Adatok beolvasása billentyűzetről

Konverziós előírások (scanf - formátumsztring)

Értékadás, műveletek

Logikai kifejezések

Vezérlési szerkezetek

Skalárszorzás

Prímszámszita

Pointeraritmetika

Láncolt lista

Feladat - Verem

Bináris fa - rekurzívan

 

 

 

C/C++ programozás

 

Bevezetés a C/C++ programozási nyelvbe

A minimális C/C++ program:

 

main()

{

}

 

vagy

 

void main()

/* Így már nem kapunk hibaüzenetet! */

{

}

 

Semmit nem csinál. A void (üres) adattípust használhatjuk

a C/C++ main függvénynél arra az esetre, ha nincs visszatérési

érték és a figyelmeztető jelzést el szeretnénk kerülni.

 

Megjegyzés fűzése bárhova: /* és */ közé lehet megjegyzést írni,

akár több sorban is. A // után is lehet megjegyzést írni, ez a

sor végéig érvényes.

 

FONTOS! Egy jó programozó, minden fontosabb, magyarázatra

szoruló programrészlethez fűz megjegyzést, hogy később könnyen

tudja értelmezni, hogy az adott programsorok mit hajtanak végre.

 

Írjunk ki valamit a képernyőre!

 

Ezt megvalósító függvény, és paraméterei:

 

int printf( const char *format [, argument, ...] );

int printf( "formátum sztring", argumentumlista );

 

Visszatérési érték: a sikeresen kiírt karakterek száma.

 

A függvény prototípusa az STDIO.H fájlban található.

Használata: #include <stdio.h>

 

Példa:

 

void main()

{

   printf("Ezt kiírja a képernyőre!");

}

 

Írjunk ki két sorban valamit a képernyőre!

 

void main()

{

   printf("1. sor\n2. sor");

}

 

Eredmény:

 

1. sor

2. sor

 

Vegyük észre a '\n' speciális karaktert, ami egy ENTER billentyű

lenyomásával egyenértékű, vagyis egy kocsi-vissza és soremelés

parancsot hajt végre.

 

Formázási lehetőségeink kiíratásnál (és máshol):

 

újsor            \n

null karakter    \0

vízszintes tab   \t

vissza-szóköz    \b

kocsi-vissza     \r

lapdobás         \f

ford. törtv.     \\

aposztróf        \`

idézőjel         \"

bitminta         \ddd

 

Példa:

 

void main()

{

   printf("   Nézzünk bele a\n\t\"C/C++\"\n     nyelvbe!");

}

 

Eredmény:

 

   Nézzünk bele a

      "C/C++"

     nyelvbe!

 

Láthatjuk az üres helyek, az új sorok és a tabulálás hatását,

valamint az idézőjelek kiírásának módját.

 

A C/C++ programozási nyelv elemi adattípusai

C típus           méret   alsó határ  felső határ  PASCAL típus

---------------------------------------------------------------

char                1              -           -      Char

signed char         1           -128          127     Shortint

unsigned char       1              0          255     Byte

short int           2         -32768        32767     Integer

unsigned short int  2              0        65535     Word

int                 4    -2147483648   2147483647     Longint

unsigned int        4              0   4294967295     -

long int            4    -2147483648   2147483647     Longint

unsigned long int   4              0   4294967295     -

float               4    -+3.4028234663852886E+38     Single

double              8   -+1.7976931348623157E+308     Double

long double         8   -+1.7976931348623157E+308     Double

 

További típusok: void, összetett (struct, union), absztrakt, stb.

Változók deklarálása

Értékadás: 1. deklarációnál, 2. később.

Mindkettő esetében számoknál az '=' jellel.

Karakterek esetében az '=' jellel aposztrófok (') között.

Szövegnél deklaráció esetében az '=' jellel idézőjelek (") között.

Később pedig egy speciális függvénnyel: strcpy();

 

Nézzünk néhány példát a gyakran alkalmazott változókra:

 

deklaráció                  // leírás

 

int i;                      // i változó egy egész számot tartalmazhat

int ii = 152;               // ii értéke: 152, egész szám

double j;                   // j változó egy duplapontosságú

                            // valós számot tartalmazhat

float k;                    // k változó egy valós számot tartalmazhat

float k2 = 1.234;           // k2 értéke valós szám: 1.234

char c;                     // c egy karaktert tartalmazhat

char z[9];                  // z max. 8 karaktert tartalmazhat

                            // a végén EOS ('\0') karakternek hely kell

char sz[6] = "Omega"        // sz egy sztring, az Omega szót

                            // tartalmazza

char *s = "Omega"           // s egy sztring...

 

Típus definiálása:

 

typedef <típusdefiníció> <azonosító>

 

typedef unsigned char byte;

typedef char str40[41];

typedef struct {

  double re, im;

} complex;

 

Lehetőség van konstansok definiálására: #define HAT 6

 

Tömb, mátrix definiálása:

 

int tomb[5];                 // 5 elemű egész számokat tartalmazó tömb

típus tömbnév[méret];        // általánosan az egydimenziós tömb

int matrix[4][2];            // 4x2-es mátrix, egész számok

típus tömbnév[méret][méret]; // általánosan a kétdimenziós tömb

 

A tömb elemeinek típusa a void kivételével tetszőleges lehet.

 

A tömb elemeire való hivatkozás: tomb[0], ..., tomb[4]

 

A mátrix elemeire való hivatkozás:

 

1. elem: matrix[0][0]

2. elem: matrix[0][1]

3. elem: matrix[1][0]

4. elem: matrix[1][1]

5. elem: matrix[2][0]

6. elem: matrix[2][1]

7. elem: matrix[3][0]

8. elem: matrix[3][1]

 

Hivatkozás a sztring egyes karaktereire, példa:

 

char s[6] = "Omega";

// A sztringet az EOS ('\0') zárja, ezért 6 karakteres tömb kell.

printf("%c%c%c%c%c",s[0],s[1],s[2],s[3],s[4]);

 

Ennek hatására kiírja: Omega

(s[5] = '\0', End Of String, sztring végét jelzi!)

Dinamikus memóriahasználat

Dinamikus memóriahasználattal való deklarálás:

 

double *a;

 

Jelentése: az 'a' változó lebegőpontos kétszeres pontosságú változóra

mutató pointert képes tárolni, de jelenleg tartalma határozatlan.

 

A memóriát dinamikusan a malloc függvénnyel foglalhatjuk le.

(Prototípusa: STDLIB.H, MALLOC.H fájlokban található.)

 

Egy típus méretét (helyfoglalását) a sizeof(típusnév) függvény adja meg.

 

Típuskényszerítés (type cast, kasztolás): i = (int)5.123;

Az i változó az 5 egész számot fogja tartalmazni, függetlenül attól,

hogy az 5.123 számmal tettük egyenlővé. Sőt: i = 5.123; esetén is, ezt

hívjuk automatikus típuskényszerítésnek (a fordító intelligens :).

 

Tehát a teljes dinamikus memóriafoglalás:

 

double *a;

a = (double*)malloc(sizeof(double));

 

Értékadás egyszerűen: *a = 5;

Kiírás például: cout << *a; vagy printf("%f",*a);

 

A lefoglalt memória felszabadítása - ha már nincs szükség rá -,

ettől dinamikus a memóriafoglalás: free(a);

Konverziós előírások (printf - formátumsztring)

jel jelző mezőszélesség pontosság méretmódosító konverziós betű

 %   -#0       15           .5          1              d

 

jelző     hatás

-         balra igazítás

+         a számoknál az előjel (+,-) mindig megjelenik

szóköz    előjel helyén a - vagy szóköz jelenik meg

0         a szóköz 0-val töltődik fel az adat előtt

#         a hexadecimális számok előtt 0x, az oktális számok

          előtt 0 előtag jelenik meg

 

Egy konverziós előírásnak legalább a kezdő % jelet és a konverzió

típusára utaló betűt (kódot) kell tartalmaznia!

 

kód   argumentum   formátum

        típusa

%c    int          egyetlen karakter

%d    int          előjeles decimális egész

%ld   long int     előjeles hosszú decimális egész

%f    float        [-]ddd.dddd, ahol a tizedesjegyek száma az

                   előírt pontosságtól függ. Fixpontos kiírási

                   mód, alapértelmezés 6 tizedes, 0 pontosság

                   esetén a tizedespont nem íródik ki.

%lf   double       hasonló a %f formátumhoz

%e,   double       [-]d.dddde+-ddd, vagy [-]d.ddddE+-ddd a

%E                 tizedesjegyek száma az előírt pontosságtól függ

%g,   double       %e, %E, ha az exponens kisebb, mint -4, vagy a

%G                 >= mint a pontosság, különben %f formátum.

%o    int          előjel nélküli oktális egész 0 előtag nélkül

%s    char*        sztring karakterei '\0' (EOS) karakterig

%x,%X int          hexadecimális egész 0x előtag nélkül

%p    void*        mutató értéke

 

Megjegyzés: EOS = End Of String, a sztring végét jelző karakter

            egy null (\0) karakter!

 

Példák, hogy könnyebben megértsük a fent leírtakat:

 

Deklaráljuk a megfelelő változókat:

 

char         c = '*';

char         *s = "csillag";

short int    i = 15;

int          j = -1234;

unsigned int k = 3;

long         m = -12000L;

float        x = -12.456;

double       y = 2.3456789;

 

utasítás                       // eredmény

 

printf("1234567890\n");        // 1234567890

printf("%c\n",c);              // *

printf("%4c\n",c);             //     *

printf("%-4c\n",c);            // *

printf("%s\n",s);              // csillag

printf("%10.7s\n",s);          //    csillag

printf("%10.2s\n",s);          //         cs

printf("%-10.7s\n",s);         // csillag

printf("%-10.2s\n",s);         // cs

printf("%d\n",i);              // 15

printf("%5d\n",i);             //    15

printf("%-5d\n",i);            // 15

printf("%05d\n",i);            // 00015

printf("%d\n",j);              // -1234

printf("%6d\n",j);             //  -1234

printf("%d\n",k);              // 3

printf("%3d\n",k);             //   3

printf("%ld\n",m);             // -12000

printf("%8ld\n",m);            //   -12000

printf("%d  %u  %ld\n",j,k,m); // -1234  3  -12000

printf("%f\n",x);              // -12.456000

printf("%10.3f\n",x);          //    -12.456

printf("%-10.3f\n",x);         // -12.456

printf("%g\n",x);              // -12.456

printf("%e\n",x);              // -1.24560e+01

printf("%lf\n",y);             // 2.345679

printf("%e\n",y);              // 2.34568e+00

printf("%9.2e\n",y);           //   2.3e+00

Adatok beolvasása billentyűzetről

Olvassunk be valamit a billentyűzetről!

 

Ezt megvalósító függvény, és paraméterei:

 

int scanf( const char *format [, argument, ...] );

int scanf( "formátum sztring", argumentumlista );

 

Visszatérési érték: a sikeresen beolvasott karakterek száma.

 

A függvény prototípusa az STDIO.H fájlban található.

Használata: #include <stdio.h>

 

Példa:

 

#include <stdio.h>

void main()

{

   int i;

   scanf("%d",&i);

}

 

A parancs egy egész számot vár a billentyűzetről, ezt a

számot eltárolja a 'i' változóban. Láthatjuk,hogy az

argumentumlista helyére memóriacímeket kell írni, ahova a

beolvasott adatok kerülnek.

Tehát, az 'i' változó memóriacíme: &i

Konverziós előírások (scanf - formátumsztring)

konverziós                input adat               argumentum

 karakter                                            típusa

 

    d        decimális egész                       int*

    ld       decimális egész                       long*

    i        egész szám, oktális és hexadeximális

             is lehet

    o        oktális szám a 0 előtag nélkül        int*

    u        előjel nélküli decimális szám         unsigned*

    x        hexadecimális egész, 0x... vagy 0X... int*

    c        karakter, a tagoló karakterek is      char*

             beolvasásra kerülnek

    s        sztring olvasása tagoló karakterig    char*

    f,e,g    lebegőpontos számok beolvasása        float*

    E,G      %lf esetén az argumentum típusa:      double*

             az L előtag esetén az argum. típusa:  long double*

    p        a printf által kiírt formátumú        void**

             mutató értékét olvassa be

    n        a formátumig beolvasott karakterek    int*

             számát adja vissza a függvény az

             argumentummal kijelölt egész (int)

             típusú válzozóban

 

A scanf formátumsztring elemei:

 

   - a tagoló (whitespace) karakterek, ezeket a függvény

     figyelmen kívül hagyja,

   - % karakterrel kezdődik a konverziós előírás, mely

     opcionálisan tartalmazhat:

        *      csillag karaktert, hatására a beolvasott szám

               eldobódik,

        n      mezőszélességet megadó decimális egész számot,

        h,l,L  opcionális méretkijelölő karaktert:

               h (short), l (long vagy double),

               L (long double)

 

Rövid példa:

 

int i;

char c;

char s[11]; // max. 10 karakter hosszú szöveg

float x;

 

scanf("%d",&i);      // egy egész szám beolvasása

scanf("%c",&c);      // egy karakter beolvasása

scanf("%s",s);       // sztring beolvasása, az & nem kell!!!

scanf("%f",&x);      // egy valós szám beolvasása

 

Kiírásuk:

 

printf("i = %d\nc = %c\ns = %s\nx = %f", i, c, s, x);

 

Eredmény:

 

i = 5      // ha 5-öst nyomtuk le

c = a      // ha az 'a' betűt nyomtuk le

s = Szia   // ha a "Szia" szót írtuk be

x = 1.234  // ha az 1.234 számot írtuk be

 

További függvények, melyek életünket megkönnyítik:

 

int getchar(void);   // karakter beolvasása egy változóba

int putchar(int c);  // karakter kiírása a képernyőre

 

A függvények prototípusa az STDIO.H fájlban található.

 

Példa:

 

int c;

c = getchar();  // nyomunk egy 'a' betűt

putchar(c);     // kiír egy 'a' betűt, hitted volna? :)

 

char *gets(char *s);     // egy sor olvasása, vagyis az Enter

                            billentyű lenyomásáig olvas be,

                            tehát '\n' karakterig

int puts(const char *s); // Egy sor kiírása, vagyis a '\n'

                            karakterig ír ki

 

A függvények prototípusa az STDIO.H fájlban található.

 

Példa:

 

char s[16]; // max. 15 karakter

gets(s);    // beírjuk: Omega a király!

puts(s);    // kiírja: Omega a király! (hitted volna?)

 

További lehetőségek kiírásra és beolvasásra:

 

cin  >> változó;  -  billentyűzetről változóba beolvasás

cout << "formázott szöveg" vagy változó;  -  kiírás

 

A prototípus az IOSTREAM.H fájlban található.

 

Példa:

 

#include <iostream.h>

void main()

{

  int i;

  cin  >> i; // beírjuk: 5

  cout << "\nBeírt szám: " << i;

  //Kiírja: Beírt szám: 5

}

 

Értékadás, műveletek

Számoknál az '=' jellel, példa: szam = 5; (int szam;)

Karakterek esetében az '=' jellel aposztrófok (') között,

példa: c = 'F'; (char c;)

Szövegnél deklaráció esetében az '=' jellel idézőjelek (") között,

példa: char szoveg[16] = "Egy egy szöveg.";

Deklaráción kívűl pedig egy speciális függvénnyel,

ami sztring másolására szolgál:

 

char *strcpy(char *cel, const char *targy);

 

Visszatérési érték: a cél.

 

A függvény prototípusa az STRING.H fájlban található.

Használata: #include <string.h>

 

Példa:

 

#include <string.h>

void main()

{

   char s[25];

   strcpy(s,"Ez egy példa.");   // 's' tartalma: Ez egy példa.

}

 

Példa #2:

 

#include <string.h>

void main()

{

   char s[25] = "Ez egy másik példa.";

   char z[25];

   strcpy(z,s);   // 'z' meg fog egyezni 's'-sel

}

 

Alapműveletek:

 

+, -     összeadás, kivonás

*, /     szorzás, osztás

%        osztás maradéka (modulo)

 

További műveletek:

 

++       inkrementálás ( i++ <=> ++i <=> i = i + 1 )

--       dekrementálás ( i-- <=> --i <=> i = i - 1 )

 

Egyszerűsítések (példa):

 

i = i + 1; helyett i++;

i = i - 5; helyett i -= 5; (további: *=, /=, %=, ...)

 

Példák:

 

int i = 2;

int j = 5;

int z = 2;

double a;

 

z = i++;     // z értéke: 2, i értéke: 3 (!!!)

z = ++i;     // z értéke: 3, i értéke: 3

z = j--;     // z értéke: 5, j értéke: 4 (!!!)

z = --j;     // z értéke: 4, j értéke: 4

z = ++i--;   // helytelen, továbbá: --i++, --i--, ++i++

 

z = i + j;        // z értéke: 7, többi változatlan

z = z * (i + 1);  // z értéke: 3, többi változatlan

z *= i + 1;       // z értéke: 3, többi változatlan

z = i - j;        // z értéke: -3, többi változatlan

z = ++i + j;      // z értéke: 8, i értéke: 3

z = --i + j++;    // z értéke: 6, i értéke: 1, j értéke: 6 (!!!)

 

a = i / j;         // a értéke: 0.4

a = (int) i / j;   // a értéke: 0, levágja a tizedesjegyeket

a = i % j;         // a értéke: 2

 

Megjegyzés: 'a' mindig valós típusú marad, függetlenül

            attól, hogy egész szám is lehet az értéke.

 

Magyarázat (a kifejezés kiértékelésének sorrendje miatt):

 

z = ++i; esetén: előbb növeljük i értékét, majd azt átadjuk z-nek

z = j--; esetén: előbb átadjuk z-nek j értékét, majd j értékét

                 csökkentjük

z = --i + j++; esetén: előbb csökkentjük i értékét, hozzáadjuk

                       j értékét és ezt átadjuk z-nek, majd

                       j értékét növeljük

 

Bitműveletek:

 

<<   balra léptetés

>>   jobbra léptetés

&    bitek közötti ÉS   (AND)     ÉS 0 1    VAGY 0 1     KV 0 1

|    bitek közötti VAGY (OR)       0 0 0       0 0 1      0 0 1

^    KIZÁRÓ VAGY        (XOR)      1 0 1       1 1 1      1 1 0

~    egyes komplemens képzés

-    kettes komplemens képzés

 

Nagyon jó példa bitműveletekre:

 

#include <stdio.h>

void main()

{

   int a,b,c;

   char *format1 = "%04x  %s  %04x = %04x\n";      // formátumsztringek

   char *format2 = "%c %04x = %04x\n";             // deklarációja, így is lehet!

   a = 0x0ff0; b = 0xff00;                         // Amit a progi kiír:

   printf("a = %d  %04x  b = %d  %04x\n",a,a,b,b); // a = 4080  0ff0  b = -256  ff00

   printf("Bitműveletek:\n");                      // Bitműveletek:

   c = a << 4; printf(format1,a,"<<",4,c);         // 0ff0  <<  0004 = ff00

   c = a >> 4; printf(format1,a,">>",4,c);         // 0ff0  >>  0004 = 00ff

   c = a & b;  printf(format1,a," &",b,c);         // 0ff0   &  ff00 = 0f00

   c = a | b;  printf(format1,a," |",b,c);         // 0ff0   |  ff00 = fff0

   c = a ^ b;  printf(format1,a," ^",b,c);         // 0ff0   ^  ff00 = f0f0

   c = ~a;     printf(format2,'~',a,c);            // ~ 0ff0 = f0f0

   c = -a;     printf(format2,'-',a,c);            // - 0ff0 = f010

}

 

Magyarázat másik példán keresztül

 

i = 000001110110 = 118

j = 000001011001 =  89

 

i << 4;

 

i értékét bitenként 4-gyel balra léptetjük

régi érték: 000001110110 = 118

új érték:   011101100000 = 1888

Gyakorlatilag 16-tal szoroztuk, a balra bitléptetés

mindig 2-vel való szorzást jelent (lépésenként).

 

i >> 4;

 

i értékét bitenként 4-gyel jobbra léptetjük

régi érték: 000001110110 = 118

új érték:   000000000111 = 7

Gyakorlatilag 16-tal osztottuk, a balra bitléptetés

mindig 2-vel való egész osztást jelent (lépésenként).

 

i & j;

 

i = 1110110 = 118

j = 1011001 =  89

e = 1010000 =  80 // bitenkénti ÉS eredménye

 

i | j;

 

i = 1110110 = 118

j = 1011001 =  89

e = 1111111 = 127 // bitenkénti VAGY eredménye

 

i ^ j;

 

i = 1110110 = 118

j = 1011001 =  89

e = 0101111 =  47 // bitenkénti KIZÁRÓ VAGY eredménye

j = 1011001 =  89 // ismételt bitenkénti KIZÁRÓ VAGY

e = 1110110 = 118 // eredménye a kiindulási állapot

Logikai kifejezések

Relációk:

 

==   egyenlő

!=   nem egyenlő

<    kisebb

>    nagyobb

<=   kisebb vagy egyenlő

>=   nagyobb vagy egyenlő

 

Logikai kifejezésekben használjuk:

 

&&   logikai és

||   logikai vagy

 

A logikai kifejezésekre példa:

 

i <= 5

j != 6

(k > 5) && (k != m)

('a' <= kisbetu) && (kisbetu <= 'z')

 

Két sztring egyenlőségének vizsgálata:

 

int strcmp(const char *s1, const char *s2);

 

Visszatérési érték:

 

<  0, ha s1 <  s2

== 0, ha s1 == s2

>  0, ha s1 >  s2

 

A függvény prototípusa az STRING.H fájlban található.

Használata: #include <string.h>

 

Példa:

 

#include <string.h>

void main()

{

   char s1[6]="Omega";

   int i;

   i = strcpy(s1,"Omega");   // i értéke 0 lesz

}

Vezérlési szerkezetek

A beugró anyaga

 

Szekvenciális vezérlés

 

utasítások sorozata, kettősponttal elválasztva

 

{                   Példa:

   P1;

   P2;              int i;

   ...              printf("%d",i);

   Pn;              ...

}

 

P1, P2, ..., Pn: utasítások

 

Szelekciós vezérlések

 

Egyszerű szelekciós vezérlés egyébként ággal

 

if (F) {     if ( i == 5 ) {

   A;          cout << "i értéke pontosan 5!";

} else {     } else {

   B;          cout << "i nem 5, hanem: " << i;

}            }

 

F: logikai kifejezés

A,B: utasítások

 

Többszörös szelekciós vezérlés egyébként ággal

 

if (F1) {            if ( i == 0 ) {

    A1;                 printf("i értéke pontosan 0!");

} else if (F2) {     } else if ( i == 1 ) {

    A2;                 printf("i értéke pontosan 1!");

...                  ...

} else if (Fn) {     } else if ( i == 9 ) {

    An;                 printf("i értéke pontosan 9!");

} else {             } else {

    B;                  printf("i értéke pontosan %d!",i);

}                    }

 

F1, F2, ..., Fn: logikai kifejezések

A1, A2, ..., An, B: utasítások

 

Esetkiválasztásos szelekciós vezérlés egyébként ággal

 

switch (K) {         switch (i) {

case H1:             case 0:

     A1;                  printf("i értéke pontosan 0!");

     break;               break;

case H2:             case 1:

     A2;                  printf("i értéke pontosan 1!");

     break;               break;

...                  ...

case Hn:             case 9:

     An;                  printf("i értéke pontosan 9!");

     break;               break;

default:             default:

     B;                   printf("i értéke pontosan %d!",i);

     break;               break;

}                    }

 

K: kulcskifejezés

H1, H2, ..., Hn: kulcskifejezés lehetséges értékei

A1, A2, ..., An, B: utasítások

 

Ha a H1 halmaz nem egyelemű, hanem elemei x1, x2, ..., xm

ekkor az első esetet így kódoljuk:

 

case x1:

case x2:

...

case xm:

     A1;

     break;

 

Megjegyzés: a break utasítás szolgál a

vezérlés megszakítására.

 

Ismétléses vezérlések

 

Kezdőfeltételes ismétléses vezérlés

 

while (F) {        F: logikai kifejezés

      M;           M: utasítások

}

 

Példa: számok kiírása 0-tól 9-ig

 

int i = 0;

while (i < 10) {

   cout << i << "\n";

   i++;

}

 

Végfeltételes ismétléses vezérlés

 

do {

   M;              M: utasítások

} while (!F);      F: logikai kifejezés

 

Példa: számok kiírása 0-tól 9-ig

 

int i = 0;

do {

   cout << i << "\n";

   i++;

} while ( i != 10 );

 

Kezdőfeltételes <=> Végfeltételes

 

while ( i > 0 ) {         do {

  // parancsok      <=>     // parancsok

}                         } while ( i <= 0 );

 

Így a végeredmény ugyanaz.

 

Növekvő számlálásos ismétléses vezérlés

 

for ( kezdeti érték; végfeltétel; növekmény ) {

    parancsok;

}

 

for ( i = a; i <= b; i++ ) {

    M;

}

 

Példa:

 

for ( int i = 0; i <= 10; i++ ) {

    printf("i értéke: %d\n",i);

}

 

Megjegyzés: Ha az i változót először hasznájuk,

akkor lehetőség van a C++ nyelvben a kezdeti érték

megadásánál deklarálni. ( int i = 0 )

 

Csökkenő számlálásos ismétléses vezérlés

 

for ( kezdeti érték; végfeltétel; csökkenés ) {

    parancsok;

}

 

for ( i = b; i >= a; i-- ) {

    M;

}

 

Példa:

 

for ( int i = 10; i >= 0; i-- ) {

    printf("i értéke: %d\n",i);

}

 

Hurok ismétléses vezérlés

 

while (1) {

      M0;

      if (F1) {

          K1;

          break;

      }

      M1;

      ...

      if (Fn) {

          Kn;

          break;

      }

      Mn;

}

 

Diszkrét ismétléses vezérlés

 

A diszkrét ismétléses vezérlének nincs közvetlen

megvalósítása se a PASCAL nyelvben, se a C/C++ nyelvben.

A megvalósítás elsősorban attól függ, hogy az ismétlési

feltételben megadott halmazt hogyan reprezentáljuk.

 

 

 

 

C / C++

Skalárszorzás

Adott két vektor x és y. Írjunk függvényt mely kiszámítja skalárszorzatukat.

#include <stdio.h>

 

double dot( double u[3], double v[3] ) {

  double d = 0;

  int i;

  for ( i = 0; i < 3 ; i++ )

    d += u[i] * v[i];

  return d;

}

 

void main() {

  double x[] = {1, 3, 0};

  double y[] = {2, 1, 1};

  printf("X x Y = %f\n", dot(x,y) );

 

  getchar();

}

 

Prímszámszita

#include <stdio.h>

 

#define MAX 10000

#define PRIM 1

#define NEMPRIM 0

 

void main() {

  int t[MAX];

  int i,j;

 

  //kezdetben legyen minden prim

  for ( i = 2; i < MAX; i++ ) {

    t[i] = PRIM;

  }

 

  for ( i = 2; i < MAX; i++ ) {

    //minden i nek a többszörösét

    //kivesszük a prímek közül

    for ( j = 2*i; j < MAX; j += i ) {

      t[j] = NEMPRIM;

    }

  }

 

  //kiírjuk a primeket

  for ( i = 2; i < MAX; i++ ) {

    if ( t[i] == PRIM ) printf("%d ", i );

  }

  printf("\n");

 

  getchar();

}

 

Pointeraritmetika

Mint az előző feladat, csak pointerekkel...

#include <stdio.h>

#include <stdlib.h>

 

#define MAX 10000

 

double dot( double *u, double *v ) {

  double d = 0;

  int i;

  for ( i = 0; i < 3 ; i++ ) {

    printf("%f, %f\n", u[i], v[i] );

    d += u[i] * v[i];

  }

  return d;

}

 

void main() {

  double *x;

  double *y;

  x = (double *)malloc(3*sizeof(double));

  y = (double *)malloc(3*sizeof(double));

 

  *x = 1;

  *(x+1) = 2;

  *(x+2) = 0;

 

  *y = 1;

  *(y+1) = 3;

  *(y+2) = 0;

 

  printf("X x Y = %f\n", dot(x,y) );

 

  free(x);

  free(y);

 

  getchar();

}

Láncolt lista

#include <stdio.h>

#include <stdlib.h>

 

struct elem {

  int value;

  elem *next;

};

 

struct linkedlist{

  elem *first;

  elem *last;

} list;

 

void vegererak(int v) {

  elem *e= (elem *) malloc( sizeof(elem) );

  if ( list.first == NULL ) list.first = e;

  else list.last->next = e;

  list.last = e;

  e->value = v;

  e->next = NULL;

}

 

void dump() {

  elem *e;

  for ( e = list.first; e != NULL ; e = e->next )

    printf("%d ", e->value );

  printf("\n");

}

 

void deletelist() {

  elem *e, *n;

  for ( e = list.first; e != NULL; e = n ) {

    n = e->next;

    free(e);

  }

}

 

void deleteval(int v) {

  elem *e, *p;

  //az e altal mutatott elemet töröljük,

  //míg p az egyel előtte levő elemre mutat

 

  for ( e = list.first, p = NULL;

        e != NULL && e->value != v;

        p = e, e = e->next );

  if ( e != NULL ) {

    if ( p == NULL ) list.first = e->next;

    else p->next = e->next;

    free(e);

  }

 

}

 

void beszur(int v) {

  //v-szerinti sorrendben szúrja be az elemeket

 

  elem *e, *p, *f;

  //e mutat a következőre,

  //p az előzőre,

  //f az új elemre

 

  f = (elem *) malloc(sizeof(elem));

  f->value = v;

 

  if ( list.first == NULL ) {

    list.first = f;

    list.last = f;

    f->next = NULL;

  }

  else {

    for ( e = list.first, p = NULL;

          e != NULL && e->value < v;

          p = e, e = e->next );

    f->next = e;

 

    if ( p == NULL )   //az elejére raktuj f-et

      list.first = f;

    else p->next = f; //valahova a közepére raktuk

    if ( e == NULL )  //a végére raktuk

      list.last = f;

  }

}

 

void main() {

  vegererak(4);

  beszur(6);

  vegererak(3);

  dump();

  deletelist();

  getchar();

}

Feladat - Verem

Valósítsd meg a verem adatszerkezetet lancolt listakkal! A verem a következő műveletekkel rendelkezzen: push() a verem tetejére rak egy elemet. pop() levesz a verem tetejéről egy elemet. urese() akkor es csak akkor ad vissza igaz erteket, ha a verem nem tartalmaz egyetlen elemet sem.

Feladat - Sor

Valósítsd meg a sor adatszerkezetet lancolt listakkal! A sor a következő műveletekkel rendelkezzen: push() a sor elejére rak egy elemet. pop() levesz a sor végéről egy elemet. urese() akkor es csak akkor ad vissza igaz erteket, ha a sor nem tartalmaz egyetlen elemet sem.

Feladat

Írj egy olyan lancolt listát, amelyikbe egy adat csak egyszer kerülhet bele. Pl, ha a 4 már eleme volt a listának, akkor nem rakja be újra.

Feladat

Írj egy lancolt listás programot, amely a rendelkezik a köv 3 függvénnyel. berak( adat ) hozzá tud adni a listahoz; torol() felszabadítja az egész listát; cserél()megcseréli az első és az utolsó elemet (mar hogyha vannak olyanok... :)

Feladat

Írj egy lancolt listás programot, amely a rendelkezik a köv 3 függvénnyel. berak( adat ) hozzá tud adni a listahoz; torol() felszabadítja az egész listát; cserél( melyiket, melyikkel )megcseréli az adott két elemet (mar hogyha vannak olyanok... :)

Feladat - Duplán linkelt lista

Írj olyan láncolt listát, ahol az elemek visszafelé is linkelve vannak. Valósítsd meg a beszúr, töröl, kiir műveleteket.

File tárolása láncolt listában

Számoljuk meg hogy egy fileban a szavak hányszor fordulnak elő.

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

 

struct elem {

  char *text;

  elem *next;

  unsigned count;

};

 

struct linkedlist{

  elem *first;

} list;

 

void dump() {

  elem *e;

  for ( e = list.first; e != NULL ; e = e->next ) {

    printf("%s: %u\n", e->text, e->count);

  }

  printf("\n");

}

 

void deletelist() {

  elem *e, *n;

  for ( e = list.first; e != NULL; e = n ) {

    n = e->next;

    free(e->text);

    free(e);

  }

}

 

void beszur(char *v) {

  elem *e, *p, *f;

  int i;

  for ( e = list.first, p = NULL;

        e != NULL && (i=strcmp( e->text, v)) <  0 ;

        p = e, e = e->next );

  if ( i == 0 ) e->count++;

  else {

    f = (elem *) malloc(sizeof(elem));

    f->text = (char *)malloc(sizeof(char)*strlen(v)+1);

      //a hossznal egyel több,

      //mert a EOS bytenak is kell hely

    f->count = 1;

    strcpy(f->text, v);

    f->next = e;

    if ( p == NULL ) list.first = f;

    else p->next = f;

  }

}

 

void main() {

  FILE *f;

  char str[1024];

  f = fopen("my.txt", "rt" );

  while ( fscanf(f, "%s", str)!= EOF ) {

    beszur(str);

  }

  fclose(f);

 

  dump();

  deletelist();

  getchar();

}

Bináris fa - rekurzívan

#include <stdio.h>

#include <stdlib.h>

 

struct elem {

  elem *left, *right;

  int data;

};

 

struct btree {

  elem *root;

} tree;

 

elem * uj(int d) {

  elem *e;

  e = (elem *) malloc(sizeof(elem));

  e->left = e->right = NULL;

  e->data = d;

  return e;

}

 

void beszur(elem *e, int d) {

  if ( e->data > d )

    if ( e->left != NULL ) beszur(e->left, d);

    else e->left = uj(d);

  else if ( e->data < d ) {

    if ( e->right != NULL ) beszur(e->right, d);

    else e->right = uj(d);

  }

}

 

void beszur( int d) {

  if ( tree.root == NULL ) {

    tree.root = uj(d);

  }

  else beszur(tree.root, d);

}

 

void felszabadit(elem *e ) {

  if ( e->left != NULL ) felszabadit(e->left);

  if ( e->right != NULL ) felszabadit(e->right);

  free(e);

}

 

void felszabadit() {

  if ( tree.root!= NULL )

    felszabadit(tree.root);

}

 

void kiir(elem *e) {

  if ( e->left != NULL ) kiir(e->left);

  printf("%d ", e->data);

  if ( e->right != NULL ) kiir(e->right);

}

 

void kiir() {

  if (tree.root != NULL ) kiir(tree.root);

  printf("\n");

}

 

void main() {

  beszur(2);

  beszur(6);

  beszur(4);

  kiir();

  felszabadit();

 

  getchar();

}