#include <stdio.h>
#include <stdlib.h> //malloc-hoz
#include <locale.h>
#include <time.h>
int main(void)
{
setlocale(LC_ALL, "");
srand((unsigned int)time(NULL));
//Pointerek - Olyan változó, amely nem közvetlenül az értéket tartalmazza, hanem annak memória címét.
//Miért hasznosak?
//Elérheted a memóriában tárolt adatokat közvetlenül - gyorsabb működés
//A malloc, calloc és free függvények segítségével dinamikus memóriakezelés, így rugalmasan kezelheted a program erőforrásait
//Összetett adatstruktúrák, mint például láncolt listák, fák, stb. megvalósítása pointerek nélkül gyakorlatilag kivitelezhetetlen.
int c = 1;
int* p;
p = &c;
printf("--------------------------------------------------------------------------------------------------------------\n");
printf("c értéke: %i\n\
\rc címe &c=%p\n\
\rpointer által mutatott hely értéke: %i\n\
\rpointer által mutatott cím=%p\n\
\rpointer címe: &p=%p\n\n",
c, //sima értékmutatás - előző laborokban már volt
&c, //cím mutatás
*p, //DEREFERÁLÁS - a pointer típusok esetében így olvashatjuk ki belőlük a mutatott változó értékét - FONTOS RÉSZ
// ez tulajdonképpen a fordítónak olyan mintha c-t írtunk volna oda, egy változón
// keresztül elviszi a címre - valójában mindig ez történik minden egyes érték...nál,
// automatikusan a fordító úgy értelmezi a kódot ahogyan a standard utasítások is
// megkövetelik
// Akkor minek vezették be külön a pointereket?
// bizonyos esetekben muszáj pointereket használni a C-BEN pl. láncolt listák
// leprogramozására. MÁS NYELVEKBEN ahol vannak láncolt lista objektumok ott is
// valójában mögötte pointeres objektumok állnak amik pointereken keresztül
// megvalósíthatóak.
// Akkor miért nem más nyelvekkel kezdtük a "pályafutásunkat"?
// Beágyazott rendszerek és mikrovezérlők programozása: Ezekben az esetekben
// a hardver erőforrásai – mint a memória és a processzor – szűkösek,
// és a C nyelv lehetővé teszi a közvetlen hardverrelvaló kommunikációt,
// valamint a pontos memória- és erőforrás-kezelést.
// Ha egy magasabb szintű nyelven megírt programban az algoritmusok vagy
// a végrehajtás sebessége nem elegendő, egyes részeket átírhatunk C-ben
// a gyorsabb végrehajtás érdekében. Bár a C kód általában részletesebb
// és "hosszabb" lehet, ez a kompromisszum lehetővé teszi a finomhangolást
// és az optimalizációt, ami elengedhetetlen lehet bizonyos alkalmazásoknál.
//
p, //sima értékmutatás - mivel pointer típus, ő egy címet tartalmaz
&p); //cím mutatás, a pointer típusnak is van egy helye a memóriában - ne zavarjon össze minket.
printf("--------------------------------------------------------------------------------------------------------------\n");
c++; //A statikus változó értékváltoztatása
printf("c értéke: %i\n\
\r*p által mutatott változó értéke: %i\n\n",
c,
*p);
*p = 20; //A pointer áltat mutatott változónak értékadás - dereferálás: értékadás, olvasás - olyan mintha...
printf("c értéke: %i\n\
\r*p által mutatott változó értéke: %i\n",
c,
*p);
printf("--------------------------------------------------------------------------------------------------------------\n");
//PRECEDENCIA SZABÁLYOK - NAGYON FONTOS RÉSZ
*p+=1;
printf("*p által mutatott változó értéke: %i\n", *p);
(*p)++;
printf("*p által mutatott változó értéke: %i\n", *p);
//*p++; //*(p++) //Ha ilyen jellegű hibával találkozunk és nem esik le mi okozza
//printf("*p által mutatott változó értéke: %i\n", *p); //akkor egy lehetséges megoldás - minden művelet után printf()-eket rakni
//Megvizsgálni hol fordul elő először - Breakpoint, Autos, Locals ...
//*(p++); //fölöslegesnek hanzik, de gyakorlatban érdemes a biztosra menni //(Megjegyzés: VIK mérnökinformatikán a jobb programozók is
//printf("*p által mutatott változó értéke: %i\n", *p); //így csinálják sok esetben)
*p+1; //Ez a kifejezés kiszámolja, //A fordító is észreveszi, a Warningokban - C6269 warning
//hogy mennyi lenne a* p értéke,
//ha 1 - gyel növelnénk, de a számolt
//értéket nem mentjük e, nem történik
//hozzárendelés).
//Így a *p eredeti értéke változatlan marad.
printf("*p által mutatott változó értéke: %i\n",*p);
*(p+1); //A két sor a konzolon láthatóan ugyanazt eredményezi
// - de van különbség közöttük
//Itt a p+1 a következő elemre mutató cím,
//amelyet dereferálunk. Ugyanígy, az így
//kapott érték sehol sem kerül eltárolásra,
//így sem a pointer p, sem az általa mutatott
//változó nem módosul.
printf("*p által mutatott változó értéke: %i\n", *p);
printf("--------------------------------------------------------------------------------------------------------------\n");
//Dinamikus tömbkezelés
int* p_int1; //Első tömb
p_int1 = (int*)malloc(10 * sizeof(int)); //,,Ha malloc-ot mondasz, mondj free-t is..."
//Második tömb
int* p_int2 = (int*)malloc(5 * sizeof(int)); //A függvény "return-öl" egy int tömb elejére mutató pointert
//Töltsük fel és írassuk is ki az első tömb és a második tömb elemeit
for (int i = 0; i < 10; i++) { //Ez a kód csak szimbolikus, a második feltöltés és kiiratást
*p_int1 = rand() % 100; //alkalmazzuk
printf("%i. tömbelem értéke az elsőből: %i\n", i, *p_int1);
p_int1 = p_int1 + 1; //itt mindig a következő címre állítom, elcsúszik a pointer
}
//free(p_int1); //Ez egy hibás felszabadítás lenne
free(p_int1 -= 10); //Ez pedig nagyon nem elegáns, túlbonyolult
printf("\n");
//Az elvárt módszer!
for (int i = 0; i < 5; i++) {
p_int2[i] = rand() % 100;
printf("%i. tömbelem értéke a másodikból: %i\n", i, p_int2[i]);
}
free(p_int2);
printf("--------------------------------------------------------------------------------------------------------------\n");
//2D-s dinamikus tömb
int** p2d_int; //mutatóKRA mutató mutató...
p2d_int = (int**)malloc(10 * sizeof(int*)); //Helyfoglalás a mutatóKRA mutató mutatóKNAK...
for (int k = 0; k < 10; k++) { //Helyfoglalás a mutatott mutatóknak...
p2d_int[k] = (int*)malloc(10 * sizeof(int));
}
for (int m = 0; m < 10; m++) {
for (int n = 0; n < 10; n++) {
p2d_int[m][n] = (rand() % 101) - 50;
printf("p2d_int[%i][%i]=%i\n", m, n, p2d_int[m][n]);
}
free (p2d_int[m]); //Mindent felszabadítottunk?
}
free(p2d_int); //Így már igen.
return 0;
}
//Gyakorló feladatok:
//1. Feladat - Ferde hajítás
// Csináljunk egy 2D-s dinamikus double tömböt,
// legyen n*2-es méretű, 'n' db 2d-s vektort tároljon.
// Az első elemek szimbolizálják az 'x' koordinátákat, a másodikak az 'y'-okat.
// "Modellezzük" egy anyagi pont mozgását, induljunk az origóból.
//
//a) Kérjünk be egy-egy 'x' és 'y' sebességet - vízszintes sebességek [m/s]
// "Kényszerítsük" a felhasználót, hogy pozitív kezdeti y sebességet adjon meg
// Kérjünk be egy lépésközt, amivel a mozgást modellezzük amely
// időközönként a koordinátákat kiíratjuk.
// Töltsük fel a tömb elemeit az anyagi pont koordinátáival a mozgás során.
// Szabadítsuk fel.
//
//b) Legyen y irányú gravitációs gyorsulás is ami csökkenti a kezdeti sebességet,
// érjen véget a program futása ha az 'y' tengely menti pozíció 0 alá esik.
//
//c) A mozgás által rajzolt grafikon görbéjét közelítsük töröttvonallal.
// --> Számítsuk ki a töröttvonal közelítő hosszát.
// Vizsgáljuk meg, hogy konvergál-e az érték többszöri futtatással, ha a lépésközt csökkentjük.
//
//d) Alakítsuk át úgy a programot, hogy a lépésközt minden egyes töröttvonal hossz kiiratással a felére vesszük,
// és újra lefuttatjuk.
// Addig írassuk ki az újabb töröttvonalak hosszát, ameddig el nem ér egy alsó határt a lépésköz.
//
//2.Feladat
// Készítsünk integrálközelítő programot.
// Legyen az integrálközelítendő függvény 3 közul kiválasztható egy menüben: 1. e^(x^2) 2. 1/sqrt(x^3+1) 3. sin(x^2)
//
//3. Feladat
// Készítsünk egy programot ami random 3adfokú polinomokat készít, az együtthatók legyenek -25, és 25 közötti egész számok.
// A polinom egy gyökét intervallumfelező módszerral. [-10^10, +10^10] között keressük.
// Próbálkozzunk nagyobb fokú páratlan főfokszámú polinomokkal is - #include <float.h> könyvtárbeli DBL_MAX-al becsüljük,
// meg mi a határa a keresés intervallumának.