Új hozzászólás Aktív témák
-
VaZso
senior tag
válasz
skoda12 #1493 üzenetére
Upsz... még mindig nem vagyok "képben"...
Itt kicsit más értékek vannak, mint amit a gépemen tapasztaltam.
Vélhetően azért, mert ez x64-es rendszer.Mégjobban elbizonytalanodtam, hogy az egyes változóknál milyen tartományt kéne figyelnem, hogy ne csorduljon túl...
Eszerint 32-bites rendszeren a short és az int is 2 byte-os és a long 4 byte-os?
Float működése ill. határai még mindig nem tiszta...
-
3man
csendes tag
Az xml-re ra lehet epiteni egy olyan config-rendszert, ahol mar azzal sem kell foglalkozni, hogy az adott valtozo int, float vagy eppen string tipusu. Sot az xml definialhatja a valtozokat, a programban a valtozonak nem is kell jelen lenniuk alapbol.
Gondolom elso hallasra furcsan hangzik, de megoldhato egyszeruen.
Eloszor letre kell hozni egy altalanos "valtozo" osztaly. /bocs, megint c++, de itt merult fel a tema./
Az xml-ben egy definicio valahogy igy nez ki : valami="100.2".class altalanos_valtozo {
public:
char *nev;
int tipus;
char *ertek;
};A valtozo neve lesz a "valami", az erteke pedig a "100.2". A tipus egyszeruen meghatarozhato, ha csak szamokat es elojelet tartalmaz, akkor int, ha pontot is ,akkor float, a tobbi esetben string. De lehet egyenileg kialakitani tobb tipust is.
Meg nehany konvertalo operatort kell az osztalyhoz adni, es mar kesz is egy kenyelmesen hasznalhato altalanos valtozo, ami egy xml kezelovel kiegeszitve egy tokeletes config kezelest biztosit.
Konnyen bovitheto, mivel az xml-be letrehozva egy ilyen bejegyzest, az automatikusan a programban is azonnal "el".
Mas kerdes, hogy ezt valamire hasznalni is kell, amit "sajnos" bele kell irni a programba. -
3man
csendes tag
"Config" filet sokkal celszerubb valamilyen szabvanyos szoveges formaban letrehozni, es nem binarisan. Semmikepp nem binarisan. Az egyik legoptimalisabb az xml formatum.
Ekkor a problemad egybol eltunik, mivel nem kell azzal foglalkozni, hogy az adott gepen hogyan nez ki a float fizikailag. Ezt az xml kezelo elintezi. -
VaZso
senior tag
Sziasztok!
Kicsit megkavarodtam... Feladatom, hogy egy config fileból beolvassak különféle változókat.
Kicsit elveszettnek érzem magam abban, hogy milyen változótípus milyen tartományokban működik és akkor még fel sem merült, hogy esetleg más architektúrán mi a különbség...
Tehát:
short: 2 byte-on tárol --> 2^16-1, ill. ha az első bit az előjelbit, akkor -32768 - 32767-ig terjed.
int: 4 byte-os --> 2^32-1 ...
long: 8 byte-os --> 2^64-1 ...
float?
double?
Hogy kezeljem? Mik a határai?
Nem igazán találtam értelmes adatot.Sima C-vel próbálkozom.
-
Karma
félisten
válasz
Sk8erPeter #1490 üzenetére
Pedig ha azok a fogalmak megvannak, az első kérdésre is könnyebb válaszolni. Persze mindkettő C++ minta (sőt, a második csak és kizárólag Symbian C++-ban van), ezért C-nél még nem kavar be.
Auto pointer: egy olyan objektum, ami ha megsemmisül a stacken, magával ránt egy hozzárendelt heapen lévő objektumot is, így amikor az auto_ptr scope-on kívülre kerül, a másik objektum biztosan megsemmisül. Ez egy egyszerűsítés, így biztosan nem maradhat meg a heapen lévő objektum pl. azért, mert valahova berakott az ember még egy returnt, és elfelejtette felszabadítani ott is a memóriát
Valahogy így néz ki:
int valami()
{
int *valami_int = new int; // heapen hoztam letre, mint a malloc C-ben
auto_ptr<int> valami_ptr(valami_int); // az auto pointerre bizom a felszabaditast
...
// ugy hasznalom, mint egy pointert
*valami_ptr = 5; // a valtozo erteket valtoztatom itt
...
return 0; // valami_ptr megsemmisul -> valami_int is torlodik
...
return 1; // valahol mashol ugyanez lezajlik
}Ha nem lenne ez az auto_ptr, akkor mindkét return elé oda kéne írni explicite a következő sort (ez a free C++-os megfelelője), amit könnyen kifelejthet az ember, ha utólag hackelget bele a függvénybe, memory leaket okozva.
delete valami_int;
Cleanup Stack: Amikor a Symbiant írták, még nagyon fejletlenek voltak a C++ fordítók, kivételdobáskor a stacken lévő objektumokra nem hívódott meg a destruktor, ami mindenféle vicces hibához vezethetett, többek között "csak" memory leakhez. Ezért a nagyokosok kitalálták, hogy "csináljunk saját kivételkezelést!", megalkották a Leave-eket és a Cleanup Stacket.
Minden heapen lefoglalt objektumot, ami nem tagváltozó, fel kell kézzel rakni a CleanupStackre, és persze le is kell venni onnan, ha olyan műveletek jönnek, amik kivételt (konkrétan leave-et) dobhatnak. Tehát mindig figyelni kell a programozónak arra, hogy mikor mi van rajta, mikor melyik objektum kinek a felelősségébe tartozik, és ennek megfelelően variálni.
Na itt jön be, hogy ha több return utasítás van, akkor kitörhet a káosz, a függvény különböző részein más lehet a CleanupStack állapota, minden returnnél megfelelően adminisztrálni kell, és ha bármit változtatni kell, mindenhol át kell írni...
Példakód:
TInt CSomething::DoSomethingL()
{
TInt result = 0;
CSomethingBig *big = CSomethingBig::NewL();
CleanupStack::PushL(big);
RSomethingResource res;
CleanupClosePushL(res);
result = res->DoSomethingDangerousL(big); // ha ez dob egy leave-et, res bezarodik, big megsemmisul
CleanupStack::PopAndDestroy(2, big); // mindket elemet megsemmisiti
return result;
}Ezt a kódot nem magyaráznám túl, ha nem baj, hiszen csak random firkáltam. A lényeg az, hogy a PopAndDestroy hívást minden return előtt meg kell hívni, pontosan.
-
Sk8erPeter
nagyúr
Gondolkoztam még ezen, hogy miért lesz átláthatóbb a függvény, ha egyetlen return van, de nem látom be, miért is lenne ez jó. Szerintem azonnal áttekinthetővé válik a dolog, hogy ha valami feltétel, amire várunk, már az elején teljesül, akkor ne is folytassa tovább a vizsgálgatást, ez gondolom akár gyorsaság szempontjából sem lehet elhanyagolható. Jester01-gyel értek egyet, sokkal kevésbé lesz átlátható a függvény a sok if-else elágazás miatt. A tanított anyagokban is mindenhol akár több return utasítás is van bizonyos feltételek teljesülése esetén.
De most tényleg, miért lenne baj, ha több return van?
___________________
"Auto-pointereknél nem para a felszabadítás több return esetén, de pl. CleanupStacknél sokkal bonyolultabb a memóriát karban tartani."
Ebből sokat nem értettem, ezt röviden el tudod magyarázni? -
Én tisztáznám magam,de azzal is belemártózok.Ezt a programot se én írtam,de mivel nem tanultam ilyesmit egyik havernak meg volt ilyen,így elkértem.
Azt is tudjátok most tanulok,így előbb megcsinálom később megértem alapon megy,mert fordítva már nehéz lesz ekkora anyagnál.Köszi,hogy szóltok ilyenért,mert ebből is tanulok.
-
-
Karma
félisten
válasz
Sk8erPeter #1486 üzenetére
Eh, mondtam, hogy naív megoldás, azt nem, hogy jó is
Meg egyébként is csak firkáltam. -
Sk8erPeter
nagyúr
Dehát ez már kapásból nem jó, ha 0-t vagy 1-et adsz be a függvénynek, hiszen ezekre is azt fogja mondani a függvény, hogy prím, és nem tételezheted fel, hogy nem fog a felhasználó beadni 0-t vagy 1-et... És ugye a 0 vagy az 1 nagyon nem prímszám...
Pontosan ezen csodálkoztam a Prog honlapján fenn lévő MINTAmegoldásoknál, hogy rossz a prímtesztelő függvény... ---> [link]
Itt így csinálták meg a függvényt:
int prime(int a){
int i,max=(int)(sqrt(a)+1);
for(i=2;i<a;i++)if(a%i==0)return 0;
return 1;
}
És ez is rohadtul mindig 1-et fog visszaadni eredményül, ha 0 vagy 1 a számunk... Ja, és még egyet igencsak elbaszarintottak benne: létrehozták a max változót, de sehol sem használják fel...
Tőlünk ugye elvárják a hibátlan megoldásokat, de ők a MINTAként feltett ZH-ban két ilyen üvöltő hibát elkövethetnek. Kicsit gáz. -
PazsitZ
addikt
Lehet amatőr kérdés, de a long int-et hogyan kell jelölni? Ugyan is ezt a warning-ot kapom:
feladat.c:53: warning: format ‘%u’ expects type ‘unsigned int *’, but argument 3 has type ‘long int *’, s bár lefordul, de szabványosan, mi lenne a long int jelölése?
google-ban nem tudom, erre pl hogyan kellene keresnem
printf("%u %u %u",a,b,c); -
-
Jester01
veterán
Más konvenciók meg pont azt mondják, hogy nyugodtan használj annyi returnt amennyit akarsz, az átláthatóság miatt
Ugyanis adott esetben sok if/else ág lenne illetve segédváltozók és/vagy ciklus lefutás után a feltétel újratesztelése is szükséges lehet.
int find(int needle, int* haystack, int size)
{
int result = -1;
if (haystack == NULL)
{
fputs("haystack NULL", stderr);
} else {
for(int i = 0; i < size; i++)
{
if (haystack[i] == needle)
{
result = i;
break;
}
}
}
return result;
}-vagy-
int find(int needle, int* haystack, int size)
{
if (haystack == NULL)
{
fputs("haystack NULL", stderr);
return -1;
}
for(int i = 0; i < size; i++)
{
if (haystack[i] == needle)
{
return i;
}
}
return -1;
}Az első esetben hiába van 1 return a függvény végén, ahhoz, hogy megtudd mit ad vissza ígyis-úgyis végig kell nézni a függvényt, hogy hol lesz az a változó beállítva. Akkor meg pont ugyanolyan egyszerű a return utasításokat megkeresni. Ha pedig mondjuk két ciklus van egymásbaágyazva akkor még több macera kijutni belőlük (mivel ugye goto-t sem használunk
)
-
Karma
félisten
válasz
Sk8erPeter #1478 üzenetére
Egy prímtesztelőnél vannak bonyolultabb függvények is
De ezt is meg lehet oldani egy returnnel.Itt egy nagyon naív példa:
int isPrime(int aNumber)
{
int result = 1; // T.F.H. igaz
int i;
int max = aNumber / 2;
for (i = 2; i <= max && result; i++) // kilépünk a ciklusból, ha a feltevés sérül
{
result = aNumber % i;
}
return result;
} -
Sk8erPeter
nagyúr
"a függvényeknek csak egyetlen returnje legyen"
Na jó, de mondjuk egy prímtesztelő függvénynél pl. azt szeretnénk, hogy 1-gyel térjen vissza, ha egy szám prím, 0-val, ha nem az, hát ott kapásból a 0-nál vagy 1-nél 0-val kell, hogy visszatérjen, tehát ott már lesz egy return 0; , ha viszont az jött ki, hogy a szám prím, akkor ugye return 1;. És akkor már két return van a függvénybenVagy nem így értetted? Mert ez szerintem még bőven átlátható, és erre az átláthatóság nem jó érv szerintem...
Ezek szerint annyira neked sem jöttek be az órái.
Az mondjuk valóban nagy előny, ha előtte jól toltad legalább Pascalban, mert akkor csak át kell szokni a másik nyelv szintaktikájára. Hát nekem nem volt túl egyszerű a 0-ról megtanulni programozni, ilyen tanárokkal...
Mondjuk most kifogtunk egy nagyon jó gyakvezt (Lengyel László, hátha ismered), aki végre úgy magyaráz, hogy az követhető, és egyáltalán nem unalmas, ráadásul bevon mindenkit a feladatmegoldásba, nem úgy ülsz ott órán, hogy mikor lesz már végre vége a gyaknak. Az nagy előny.
-
Karma
félisten
válasz
Sk8erPeter #1476 üzenetére
Az exit tényleg durva. De ha már ott tartunk, számomra bevált az a gyakorlat, és egyébként is rengeteg konvenció azt is mondja, hogy a függvényeknek csak egyetlen returnje legyen, pont az átláthatóság miatt.
Egyszerűbb, ha az ember felelősségekkel tervez. Egy számot ellenörző függvénynek köze sincs a teljes program futásához (jó esetben, retardált feladatokat leszámítva), így oda értelemszerűen nem kerülhet exit. Igazából az alkalmazáslogikának 99%-ának semmi köze hozzá.
Ő "tanított", de nem programozni, hanem csak ledarálta a C nyelv alapjait. Szerencsémre az elv már korábban megvolt, Pascalban elég sokat versenyeztem, így a C nem volt nagy falat. Elővizsgával simán lenyomtam elsőre, meg általában a többi programozási tárgyat is.
-
Sk8erPeter
nagyúr
válasz
dabadab #1455 üzenetére
"Mert kezdő
"
Mondjuk így se igazán értem, mert nálunk kezdetektől fogva azt verték a fejünkbe, hogy return. Sőt, azért is szóltak, hogy külön függvény se lépjen ki hasonló módon, idézek:
"Függvény ne hívjon kilépéssel, hasonlókkal kapcsolatos dolgokat, mert a felsőbb szintű kódot ez meglepetéssel fogja érinteni (fájlok lezárása, takarítás elmarad). Ha szükséges, akkor legyen a programnak valami fatal_error() függvénye, azt hívjuk."
(Forrás: http://infoc.eet.bme.hu/gyakorlatok/)"Az exit() használata tulajdonképpen ugyanannyira problémás, mint a goto, ugyanazon okok miatt."
Akkor ezt most megjegyeztem, hogy az exit() függvényt se fogom sosem használni.(#1459) Karma: titeket is Poppe tanított? Első alkalommal (tavaly) minket is, de nekem annyira megtetszett a tantárgy, hogy felvettem idén is.
Ugyebár nincs kereszt progból... és Poppe órái szvsz olyan szinten unalmasak voltak, hogy egyáltalán nem keltette fel az érdeklődésem a programozás iránt (előtte középsuliban persze egyáltalán nem volt programozás), és ezzel még kb. az évfolyam fele így volt.
Aztán amikor nyáron elkezdtem a PHP-vel foglalkozni, akkor rájöttem, hogy a programozás jó dolog. És most már ráfeküdtem a C-re is, aláírás megvan, már csak a vizsgára kell gyakorolni, mint egy elmebeteg.
-
bpx
őstag
válasz
Darth_Revan #1474 üzenetére
eleve karaktertömbbe olvasol be a billentyűzetről, és ha kell valamit számolni, elég akkor pl. int-té konvertálni (pl. sscanf-el, ahogy a korábbi kódodban csináltad, vagy akár atoi)
(feltéve, hogy nem "hülye-biztos" programot kell írni, mert akkor marad a karakterenkénti ellenőrzött adatbevitel)
-
Karma
félisten
válasz
Darth_Revan #1471 üzenetére
Na, ha ezt mondtad volna először, mindjárt lenne a helyzet.
Akkor meg tárold el a simán a karaktereket, és majd később sscanf-fel konvertáld őket számmá, ha számolni is kell velük. Nem jó így? Mi is lesz belőle a végén?
-
Karma
félisten
válasz
Darth_Revan #1469 üzenetére
unsigned char?
-
Karma
félisten
válasz
Darth_Revan #1467 üzenetére
Hát az biztos, hogy nem az & operátorral, ami visszaadja az adott változó címét, jelen esetben a tömböd első elemére mutató konstans pointer címét
Helyette, amikor kiírsz, csináld ezt például:
for (int i = 0; i < szam; i++)
{
putchar(tomb[i]);
} -
Darth_Revan
veterán
azt hogy lehet megoldani, hogy char tmb[szam] tömbbe (szam-ot a fenti módszerrel adom meg) eltárolók scanf-el billentyűzetről beolvasott decimális számokat, majd kiírom őket? Megpróbáltam volna kiíratni for ciklussal a &tmb-t de vagy semmit se ír ki (üres) vagy csak random karaktereket
-
doc
nagyúr
válasz
Darth_Revan #1463 üzenetére
nekem (OSX, gcc) jol mukodik
MOD: ugy tunik a te keszulekedben van a hiba... milyen fordito?
-
Gyuri16
senior tag
válasz
Darth_Revan #1463 üzenetére
nalam jol mukodik. gcc 4.3.2
(utolso printf-bol hianyzik egy ", illetve egy return 0 a vegere ) -
Darth_Revan
veterán
Hali
Adott az alábbi C program:
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char **argv)
{
if (argc <2)
{
printf ("Kevés paraméter");
exit (2);
}
int szam;
sscanf (argv[1], "%d", &szam);
printf ("szam: %d, szam);
}Beírom, hogy " ./script neve ami lefordítja szám " és akármilyen számot adok meg nem azt adja vissza, hanem a tízszeresét..miért?
-
Jester01
veterán
C89 szabvány szerinti C nyelvben illetve C++ nyelvben csak fix méretű tömb van. C99-ben van dinamikus is. GCC meg szeret alapból nagyon laza lenni, házi feladat vagy hordozható kód esetén ajánlott a -ansi -pedantic -Wall. Ezen felül bizonyos warningok meg csak bekapcsolt optimalizáció mellett jelenkeznek.
MOD: haha a klónom gyorsabb volt
Sőt tulajdonképpen mindenki. Na mindegy.
MOD #sok:
$ gcc -ansi -pedantic -Wall dab.c
dab.c: In function 'f':
dab.c:5: warning: ISO C90 forbids variable length array 'x' -
dabadab
titán
"Egyébként nem úgy volt, hogy stacken tömböt csak fix méretben lehet létrehozni?"
Én nem tudok ilyenről és nekem ez teljesen jól működik:
#include <stdio.h>
void f(int size)
{
int x[size];
printf("%d\n",sizeof(x));
}
int main()
{
int c;
for ( c = 1 ; c < 10 ; c++ ) f(c);
return 0;
}./x
4
8
12
16
20
24
28
32
36szerk: látom, neked volt lelkierőd elolvasni a dokumentációt
-
Karma
félisten
Áááháá! Megvan! Nem vagyok teljesen up-to-date, a C99 szabvány engedi a változó hosszúságú tömböt is stacken, ha a blokk elején ismert a hossz, tehát pl. egy függvény paramétere a tömb mérete.
float read_and_process(int sz)
{
float vals[sz]; // VLA, size determined at runtime
for (int i = 0; i < sz; i++)
vals[i] = read_value();
return process(vals, sz);
}#1460: Wikipédián találtam
Elnézve a C99 újításait, gyanúsan C89-et "oktatott" anno Poppe prog1 órán.
-
Karma
félisten
válasz
dabadab #1457 üzenetére
Az RVCT nekem mindig rinyál.
Egyébként nem úgy volt, hogy stacken tömböt csak fix méretben lehet létrehozni? Még én is ezt állítottam nemrég, de ez a sor (bár felrobbant, ha futtatja az ember) elbizonytalanított egy kicsit a hitemben. Vagy az csak a Pascalban volt így, és valamiért összekeverem? Égő
-
dabadab
titán
válasz
Sk8erPeter #1454 üzenetére
"miért használsz mindenhol exit(0)-t?"
Mert kezdő
(Mondjuk a voidra definiált main()-re azért sikoltoznia kellene a fordítónak.)
Az exit() használata tulajdonképpen ugyanannyira problémás, mint a goto, ugyanazon okok miatt. -
Sk8erPeter
nagyúr
dabadab, Karma, kovsol: köszi a válaszokat!
Nálunk mondjuk a gyorsrendezés algoritmusánál sem használtak goto-t. Úgyhogy asszem maradok továbbra is annál, hogy NEM használok goto-t, amíg nem jön elő olyan helyzet, hogy mindenképp arra lesz szükségem - amit meg kétlek, hogy előállna.KISS filozófia, ez tetszik
A cikket pedig majd elolvasom, ha lesz időm, köszi.(#1451) grabber: miért használsz mindenhol exit(0)-t? Miért nem return 0; vagy return 1-et?
Mi ez az exit-mánia?
-
Karma
félisten
válasz
grabber #1451 üzenetére
Hát hasonlítsd össze a két kódot, elég jól látszik, a hibaüzenetek is beszédesek.
Pl.:
1) A File és a FILE két külön dolog (ez nem Pascal, a kis- és nagybetű számít!). Az utóbbi az érvényes, az előző meg a C számára ismeretlen fogalom, reklamál is miatta.
2) Ugyanebben a sorban kihagytál egy pontosvesszőt.
3) A legelső include-odat elírtad, "inlude" lett helyette, ez adja a többi hibaüzenet nagy részét.
4) A fájl elérési útvonalában nem jól írtad a \ jeleket. Mivel az escape karaktereket is az jelzi, a backslasheket kétszer kell beírni, mint a példádban.Azt hiszem ennyi az össz hiba.
-
Hali!
Valamiért nem akar ez működni és nem tudom miért.Annyira nem lenne érdekes,mert másik kóddal működik,de meg szeretnék tanulni programozni amihez értenem is kell.HA már VIK akkor csatlakozok,hogy a goto-ért exit jár
#inlude <stdio.h>
#include <stdlib.h>
#include <conio.h>
main ()
{
File*fp
char c;
fp=fopen("C:\prog\blabla.txt","r");
if(fp==NULL){printf("Hiba a fajl olvasasnal");exit(1);}
while(!feof(fp)){
c=fgetc(fp);
fputc(c,stdout);
}
fclose(fp);
exit(0);
}Ez nem akar működni,VS8 fatal error C1021: invalid preprocessor command 'inlude'
Code blocks: progi\main.c|1|invalid preprocessing directive #inlude|
progi\main.c|6|warning: return type defaults to `int'|
progi\main.c||In function `main':|
progi\main.c|7|error: `File' undeclared (first use in this function)|
progi\main.c|7|error: (Each undeclared identifier is reported only once|
progi\main.c|7|error: for each function it appears in.)|
progi\main.c|8|error: `fp' undeclared (first use in this function)|
progi\main.c|8|error: syntax error before "char"|
progi\main.c|9|warning: implicit declaration of function `fopen'|
progi\main.c|9|warning: unknown escape sequence '\p'|
progi\main.c|9|warning: unknown escape sequence '\P'|
progi\main.c|10|warning: implicit declaration of function `printf'|
progi\main.c|11|warning: implicit declaration of function `feof'|
progi\main.c|12|error: `c' undeclared (first use in this function)|
progi\main.c|12|warning: implicit declaration of function `fgetc'|
progi\main.c|13|warning: implicit declaration of function `fputc'|
progi\main.c|13|error: `stdout' undeclared (first use in this function)|
progi\main.c|15|warning: implicit declaration of function `fclose'|
||=== Build finished: 8 errors, 9 warnings ===|Helyette ez müxik,de még alakítani,kell hogy beolvassam dinamikus adatszerkezetbe.
#include <stdio.h>
void main()
{
int c;
FILE *fp;
if( (fp = fopen("C:\\prog\\blabla.txt","rt")) == NULL )
{
printf("\nHiba a blabla.blabl megnyitásánál !");
// Kilépés a programból
exit(0);
}
// Elôolvasás.
c = fgetc(fp);
// Amíg nincs file vége.
while( !feof(fp) )
{
printf("\nA beolvasott karakter : %c",c);
// Olvassa a következôt.
c = fgetc(fp);
}
// A file lezárása.
fclose(fp);
} -
Karma
félisten
válasz
Sk8erPeter #1447 üzenetére
Tudom hogy VIK-en mi a helyzet, én is informatikus-hallgató vagyok (félig)
Viszont egy másik fórumozónak segítettem Pascalban, és ő másolt be órai kódot, ami hemzsegett tőle. Nem mondta el, melyik szak, én részemről GTK-ra tippelnék, vagy TTK-ra.
Nem hibás elképzelés! Sőt, mint írtam az üzenetem végén, ha egységesen akarod kezelni a stacken, globálisan és a heapen lévő tömböket, akkor nincs is nagyon más lehetőséged rá. Hacsak nem varázsolsz struktúrákkal, és írsz OO kódot nyers C-ben. Good stuff. Szóval teljesen jó.
Egyszerűen, ahogy 3man is mondta, amit nem Neked kell karbantartanod, az nem lesz hibalehetőség később. A KISS ("Keep It Simple, Stupid!") filozófia általában jó eredményeket hoz.
Értettem mire gondolsz az iterátor szóval
, csak belejavítottam.
Apropó goto. Igazából a dolog kettős. Van olyan helyzet (főleg C-ben, meg ahogy kovsol is írja, assemblyben végképp), amikor előnyös a használata. Például hibakezelésre kivételek helyett, vagy brutálisan mély feltételeket szétbontani (Linux kernelben láttam most rá egy példát, amikor az előbb rákerestem). Viszont nem arra való, hogy a program teljes logikáját ezzel írja meg az ember, mint amit az említett órán csináltak ("ha a user 1-et ír be, kezdjük elölről a programot" jellegű varázs). Itt van róla egy hosszú, de annál érdekesebb leírás.
-
dabadab
titán
válasz
Sk8erPeter #1447 üzenetére
A goto azert nem jo, mert tonkrevagja a program strukturajat, ami nehezebbe teszi a hibakeresest, a kod karbantarsat es megerteset is.
Azt mondjuk nem art nem elfelejteni, hogy Dijsktra '68-ban irta "Go To Statement Considered Harmful" cimmel megjelent levelet, amikor a strukturalt programozas meg nem volt igazan mainstream es teljesen hetkoznapi volt a spagettikod, amiben gotoval ugraltak ossze-vissza. Bizonyos helyzetekben azon a goto hasznos lehet, mert eppen pont az adja a leghatekonyabb vagy a legattekinthetobb kodot - annak idejen a Kandon is belefutottam abba, hogy gyakorlaton instantegyes volt a goto, eloadason meg a quicksortbol egy gotos verziot prezentalt a tanar, mert az volt a legegyszerubb.
Mindent osszefoglalva, a goto elleni liheges mara nagyreszt okafogyotta valt (ma mar senki nem hasznalja ugy, ahogy a hatvanas evekben), az ellene valo horges mogott pedig ritkan talalni ertelmes okokat. -
kovsol
titán
válasz
Sk8erPeter #1447 üzenetére
goto val ugyan az a helyzet itt nálunk is
persze mikor assembly óra van ott ugrások nélkül kivitelezhetetlen a dologde ugye ez itt a C topic
-
Sk8erPeter
nagyúr
Nem, BME-n kifejezetten és erősen tiltják a goto utasítás használatát! Ezt a tanárok "halálfejes hibának" nevezik, ha ilyet teszel a ZH-dba, akkor rárajzolnak egy halálfejet (egyébként tényleg rárajzolják, ZH-megtekintésnél pár papíron láttam is
), és arra a feladatra - akármilyen szép is a többi része - eleve 0 pontot adnak. (olyan esetekben is kapsz ilyet, ha nem szabadítod fel a dinamikusan lefoglalt memóriát, amikor kellene, vagy inicializálatlan változóval dolgozol, stb.)
Elképzelhető, hogy régebben volt olyan tanár, akinek nem verték a fejébe, hogy goto-t nem használunk, de szerintem most már selejtezik az ilyeneket.
Pascalt nem is tudom, tanítanak-e még egyáltalán... Villamosmérnöki és Informatikai Karon biztos, hogy nem, ott C-vel kezdenek. De én úgy tudom, hogy még az építészek is alap C-t tanulnak. Pascalról mostanában egyáltalán nem hallottam, hogy valahol tanítanának még BME-n.A lényegre térve nem igazán értem, miért olyan nagyon hibás az elképzelés, hogy kívülről adjuk meg a függvénynek a méretet.
Jahh, de az utolsó bekezdésben azt írod, hogy végül is van elfogadható érvelés erre is: akkor tehát mégis jó úgy?
Az "iterátor" szót lehet, hogy rosszul használtam, de arra az elemre gondoltam, amivel bejárod a tömböt.A goto utasításra visszatérve: tudom, hogy a használata egy undormány-hányadék hiba, és soha nem is tettem, mert direkt meg se néztem, hogy kell azt egyáltalán
De érdekelne, konkrétan milyen szempontból oltári baromság a goto használata. Úgy emlékszem, hogy futásidejű összeomlásokat eredményezhet, meg hasonlókat, de a pontos érveket már elfelejtettem.
(#1442) 3man: értem, köszi. Tehát akkor érdemes mégis kézzel átadni (ha sima C-ben programozol) a tömbméretet, ugye?
(#1446) bama: most mi a kérdés? Egyébként ha ez egy prímtesztelő függvény, akkor szvsz elég furcsa, minek kell 4-gyel shiftelni a számot...
-
bama
csendes tag
Hi 3man!!!
Segitesz a progiba???
void isPrim(int number){
if (number <<4){
return number;
for(int i=4, i*i<number,i++);
if(number % i=0)
return 0;
return 1;
}Thanx
-
3man
csendes tag
Termeszetesen debuggerekkel es tarsaikkal helyettesitheto a modszerem.
De amikor 10 netalan 100 kulso tesztelod van, akkor nem biztos, hogy ez kenyelmes modszer.
Mi a legegyszerubb megoldas?
Az AddVectoredExceptionHandler() -el elkapsz minden nem tervezett esemenyt, es logolsz minden fontos dolgot. A lefoglalt teruletek mutatolistaihoz rendelt nev alapjan barmilyen memoria hiba pontosan lokalizalhato akar ugy, hogy nem is debug modban fut a program. Egy callstack-hez hasonlo kovetes is beepitheto ebbe a logba.
Ugyan a debug mod azert van, hogy ezt elvegezze, de megeshet, hogy igy tul lassu a program. Ha a programot a vegleges formajaban kell tesztelni, akkor a debug mod mar kiesik, de a hiba megis egyszeruen detektalhato. -
Karma
félisten
válasz
Sk8erPeter #1435 üzenetére
Hát nem tudom, oktatnak érdekes dolgokat
Mondjuk production kódot még nem írtam/láttam sima C-ben, lehet hogy tényleg van ilyen konvenció.
De nem esküdnék meg rá. Nemrég láttam, hogy valahol a BME-n is goto-val tanítják a Pascalt!
Akkora lett a fejem hogy csak na...
Egyébként az, hogy végigiterálsz a tömbön, még nem jelenti azt, hogy iterátorral dolgoznál. Az iterátor egy objektum-orientált minta. Röviden: ahelyett, hogy ismerned kéne a tömb/lista/stream/kismacska belső szerkezetét, és ezt figyelembe véve temérdek kódot generálnál, kérsz a kollekciótól egy iterátort, egy általános interfészt megvalósító objektumot, aminek ilyen műveletei vannak tipikusan: hasNext(), next(), removeCurrent(), satöbbi. Így szerkezettől független kódot tudsz írni
A szempontod egyébként jogos, de most hogy leírtam az előző blokkot leesett, hogy igazából miért is jobb kézzel átadni a hosszt kívülről: ezzel egységesen lehet kezelni a fix méretű és a heapen lévő tömböket is!
-
3man
csendes tag
válasz
Sk8erPeter #1435 üzenetére
Minel kevesebb dologra kell figyelni kodolaskor, annal kisebb az eselye a tevedesnek.
-
3man
csendes tag
válasz
Sk8erPeter #1435 üzenetére
Ha az osztaly tartalmazza a tomb meretet, akkor egy gonddal kevesebb, nem kell ra figyelni.
De ez ugyan az, mint amikor atadod kezzel. -
doc
nagyúr
ezt milyen megfontolasbol irtad a 'C' topicba? az osztaly ismeretlen fogalom a C-ben
ezzel inkabb a programozas totyikba menj, meg nem art leirni hogy milyen nyelvrol van szo, plusz az altalad eddig megalkotott kodot berakni, azt ne vard hogy valaki csak ugy megirja helyetted a hazidat -
Badb0y
addikt
Valaki hozzáértő ezt össze tudja dobni
?
Készítsen olyan FARM-ot leíró osztályt, melyben három fajta állatot tartanak nyilván.
A FARM-on végezhető műveletek:- AddMarha (név, kor, tejhozam) új marha felvétele
- AddLo (név, fogszám) új ló felvétele
- AddTyuk (név, tojáspernap) új tyúk felvétele
- Kill(név) Egy, a megadott nevű állat lemészárlása
- List () a még élő állatok attribútumainak listázásaÉletmentő lenne
-
Sk8erPeter
nagyúr
Abból indultam ki, hogy nekünk azt erőltették, hogy ha akár statikus tömbökkel is dolgozunk (persze, nem a pointertömbökre gondoltam
), és azokat adjuk át a függvényeknek, akkor lehetőleg adjuk át a méretét is, mert így könnyebb kezelni (pl. ha iterátorral rohangászol végig a tömbelemeken, akkor mittomén, for ciklusban a feltétel lehet az, hogy i<meret, stb. - persze úgy is lehetne, hogy tomb[i] != '\0' ), nem kell a függvényen belül is sizeof()-fal p×csölni, és így esetleg pl. main()-ben mondjuk elég egyszer sizeof-olni (talán ez gyorsaság szempontjából is érdekes lehet, fene tudja). Ez nem lehet elfogadható szempont? A 2-3. pont mondjuk teljesen igaz.
-
Karma
félisten
válasz
Sk8erPeter #1433 üzenetére
Nem nekem szól a kérdés, de azért van pár ötletem:
1) Méretet átadni stack/statikus tömböknél redundáns információ (sizeof() megmondja).
2) Egyébként is, ezt a "belső" információt kívülről átadni csak még egy hibaforrás.
3) A \0 karaktertömböknél elmegy (bár nem 100%-os biztonság), pointertömböknél már körülményesebb (mi van, ha nincs tele a tömb? Mivel töltöd fel?), egyéb tömböknél meg teljesen megvalósíthatatlan önmagában.Az igazi megoldás tényleg a tömbosztályok használata, de osztályok (szintaktikailag) csak a C++-ban vannak. Szemantikailag viszont megoldható C-ben is egy kis gondolkodással: struktúrával és az azt manipuláló függvényekkel - bár szerintem nem találom fel a spanyolviaszt, biztosan más már írt ilyet.
-
Sk8erPeter
nagyúr
Értem, köszi!
(#1428) 3man: még C++-hoz nem konyítok, de csak érdeklődésképp kérdezem, hogy miért nem egyszerűbb a túlindexelés elkerülésére osztály létrehozása helyett mindig "kényszerűen" átadni a tömbméretet is mondjuk függvénynek, vagy végigszaladni a tömbelemeken a lezáró nulláig, hogy megtudjuk, hány eleme van, és utána ezzel dolgozzunk?
-
Karma
félisten
Nem azért mondom (nem is tudom, van külön C++ topik is?), mindössze az, hogy ez tényleg sokkal körülményesebb C-ben. Egyébként én meg (Symbian) a HookLoggert szoktam használni, ha memory leakre vadászom: a saját kódom módosítása nélkül végzi el ugyanezt, amit Te az előbb manuális módszerként leírtál. (Rendszerszinten áll rá az Alloc/Free-re).
Linuxon és tsa. másik alternatíva lehet még a Valgrind is.
-
3man
csendes tag
"Igy kiszurheto olyan rejtett memoria hiba, ami akkor keletkezik ha lemasolok egy pointert, de az eredetit felszabaditom. "
Az kifelejtettem, hogy ennek a kiszuresehez minden [] operatornal ellenorizni kell, hogy az adott pointer benne van-e meg a listaban. Ez nagyon lelassitja a programot, de ezt eleg csak akkor futtatni, ha valamilyen bug van a programban.
Egy rutinos programozo mondhatna erre, hogy ilyen hibak nala nem fordulhatnak elo. En erre csak azt mondom, sose lehet tudni.
-
3man
csendes tag
Ha mar igy kiveseztetek a tomboket, erdemes megemliteni, hogy a legeldugodtabb bugokat a tombok tulindexelesevel lehet krealni.
Ugyanis az tortenik, hogy ha letrehozok egy int tomb[100] meretu tombot, es utanna beleirok mondjuk a tomb[234]=1 elemebe ezzel a sorral, akkor az a memoriaban utanna levo valamelyik valtozoba fog belebarmolni. Ez azutan vagy lathato hibat okoz, vagy lopakodo uzemmodban egyszercsak ertelmetlen dolgokat fog a program csinalni teljesen mashol, olyan helyen, aminek semmi koze a tomb[] hoz.
Erre mar jol kezelheto array osztalyok vannak, erdemes szetnezni es valogatni ezek kozt. A legegyszerubb, ha az ember egy sajat array osztalyt hoz letre, es minden tipusu tombot ezzel definial.
Ebben letre lehet hozni egy []-operatort, ahol az indexelesnel ellenorizni lehet, hogy az index a tomb merete alatt van-e. A tomb letrehozasanal pedig el lehet tarolni a meretet. Ezzel az apro dologgal rengeteg fejfajastol lehet megszabadulni.Ehhez kapcsolodik a memoria kezeles. Ha az ember meg kezdo, nem mindig tudja ugy felepiteni a programot, hogy minden lefoglalt memoria mindig jo helyen es jo idoben szabaduljon fel.
Minden new utasitast erdemes sajatra cserelni. Ez akar egy egyszeru makroval is megteheto. Egy mutato-listat letrehozva le kell tarolni minden lefoglalt cimet.
Amikor uj cimet hozok letre, erdemes vegignezni a listat, hogy nem esik bele valamelyik mar letrehozott memoria reszbe az uj kezdocim. Igy kiszurheto olyan rejtett memoria hiba, ami akkor keletkezik ha lemasolok egy pointert, de az eredetit felszabaditom. Ez kezdo hiba, de barki tevedhet. A program viszont eszre fogja venni a tevedest. Termeszetesen a delete-nel a a listabol torolni kell a mutatot.
Ezt a modszert kiegeszitve azzal, hogy minden sajat new hivasnak nevet adok, a nem felszabaditott memoriat barmikor ki lehet listazni.
Nevadas helyett lehet hasznalni a __line__ __file__ __function__ makrokat, amikkel a felszabaditatlanul maradt new utasitas pontos helyet vissza lehet kovetni.Ezzel az ket egyszeru modszerrel szinte az osszes memoria bug kiirthato egy akarmilyen bonyolult programbol.
-
Karma
félisten
válasz
Sk8erPeter #1424 üzenetére
Ezért fésűs (a nyilak a pointereket jelölik):
Egy kicsit elrontottam a képet, minden szó végén ott van még egy 0 is, lezárva a szavakat. A függőleges oszlopban meg csak akkor vannak 0-k, ha calloc-kal lett lefoglalva, vagy kézzel ki lett előre nullázva. De sajnos Excelben rajzoltam, és becsuktam a doksit
-
bpx
őstag
válasz
m0h0senator #1425 üzenetére
egy számról sokféleképpen meg lehet állapítani hogy hány jegyű, de a feladat szövege sugallja (karaktertömb), hogy érdemes karakterenként bekérni a számot
ekkor legfeljebb 5 karaktert kell egyenként bekérni, amit rögtön lehet ellenőrizni is, hogy beleesik-e a 0..7 tartománybaszintaktika: a legegyszerűbbet amit csak lehet (dinamikus memóriafoglalás itt felesleges)
char tomb[5];
char c;
....
c = getch();
....
tomb[0] = c; -
m0h0senator
őstag
Sziasztok,
adott egy feladat: bekérünk egy számot a felhasználótól, a szám tulajdonságai: számjegyei 0-7 ig lehetnek és max 5 jegyű lehet. ezt a számot egy karakter tömbben tároljuk el. Az lenne a kérdésem,hogy hogy döntöm el a számról, hogy hány jegyű? És a karakter tömbnek milyen szintaktikái vannak?
előre is köszönöm
-
Sk8erPeter
nagyúr
Nem a * operátor sorrendjén voltam meglepődve, hanem magán a "byte" típuson.
Eddig nem használtam, és nem is igazán láttam gyakorlati feladatokban konkrétan ezt a típust. Szóval erre kérdeztem, hogy mire jó.
Egyébként jó, hogy felhívtad a figyelmem, hogy attól még, hogy a csillagot a típus mögé rakom közvetlenül, nem lesz a következő változó is automatikusan pointer(mondjuk ez viszonylag egyértelműnek látszik, de nehogy elcsesszem valamikor - most már nem fogom)
Köszi a választ ismét!(#1422) Karma: neked is köszi! Ez mitől lesz egyébként "fésűs adatszerkezet"?
-
Karma
félisten
Pfff, az előbb a fórummotor kidobta a szerkesztésemet a kukába...
Szóval az általad említett problémának van egy alternatív megoldása, ha az adott környezet úgy kívánja meg (szerencsére a legtöbbet ilyenben dolgozok, én a típushoz szeretem kötni a *-ot és a &-et
):
int* first;
int* second; -
Karma
félisten
válasz
Sk8erPeter #1420 üzenetére
"És hogy is van tovább?
"
Igazából nincs itt sok már, csak azért tereltem el a szót, hogy ne legyen kavar.
A pointer a háttérben mindig egy 32/64 bites int szám, egyszerű változó, és úgy is viselkedik, mintha egy sima int változód lenne."Mondjuk jelen esetben a példaprogramnál ez nem volt világos, hogy minek foglaltunk akkor helyet az adatoknak, ha utána rögtön az eltárolás után meg is szabadultunk tőle. Igaz, erre lehetne azt mondani, hogy mivel nem volt része a feladatnak az, hogy tovább tárolgassuk, és még csináljunk vele valamit, csak a szavakra darabolás."
Pontosan ez történt
Felépíti, és el is tünteti. Szerintem durva pontlevonás járna érte, ha nem tenné a hallgató. Viszont cserébe jól bemutatja, hogy egy fésűs adatszerkezetet hogy kell felszabadítani.
-
shev7
veterán
válasz
Sk8erPeter #1420 üzenetére
mert ha egytol indexelnenk, akkor
p[1] = *p
p[2]= *(p+1)
.
.
.0-s indexelesnel mindket oldalon ugyan az a szam van
"hogy lehet deklarálni úgy egy változót, hogy byte *p; . Ez mire jó ebben a formában? "
Na most ennek utananeztem, hogy ne irjak hulyeseget. A lenyege, hogy egyertelmu legyen. A * operator ugyanis jobbra kot. Barmennyire is irod kozel a tipushoz
Szoval ha irsz egy ilyet:
long* first, second;
akkor deklaraltal egy long pointert (first) es egy long valtozot (second). De akkor mar miert nem irnad le egyertelmuen:
long *first, second; es igy senki nem fogja azt gondolni hogy ket pointert deklaraltal.
-
Sk8erPeter
nagyúr
Köszi a válaszokat, Karma és shev7, azt hiszem, már nagyjából értem.
"magát a pointert sikeresen definiáltuk, 4 byte-ot kapott a stacken (vagy globálisan), mint egy átlagos változó. De ezt most felejtsük el egy pillanatra, mert irreleváns." És hogy is van tovább?
"Dehogynem. Amire meghívod a free-t, az felszabadul, az értékei érvénytelenné és elérhetetlenné válnak."
Mondjuk jelen esetben a példaprogramnál ez nem volt világos, hogy minek foglaltunk akkor helyet az adatoknak, ha utána rögtön az eltárolás után meg is szabadultunk tőle. Igaz, erre lehetne azt mondani, hogy mivel nem volt része a feladatnak az, hogy tovább tárolgassuk, és még csináljunk vele valamit, csak a szavakra darabolás.(#1413) shev7: "Ott a kovetkezo egyenloseg igaz: p[5] = *(p+sizeof(int)*5)" Ettől egy kicsit megijedtem, mivel pont nem ezt tanultuk, hanem azt, hogy azzal egyenlő, hogy *(p+5).
De látom később megbeszéltétek, hogy valóban az utóbbi a jó.
Itt viszont nem értettem az összefüggést: "ja es ezert indexeljuk 0-tol a tomboket C-ben" azzal, amit ezelőtt írtál.
Egyébként számomra az is újdonság volt, hogy lehet deklarálni úgy egy változót, hogy byte *p; . Ez mire jó ebben a formában? Még konkrét programban kevésszer láttam így deklarálva egy változót, de valamilyen szempontból nyilván hasznos lehet.Köszi nektek a türelmes válaszokat!
-
Karma
félisten
"de ugye ez csak byteoknal mukodne ilyen egyszeuen. Int-nel mar bonyolultabb a tema. Ott a kovetkezo egyenloseg igaz: p[5] = *(p+sizeof(int)*5)"
Nem igaz!
Ha a p ebben a példában egy int*, akkor automatikusan egy egész értéknyit lép előre, nem kell és nem szabad a sizeoffal varázsolni benne! Tehát 32 biten "p+1" az 32 bittel előrébb mutat, nem csak egy bájttal!
-
Sk8erPeter
nagyúr
Szóval akkor pl. az általam mutatott példában az ujtomb nevű tömb nem tömb, hanem pointer. De a tömb olyan, mint egy pointer, mert pl. függvénynek már eleve a címet adjuk át, ha tömböt adunk át. De a pointernek mások a tulajdonságai, szabadon, futásidőben változtatható a memóriaigénye, ide-oda állítgatható, stb., míg a tömbnek már fordításkor meghatározott a memóriaigénye, akármilyen adatot pakolászunk is bele (persze a megadott típus szerinti méretkorlátokon belül). Tehát a tömbnek ha megszakadunk, sem tudunk változtatni futásidőben a memóriaszükségletén.
Az eddigiek helytállóak? És "csupán" ilyen szempontból van eltérés?Szerk.: jól "egyszerre" írtuk a hsz.-eket, olvasom is a válaszaitokat.
-
Karma
félisten
válasz
Sk8erPeter #1412 üzenetére
"A double *ujtomb; sorban tehát deklarálunk egy pointerváltozót ujtomb néven, aminek csak később foglaljuk le a szükséges memóriát, először még csak meghatározzuk, hogy "lesz ilyen"."
Igen. Bár ha nagyon szőrözni akarnék, ahogy egyszer már tettem, a megfogalmazás nem tökéletes: magát a pointert sikeresen definiáltuk, 4 byte-ot kapott a stacken (vagy globálisan), mint egy átlagos változó. De ezt most felejtsük el egy pillanatra, mert irreleváns.
"Amikor megtudtuk az eredeti tömb számunkra szükséges elemeit megszámolva, mekkora új tömbre van szükségünk, azután lefoglaltuk neki a számára szükséges memóriát. Ezután tömbként és egyben pointerként használtuk fel a későbbiekben, rakosgattunk bele elemeket, és itt ez most kicsit zavaros számomra, hogy akkor most melyik fogalmat is használjuk, ami helytálló. Mert tömbnek foglalunk helyet, de pointertömb...
"
Nem, mi csak és kizárólag pointerként használtuk, nincs külön olyan, hogy "tömbként" használni. Ez a szép a C-ben (konkrét és ironikus értelemben is), hogy ilyen egyszerű
Mint írtam korábban, a p[n] subscript operátor az ekvivalens a *(p+n) művelettel.
A pointertömb egy teljesen más fogalom. Pl. int **valami; egy int pointerre mutató pointer, amivel (hasonlóan a második példakódhoz) tömbök tömbjét lehet megvalósítani. Ugyanezt lehet fix méretben is: int valami[5][2];.
"Ráadásul - bocsi az értetlenkedésért, csak vannak ilyen homályos pontok - akkor a memóriafoglalással ezek szerint nem "méretezünk", hanem nem tudom, mit csinálunk
"
A memóriafoglalással memóriát foglalunk
"És még egy pluszkérdés: a main()-ben free-vel felszabadítjuk a memóriát, de ekkor nem "szabadulunk meg" egyben az adatszerkezet már korábban eltárolt értékeitől is?"
Dehogynem. Amire meghívod a free-t, az felszabadul, az értékei érvénytelenné és elérhetetlenné válnak. (Legalábbis így kell bánni vele, ha nem akarsz bugzani.)
Fontos megjegyezni, hogy egy dinamikus pointertömbnél az alstruktúrákat egyesével fel kell szabadítani, a fordító nem fogja kibogozni!
-
shev7
veterán
válasz
Sk8erPeter #1412 üzenetére
bar nem nekem szol a kerdes probalok valaszolni, ha mar itt vagyok:
"A double *ujtomb; sorban tehát deklarálunk egy pointerváltozót ujtomb néven, aminek csak később foglaljuk le a szükséges memóriát, először még csak meghatározzuk, hogy "lesz ilyen"."
Lenyegeben igen.
Amikor megtudtuk az eredeti tömb számunkra szükséges elemeit megszámolva, mekkora új tömbre van szükségünk, azután lefoglaltuk neki a számára szükséges memóriát.
Inkabb nevezzuk memoriateruletnek, de igen.
Ezután tömbként és egyben pointerként használtuk fel a későbbiekben, rakosgattunk bele elemeket, és itt ez most kicsit zavaros számomra, hogy akkor most melyik fogalmat is használjuk, ami helytálló. Mert tömbnek foglalunk helyet, de pointertömb...
Na itt kezdodik a fogalomzavar. Eloszor is ne hivd pointertombnek mert az nem az. A pointertom az szamomra a pointerek tombjet jelenti, es itt nem errol van szo. Hogy mi is tortenik ahhoz egy kis magyarazat.
Vegyunk eloszor egy egyszeru byte pointert: byte *p;
a p valtozo tartalma egy memoria cim. A *p ahogy a deklaraciobol is olvashato egy byteot jelent (vagyis a p pointer altal mutatott erteket). Ha tovabbmegyunk a *(p+1) - a p memoriaterulet utani byte-on levo byte-ot jelenti. Na es most jon a turpissag, maradjatok meg velemhogy ne legyen olyan bonyolult az elet, behoztak ezt a tomb pointer megfeleltetest. (illetve nem behoztak, eddig is igy mukodott, csak mivel korabban nem voltak pointerek, nem foglalkoztunk a problemaval) Azaz a p[5] az megegyezik azzal mintha azt irnad hogy *(p+5).
de ugye ez csak byteoknal mukodne ilyen egyszeuen. Int-nel mar bonyolultabb a tema. Ott a kovetkezo egyenloseg igaz: p[5] = *(p+sizeof(int)*5)
Namost mivel ez alapbol igy mukodott tomboknel, ( ha deklaralsz egy olyat hogy
int tomb[100]; akkor a tomb igy magaban egy pointer, es a hatterben pont egy ilyen konverzio zajlik le) akkor a pointerek bevezetesevel csak annyi tortent, hogy ez "mukodik a masik iranyba is"MOD: ja es ezert indexeljuk 0-tol a tomboket C-ben
-
Sk8erPeter
nagyúr
Huhh. No, akkor valóban vannak homályos foltok.
Megpróbálom értelmezni akkor a lényegi kérdést, kérlek javíts, ha valamit rosszul gondolok:
A double *ujtomb; sorban tehát deklarálunk egy pointerváltozót ujtomb néven, aminek csak később foglaljuk le a szükséges memóriát, először még csak meghatározzuk, hogy "lesz ilyen". Amikor megtudtuk az eredeti tömb számunkra szükséges elemeit megszámolva, mekkora új tömbre van szükségünk, azután lefoglaltuk neki a számára szükséges memóriát. Ezután tömbként és egyben pointerként használtuk fel a későbbiekben, rakosgattunk bele elemeket, és itt ez most kicsit zavaros számomra, hogy akkor most melyik fogalmat is használjuk, ami helytálló. Mert tömbnek foglalunk helyet, de pointertömb...
A második feladatban már megint ez a fogalmi zavar a bajom. (pointer, tömb, pointertömb...)
Ráadásul - bocsi az értetlenkedésért, csak vannak ilyen homályos pontok - akkor a memóriafoglalással ezek szerint nem "méretezünk", hanem nem tudom, mit csinálunkÉs még egy pluszkérdés: a main()-ben free-vel felszabadítjuk a memóriát, de ekkor nem "szabadulunk meg" egyben az adatszerkezet már korábban eltárolt értékeitől is?
Bocs a sok kérdésért, és köszönöm az eddigi és további segítséget.
(#1411) shev7: pont most küldtem a hsz.-t.
köszi, rögtön végiggondolom, hogy leülepedjen.
És igen, jól látod, még nem jött át, kicsit zavar van most az agyamban.
De már dereng valami!
-
shev7
veterán
válasz
Sk8erPeter #1399 üzenetére
de pont errol beszeltem. Az ujtomb valtozo nem egy "statikus" tomb. Az egy pointer. Amirol mit is irtam? Ja tenyleg, azt hogy futasi idoben lehet neki memoriat foglalni.
Tehat megegszer, mert ugy tunik nem jon at
ha egy valtozot igy deklaralsz
int *tomb
az egy pointer lesz. Ponternek futasi idoben foglasz meretet, ujra foglalod stb...
ha egy valtozot igy deklaralsz:
int tomb[100]
az egy tomb, array, nevezzuk akarminek, lesz. A pointernek foglalt terulettel ellentetben ennek a memoriaigenye mar forditaskor eldol, es a stack-en fog csucsulni megvaltoztathatatlanul, es nem a heap-en ahogy a pointer altal foglalt terulet, amivel azt csinalsz amit akarsz, lefoglalod, felszabaditod, ujrafoglalod.
Ertem?
-
Karma
félisten
válasz
Vasinger! #1407 üzenetére
Középre zárni úgy kell, hogy fogod a szöveged hosszát, elosztod kettővel, kivonod a képernyő szélességéből, és a kapott számszor kiírsz egy szóközt. De most ezzel asszem lelőttem a poént.
Egyébként meg egyszerű: a \t\n\a nem az, mint amit Te az előbb leírtál
Ez most egy tab, utána egy sortörés, végül csilingelés. Hasonlítsd össze -
Vasinger!
nagyúr
Mért nem müxik a tabulátor, ha így írom be?:
System.Console.WriteLine("\t\n\aszöveg");
Elvileg új sorba, bekezdéssel és pittyogással kéne kiírnia azt, hogy szöveg. Ebből a bekezdés nem működik.
Ha már itt vagyok, hogy lehet több sorral lejjebb menni nem csak egyel és középre zárni a szöveget? -
Karma
félisten
válasz
Sk8erPeter #1405 üzenetére
Félreértelmezted a második példát, ott sincs szó átméretezésről, egyszerűen egy tömbök tömbje szerkezetben foglalgat memóriát. Az első példára is igaz az viszont, hogy átméretezni pusztán malloc-kal nem lehet egy már lefoglalt tömböt. A realloc-kal hamarabb (realloc = malloc + memcpy + free egyben).
Az eredeti üzenet meg a fix szélességű stack/globális tömbökről szólt, nem a heapen lévőkről. Azokat tényleg nem tudod változtatni, se dinamikusan kiszabni, erre elég jó volt a kétsoros példakód.
-
Sk8erPeter
nagyúr
A kolléga itt azt mondja, nem lehet futásidőben növelni a tömb méretét. De most akkor itt nem éppen az történik? Itt tulajdonképpen pointerrel és/vagy tömbbel játszik, de a kettő bizonyos szempontból hasonló, mégis más a kettő, és most már akkor kezdem azt sem érteni, amit azt hittem, eddig értettem
Tehát itt a mutatott példában pl. egy új tömbnek már futásidőben foglal akkora memóriát, amekkora számára szükséges. A másikban meg még bővíti annyival, amennyi kell, mivel csak egyszer olvashatjuk be az állományt. Ugyanúgy kezeli, mint egy tömböt. De akkor most mi is az igazság?
-
Vasinger!
nagyúr
Köszi a segítséget, így már megy. De mi suliban is csak arra a zöld nyílra mentünk és nem indult újra. Miért is van ez? Valamit mit ha be kéne írni vagy törölni kellene.
Meg ha elindítom simán saját gépen, ott is egyből újraindul.
Közben kipróbáltam amit írtál, az segített. Console.Readkey();
-
Karma
félisten
válasz
Sk8erPeter #1402 üzenetére
Van aki dolgozni is jár
Mindjárt nézem...
Megnéztem... Mi is a kérdés?
-
Sk8erPeter
nagyúr
válasz
Sk8erPeter #1399 üzenetére
Most akkor itt megállt a tudomány?
Mert a kérdésre még akkor mindig nem tudom a választ a dinamikus memóriafoglalással kapcsolatban.
Mármint hogy tömb-nem tömb, futásidőben történő méretnövelés, stb... Amiről korábban szó volt, hogy állítólag nem lehet tömbnek futásidőben változtatni a méretét. Most akkor mi van?Fogalmi képzavar?
(#1403) Karma: OK, köszi, nem sürgetésképpen írtam, csak azt hittem, hogy akkor skippeltétek a hsz.-t, mert túl hosszúra sikerült a példák miatt.
-
bpx
őstag
válasz
Vasinger! #1400 üzenetére
mit értesz az alatt hogy újraindul?
elindítod és rögtön eltűnik az ablak? akkor indítsd debug nélkül (ctrl+f5) vagy írd be a végére hogy Console.Readkey(); és akkor még vár egy gombnyomásra mielőtt kilépnesorok számozása: tools / options / text editor / all languages / line numbers pipa be
Új hozzászólás Aktív témák
● olvasd el a téma összefoglalót!
● ha kódot szúrsz be, használd a PROGRAMKÓD formázási funkciót!
- Samsung Galaxy S22 és S22+ - a kis vagány meg a bátyja
- Milyen autót vegyek?
- Milyen asztali (teljes vagy fél-) gépet vegyek?
- Eredeti játékok OFF topik
- Audi, Cupra, Seat, Skoda, Volkswagen topik
- Egyéni arckép 2. lépés: ARCKÉPSZERKESZTŐ
- RAM topik
- Autós topik
- Milyen egeret válasszak?
- Melyik tápegységet vegyem?
- További aktív témák...
- IPhone 15 Pro max 256GB gyári független 2026.11.09. Apple jótállás
- FÓLIÁS! LG UltraFine 32UN88A-W Ergo IPS Monitor! 3840x2160
- FÓLIÁS! LG UltraGear 27GS85Q-B Gamer IPS Monitor! 2560x1440 / 200Hz / 1ms / FreeSync
- Thinkpad T14 Gen4 14" FHD+ IPS i7-1355U 16GB DDR5 512GB NVMe ujjlolv IR kam gar
- Spirit of Gamer ELITE K70 Gaming Billentyűzet
- ÁRGARANCIA!Épített KomPhone Ryzen 5 7600X 32/64GB RAM RX 7800 XT 16GB GAMER PC termékbeszámítással
- Azonnali készpénzes AMD CPU AMD VGA számítógép felvásárlás személyesen / postával korrekt áron
- DELL Thunderbolt Dock - WD19TB modul 02HV8N (ELKELT)
- Telefon felvásárlás!! Apple iPhone SE (2016), Apple iPhone SE2 (2020), Apple iPhone SE3 (2022)
- ÁRGARANCIA!Épített KomPhone Ryzen 7 5800X 16/32/64GB RAM RTX 5070 12GB GAMER PC termékbeszámítással
Állásajánlatok
Cég: PCMENTOR SZERVIZ KFT.
Város: Budapest
Cég: Laptopszaki Kft.
Város: Budapest