PDA

View Full Version : [C] Inizializzare una matrice di stringhe, membro di una struttura.


LacioDromBuonViaggio
19-01-2009, 19:10
Salve a tutti,
da main io scrivo questo

char *str[]={"ciao","ciao","ciao"};

e funziona tutto!

Ma non riesco a inserire quella variabile in una struttura.


struct struttura
{
char *str[];
}

main()
{
struct struttura item;
item.str[]={"ciao","ciao","ciao"};
}



mi da questo errore:
error: expected expression before ‘]’ token

Qual è la sintassi giusta?
Ho provato anche:

item->str[]={"ciao","ciao","ciao"};
item.str={"ciao","ciao","ciao"};
item->str={"ciao","ciao","ciao"};

e a definire char **str;
ma niente!

Ho incluso stdlib.h e string.h.

Soluzioni?

DanieleC88
19-01-2009, 19:37
Perché non puoi fare quella cosa con un'assegnazione, lo puoi fare solo durante un'inizializzazione (come hai fatto all'inizio). ;)

LacioDromBuonViaggio
19-01-2009, 19:41
Perché non puoi fare quella cosa con un'assegnazione, lo puoi fare solo durante un'inizializzazione (come hai fatto all'inizio). ;)

eh si ma quindi come risolvo?
io voglio inizializzare quel valore dal main.. anche perchè da struttura non lo posso fare, visto che mi converrebbe in quanto costante!

DanieleC88
19-01-2009, 19:56
Dipende, a seconda di ciò che devi fare. Può esserti più comodo fare un'array bidimensionale dando una grandezza fissa alle stringhe, ed allora basterebbe fare una cosa tipo:
strcpy(struttura.stringhe[0], "stringa1");
strcpy(struttura.stringhe[1], "stringa2");
strcpy(struttura.stringhe[2], "stringa3");

Altrimenti, se vuoi usare dei puntatori devi malloc()-are le tre stringhe e poi fare la strcpy(). Naturalmente, dovrai ricordarti di fare una free() corrispondente per ognuna delle tre stringhe, al termine del main().

P.S.: ora non ricordo con esattezza, ma con GCC dovrebbe esserti possibile anche fare una cosa del genere:
struct struttura
{
char *str[];
}

int main()
{
struct struttura item = { str: {"ciao","ciao","ciao"} };

/* ... */
return 0;
}
Prova, magari sei fortunato.

LacioDromBuonViaggio
19-01-2009, 20:28
P.S.: ora non ricordo con esattezza, ma con GCC dovrebbe esserti possibile anche fare una cosa del genere:
struct struttura
{
char *str[];
}

int main()
{
struct struttura item = { str: {"ciao","ciao","ciao"} };

/* ... */
return 0;
}
Prova, magari sei fortunato.
Proverò a fare così visto che uso GCC!

Mi serve che sia proprio tutto senza COSTANTI (in pratica sto facendo una specie di space invaders e quella matrice di stringhe rappresenta il 'disegno' di tutti gli item, quindi deve poter essere 3x2 4x4 1x5 ecc ecc..)

Se dovessi usare la malloc che sizeof ci metto? Mi sembra strano..

DanieleC88
19-01-2009, 21:23
Se vuoi una cosa tipo quella puoi anche semplicemente mettere l'array in una variabile statica globale che sarà letta solo da chi disegna, ed inizializzarla staticamente.

Altrimenti dovresti allocare la dimensione giusta, e cioè il numero di caratteri di cui quella particolare stringa di compone, più uno per il terminatore di stringa ('\0'), il tutto moltiplicato per sizeof(char). Alternativamente, potresti usare strdup(), che non si limita a ricopiare la stringa, ma la duplica sull'heap, allocandone dinamicamente (ed automaticamente) la memoria. Ovviamente, in tal caso, non dimenticare la free(). ;)

LacioDromBuonViaggio
19-01-2009, 21:31
Se vuoi una cosa tipo quella puoi anche semplicemente mettere l'array in una variabile statica globale che sarà letta solo da chi disegna, ed inizializzarla staticamente.


Non ne voglio variabili globali!
Comunque mi chiedo come mai nel main funziona, invece con il membro della struttura non va!

DanieleC88
19-01-2009, 21:36
Era solo una possibilità quella delle variabili globali. ;)

In che senso non funziona, quale dei vari metodi? Alle brutte fatti una piccola routine di inizializzazione e fai le strdup().

LacioDromBuonViaggio
19-01-2009, 21:49
Era solo una possibilità quella delle variabili globali. ;)

In che senso non funziona, quale dei vari metodi? Alle brutte fatti una piccola routine di inizializzazione e fai le strdup().

Il fatto è che se creo la matrice di stringa dal main e la inizializzo sul momento:
int *str[]={"ciao","ciao"};
funziona tutto senza allocazioni varie o altro.

Probabilmente non conosco la sintassi giusta per inizializzare quel membro della struttura! :muro:

DanieleC88
19-01-2009, 22:27
Il fatto è che se creo la matrice di stringa dal main e la inizializzo sul momento:
int *str[]={"ciao","ciao"};
funziona tutto senza allocazioni varie o altro.

Probabilmente non conosco la sintassi giusta per inizializzare quel membro della struttura! :muro:
Diciamo che... non lo fai. :D
Per farlo dovresti usare una sintassi come quella che ti ho scritto sopra, ma non puoi passare un'array di dimensione variabile dentro una struttura, la quale è richiesto che abbia dimensione fissa (ognuno dei suoi campi deve avere una dimensione ben nota a compile-time, sennò salta tutto). Quindi purtroppo non funziona. :cry:
Non mi viene in mente nessun'altra soluzione se non allocare il tutto dinamicamente.

ciao ;)

LacioDromBuonViaggio
20-01-2009, 13:47
Ho risolto bypassando il problema.

Ovvero nella struttura metto un normale puntatore a char:



struct item
{
int var;
int var2;
char *p; //puntatore al vettore di stringhe
};


e poi da main creo prima il vettore di stringhe e poi gli associo il puntatore:


main()
{
char *disegno[]={"q_p"," ! "},

struct item mostro={var1,var2,disegno[0]};

printf("%s\n",mostro.p); //prima stringa
printf("%s\n",mostro.p+strlen(mostro.p)+1);
//... e così via moltiplicando per i l'offset in un eventuale ciclo for
}

DanieleC88
20-01-2009, 16:11
Non è scomodissimo? Fai un char ** e campa felice. ;)

~FullSyst3m~
20-01-2009, 17:21
Spero di stare lontano dal C più tempo possibile :D

DanieleC88
20-01-2009, 17:32
Spero di stare lontano dal C più tempo possibile :D
Oh, ma non temere, questo non era certo il peggio che si potesse fare con il C. :asd:

~FullSyst3m~
20-01-2009, 17:50
Oh, ma non temere, questo non era certo il peggio che si potesse fare con il C. :asd:

Appunto, non voglio immaginare il peggio perchè mi vengono i capelli bianchi :D

Vincenzo1968
20-01-2009, 17:57
Spero di stare lontano dal C più tempo possibile :D

Tratto da Todo Modo di Leonardo Sciascia:

...
Il commissario sollevò il lenzuolo, guardò, sospirò; lo lasciò ricadere.
«Chi è?» domandò a don Gaetano.
«Il presidente della Furas. L'onorevole Michelozzi... Eletto senatore
alle ultime: ma si è dimesso per assumere la presidenza della Furas.
Ottima persona: colta, zelante, onesta...».
«E se ne può dubitare?» disse il commissario. Ma ci mise una vibra-
zione d'ironia, come a dire: anche se volessi, non potrei.
«Già» disse don Gaetano, riflettendo quella vibrazione come un raggio
su uno specchietto e rimandandola al commissario col senso di: non
c'è niente da faro, mio caro, bisogna che tu ci strida.
...


:bimbo:

LacioDromBuonViaggio
20-01-2009, 18:00
Non è scomodissimo? Fai un char ** e campa felice. ;)

ma faccio un char p** nella struttura? o poi lo associo al vettore di stringhe in modo da poterlo utilizzare meglio quando poi faccio la stampa?

~FullSyst3m~
20-01-2009, 18:09
Tratto da Todo Modo di Leonardo Sciascia:


:bimbo:

Mi ha colpito nel profondo questa citazione... ma mai di quanto mi può colpire (e fare svenire) il C :asd:

cionci
20-01-2009, 18:18
Mi ha colpito nel profondo questa citazione... ma mai di quanto mi può colpire (e fare svenire) il C :asd:
Sei un po' OT ? ;)

cionci
20-01-2009, 18:35
Non è scomodissimo? Fai un char ** e campa felice. ;)
A me sembra che vada bene, è una ottima soluzione se le stringhe sono sempre quelle ;)

DanieleC88
20-01-2009, 18:50
A me sembra che vada bene, è una ottima soluzione se le stringhe sono sempre quelle ;)
A me sembra scomodo fare tutte quelle somme di offset, in più metti una chiamata a strlen() per ogni membro da saltare; oltretutto diventa scomodo al variare delle stringhe. Io mi sporcherei le mani una ed una sola volta per fare un codice che inizializzi dinamicamente la matrice e i suoi contenuti ed uno che la liberi alla fine, poi il resto diventerebbe banale. ;)

~FullSyst3m~
20-01-2009, 18:53
Sei un po' OT ? ;)

Ehm... perchè? :stordita:

cionci
20-01-2009, 18:59
Ehm... perchè? :stordita:
Perché non sei di aiuto per risolvere il problema della discussione ;)

Daniele: quelle somme nemmeno le avevo viste :stordita:
E non capisco cosa voglia ottenere.

DanieleC88
20-01-2009, 19:19
Daniele: quelle somme nemmeno le avevo viste :stordita:
E non capisco cosa voglia ottenere.
Credo volesse linearizzare la matrice, ma è un metodo scomodissimo. :)

cionci
20-01-2009, 19:29
Credo volesse linearizzare la matrice, ma è un metodo scomodissimo. :)
Poi tra l'altro non so se il compilatore abbia l'obbligo di allocare quelle stringhe una vicino all'altra ;)

DanieleC88
20-01-2009, 19:32
In effetti sì, non lo obbliga nessuno. :D
Al limite dovrebbe fare un unico stringone, ma comunque sarebbe molto scomodo e poco efficiente.

cionci
20-01-2009, 19:39
Più che altro mi domandavo a cosa servisse fare una cosa del genere...sentiamo che ci dice ;)

~FullSyst3m~
20-01-2009, 19:44
Perché non sei di aiuto per risolvere il problema della discussione ;)

Daniele: quelle somme nemmeno le avevo viste :stordita:
E non capisco cosa voglia ottenere.

Hai ragione, excuse me :)

LacioDromBuonViaggio
20-01-2009, 19:46
Poi tra l'altro non so se il compilatore abbia l'obbligo di allocare quelle stringhe una vicino all'altra ;)

Beh se faccio
char *p[]={"ciao","ciao"};
essendo un vettore credo proprio che gli elementi sono salvati in memoria uno dietro l'altro.

Non ho ancora avuto modo di provare la soluzione char **prt. Ma per evitare di farlo e dover rivenire qui a scrivere qualcuno mi consiglia la sintassi giusta?

Io pensavo a:

struct str{
char **ptr; //il puntatore al vettore di stringhe
};

main()
{
char *p[]={"ciao","buona"};

struct str prova={p}; //così? (al posto di p[0])

printf("%s",prova.ptr[1]); //siamo sicuri che questo mi stampi "buona"?
}




Vi terrò informati!

DanieleC88
20-01-2009, 19:55
No, in quel modo non può funzionare. ;)

Comunque, te l'ho già detto prima, non puoi inserire in una struttura un'array di dimensione variabile di puntatori, non te lo farà fare nessun compilatore, temo.

cionci
20-01-2009, 19:59
Beh se faccio
char *p[]={"ciao","ciao"};
essendo un vettore credo proprio che gli elementi sono salvati in memoria uno dietro l'altro.

Non è assolutamente detto, i due "ciao" possono essere allocati dove vuole lui e ricorda che essendo due literal constant non possono essere modificati.

Certo che ti stampa "buona" ;)
Sinceramente non ho capito se ti servono tutte le stringhe nella struttura o una sola.

cionci
20-01-2009, 20:00
No, in quel modo non può funzionare. ;)

Comunque, te l'ho già detto prima, non puoi inserire in una struttura un'array di dimensione variabile di puntatori, non te lo farà fare nessun compilatore, temo.
Funziona funziona...è un puntatore quello ;)

DanieleC88
20-01-2009, 20:06
Funziona funziona...è un puntatore quello ;)
Uh, è vero, l'avevo letto distrattamente. Errore mio. :fagiano:

LacioDromBuonViaggio
20-01-2009, 20:20
Non è assolutamente detto, i due "ciao" possono essere allocati dove vuole lui e ricorda che essendo due literal constant non possono essere modificati.

Certo che ti stampa "buona" ;)
Sinceramente non ho capito se ti servono tutte le stringhe nella struttura o una sola.

Se lo stampa mi va benissimo!
Come già detto un pò di post fa sto facendo un gioco di space invaders e devo stampare a video i 'mostri'.. I vettori di stringhe rappresentano quei mostri e io li devo stampare uno sotto l'altro:

q...p
!O!
!
Una roba del genere! Però ho molti mostri diversi, quindi più strutture 'mostro' con variabili diverse e soprattuto con dimensioni diverse (un mostro può essere 2x3 oppure 4x3 e così via).

Per ora l'esempio dell'offset, pur non essendo elegante, funziona!

LacioDromBuonViaggio
22-01-2009, 10:05
Non è scomodissimo? Fai un char ** e campa felice. ;)

Ho provato la soluzione di daniele e funziona a meraviglia! :D
-Nella struttura dichiaro char **draw,
-Nel main creo char *disegno[]={"xxxx","xxxx"};
-Associo draw=disegno e posso accedere agli elementi del vettore direttamente con struttura.draw[0] e struttura.draw[1].

Ottimo!

Ora avrei un altro quesito credo un pò più semplice, anche se andrò un pò OT, riguardante il passaggio di matrici tra funzioni/procedure.


void stampa_mat(int mat[3][3]); //prototipo

main()
{
int mat[3][3]={ inizializzazione };
stampa_mat(mat);
}

void stampa_mat(int mat[3][3])
{
//definizione procedura
}


Questo funziona benissimo, il fatto è che vorrei utilizzare una forma diversa nel prototipo (quando passo 4,5 matrici in una funzione diventa troppo lungo) quindi pensavo a un prototipo tipo

void stampa_mat(int **);

Però mi da errore di 'incompatible pointer type'!
Cosa dovrei mettere?
Volendo posso mettere anche nella definizione una roba del genere
void stampa_mat(int mat**)
sempre che sia compatibile col prototipo?

LacioDromBuonViaggio
22-01-2009, 18:05
Vi scrivo il codice (copiate e incollate):

#include <stdio.h>

void stampa(int **mat);

main ()
{
int i,j;
int mat[2][3];

for(i=0;i<2;i++)
for(j=0;j<3;j++)
mat[i][j]=69;

stampa(mat); //passing argument from incompatible pointer type
}

void stampa(int **mat)
{
int i,j;
for(i=0;i<2;i++)
{
for(j=0;j<3;j++)
printf("%d ",mat[i][j]);
printf("\n");
}
}


Non voglio mettere void stampa(int mat[2][3]), quindi come devo fare??