Sziasztok!
Úgy rémlik van itt egy-két Gtk+ fejlesztésben jártas ember. A problémám a következő:
Van egy struktúrám, aminek egy eleme GArray* típusú, ami pedig egy másik struktúrából veszi az adatokat.
A fő struktúra feltöltése rendben megtörténik, de mikor átadom egy az adatokat kiírató függvénynek, a GArray*-ból
nem akarja kivenni az adatokat.
Leegyszerűsítettem a kódot. Megnéznétek, hol a hiba?
#include <glib.h>
typedef struct _Fo Fo;
typedef struct _Resz Resz;
struct _Resz
{
gint resz_id;
gchar *resz_nev;
};
struct _Fo
{
gint id;
gchar *nev;
gint db;
GArray *reszek;
};
void
kiir (Fo * fo)
{
gint i;
g_printf("KIIR: \n=====\n");
g_printf("FO ID: %d\n", fo->id);
g_printf("FO NEV: %s\n", fo->nev);
for (i=0; i < fo->db; i++)
{
Resz *resz = &g_array_index(fo->reszek, Resz, i);
g_printf(" %d. resz_id: %s\n", i, resz->resz_id);
g_printf(" %d. resz_nev: %s\n", i, resz->resz_nev);
}
}
int
main (int argc, char *argv[])
{
Fo *fo = g_malloc(sizeof(Fo));
fo->reszek = g_array_new(TRUE, TRUE, sizeof(Resz));
gint i;
fo->id = 1;
fo->nev = "Elso";
fo->db = 3;
g_printf("ADATOK:\n=======\n");
g_printf("FO ID: %d\n", fo->id);
g_printf("FO NEV: %s\n", fo->nev);
g_printf("FO RESZEK DARABSZAMA: %d\n", fo->db);
for (i=0; i < fo->db; i++)
{
Resz *resz = g_malloc(sizeof(Resz));
resz->resz_id = 10+i;
resz->resz_nev = g_strdup_printf("%d. resz", i);
g_array_append_val(fo->reszek, resz);
g_printf("%d. resz_id: %d\n", i, resz->resz_id);
g_printf("%d. resz_nev: %s\n", i, resz->resz_nev);
g_free(resz);
}
g_printf("\n");
kiir (fo);
g_free(fo);
return 0;
}
Előre is nagyon köszönöm a segítséget!
Üdv
- 1012 megtekintés
Hozzászólások
Egy valamelyest javított verzió:
#include <glib.h>
typedef struct _Fo Fo;
typedef struct _Resz Resz;
struct _Resz
{
gint resz_id;
gchar *resz_nev;
};
struct _Fo
{
gint id;
gchar *nev;
gint db;
GArray *reszek;
};
void
kiir (Fo * fo)
{
gint i;
g_printf("KIIR: \n=====\n");
g_printf("FO ID: %d\n", fo->id);
g_printf("FO NEV: %s\n", fo->nev);
for (i=0; i < fo->db; i++)
{
Resz *resz = g_array_index(fo->reszek, Resz*, i);
g_printf(" %d. resz_id: %d\n", i, resz->resz_id);
g_printf(" %d. resz_nev: %s\n", i, resz->resz_nev);
}
}
int
main (int argc, char *argv[])
{
Fo *fo = g_malloc(sizeof(Fo));
fo->reszek = g_array_new(TRUE, TRUE, sizeof(Resz*));
gint i;
fo->id = 1;
fo->nev = "Elso";
fo->db = 3;
g_printf("ADATOK:\n=======\n");
g_printf("FO ID: %d\n", fo->id);
g_printf("FO NEV: %s\n", fo->nev);
g_printf("FO RESZEK DARABSZAMA: %d\n", fo->db);
for (i=0; i < fo->db; i++)
{
Resz *resz = g_malloc(sizeof(Resz));
resz->resz_id = 10+i;
resz->resz_nev = g_strdup_printf("%d. resz", i);
g_array_append_val(fo->reszek, resz);
g_printf("%d. resz_id: %d\n", i, resz->resz_id);
g_printf("%d. resz_nev: %s\n", i, resz->resz_nev);
// g_free(resz);
}
g_printf("\n");
kiir (fo);
g_free(fo);
return 0;
}
- A hozzászóláshoz be kell jelentkezni
Nagyon szépen köszönöm! Működik.
Egy valamit viszont nem értek. A main() for ciklusában minden körben lefoglal egy memóriarészt a *resz-nek.
Ezt miért nem kell felszabadítani?
Köszi
- A hozzászóláshoz be kell jelentkezni
A ciklisban azért nem kell, mert most a GArray mutatókat tartalmaz, amik a lefoglalt területekre mutatnak.
Persze kilépés előtt fel kell ezeket szabadítani, mint ahogy a GArray-t is...
"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o
- A hozzászóláshoz be kell jelentkezni
Kerdes: abbol nem lesz gond, hogy a resznev es a fo.nev is mutato, de nincs neki hely foglalva?
- A hozzászóláshoz be kell jelentkezni
Nincs hely foglalva, mert nem kell, hiszen egy konstans stringre van állítva:
fo->nev = "Elso";
"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o
- A hozzászóláshoz be kell jelentkezni
(_Nem_ vagyok gtk guru...)
Létrehozol egy GArray-t Resz structokból:
fo->reszek = g_array_new(TRUE, TRUE, sizeof(Resz));
Majd hozzáadsz egy Resz mutatót:
Resz *resz = g_malloc(sizeof(Resz));
...
g_array_append_val(fo->reszek, resz);
Pedig ide nem mutató kéne.
"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o
- A hozzászóláshoz be kell jelentkezni
Csekély C tudásomat elővéve sztem de. Mert ha byval adja át a struct-ot akkor a g_array_append nem fogja tudni módosítani, mert csak egy local copy-t kap. Ha yól emléxem azt tanították, hogy minden olyan esetbe ahol a függvényben a bejövö paramétereket akarom módosítani a hívó számára, pointert kell átadnom. Egyedül tömbök esetén nem áll ez.
Majd a C tudósok lehurrognak...
- A hozzászóláshoz be kell jelentkezni
Itt lehet valahol az igazság!
Az igazság az, hogy a kód egy program része. Az említett példa csak egy egyszerű másolata a hibás résznek.
Úgy csináltam meg, hogy önmagában is működjön, de ugyanazokkal a hibákkal.
A hiba pedig az, hogy az adatok kiírásakor a GArray adatainak kivételével mindent szépen visszaad, csak a GArray adatai helyett ad mindenféle memóriából vett karaktersorozatokat.
A jelenlegi helyzet az, hogy a példaprogram módosított változata szépen működik, de az eredeti programom (a példához hasonló felépítésben) nem.
Akkor hogy is van ez a g_array_append_val()?
Köszi a segítséget!
- A hozzászóláshoz be kell jelentkezni
Jelzem _NEM_ értek a C programozáshoz, amit tudok, azt is úgy verték belém.
Amennyire én látom, a g_array_append_val egy void metódus, azaz nincs értelmes visszatérési értéke.
Ebben az esetben a neki átadott GArray-nak pointernek kell lennie, hiszen nem a módosított GArray ojjektummal tér vissza, hanem az eredeti GArray objektumot módosítja
Esetleg megpróbálhatod azt, hogy
g_array_append_val(&fo->reszek, resz);
[code]
vagy
[code]
g_array_append_val((GArray *)fo->reszek, resz);
De télleg nem értek hozzá, lehet hülyeségeket beszélek.
- A hozzászóláshoz be kell jelentkezni
A tömbben vagy Resz típusú elemekre mutató pointereket tárolsz (ilyenre alakítottam át én), vagy Resz típusú elemeket tárolsz.
1. pointer tömb
Ilyenkor g_array_new-nál és a g_array_index-nél is Resz*-ot kell megadni, mivel az elemek pointerek.
2. Resz típusú elemeket tartalmazó tömb
Ilyenkor marad az amit Te is csináltál a g_array_new-nál és g_array_index-nél, azonban a g_array_append_val-ban hibáztál, mivel nem a Resz típusú elem címét kell átadni, hanem magát az elemet.
Beszúrom ide a nem pointeres verziót is. Itt sem törekedtem a tökéletes megoldásra, szóval a helyes felszabadítás most is elmaradt, mert nem volt hozzá kedvem.
#include <glib.h>
typedef struct _Fo Fo;
typedef struct _Resz Resz;
struct _Resz
{
gint resz_id;
gchar *resz_nev;
};
struct _Fo
{
gint id;
gchar *nev;
gint db;
GArray *reszek;
};
void
kiir (Fo * fo)
{
gint i;
g_printf("KIIR: \n=====\n");
g_printf("FO ID: %d\n", fo->id);
g_printf("FO NEV: %s\n", fo->nev);
for (i=0; i < fo->db; i++)
{
Resz *resz = &g_array_index(fo->reszek, Resz, i);
g_printf(" %d. resz_id: %d\n", i, resz->resz_id);
g_printf(" %d. resz_nev: %s\n", i, resz->resz_nev);
}
}
int
main (int argc, char *argv[])
{
Resz resz;
Fo *fo = g_malloc(sizeof(Fo));
fo->reszek = g_array_new(TRUE, TRUE, sizeof(Resz));
gint i;
fo->id = 1;
fo->nev = "Elso";
fo->db = 3;
g_printf("ADATOK:\n=======\n");
g_printf("FO ID: %d\n", fo->id);
g_printf("FO NEV: %s\n", fo->nev);
g_printf("FO RESZEK DARABSZAMA: %d\n", fo->db);
for (i=0; i < fo->db; i++)
{
resz.resz_id = 10+i;
resz.resz_nev = g_strdup_printf("%d. resz", i);
g_array_append_val(fo->reszek, resz);
g_printf("%d. resz_id: %d\n", i, resz.resz_id);
g_printf("%d. resz_nev: %s\n", i, resz.resz_nev);
// g_free(resz);
}
g_printf("\n");
kiir (fo);
g_free(fo);
return 0;
}
- A hozzászóláshoz be kell jelentkezni
Pont erről beszélek. Kösz, hogy leírtad helyettem. :)
Egyébként ez a verzió valószínűleg gyorsabb mint a mutatós, bár a különbség nem számottevő (persze attól függ...).
"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o
- A hozzászóláshoz be kell jelentkezni
Azért tévedsz, mert azt hiszed, a g_array_val függvény.
Pedig az egy makró.
http://developer.gnome.org/doc/API/glib/glib-arrays.html#G-ARRAY-APPEND…
"Note: g_array_append_val() is a macro which uses a reference to the value parameter v. This means that you cannot use it with literal values such as "27". You must use variables."
Egyébként pont ezért szokták a makrókat nagybetűvel írni, mert akkor egyértelmű. Igaz, hogy más szempontból kevésbé szép. :)
"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o
- A hozzászóláshoz be kell jelentkezni
Áááá, átsiklottam felette. Mea culpa.
- A hozzászóláshoz be kell jelentkezni
Na, született egy működőképes változat. Így most minden mutatókkal megy, bár egy kicsit elbizonytalanodtam a fentebb említett teljesítménybeli különbség miatt. Használat közben ugyan nem érzékelhető...
Most rendben működik, nem merem bántani.
#include <glib.h>
typedef struct _Fo Fo;
typedef struct _Resz Resz;
struct _Resz
{
gint resz_id;
gchar *resz_nev;
};
struct _Fo
{
gint id;
gchar *nev;
gint db;
GArray *reszek;
};
void
kiir (Fo * fo)
{
gint i;
g_printf("KIIR: \n=====\n");
for (i=0; i < 3; i++)
{
Resz *resz = &g_array_index(fo->reszek, Resz, i);
g_printf(" %d. resz_id: %d\n", i, resz->resz_id);
g_printf(" %d. resz_nev: %s\n", i, resz->resz_nev);
}
}
int
main (int argc, char *argv[])
{
Fo *fo = g_malloc(sizeof(Fo));
gint i;
fo->reszek = g_array_new (TRUE, TRUE, sizeof (Resz));
for (i=0; i < 3; i++) {
Resz *reszek = g_malloc(sizeof(Resz));
reszek->resz_id = i;
reszek->resz_nev = g_strdup_printf("resz %d", i);
g_array_append_val(fo->reszek, *reszek);
g_printf("resz %d: %s\n", i, reszek->resz_nev);
}
for (i=0; i < 3; i++) {
Resz *reszek = &g_array_index(fo->reszek, Resz, i);
g_printf("vissza %d: %s\n", reszek->resz_id, reszek->resz_nev);
}
kiir(fo);
return 0;
}
Nagyon szépen köszönöm mindenkinek a segítséget!
Üdv
- A hozzászóláshoz be kell jelentkezni