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!
- 10929 megtekintés
Hozzászólások
Szeretnéd, de nem fog sikerülni!:)
- A hozzászóláshoz be kell jelentkezni
+1 :)
- A hozzászóláshoz be kell jelentkezni
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 hozzászóláshoz be kell jelentkezni
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?
- A hozzászóláshoz be kell jelentkezni
programnyelv sem derult ki, meg a vege is hianyzik a pasztanak :p
--
NetBSD - Simplicity is prerequisite for reliability
- A hozzászóláshoz be kell jelentkezni
C C++ fórumban vagyunk :-)
- A hozzászóláshoz be kell jelentkezni
Akkor már "csak" kétesélyes a dolog, ugye :D
- A hozzászóláshoz be kell jelentkezni
http://i47.tinypic.com/2v8gubm.jpg
bocs, nem lehetett kihagyni
- A hozzászóláshoz be kell jelentkezni
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.
- A hozzászóláshoz be kell jelentkezni
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
- A hozzászóláshoz be kell jelentkezni
Esetleg, ha nem for()-ral szerveznéd a ciklust? ;)
- A hozzászóláshoz be kell jelentkezni
Nem ertem mire gondolsz...
:)
While mivel lenne jobb itt most ?
- A hozzászóláshoz be kell jelentkezni
Az semennyivel.
Ellenben a do-while a ciklus végén simán ellenőrizhet (kisebb)egyenlőségre.
- A hozzászóláshoz be kell jelentkezni
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
- A hozzászóláshoz be kell jelentkezni
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).
- A hozzászóláshoz be kell jelentkezni
Már hogy lenne kevésbé optimális, a fordító mindent tud, ügyesen kikalkulálja fordítási időben :-)
Fuszenecker_Róbert
- A hozzászóláshoz be kell jelentkezni
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 = ...
- A hozzászóláshoz be kell jelentkezni
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 hozzászóláshoz be kell jelentkezni
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?".
- A hozzászóláshoz be kell jelentkezni
"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
- A hozzászóláshoz be kell jelentkezni
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
- A hozzászóláshoz be kell jelentkezni
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
- A hozzászóláshoz be kell jelentkezni
É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.
- A hozzászóláshoz be kell jelentkezni
de C-ben nem deklaralhatod a for ciklus fejleceben, csak C++-ban (igaz nem is derult ki, hogya topik C vagy C++)
- A hozzászóláshoz be kell jelentkezni
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.
- A hozzászóláshoz be kell jelentkezni
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.
- A hozzászóláshoz be kell jelentkezni
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]
- A hozzászóláshoz be kell jelentkezni
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.)
- A hozzászóláshoz be kell jelentkezni
jogos. Bar en rendre elhagyom a struct-ot c++-ban.
- A hozzászóláshoz be kell jelentkezni
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
- A hozzászóláshoz be kell jelentkezni
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.
- A hozzászóláshoz be kell jelentkezni
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.
- A hozzászóláshoz be kell jelentkezni
Ez nem parasztvakitas, hanem egy nagyon jol hasznalhato feature
- A hozzászóláshoz be kell jelentkezni
dupla
- A hozzászóláshoz be kell jelentkezni
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 :-) )
- A hozzászóláshoz be kell jelentkezni
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
- A hozzászóláshoz be kell jelentkezni
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).
- A hozzászóláshoz be kell jelentkezni
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
- A hozzászóláshoz be kell jelentkezni
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á.
- A hozzászóláshoz be kell jelentkezni
Bocs, my fault! Elnézést kérek
- A hozzászóláshoz be kell jelentkezni
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
- A hozzászóláshoz be kell jelentkezni
jo kis dependency hellt lehet vele csinalni! :)
--
NetBSD - Simplicity is prerequisite for reliability
- A hozzászóláshoz be kell jelentkezni
:D
---
Egy jól megállapított probléma félig megoldott probléma.
- Charles Kettering
- A hozzászóláshoz be kell jelentkezni
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
- A hozzászóláshoz be kell jelentkezni
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 hozzászóláshoz be kell jelentkezni
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.)
- A hozzászóláshoz be kell jelentkezni
"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 hozzászóláshoz be kell jelentkezni
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 hozzászóláshoz be kell jelentkezni
"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).
- A hozzászóláshoz be kell jelentkezni
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.
- A hozzászóláshoz be kell jelentkezni
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)
- A hozzászóláshoz be kell jelentkezni
"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
- A hozzászóláshoz be kell jelentkezni
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?
- A hozzászóláshoz be kell jelentkezni
persze
--
NetBSD - Simplicity is prerequisite for reliability
- A hozzászóláshoz be kell jelentkezni
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];
...
...
}
- A hozzászóláshoz be kell jelentkezni