Newsgroup: it.comp.lang.c
Titolo: Array dinamico di stringhe

Salve a tutti.
Devo dichiarare un campo di una struct in modo che sia un array di stringhe
lunghe 7, di cui non so a priori la cardinalita'.
Come si fa? Per caso, cosi?
struct ... {
    ...
    char * (descrizione[7]);
    ...
} struttura;
In questo caso,
quando alloco memoria per l'array, com'e' l'istruzione? Cosa ci va nel
sizeof()?
struttura.descrizione = malloc(N * sizeof( ? ));
Grazie a chiunque voglia darmi un aiuto.
Ciao,
Ema


devi fare:
struttura.descrizione[0] = malloc(N * sizeof(char));
e cosě via per tutte e sette le lunghezze.
--------------------------------
Inviato via 
http://arianna.libero.it/usenet/


Non credo tu abbia capito.
Non ho dichiarato (lasciamo stare la struct, che e' un particolare inutile)
char (* descrizione)[7];
ovvero un array lungo 7 di puntatori a caratteri.
In questo caso la lunghezza dell'array e' fissa e per ogni stringa devo
allocare memoria.
Non e' quello che serviva a me.
A me serviva (ma a questo punto credo non si possa fare) un array di
stringhe.
Le stringhe so che sono tutte lunghe 7, pero' non so quante sono le stringhe
(quindi non so quanto e' lungo l'array).
Io volevo allocare spazio per l'array in una botta sola (come fosse un array
di interi, per intenderci), senza dover allocare memoria per ogni singola
stringa.
Altrimenti la soluzione e' banale:
char * * descrizione;
descrizione = malloc(N * sizeof(char *));
for (i=0; i<N; i++) descrizione[i] = malloc(7 * sizeof(char));
ecco, io volevo evitare di fare il for, se possibile; qualcosa tipo (notare
le parentesi nella dichiarazione):
char * (descrizione[7]);
descrizione = malloc(N * sizeof(char[7]));
Ovviamente quest'ultima sintassi e' errata.
Grazie lo stesso.
Ciao,
Ema

 [snip]
Non che per il tuo caso sia complicata eh ...
Sanity check a parte (questo non esclude la possibilita` di trovare
altri modi; come sempre in C del resto) ...
[code]
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef char string_t[7];
int main(void)
 {
   string_t *array = NULL;
   int num, i;
   scanf("%d", &num);
   array = (string_t *)calloc(num, sizeof(string_t));
   for (i = 0; i < num; i++)
    {
       strncpy(array[i], "1234567890", sizeof(array[i]) - 1);
    }
   for (i = 0; i < num; i++)
    {
       printf("%2d. [%s]\n", i, array[i]);
    }
   free(array);
   return 0;
 }
[/code]
Ciao.
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it

 Ciao.
Ok, grazie 1000, tutto chiaro.
Mi immagino che senza passare al tipo "intermedio" string_t, non si possa
fare... vero?
Comunque ottima soluzione. Grazie.
Ema

 [snip]
LOL, povero typedef, che ti ha fatto? ;P
Si puo` fare in parecchi modi, anche senza usare la typedef per la tua
gioia; ad esempio, mi viene in mente questo (soliti sanity check mancanti):
[code]
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* comodita` */
#define         string_t        struct strings_t
struct strings_t
 {
   char content[7];
   string_t *next;
 };
static __inline__ void __free_strings(string_t *ptr)
 {
   if (ptr)
     {
       __free_strings(ptr->next);
       free(ptr);
     }
 }
static __inline__ void __add_string(string_t *new, string_t **list)
 {
   string_t *scan = NULL;
   if (!*list)
    *list = new;
   else
    {
      /* ipotizziamo un inserimento in coda, senza ordinamento*/
      for(scan = *list; scan->next != NULL; scan = scan->next);
      scan->next = new;
    }
 }
int main(void)
 {
   string_t *array = NULL, *tmp = NULL;
   int num, i;
   scanf("%d", &num);
   for (i = 0; i < num; i++)
    {
       tmp = (string_t *) calloc(1, sizeof (string_t));
       strncpy(tmp->content, "1234567890", sizeof(tmp->content) - 1);
       __add_string(tmp, &array);
    }
   for (i = 0, tmp = array; tmp != NULL; tmp = tmp->next, i++)
    printf("%2d. [%s]\n", i, tmp->content);
   __free_strings(array);
   return 0;
 }
[/code]
Ma senza una *reale* motivazione legata all'implementazione delle
operazioni che dovrai effettuare sul tuo tipo di dato, non vi e` una
_concreta_ necessita` di fare altrimenti se non il puro folklore :)
In questo caso, ad esempio (con l'inserimento in coda), ha poco senso
implementare il tuo tipo di dato come una lista; risulta piu` performante
(e di piu` semplice realizzazione ... nel senso di Keep It Simple Stupid,
non che sia qualcosa di complicato) l'esempio precedente. Diverso il
discorso se tu dovessi effettuare particolari tipi di operazioni (esempio:
ricerche).



Mamma mia, ho scatenato la tua creatività... :-)
Grazie.
Ho adottato la soluzione col typedef (non è poi cosi' tanto antipatico, poi
ti spiego)
perche' in realta', mi serviva un array, e non una lista.
Evitare il typedef era una scelta personale di stile.
Ovvero, non essendo un t_string_7 un tipo poi cosi' rilevante per
l'applicazione nel suo complesso, avrei preferito evitarlo.
C'e' un altro fatto.
Che se uno ha tanti array come quello che volevo io, le cui stringhe hanno
pero' lunghezze diverse, uno deve definirsi tanti tipi similari (t_string_7,
t_string_9, t_string_32, ecc...) che servono _solo_ per il trucchetto
dell'allocazione ma che poi, in effetti non vengono usati altrove.
Ecco, mi disturbava un po' definire un tipo
1) non molto interessante di per se'
2) con un "mono-utilizzo", nel senso appena descritto.
Era questione di gusti, ma anche di curiosita', di sete di sapere da chi e'
piu' esperto di me.
Devo dire che hai placato la mia sete.
Grazie di nuovo,
Ema

   array = calloc(num * 7);
?
Grazie mille !
Ciao
E.


Allora:
1) Non e' quello che serviva a me. Nel senso che
    char (* array)[7];
    dichiara un array lungo 7 di puntatori a caratteri, credo,
    mentre a me serviva un array di stringhe lunghe 7.
    La dichiarazione giusta dovrebbe essere char * (array[7]);
2) Usando quest'ultima dichiarazione, non mi e' stato possibile scrivere
    una istruzione di malloc senza ottenere errori in compilazione.
Il trick del typedef, invece, ha risolto ogni problema.
Ciao,
Ema