Newsgroup: it.comp.lang.c
Titolo: Aiuto... C & Stringhe...

Ciao a tutti,
mi serviva una mano per risolvere questo problema (a livello
didattico):
devo leggere un file di testo (in formato html), ed estrarre tutti i
tag.
La funzione che fa questo restituisce 0 se tutto ok o un numero se c'è
un errore.
Il tag viene passato alla funzione main tramite un puntatore ad una
struttura (int leggi_Tag (tag_struttura *tag).
Il problema è che non conosco a priori quanti caratti ha il tag, mi è
richiesto di non "sprecare" memoria, e di utilizzare solo la libreria
standar <stdio.h>. Ho tentato una soluzione del genere (per
memorizzare il tag):
definisco:
int flag ,c,numero_carattere;
char *Str;
1) leggo il file un carrattere alla volta c=getc(file)
2) quando c è uguale a < pongo un flag a 1
3) se il flag = 1 memorizzo in str c ... numero_carattere++
Questa è la mia difficoltà come faccio a fare il punto 3 ?
Tenendo presente che devo aumentare lo spazio allocato per ogni nuovo
carattere.
Nella prima implementazione avevo creato un array char Str[20]; e
tutto andava bene fino a quando il tag era meno di  20 caratteri.
Ripeto che il problema è accademico, quindi la soluzione non può
essere del tippo creo un array di 250 caratteri così sono
tranquillo....
Vi ringrazio a tutti in anticipo...
Alessandro (Super_Gulp)

 carattere.
chiaramente allocare spazio per ogni carattere letto e'
una cosa assurda sia da un punto di vista pratico sia da
un punto di vista di esercizio didattico.
una cosa molto semplice che puoi fare e' crearti una
specie di stringa a lunghezza variabile.
in pratica invece di 1 variabile ne hai tre,
uno e' un puntatore a carattere, che punta
all'inizio dell'array di caratteri che rappresenta la
stringa e poi ti memorizzi due interi, uno che ti
dice quanti caratteri hai effettivamente memorizzato
e uno che ti dice quanto e' realmente lungo l'array.
Esempio, tanto per dare l'idea
(da rivedere e ripulire secondo il tuo gusto)
inizializzi la struttura dati
char *s;
int slen; /* spazio usato */
int stot; /* spazio totale allocato */
/* inizializzo un array di caratteri lungo 32,
che contiene una stringa vuota (e quindi che occupa 1 carattere)
e memorizzo spazio totale (stot) e spazio usato (slen) */
s=malloc(32);
s[0]=0;
slen=1;
stot=32;
a questo punto, per aggiungere un solo carattere, puoi fare
una cosa come questa:
/* aggiunge il carattere x */
/* controlla se e' necessario "allungare" l'array */
if (slen==stot)  /* ovvero se e' tutta usata ... */
{
  /* nuova lunghezza, assumiamo vada avanti a step di 32 byte,
     chiaramente la dimensione dello step e' un compromesso tra
     spreco di memoria e numero di realloc richieste */
  stot += 32;
  s = realloc(s,stot);
  /* controllo se la realloc e' andata a buon fine */
  if (!s) Ma_Porca_Putt_Come_Sarebbe_Err_Mem_Ho_4Gb_o_No();
}
/* ora posso aggiungere il carattere x*/
s[slen]=x;    /* il carattere va dove era il terminatore */
s[++slen]=0;  /* nuovo terminatore */
Questa piu' o meno e' l'idea.
Chiaramente se devi attaccare una stringa invece che un solo
carattere controllerai se ti basta lo spazio, poi
se non ti basta sai di quanto allungare, lo fai, e poi
puoi usare una strcat e ricordarti di aggiornare slen e stot.
A seconda delle tue capacita' ed esigenze puoi fare
una cosa piu' o meno elegante. Per esempio puoi
definire una struttura dati tipo:
typedef struct { char *v;
                 int len,tot;
               } sVar;
e poi farti delle funzioni che usano questo nuovo tipo di
dato al posto delle stringhe,
quindi per esempio fare una funzione per inizializzare:
Init(sVar *sv)
{
   sv->v = malloc(32)
   sv->len = 1;
   sv->tot=32;
   sv->v[0]=0;
}
una funzione per aggiungere un carattere,
AddChar(sVar *sv, char x) { ... }
una funzione per accodare una stringa (tipo la strcat)
sVarCatS(svar *sv, char *s) { ... } e una per accodare una sVar ad una
altra sVar eccetera eccetera.
La struttura interna e' sempre quella:
controlli se hai ancora abbastanza spazio inutilizzato, e se non
basta fai una realloc.
A quel punto puoi usare diverse di queste variabili in modo
piu' o meno trasparente, tipo
sVar *v1, *v2;
v1=malloc(sizeof(sVar));
v2=malloc(sizeof(sVar));
Init(v1); Init(v2);
SetString(v1,"Sono un birichin");
AddChar(v1,'o');
etc.etc.etc.
ciao,
g.

Ti ringrazio molto ... ma ho problema:
in fase di compilazione alla riga
s=malloc (32);
ho il seguente messaggio di warring:
incompatible implicit declaration of built-in function 'malloc'.
grazie ancora


Mi rispondo da solo :
#include <stdlib.h>
grazie 1000000

 carattere.
Puoi utilizzare realloc:
Str=realloc(Str,numero_carattere);