Új hozzászólás Aktív témák
-
kingabo
őstag
A sizex-et add át egy lokális változónak, mert azt nem változtathatod. (mi van ha const 4-el hívom meg? ) Illetve ha nem négyzetes a mátrix, akkor kellene a sizey is. Illetve szerintem egy új tömbbel kéne visszatéred, hogy az eredetit ne rontsd el. Az első sorban az int x lenne a visszatérési érték és az fv neve? Tömböt kéne visszaadnod, meg egy beszédesebb nevet az fv-nek. Ja és nem ártana egy return is, ha már van visszatérési érték.
[ Szerkesztve ]
-
kingabo
őstag
válasz FehérHolló #2286 üzenetére
AxB-s tömböt írt a feladatban. Ha hajtogattál valaha életedben meg simán el tudnád képzelni, hogy oldható meg nem négyzetes mátrixra is.
(#2284) Karma: a megszokás hatalma. C++-ban nálam mindkét bemenő param const lenne és így már teljesen igaz amit mondtam. Én nem tartom szépnek a bemenő paraméterek változtatását, ha nem címszerintiek (de izlések és pofonok), de pl adában nem is változtathatod meg. Azt meg ne döntsd el, hogy megbuknék-e Pláne éjjel 2kor.
[ Szerkesztve ]
-
kingabo
őstag
válasz FehérHolló #2296 üzenetére
Látom elgurult a gyógyszered...
Arra céloztam, hogy a kisebb dimenzió méretű, négyzetes résztömbre simán működik. Rajtad kívül senki sem akart nem egésszel indexelni. -
kingabo
őstag
A pointerezést holnap megpróbálom összeírni, meg a "mágiás" részt. már ha elfogadod tőlem, nem írja meg elöbb senki sem, nem google-zol rá
"Ja a lényeg kimaradt: a zh példában ha jól emlékszem 8x8-as tömb volt megadva."
Ez esetben a progi elejére:#define MAX_MERET 8 és tömb deklarációnál ciklusoknál MAX_MERET-et írod be. C-ben nincs const, csak így lehet megoldani, a precompiler fogja minden egyes helyen behelyettesíteni a kódban a MAX_MERET helyére a 8-at. Azért célszerű így csinálni, mert ha valaki azt mondja, hogy mégse 8 hanem 10 elemű a tömb, akkor 1 helyen átírod, újrafordítod és kész is vagy, nem kell mindenütt cserélgetni.aztán meg debuggolni ha valahol mégis kimaradt. A keres + csere működhet, ha a kódban nincs pl 128, de ha van, máris nem lehet keres+cserét használni"Az én hibám hogy AxB-t írtam, de ha kukacoskodni akarnék nem kötöttem ki hogy A!=B "
Viszont azt se írtad, hogy A==B , ezért vettem úgy hogy nem egyenlők.
Nem bme-s vagyok, nem tudom ott hogy oktatják/nem oktatják a programozás. Számomra teljesen logikus volt, hogy AxB-sre ha nem megy a dolog, akkor megszorítom a kisebb dim szerinti négyzetes mátrixra... -
kingabo
őstag
válasz Korcsii #2301 üzenetére
"i, i-1 és/vagy i+1 is létezzen"
Jobban mondva ezek az indexek is a tömbön belül legyenek: legalább 0 és legfeljebb n-1, ha n elemű a tömb."különben szépen elszáll a program..."
Miért szállna el? Nagy valószínűséggel csak memória szemetet hasonlítgatna, ha dinamikusan lett lefoglalva a tömb, ha nem akkor a veremben elötte/utána lévő dolgokat. A c, c++ nem figyeli, hogy tömbön belül indexeltél-e. (pl a pascal-lal/ada-val ellentétben) Esetleg, ha nagyon rossz helyre menne, az oprendszer nem hagyja. c++-ban acces vialation kivételt dob ha jól rémlik, c alatt passz[ Szerkesztve ]
-
kingabo
őstag
Hát ez "picit hosszú lett. Remélem érthető. Ha kérdésed van kérdezz nyugodtan, ha a többiek valami hibát találnak szóljanak és modikkal javíttatom.
A pointer az egy mutató a memória egy pontjára, vagyis egy memória címet tárol (egy int-et). Minden pointernek meg kell mondani, hogy milyen típusra mutat, hogy a fordító tudja, mi van ott: pl char vs float, mekkora (1byte vs 4byte). A pointert minden esetben használat elött inicializálni kell! (egyszerűbben: értéket kell neki adni), mivel a pointer "kezdeti értéke" nem NULL (==megegyezés szerint nem mutat sehova sem /semmire sem), hanem valamilyen memória szemét, ha ezt a szemetet akarod felhasználni arra, hogy elérd a pointer által mutatot memória helyet elég csúnya dolgok történhetnek ("jobb esetben" az oprendszer nem hagyja, "rosszabb esetben" felhasználhatják a program eltérítésére). Pointer deklarálása: a "mutatandó" érték típusa és a változó neve elé egy *:
int * p;Érték adás:
- NULL:
int *p = NULL;
- Egy másik pointer(1), vagy pl tömb esetén annak egy tetszőleges eleme(2) (részletesen lentebb)
int *pt,*pt1,t2[]={1,2,3,5};
pt = t2; //(2)
pt1 = pt; //(1)
pt = pt1 + 3; //(2) a t2 4. elemére mutat (1+3)- Egy változó címe: a váltózó elé a '&' jelet kell írni
int *p, i = 5;
p = &i;
- Dinamikusan foglalunk le memóriát (ld. késöbb)Pointer értéke vs pointer ÁLTAL MUTATOTT memória hely értéke: ezek keverése miatt lehet igen csúnya dolgokat (==hibákat) művelni. A pointer értéke egy memória cím, ami (jó esetben) egy megfelelő értékre mutat. A pointer által mutatott hely értéke az elején részletezett, a pointer deklarácójakor megadott típusú érték. Ezt elérni a pointer neve elé tett *-al lehet. Pl az előző részből az utolsó példában a 'p' pointer értéke az 'i' változó CÍME a memóriában. Az általa mutatott ÉRTÉK, vagyis a *p értéke 5 (*p = i = 5).
A gondot az okozhatja, hogy "véletlenül" lemarad a 'p' elől a *, így a pointer kap értéket, nem az általa mutatott memória cím. Vagyis ha az 'i'-nek értéket akarunk adni a 'p' pointeren keresztül akkor így kell *p = 6; // ==i;. A következő kód hibás, csak szemléltető ellenpélda:p = 6;, ekkor az 'i' értéke nem változik, a 'p' értéke egy, a programunktól független (nem a program egy változójára, vagy általa dinamikusan lefoglalt memória területre mutat), a 6-os memória címre fog mutatni, ahol biztosan semmi keresni valónk nincs és valószínűleg az oprendszer adatai vannak, vagyis semmi jóra ne számítsunk. (akit érdekel picit részletesebben itt az utolsó 2 sor)Egy dimenziós tömb: avagy a vektor. Egy 'n' elemű vektor, n db a memóriában egymás után lévő érték. (mint linalgból) Szemléletesen pl 3 elemű tömb (az '_' helyére kerülnek az értékek: |_|_|_|
Pl: int t[]={1,2,3,5};
A dolog szépsége az, hogy a 't' is egy pointer lesz, mely a tömb első elemének memóriabeli címére fog mutani.
A tömb elemeinek elérése
- a pointer eltolása, vagyis a pointer értékéhez hozzáadva, vagy levonva belőle. Fontos: nincs semmilyen védelem, hogy a pointer ne tudjon a tömbről "lemenni". Célszerűbb (főleg az elején), inkább a másik megoldást alkalmazni, kisebb a hiba lehetősége.
pl (a fenti t-t felhasználva): int *masodikElem = t+1; // a t 2. elemére mutat (1+1)
int harmadikElemErteke = *(t+2); //t eltolva 2-vel, vagyis a 3
. elem címére mutat és vesszük a címen lévő értéket
- a [] operátort használva. a változó után írva, a zárójelek közé egész számot, vagy egész típusú változót írva.Fontos: a megszokottól eltérően, c-ben az indexelés 0-tól n-1-ig történik! Vagyis pl, a zárójelek közé 0-át írva az általunk megszokott első elemet, n-1-et írva az általunk megszokott utolsó elemet kapjuk. További megjegyzendő tény, hogy nincs semmi védelem az ellen, hogy ne "menjünk le" a tombről. Más szóval ha a c-s indexeléssel nézve a -1-edik vagy az n-edik elemét akarjuk elérni a tömbnek (ami nem létezik), akkor a memóriában a tömb elött és utána lévő értékeket fogjuk elérni, amiről már a legelején megemlítettem, hogy mindent csak jót nem jelent! (Érdekesség: a fordító ezesetben átfordítja az előző változatra. pl t[2]-ből *(t+2) lesz)Dinamikus helyfoglalás: adott a probléma: fordítási időben meg kell adnunk, hogy mekkora lesz a tömbünk mérete. Viszont, ha ez az érték csak futási időben derül ki, mert pl a felhasználó fogja megadni, akkor dinamikusan, azaz futási időben kell a tömböt lefoglalni. Módja 1 dimes tömb esetén:
- 1 deklarálni egy megfelelő típusú pointert, ami majd a tömb első (azaz 0.) elemére fog mutatni
- malloc-kal lefoglani n db, a fenti pointer által mutatott típusnak megfelelő méretű, folytonos memória területet
- a pointer típusára konvertálni a malloc által visszaadott pointert (ha valakit érdekel miért kédezzen rá, de nem igazán ez a szint, szerintem)
pl:int *p, n = 0;
//... n értéket kap
p = (int*) malloc (sor * sizeof (int));
Ha pl int helyett float kell, akkor 3 (azaz három) helyen kell cserélni a típust: a pointer deklarációjánál, a sizeof paraméterében (ez adja meg, hogy mekkora helyet foglal 1 adott típusú változó), illetve a malloc elött.
Esetleg célszerű egy if ágban lekezelni, hogy sikeres volt-e a hely lefoglalása:
if ( (ppt = (int*) malloc (oszlop * sizeof (int)) ) == NULL)
{ printf ("nincshely");
exit (1);
}//if
A fenti kód megpróbál oszlopnyi int-et lefoglalni, ennek első elemre mutató pointerét értékül kapja a ppt. Ezt utána megvizsgálunk, hogy NULL-e (ez az ami nem mutat sehova, vagyis nem sikerült lefoglalni), ha NULL, akkor a hibáról értesítjük a felhasználót és 1-es hibakóddal termináljuk (befejezzük) a program futását.
Memória felszabadítása: az általunk malloc-kal lefoglalt memóriát senki sem fogja felszabadítani, így ha már nincs rá szükségünk, vagy ugyanazt a pointert akarjuk használni egy újabb terület lefoglalásához, akkor elötte kötelező felszabadítani a memória területet, illetve célszerű a pointernek a NULL értéket adni. Ha az elöbbit elfelejtjük a programunk elszívárogtatja a memóriát (memoryleak). A felhasználó ebből azt veszi észre, hogy minnél többször futtatja a programunkat, annál több szabad hely fogy el, amit a program lefutása után nem kap vissza. A második inkább csak biztosági szempontok miatt szükséges, nehogy valaki véletlenül (esetleg rossz akaratúak direkt) a már felszabadított memória területről próbáljanak olvasni, esetleg írni (amivel más adatai írodnak felül) Fontos: NE felejtsük el felszabadítani a lefoglalt területet!
Felszabadítás: free(pointer); //ahol a pointer egy dinamukusan lefoglalt
memória terület kezdőcíme
Tényleg ne maradjon le az a free! Nem lehet elég sokszor hangsúlyozni.Több dimenziós tömbök: az egyszerűség kedvéért csak 2 dimes tömb, de ez alapján könnyen megoldható magasabb dimszámra is. (ugyanazt kell elvégezni még annyiszor, amíg el nem érjük a kívánt dim-et, ami alább következik)
Megvalósítás(elmélet): 2 dimes tömböt c-ben csak úgy tudunk megvalósítani, hogy létrehozunk egy tömböt, amely minden eleme a 2 dimes tömb egy sorára mutat.
Pl: 3x4-es tömb: van egy 3 elemű tömbünk, amelynek minden eleme egy-egy 4 elemű tömb első elemére mutat. Szemléletesen (a mutatást a -> jelőli)
_
|_| --------------> |_|_|_|_| első sor
|_| --------------> |_|_|_|_| második sor
|_| --------------> |_|_|_|_| harmadik sorTömbben lévő értékek elérése: mesélve: először (a fenti 3x4-es pl-nél maradva) a 3 elemű tömbben kell megkeresni a kiválaszotott sort tartalmazó tömb címét. Ezután elugrani erre a címre és a megadott oszlop elemének címét meghatározni.
Konkrét pl-en: próbáljuk meghatározni a fenti tömb (szokásos indexeléssel) a 3. sor 2. oszlopában lévő elemet. Ekkor először meg kell tudnunk a 3. sort tartalmazó vektor címét, vagyis t[2]-t (==t[3-1]). Ezután már csak a 2. oszlop elemét kell venni, vagyis t[2][1] (ld. előbb). Megvalósítás a pointer eltolásos technikával, inkább csak érdekesség képpen: a 3. sor címe: *(t + 2), az így megkapott vektor a 2. elemének értéke: *( *(t + 2) + 1)
2 dimes tömb lefoglalása: a fenti szemléltető ábrán is (remélhetőleg) jól látszik, hogy 4 (azaz négy) darab tömböt kell lefoglalnunk, melyek a memóriában "bárhol" lehetnek (az össz megkötés annyi, hogy a tömb elemei egymás után jönnek):
- 3db 4 elemű tömböt (vagyis lesz 3db pointerünk)
- 1db 3 elemű pointereket tartalmazó tömböt (vagyis ennek típusa pointereket tartalmató tömb, ami viszont szintén egy pointer, vagyis 2db csillag kell deklarációnál)
Pl:
//2 dimes tömb lefoglalása
int **ppt, sor, oszlop, i,j;
//.. értékadás a sor-nak és az oszlop-nak
//első rész lefoglaljuk az oszlop vektort, ami majd tárolja a
sorok címeit
if ( (ppt = (int**) malloc (sor * sizeof (int*)) ) == NULL)
{ printf("nincshely");
exit(1);
}//if
//második rész lefoglaljuk egyesével a sorokat
for (i = 0; i < sor; i++)
if ((ppt[i] = (int*) malloc (oszlop * sizeof (int)) ) == NULL)
{ printf ("nincshely");
exit (1);
}//if
//for//2 dimes tömb bejárása:
for(i=0;i<sor;i++)
{
for(j=0;j<oszlop;j++)
{
ppt[i][j]=j; //itt tetszüleges int állhat; értékadás
printf("%d ",ppt[i][j]); //érték "lekérése"
}//forj
printf("\n");
} //fori//2dimes tömb felszabadítása:
for(i = 0; i < sor; i++)
free(ppt[i]);
free(ppt);Pont úgy ahogy a fenti pl-nél maradva 4 tömböt kell lefoglalni 4-et is kell felszabadítani!
2 dimes tömb megvalósítása 1 dimes tömbbel: a 2 dimes tömb felfogható úgy is, hogy egymás után írjuk a sorait, így egy 1 dimes tömböt kapunk. A korábbi 3x4-es pl, így egy 1x12-es vektorra módosul. Egyetlen "probléma", hogy hogyan lehet kiszámolni a harmadik sor második elemének indexét. A megoldás nagyon egyszerű, csak végig kell gondolni mi történt az eredeti tömbbel (a szokásos indexelést használva): leírtunk egymás után 2 sort (2 * 4 elemet), majd a 3. sort megkezdve leírtunk még 2 elemet, vagyis meg is lett a 3.sor 2. eleme. (persze a többit is leírtuk, de az index kiszámításához nincs rájuk szükség) Vagyis mostmár általánosan: az x-edik sorhoz elötte el kell mennünk x-1 sor elemein, majd az x. sor elemei közül még az y-adikig. Legyen mondjuk minden sorban n db elem, ekkor az x-edik sor y-adik eleme: (x - 1) * n + y. Már csak azt kell végig gondolni, hogy a c féle 0-tól való indexelés változtat-e valamit vagy sem. Vagyis, ha a (innentől már a c-s indexelés) 0. sor 1. (ami nálunk az 1 sor 2. eleme) elemének az indexét kell meghatároznunk, akkor az 0 * n + 1 indexű lesz, ha az 1. sor 3. eleme 1 * n + 3, vagyis általánosan x-edik sor y-adik eleme: x * n + y.
Magasabb szinten, esetleg optimalizáláskor jöhet jól, ugyanis ezzel a módszerrel a tömb tetszőleges eleme 1 lépésben megkapható, míg a korábban leírt változattal csak 2 lépésben
Több dimenziós tömbök: csak vázlatosan: vizuális típusú embereknek: téglapból (XxY) úgy lehet téglát(XxYxZ) készíteni, hogy az (x,y) koordináta "fölé is teszünk 1 vektort(magasság)". Ezesetben ugyanúgy lesz 1 tömbünk, ami a sorokra mutató pointereket fog tartalmazni, viszont a sorok most szintén pointereket fognak tartalmazni, ezek lesznek az (x,y) helyen a fölé tett vektorra mutató pointerek. Vagyis lesz 1db X elemű tömb(int***), amiben lesznek a sorokra mutató pointerek (int**), lesz Xdb Y elemű vektor(int**), amik a magasság vektorokra mutató pointereket (int*) tartalmaznak és lesz X*Ydb Z elemű vektor (int*), ami tartalmazza a magasság adatokat (int).
Másként lehet úgy is nézni, hogy van egy vektorunk, aminek minden elem 1-1 két dimes tömbre mutat. Magasabb dim-ek ezzel a rekurzióval előállíthatók, vagy alkalmazható a fenti dim csökkentő módszer, bonyolultabb képlettel.Láncolt listák: mese: aki érti a 2 dimes tömböknél történteket, annak ez sem jelenthet gondot. A láncolt lista azt az ötletet használja fel, amit a sorok címének meghatározására használtunk fel. Viszont itt azt szeretnénk, hogy tárolhassunk a pointer mellett még adato(ka)t, illetve ne egy sorra mutasson a pointer, hanem egy másik ugyanilyen elemre. Ilyen adatszerkezetet használnak, akkor ha pl nem tudjuk előre, hogy mennyi adat lesz és a felhasználó sem tudja előre. Béna példa: mennyi madarfajt tudsz felsorolni? Ezt a példát tovább víve, a listában tárolandó adat a madárfaj neve, a pointer értéke kezdetben NULL, aztán ha a felhasználó megad egy újabb madárfajt, akkor dinamikusan létrehozunk még egy ilyen lista elemet, és ennek címét állítjuk be az előbb említett pointernek. Célszerű egy külön pointerben eltárolni a lista első elemét (fej/fej elem), és bejáráskor egy másik pointerrel (akt) végig menni rajtuk. (így nem veszik el az eleje)
Megvalósítás: szükséges hozzá tudni mi az a struct! A lista típusa egy struct lesz, ami lehetővé teszi, hogy adatokat is tárolhassunk és mutathassunk egy másik azonos típusú struct-ra.
Saját structunk létrehozása, illetve a fej deklarálása:
typedef struct madarFaj
{
char nev[30];
struct madarFaj *kov; // kov pointer madarFaj típusú
struktúrára
}MADARFAJ; //létrehoztuk a MADARFAJ nevű típust
MADARFAJ *fej, *akt;
char madarFajNeve[30];Új létrehozása és értékadások:
//ciklusban madárfaj bekérése
MADARFAJ p = (MADARFAJ*) malloc (sizeof (MADARFAJ) );
//új listaelem lefoglalása
p->nev = madarFajNeve; //elmentjük a faj nevét
p->kov = NULL; //még nincs következő lista elem, ezért nem mutat sehova sem
akt->kov = p; //hozzá fűzzük a listához az új elemet.Fontos: mivel a lista elemei is dinamikusan lefoglalt memória terültetek, ezért egyesével végig kell menni minden lista elemen és fölszabadítani!
akt = fej;
while (akt != NULL) //amíg van elem a listában
{
MADARFAJ *p = akt; //elmentjük az aktuális listaelem címét
akt = p->kov; //az aktot a következő elemre állítjuk
(felszabadítás után nehéz lenne)
free(p);
}[ Szerkesztve ]
-
kingabo
őstag
Remélem elhiszed, hogy a fenti hsz-t nem 2 sec alatt írtam meg.
Sztem nem a felfogásoddal van a gond, hanem hogy egyetemen b@sznak magyarázni. Nem véletlenül van középsuliban tanár, egyetemen előadószerk: kár, hogy itt a ph!-n nem lehet olyat csinálni mint egyes másik oldalakon, hogy a kódot autómatikusan színezni, esetleg hosszabb soroktól nem zuhanna szét az oldal. (amit tudtam javítottam, van pár komment sor ami nem fért ki egy részét átküldtem új sorba, de oda meg elfelejtettem //-t tenni, 1 még maradt benn)
[ Szerkesztve ]
-
kingabo
őstag
válasz RexpecT #2314 üzenetére
Tudom ez Neked nem segít, de az elemeket (érték, multiplicitás) formában szokás tárolni. Ez alapján (nekem!) az tűnik logikusnak, hogy egy indexre beírod az értéket utána a multiplicitását. vagyis: 3 3 1 3, hogy az 5. elem mi a fene lehet nem tudom.
A másik kérdést nem igazán értem, hogy mire akar célozni. A tömb egy elemének maximális értékét a típusa határozza meg, pl 32 bites gépen, int esetén 2^31-1; unsigned int esetén 2^32-1. Hogy erre gondoltak-e nemtom.szerk: elöbb nem vettem észre, hogy int típusú a tömböd. Ezeseben szerintem a max a 2^31-1. A többiek majd vagy megerősítik vagy kijavítanak.
[ Szerkesztve ]
-
kingabo
őstag
válasz Pcmagicnet #2345 üzenetére
Végülis így is megoldható.
5letek: a sok if helyett lehetne egy switch-ben:
switch (c)
{
case 'a': ++a; break;
...
case 'z': ++z; break;
}A case ágak végére KELL a break.
Esetleg használhatnál tömböket a számokhoz, betükhöz és sokkal rövidebb lenne a kód. -
kingabo
őstag
válasz Pcmagicnet #2349 üzenetére
Őőő, bocs csak most vettem észre: a hisztogrammban %-os eloszlást szokás mutatni. Tehát a-ból van 5%, e-ből 12%... az összegük meg 100%. VAgyis minden elemre le kell osztani a karakterek számával és megszorozni 100-al. (az osztásnál használj kasztolást, hogy ne int hanem float osztás legyen: int-nél 1/10 = 0 float-nál: 1/10=0.1)
(#2348) RexpecT: majd késöbb átnézem, ha nem jön addig senki sem.
-
kingabo
őstag
válasz RexpecT #2348 üzenetére
Tedd az u = u * f;-et a ciklus végére és nem kell az if, ill írhatod ezt is helyette u*= f;. Vagy még szebb, ha a for-ban az i++ után teszed.
"Annyi a baj, hogy mindig az első naphoz képest fárad a csiga, az én kódomban meg mindig az előzőnaphoz."
Pont fordítva. A Te progid a feladatban megadott pl-re rossz eredményt fog adni, mivel amikor kiér a csiga, Nálad akkor is visszacsúszik.
C-ben nincs konstans. A legegyszerűbb az, ha deklarálsz még 1 változót, amiben azt tárolod, hogy mennyivel mászik kevesebbet naponta a csiga és ezt vonod le az u-ból.Legközelebb programkódként idézd a progid, mert könnyebb átlátni, ha benne vannak a tabok.
(#2351) Pcmagicnet: ezt már akkor se értettem igazán, hogy mit akartál ezzel leírni. (csak kimaradt a hsz-ből)
Szerintem nem jó, mert ha pl van 10db 'a' betűd és semmi más, akkor (ha jól értem a kódod) 70% lesz az 'a'-k aránya a 100% helyett.[ Szerkesztve ]
-
kingabo
őstag
válasz Pcmagicnet #2353 üzenetére
Ezt írtad :"kinyomtatja a bemenetre adott különböző karakterek előfordulási gyakoriságának hisztogramját" Ebben én nem látom sehol sem, hogy soronként kéne számolni, inkább az egészre.
"van 10db karakterem , ebből 6db 'a', és 4db 'b'. Akkor úgy kellene megjeleníteni, hogy 60% 'a', és 40% 'b' ?"
Szerintem így lenne értelme.
-
kingabo
őstag
válasz Pcmagicnet #2355 üzenetére
A az 'i2' és a 'k2' azok milyen betűk?
Ehelyett :printf("(%1.1f%s) \n", (a / k), "%" ); ez is írható: printf("(%1.1f\%) \n", (a / k));. Ha egy string-ben egy foglalt operátort akarsz használni, mint itt pl a %-ot, vagy idézőjelet("), akkor szimplán írj elé egy \ jelet.Ha a \ jel kellene az így néz ki: \\ Pont ugyanígy a printf("%s","*"); helyett printf("\*"); Illetve ha csak 1 karaktert íratsz ki akkor szebb a %s helyett a %c.
Ha akarsz a progidon rengeteget rövidíteni: ascii. Kicsit bővebben, a ciklusban a c1 a bekért betű ascii kódját fogja tárolni (vagyis ha nem %c-vel íratod ki, hanem %d-vel akkor a betű helyett az ascii kódja kerül a képernyőre). Az ascii kódot pedig szépen fel tudod használni egy tömb indexelésére. Pl a szám tömb indexeléséhez:
if (c1>='0' && c1 <='9')
{
++szam[c1-48]; //a 0 ascci kodja 48, vagyis ezt le kell vonni
}
Hasonlóan rövid lesz a betűk esetén is az 'A' esetén 65-t kell levonni, a 'a' esetén 97-et. Persze a megfelelő méretű tömböket elötte le kell foglalni.(#2356) Pcmagicnet: ránézésre jó, kipróbálod és kiderül.
-
kingabo
őstag
válasz Pcmagicnet #2359 üzenetére
De sikerült megoldanod a * kiíratást az a lényeg. Én meg kétszer is megnéztem mit akarsz mire rájöttem.
A kódtáblát én sem tudom fejből, ezért is linkeltem.
Nincs mit!(#2358) Carpigabi: nagy segítség lett volna ha elforgatod a képeket. Az első képen az 1 egy ciklust jelől, a 2 return-t (szerintem). Ha jól sejtem, valamilyen iterációval számol ki adatokat.
-
kingabo
őstag
válasz RexpecT #2361 üzenetére
Leírom megint hátha: Legközelebb programkódként idézd a progid! (a félkövér gomb alatt van a programkód gomb )
"Viszont azt is meg kellene oldani, hogy a csiga ne tudjon negatív irányba visszacsúszni,de erre még nem jöttem rá, hogy hogyan is kellene."
A korábban idézett megoldásodban két pozitív számot szoroztál össze, ami mindig pozitív lesz. Ha az előző hsz-emben leírt módszert használod, akkor a for ciklus-ba tegyél egy + feltételt, hogy a visszacsúszás pozitív, vagy a ciklusban miután viszacsúszás új értéket kap megvizsgálod, hogy nempozitív-e, ha igen akkor egy break;-kel kilépsz a ciklusból. Illetve a Failure-ös részbe akkor is be kell lépni, ha a visszacsúszás nempozitív.Nincs mit!
-
kingabo
őstag
válasz Korcsii #2370 üzenetére
"kingabo: strcpy jó, csak épp semmi nem létezik, amit neki adni kéne..."
Hogy hogy nem létezik? Tehát amit beolvas a file-ból az semmi?(#2372) gergo00: maga a string is egy tömb. Vagyis a 3. dim a beolvasott szövegeket fogja tárolni.
(#2371) gergo00: miért foglalsz le 255 oszlopú tömböt, ha a ciklus végén 6 oszlop után új sort kezdesz?
[ Szerkesztve ]
-
kingabo
őstag
válasz Korcsii #2375 üzenetére
Ok, igazad van.
A szemem az értékadáson akadt meg illetve ezen a mondaton: "csak viszont igy a tomb2 memoriacime mindig felulirodik es az utolso elem tartalma lesz mindig benne" Erre megoldás az strcpy, azt viszont tényleg nem vettem észre, hogy nincs hely foglalva a paramétereknek.[ Szerkesztve ]
-
kingabo
őstag
válasz Pcmagicnet #2377 üzenetére
Pár hsz-el feljebb van minta a file-ból való olvasásra. A for ciklust akkor szokás használni, ha tudod, hogy hányszor kell lefutnia, mert pl a file első sorában megadod a sorok számát, egyébbként a while. A probléma is ehhez köthető. A ciklus magod össz vissz ennyit tartalmaz: hossz[i] = c; /* rövidített ciklus */, ezért is célszerű (pláne kezdőknek) a ciklus magot új sorba írni. A másik probléma az, hogy nem vizsgálod meg sehol sem a szavak hosszát, hanem egyből bele is teszed a tömbbe.
A ? operátornak nem ez a "megszokott" használati esete, ez átláthatóbb lenne sokkal if-ként.
valtozo = (feltetel) ? ertek_ha_igaz : ertek_ha_hamis
Én így csinálnám: ha a beolvasott szó hossza megfelelő, akkor átmásolnám tömbbe és növelném a tömbbeli szavak számát. mielött neki esnél egy problémának találj ki rá egy programozási nyelvtől független algoritmust, próbáld ki papíron, hogy jó-e. Így kivédhető lett volna az, hogy meg se vizsgáltad a beolvasott szó hosszát.[ Szerkesztve ]
-
kingabo
őstag
válasz Sk8erPeter #2384 üzenetére
Egyet értek!
-
kingabo
őstag
Naná, hogy elszáll!
Ez mi: *(ar+(i*sizeof(int)))??? A 400-adik elemre fogsz a ciklus végén mutatni! A pointerhez, ha hozzá adsz x-et, akkor a fordító tudja, hogy hány byte-tal kell arrébb mennie a tömbben az x-edik elemhez. Ráadásul írhatnál ar[i]-t is, ami sokkal átláthatóbb. sok értelme volt annó leírnom ezeket, ha el se olvasta senki sem...
Ha meg fordítási időben tudod a tömb méretét miért szórakozol dinamikus memória kezeléssel?[ Szerkesztve ]
-
kingabo
őstag
Emlékeim szerint leírtam, hogy a fordító hogyan határozza meg a adott elem memória beli címét, meg példákat, ezért nem értem a sizeof-os dologot miért írtad. Ha void* -ként kezelted volna akkor okés lenne, de ezen a szinten nem jön elő.
Csak kiváncsiságból ez *(ar + i ) miért tetszik jobban ennél ar[i]?ui: nem számon kérés akart lenni, az előző hsz-em, csak furcsa volt az a sizeof-os hiba.
(#2404) j0k3r!: ez fel se tűnt. Teljesen igazad van, bár mintha jobb fordítók sipákolnának ezért.
szerk: se gcc, se g++ nem szólt még -wall-al sem... Akkor csak a c#-é.
[ Szerkesztve ]
-
kingabo
őstag
válasz Szőkecica #2406 üzenetére
Ki kell jelölni a forráskódot és utána megnyomni a programkód gombot.
A for helyett inkább egy while ciklus kéne: kiírod az adatokat 1 oldalra egy for-ral, bekérsz addig amíg az előre/visszalépés gombját meg nem nyomják, aztán megvizsgálod, hogy merre kell lapozni és ehhez állítod a for alsó felső határát ugrás a while elejére. (pl)
-
kingabo
őstag
válasz Szőkecica #2410 üzenetére
Előjeles szám a legfelső biten tárolja az előjelet, de ezzel egy hasznos bitet elvesztünk az előjel nélkülihez képest. Vagyis az előjelnélküli által tárolt legnagyobb max szám az a duplája az előjeles által tárolt max-nak.
Az azt jelenti, hogy az a változó 0 és 255 közötti értékeket vehet fel.
Itt jól megfigyelhető a signed és az unsigned által tárolható min és max értékek: [link] (c#-ról van szó, de ez ne zavarjon meg
-
kingabo
őstag
válasz Szőkecica #2412 üzenetére
"Azt hittem hogy az ami előtt van egy - jel :-)"
De kell valahogy azt a '-' jelet tárolnod. Akkor próbálom visszafelé. Van a "sima" char, ami -128 és 127 közötti értéket vehet fel. Ez binárisan úgy van megvalósítva (nagy vonalakban, részletesebben kettes komplemens szám ábrázolás), hogy van 8db bited, az első bit elmegy az előjel bitnek, a maradék 7 biten pedig lehet tárolni 2^7 értéket vagyis 128-at (a pozitív oldalon azért csak 127-ig megy, mert a 128-adik érték a 0 ). Ha a char elé odaírod, hogy unsigned, vagyis unsigned char ertek;, akkor előjel nélküli változót deklarálsz. Ekkor az előjelnek fenntartott bit is felhasználható értékes bitként, vagyis 2^8-an számot tudsz tárolni. Mivel mindkét esetben 8biten vagyis 1 byte-on tárolod az adatokat, ezért a sizeof ugyanazt a méretet fogja megadni. Ugyanez érvényes az pl az int-nél is, csak ott 1byte, helyett ált 4byte-on tárolod az adatokat.Ha próbálgatni akarsz: deklarálj egy előjeles és egy előjel nélküli char-t. Az előjelesnek adj egy pozitív számot értékül, aztán kasztolással* add értékül a változót az előjel nélkülinek. Ugyanezt próbáld ki negatív számmal is, aztán szerep cserével, 127-nél nagyobb értéket adj az előjel nélkülinek és ezt a változót add értékül az előjelesnek. Ja és természetesen minden értékadás pár után írasd is ki, hogy lásd a különbségeket.
*kasztolás: egy adott típusú változót "átalakítani" másik típusúvá. (kisebb-ről nagyobbra, tehát pl: char-ról int-re megkötés nélkül lehet, de visszafelé nagy valószínűséggel adat vesztés lesz, mivel az int-be jóval nagyobb számok is beleférnek)
Pl: char elojeles = -5;
unsigned char elojelnelkuli = =(unsigned char) elojeles;Bocs ennél érthetőbben nem tudom elmagyarázni. Ha valami kimaradt, vagy nem érthető, akkor kérdezz nyugodtan.
-
kingabo
őstag
válasz lalbacsi #2448 üzenetére
Hali!
Először is: légy szíves használd a programkód gombot, hogy olvasható legyen az idézett kódod! (pár hsz-el feljebb képpel le van írva hogy hogyan kell!)
Baromi régen borland pascalban rajzolgattunk, elvileg borland c-ben ugyanazok az fv-k csak nyilván c-s stílusban...Pascalos kód: egy "forgó" kereket rajzol ki a képernyő közepére, ha minden igaz, remélem sikerül hasznát venni. (szerintem c-s "szemmel" is olvasható a kód, ha valami nem világos kérdezz, hátha rémlik még )
uses crt,graph;
var i,gd,gm,x,y,r,vx1,vx2,vy1,vy2,f:integer;
ra:real;
function radian(fok:integer):real;
begin
radian:=fok*pi/180;
end;
begin
detectgraph(gd,gm);
initgraph(gd,gm,'c:\bp\bgi');
f:=30;
x:=getmaxx; x:=x div 2;
y:=getmaxy; y:=y div 2;
r:=100;
setlinestyle(3,$0101,3);
circle(x,y,r);
repeat
cleardevice;
setcolor(white);
circle(x,y,r);
for i:=1 to 12 do
begin
setcolor(white);
f:=f+30;
ra:=radian(f);
vx1:=x+trunc(r*cos(ra));
vy1:=y+trunc(r*sin(ra));
line(x,y,vx1,vy1);
end;
delay(60);
for i:=1 to 12 do
begin
f:=f+30;
setcolor(black);
ra:=radian(f);
vx1:=x+trunc(r*cos(ra));
vy1:=y+trunc(r*sin(ra));
line(x,y,vx1,vy1);
end;
f:=f-720;
f:=f+5;
until keypressed;
readln;
end.[ Szerkesztve ]
-
kingabo
őstag
Bocs, ezt nem tudtam kihagyni: write in c
-
kingabo
őstag
válasz Sweet Lou 6 #2455 üzenetére
Gondolom az sem véletlen, hogy a kettőspont c (: C) smiley-t szúrtad be.
-
kingabo
őstag
Próbáld meg úgy, hogy papírra csak az algót írod fel nem c-sen, hanem általánosan prg nyelv függetlenül. (beolvasás helyett pl egyszerűen tömböt használsz) Illetve nagy segítség lehet, ha pl egy minta filet, akár így x és y formában felírsz és abból "kézzel" építed fel az adat struktúrát. (lesz 5leted az algóra): X , Y , Y , X, X, Y, X, Y, Y
-
kingabo
őstag
Nekem ennyire mélyen nem kellett c-s file kezelés, sajnos.
Esetleg próbáld meg ezeket: [link], posix (hátha mond valamit) szabványban a hálózati kommunikációs részhez kell, szintén little-big endian konverzió miatt.A másik, hogy elő jöhet-e a dupla nulla? Fölösleges olyannal szívni, amit nem kell leprogramoznod.
A for írható így is:
for(i=0;i<4;j--;i++;){
s[i]=sc[j];
}[ Szerkesztve ]
-
kingabo
őstag
Gondolom érted magát a kivételt és hogy mi okozhatja.
Nem tudom miben fejlesztesz, ha van rá lehetőség próbáld lépésenként futtatni, hogy megtaláld a hiba helyét, pontos okát. Ha nincs rá, akkor tele kell pakolni a progit kiíratásokkal, hogy megtaláld, hogy pontosan hol váltódik ki a kivétel. Ha a hely megvan, akkor a változók értékeit/változásait írasd ki.
Haramadik lehetőség, hogy annyira lecsupaszítod a kódot amennyire csak lehet, de még a hibás rész benne van és ezzel próbálsz rájönni a hibára, vagy esetleg azt osztod meg itt, hátha valaki kiszúrja mi a gond. -
kingabo
őstag
válasz Jester01 #2668 üzenetére
Úgy rémlett, hogy korábban én a noskipws-t használtam erre a problémára, a leírásban nem találtam semmit ami miatt ne működne. Viszont baromira érdekel, hogy mivel keverem?
Akkor marad a cin.get vagy a cin.getline. (sztem megéri kiszedni a sorvége jelet is a pufferből) -
kingabo
őstag
válasz Rickazoid #2745 üzenetére
Ahogy Jester01 ajánlotta sort olvass be, amit az atoi-val (ascci to int) alakíts át számmá és ennek az eredményét vizsgáld a switch-ben. Elötte persze ellenőrizni kell, hogy mit adott vissza az atoi: pl 11a esetén 11-t, a esetén 0-t (de 0 esetén is 0-t ad vissza, ami jó!), ilyenkor nyilván újra be kell kérni.
[ Szerkesztve ]
-
kingabo
őstag
válasz Barett 50cal #2751 üzenetére
Olvass vissza pár hsz-t, ehhez nagyon hasonló dologról volt szó.
-
kingabo
őstag
válasz PetyaMIK #2762 üzenetére
Helló!
Jester01 észrevételein felül, while-ba kéne még egy feltétel, hogy ne kérhesd be a 101-edik értéket. Illetve kiíratásnál használhatod az index+1-et is, így nem lesz szükséged az Edik változóra.
Ja és egy kérés legközelebb a kód beillesztése után jelőld ki a kódot és nyomd meg alul a Programkód gombot, úgy nem fognak a tabulálások elveszni.
[ Szerkesztve ]
-
kingabo
őstag
Ez a szabványos c-ben nincs benne, a Borland tette bele a turbo c-be (meg pascalba), tudtommal.
Feribacsi555 :Ezzel tehetsz egy próbát: changing text color in c
[ Szerkesztve ]
-
kingabo
őstag
válasz TheRolf #2813 üzenetére
Hali!
Csak gyorsan átfutva az tűnt fel, hogy a string-ben az n+1-edik elemre hivatkozol. Pl van egy 5 hosszú stringed, akkor az indexek 0 és 4 között vannak a string[len-i] i=0 esetén viszont 5. Megoldás vonj le még 1-et az indexből, vagyis így nézzen ki string[len - i - 1].
Hibakereséhez ajánlom a debugger használatát.
Ú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!