struct tomb

 ( expandnames | 2012. június 12., kedd - 17:29 )

Hello,

van egy struct:

struct owe {
ar *p_name;
int p_claim;
};

ebbol csinalok egy tombot:

struct owe o[peers];

majd egy ciklussal fel szeretnem tolteni:

for (i=0; i (kissebb) peers; i++){
printf("%d. name: \t\t",i+1);
scanf("%s",&o[i].p_name);
printf("%d. claim: \t\t",i+1);
scanf("%s",&o[i].p_claim);
}

Hozza szeretnek ferni a peers szamu strukturaimhoz, de valamiert nem jol jelenik meg az ertek:

for (i=0; i(kissebb)peers; i++){
printf("%s: %d\n",&o[i].p_name,o[i].p_claim);
}

A program rendesen lefordul, hanem amikor az adattagokat akarom kiolvasni, amit scanf-el olvastam be akkor valamiert hibas erteket kapok vissza a tagok p_claim tagjara, valamint az elso adattagok ha tul hosszuak akkor a kovetkezo adattagok int-jei rafutnak az elozo tagok stringjeire..

Elore is koszonok minden hozzaszolast!

Hozzászólás megjelenítési lehetőségek

A választott hozzászólás megjelenítési mód a „Beállítás” gombbal rögzíthető.

Szeretnéd, de nem fog sikerülni!:)

+1 :)

struct owe o[];

Mekkora méretű legyen a tömb? Ez ebből nem derül ki...

G.
============================================
"Share what you know. Learn what you don't."

A kérdés sem derül ki számomra. Sőt, a példakód vége sem. Vagy ez olyan kaland-játék-kockázat stílusú lapozgatós kérdés lesz?

programnyelv sem derult ki, meg a vege is hianyzik a pasztanak :p

--
NetBSD - Simplicity is prerequisite for reliability

C C++ fórumban vagyunk :-)

Akkor már "csak" kétesélyes a dolog, ugye :D

http://i47.tinypic.com/2v8gubm.jpg

bocs, nem lehetett kihagyni

szögletesnyitójel spésznélkül code szpésznélkül szögleteszárójel és ennek záró párja közé tedd a kódot.

http://hup.hu/filter/tips blokk formázás rész.

Csak hogy legyen egy megoldas fele is...
Szerk.: Persze ez nem tolti fel az utolso elemet :D

#include 

typedef struct alma_t {
    int a;
    char z;
};

int main(const int argc, const char* argv[])
{
    struct alma_t zoldalma[10];
    
    struct alma_t* x = zoldalma;
    for ( x ; x != &zoldalma[9] ; x++ ) {
        x->a = 5;
        x->z = 'a';
    }
    
    x = zoldalma;
    for ( x ; x != &zoldalma[9] ; x++ ) {
        printf("%c -> %i\n", x->z, x->a);
    }
    return 0;
}

Viccess de mukodik igy:

...
    for ( x ; x < &zoldalma[10] ; x++ ) {
        x->a = 5;
        x->z = 'a';
    }
...

Ez vajon biztonsagos ?

P.S.: boccs a sok szerk. miatt.

Szerk megint.:
Annak tunik, mert az ott csak egy cim, amig nem probaljuk olvasni / irni nem lesz gond :D

Esetleg, ha nem for()-ral szerveznéd a ciklust? ;)

Nem ertem mire gondolsz...
:)
While mivel lenne jobb itt most ?

Az semennyivel.
Ellenben a do-while a ciklus végén simán ellenőrizhet (kisebb)egyenlőségre.

Naná, hogy működik, sőt, biztonságos is.
Igazából én az első formát (x < &zoldalma[9]) ritkábban látom, valahogy a második verzió terjedt el jobban. Talán amiatt, hogy 10-et nem írunk a kódba, ehelyett van #define, vagy const.

Emlékeim szerint ez is tökéletesen működik:

for (; x < zoldalma + 10; x++)

Ez a forma kellemesebb a szemnek, nincsen benne annyi saláta, mint a fenti változatokban.

Fuszenecker_Róbert

unsigned index;

for (index = 0; index < sizeof(array)/sizeof(*array); index++) {
array [ index ] .a = 7;
array [ index ] .z = 'a';
}

És nem, nem lesz kevésbé optimális, mintha pointert használnánk (gcc -O2 mellett biztosan nem).

Már hogy lenne kevésbé optimális, a fordító mindent tud, ügyesen kikalkulálja fordítási időben :-)

Fuszenecker_Róbert

Hello Fuszi !
1000 eve nem hallottam feloled :)

Megkerdeztem itt az okosokat a cegnel, mindenki az indexelesre szavazott... Persze jo ez igy... de ez az elfogadott:

for(int i = 0 ; i < SIZE ; i++) {
   array[i].x = ...

Hello, Marczis kolléga!

Igen, ezért írtam és is azt, hogy "emlékeim szerint", mert kerülöm én is ezt a formát. Az indexelés tűnik a jobb útnak.
A pointeraritmetika szép dolog C-ben, de pl. C++-ban az indexer (vagy tudom is én, hogy hogy hívják -- operátorkockászárójel) elvégezhet egy csomó műveletet, pl. indexhatár-ellenőrzés. Meg lássuk be, szebb is :-)

Viszont nem akarom elvenni a programozótól az ő programozói szabadságát. Lehet, hogy mások a többi formát részesítik előnyben, mert nekik az a logikusabb. Vagy szebb.

Fuszenecker_Róbert

a pointer átadás valamivel gyorsabb, de nem annyival hogy megérje (azért a fordító sem tud mindent kitalálni, főleg ha cikluson belűl variálsz nagyokat, illetve kevésbé átlátható a kód egy obfuszkált for ciklussal).
Az indexhatár ellenőrzés pedig csak fordítási időben mérvadó, ott is csak warnyingolni fog hogy "há hülye vagy te?".

"Az indexhatár ellenőrzés pedig csak fordítási időben mérvadó, ott is csak warnyingolni fog hogy "há hülye vagy te?"." -- pedig én már írtam olyan kódot, ahol volt futásidőben indexhatár-ellenőrzés.

Fuszenecker_Róbert

az hogy te magad lekezeled azt az esetet, hogy ne történhessen meg, meg az hogy a compiler felsikít, hogy nincs allokálva memória arra a területre, ahol matatni szeretnél, az két különböző kategória szerintem

Szeretek veled vitatkozni, mert értelmes ember vagy.
De ezt most nem értem. Azt írtam pár kockával feljebb, hogy "A pointeraritmetika szép dolog C-ben, de pl. C++-ban az indexer (vagy tudom is én, hogy hogy hívják -- operátorkockászárójel) elvégezhet egy csomó műveletet, pl. indexhatár-ellenőrzés."

Ez alatt én pontosan ezt értem. Valóban, az operator[] lehetőséget ad arra, hogy futásidőben ellenőrzést végezz. Ettől még a fordító is teszi a dolgát.

Az a baj, hogy ugyanarról beszélünk, és ez így nem vita :-)

Fuszenecker_Róbert

Én ezt az alakot kedvelem ilyen esetekben:

struct alma_t* x;
for ( x = zoldalma ; x != &zoldalma[9] ; x++ ) ...

De mivel cikluson kívül úgysem használjuk az x-et, ezért szerintem felesleges cikluson kívül deklarálni.

de C-ben nem deklaralhatod a for ciklus fejleceben, csak C++-ban (igaz nem is derult ki, hogya topik C vagy C++)

Jelen kérdésben a type name[] vs. type name[num] a nem mindegy.

Ha tudod mennyi lesz, akkor a második, ha nem, akkor az első (vagy type *name) és malloc(num * sizeof(type))

--------------------------------------
Unix isn't dead. It just smells funny.

Elnézést nem kötekedni akarok csak nem értem.
Ennek mi értelme van (azon kívül hogy a gcc ezt írja rá: warning: useless storage class specifier in empty declaration):

typedef struct alma_t {
    int a;
    char z;
};

Gondolom inkább ennek lenne értelme:

typedef struct {
     int a;
     char z;
} alma_t;

És akkor később elég lenne csak ennyit írni:

alma_t zoldalma[10];

Bocs, ha hülyeséget kérdezek, nem értek C programozáshoz.

Jogos.
Ez a typedef, meg a c / c++ miatt van nalam...
Mert ugye ezt szoktam irni:

struct z {
    int a;
    int b;
} b;

es akkor a z a type, a b meg mar egy "egyed..." igy ugye amikor nem akarok egyedet a z ott marad fent :D

Tehat ez c++ -ban mukodik:

struct z {
    int a;
    int b;
} b;

int main(const int argc, const char* argv[])
{
    z elso;
    
    b.a = 5;
}

de c-be viszont nem:

[0][xxxx@sonya:/home/marczis/tmp]
gcc test.c 
test.c: In function 'main':
test.c:9:5: error: unknown type name 'z'
[1][xxxx@sonya:/home/marczis/tmp]
g++ test.c 
[0][xxxx@sonya:/home/marczis/tmp]

Azért ha "z elso;" helyett "struct z elso;" -t írsz, még C-ben is lefordul. (Az, hogy elhagyhatod a struct kulcsszót, az csak simán egy C++ eye-candy. De ha így írod, azt megeszi egy rndes C-fordító és egy rendes C++-fordító is. (És amúgy nem z a type, hanem struct z.)

jogos. Bar en rendre elhagyom a struct-ot c++-ban.

Nem eye-candy amugy, hanem C++-ban a struct az picit mas, mint C-ben, az elobbinel egy buta classrol van szo, aminek nem tud privat/protected/virtual membere lenni. Asszem.
--
Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant. | Gentoo Portal

Asszem

Egyáltalán nem "buta". A struct ugyanolyan mint a class, viszont a memberjeinek default láthatósága, illetve a default öröklődés public.


struct A1 : B {};
class A2 : public B {};

struct A3 { private: int x; };
class A4 { int x; };

A1 == A2, A3 == A4, illetve még annyi, hogy forward deklarációnál a definícióban szereplőt kell megadni.

Az az eye-candy, hogy "struct x" helyett kesobb irhatok siman csak "x"-et tipukent. Ez parasztvakitas. Az, hogy a struct C++-ban a class-nak specialis formaja, az egy masik szempont.

Ez nem parasztvakitas, hanem egy nagyon jol hasznalhato feature

dupla

Szeretném, ha elmagyaráznád, hogy ez az apróság, hogy nem kell kiírnom a struct kulcsszót, neked hol "nagyon használható feature". (Attól eltekntve, hogy spórolok 7 karaktert mindegy egyes ilyen adatszerkezet leírásánál :-) )

nezd meg hogy mire hasznaljak a typedef-t es mi az elonye, aztan gondold at ujra az egeszet.
Nem az a 7 karakter a sporolas mert egy jobb erzesu ide elintezi neked

Innen indultunk ki, ahol ez allt:

struct z {
int a;
int b;
} b;

int main(const int argc, const char* argv[])
{
z elso;

b.a = 5;
}

Ebbol indultunk ki, en typedef-rol nem beszeltem, hanem csak arrol, hogy "z elso" helyett "struct z elso" kell, es maris eszi a C-fordito (es ez a forma - nem kell a struct - nekem igy csak szemcukorka).

c-ben struct z elso <> z elso es a typedef hasznalata nem szemcukorka, csak nem tudod hasznalni, de ezt megbocsajtom neked mert latszik, ezert beszelsz hulyeseget

Akkor még egyszer. Fent szerepel egy kód, amit nem én írtam. Ellenben aki írta, azt mondta, hogy ez sajnos C++-ban így ahogy van fordul, de C-ben nem. Én meg csak annyit mondtam, hogy ha oda tenné a struct-ot, akkor C-ben és C++-ban is fordulna (és szerintem ugyanazt is jelentené, de ugye mint jelezted, én ehhez nem értek). Kifejtenéd, hogy az általam idézett kódban hol van typedef, és az általam idézett kódban vajh mi a különbség a "struct z b" és a "z b" között? Ha már egyszer te értesz hozzá.

Bocs, my fault! Elnézést kérek

a szinonima letrehozasan kivul milyen jol hasznalhato feature-el rendelkezik?

---
Egy jól megállapított probléma félig megoldott probléma.
- Charles Kettering

jo kis dependency hellt lehet vele csinalni! :)

--
NetBSD - Simplicity is prerequisite for reliability

:D

---
Egy jól megállapított probléma félig megoldott probléma.
- Charles Kettering

igen, a C++-os "struct" utasitas a C-s "typedef struct"-nak felel meg, ennek "kihasznalasaval" lekodolhato ritka esetek egyike, amikor lehet olyan C programot irni, ami nem fordul le C++-kent forditva, pl. "typdef valami" es "struct valami" is van a a C-s forraskodban, ez C++-ban mar utkozes

Igen, de a ketto ott fugg ossze, hogy mivel a struct az a class egy specialis formaja ezert nem kell kiirni, hogy struct. Hiszen, amikor osztalyt adsz meg tipuskent, akkor se irod ki, hogy class. Vagyis az egyik a masikbol kovetkezik. Szerintem. Hiszen ezen a ponton mar nincs ertelme megkulonboztetni a struct-ot a class-tol.
--
Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant. | Gentoo Portal

No ez az ami nem jutott eszembe, de teljesen igazad van, es igy mar sokkal elfogadhatobb. (Ettol meg szemcukorka annak, aki a C++-bol kb. az eredeti C-with-classes funkcioit hasznalja ki, es nem az egymillio extremitast.)

"az elobbinel egy buta classrol van szo, aminek nem tud privat/protected/virtual membere lenni"

Tud, csak struct-nal default a public, class utasitasnal meg default a private, ennyi a kulonbseg. Unionnal mar tobb kulonbseg is van, union pl. nem lehet szulo es gyerekosztaly sem

A kérdezőnek: még mindig hibás a bemásolt kódod, egészen elképesztő, hogy egy copy+paste problémát jelent. Vagy az, hogy utána nem nézed át mégegyszer, hogy tényleg jót másoltál-e be. Ez így szakmai igénytelenségnek tűnik számomra.

A többieknek: Bohóckodtok itt mindenféle dolgokkal (pointerezés, optimalizáció, boundary check, etc.), de egyikőtök sem válaszolja meg a problémát. Így kár volt hozzászólnotok!

expandnames, több probléma is van az általad beillesztett kóddal:
1. Nem foglalsz memóriát az owe.p_name -nek. Itt az történik, hogy a bevitt sztringet a struktúrában a p_name pointer számára fenntartott helyre fogja írni a scanf. 32-bit esetén 4 byte hosszú a pointer, tehát 3 karakter hosszú sztring fér itt el anélkül, hogy átlógna a struktúra következő p_claim tagjába, vagy a következő struct adataiba. Sztringet például úgy olvashatsz be, hogy feklarálsz neki egy char szoveg[80]; tömböt, és arra irányítod a scanf függvényt. Ekkor 79 karaktert vihetsz be puffeltúlcsordulás nélkül (tudván, hogy a sztring automatikusan kiegészül egy \0 karakterrel). Egy másik lehetséges megoldás az, ha a p_name pointer segítségével memóriát foglalsz le, és a scanf függvényt arra a memóriaterületre irányítod.
// a ciklus belsejében
o[i].p_name = (*char)malloc(1024 * sizeof(char))
if (o[i].p_name == NULL) { printf("Memoria lefoglalasa sikertelen\n"); exit(1);}
// es itt mar mehet a scanf, de & operator nelkul, mert mar eleve pointerunk van
scanf("%s", o[i].p_name);

A p_name kiiratásánál sem kell a & operátor, mert már pointerünk van:
printf("%s: %d\n",o[i].p_name,o[i].p_claim);

A végén pedig fel kell szabadítani a lefoglalt memóriákat. Ugyanúgy végigmész a struct tömbön egy ciklussal, a cilusmagban pedig így lesz a felszabadítás:
free(o[i].p_claim);

2. Amikor az owe.p_claim-set olvasod be, ott a scanf-nál %s-t használsz. Sztringet nem szabad beolvasni akkora helyre, amit a fordító int-nek tartott fenn. Ez már puffeltúlcsordulás.
// helyesen:
scanf("%d",&o[i].p_claim);

3. Ez nem hiba, csak egy apró meglátás: a tömb méretét általában konstanssal szokták C-ben megadni. Az az elfogadott, hogy a konstansok nevét csupa nagy betűvel írjuk. Tehát a tömb lefoglalásához valami ilyesmit használnék:

// Például a kezdeti include-ok után
#define PEERS 1

Végül a tömböt így deklarálod:
struct owe o[PEERS];

Javaslom, nézz utána a következő témáknak több C-könyvben is: tömbök kezelése; pointerek kezelése; dinamikus memória használata (malloc/free)!

"A többieknek: Bohóckodtok itt mindenféle dolgokkal (pointerezés, optimalizáció, boundary check, etc.), de egyikőtök sem válaszolja meg a problémát. Így kár volt hozzászólnotok!"

Te is vagod hogy miert szaladtak el itt a dolgok (mert konkretan se kerdes, se problema, csak egy befejezetlen "valami" volt elso korben). Gyonyoru szepen +1-eztel is ra masodikkent. Ennek okan kicsit butan nezek, mikor egy ilyen kicsuszik a szadon (akarom mondani kezeden).

Jogos az értetlenkedésed... a probléma megfogalmazása valóban jellemezhető úgy, hogy gyenge kezdés után erős visszaesés. :D
Azért írtam mégis, amit írtam, mert közben a kérdező viszonylag értékelhető módon kiegészítette a probléma leírását.

Ha hozzáír a threadhez és nem csak az indító szálat módosítgatja, akkor a többiek is észrevették volna. Ha nem mondod, nekem fel se tűnik (mert automatikusan görgetek lefele az új hozzászólásokhoz, nem olvasom el újra amit már egyszer elolvastam)

"if (o[i].p_name == NULL) { printf("Memoria lefoglalasa sikertelen\n"); exit(1);}"

ez igy leakelni fog (ami akkor lesz baj, ha fv-e lesz valamikor refaktoralva)

--
NetBSD - Simplicity is prerequisite for reliability

Oké, és mit kellene tenni,hogy ne leak-eljen? Jól gondolom, hogy az exit(1) előtt végigmenni a o tömbön, és a sikeresen lefoglalt pointereket free-vel felszabadítani?

persze

--
NetBSD - Simplicity is prerequisite for reliability

struct owe {
char *p_name;
...
...
}

scanf("%s",&o[i].p_name);

Hol foglaltál helyet a p_name stringnek?
Akár malloc() függvénnyel minden egyes vektorbeli p_name-nak, vagy alábbi statikus (alább max 100 byte hosszú) módon.

struct owe {
char p_name[100];
...
...
}