struct tomb

Fórumok

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ások

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

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."

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 <stdio.h>

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

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

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?".

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

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]

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.

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).

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á.

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 

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).

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)

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];
...
...
}