Newsgroup: it.comp.lang.c
Titolo: problema con stringa lunga

Ciao a tutti!
ho bisogno di un aiuto:
sto scrivendo un prg che mi fa uno scan delle directory, dalla
root alla corrente.
mano a mano che vado avanti, 
immagazino il path a cui sono arrivato in "work_dir".
però io ho settato work_dir lungo 100... e che succede se ci metto un
path lungo 102 caratteri?
presumo un crash...
non posso sapere a priori se sono in "/home" o in
"/urs/share/lib/libdd/cas/......."
quindi: mi dite un metodo intelligente di usare un "work_dir" di altro
tipo?
iciao!
grazie!
ecco il mio prg:
int
main (int argc, char *argv[])
{
	gchar *directory, *paths;
	gchar work_dir[100]; //  ?!?!??!
	gchar *slash="/";
 
	getcwd (directory) ;
	//strcpy(work_dir, slash);
 
	while (directory)
	{
		paths = strsep(&directory, slash);
 
		strcat(work_dir,slash);
		strcat(work_dir,paths);
 
		g_print ("%s\n", work_dir );
	}
}
-- 
ciao
Linux hobbes 2.4.7

tipo?
Allora, un modo potrebbe essere di usare una stringa allocata
dinamicamente, magari partendo da 100.
Ti tieni un contatore dei caratteri inseriti e quando ti trovi a dover
inserire il 101-esimo rialloci la stringa (magari a 200)... e cosi
via, incrementando di 100 (o un valore che ti pare) ogni volta, per
quando possa essere improbabile che tu debba andare oltre.
Il modo in cui effettivamente gestisci il path (un singolo array di
char, un vettore multidimensionale di stringhe, una lista di stringhe,
etc.) dipende solo dalle tue preferenze e alla fine cambia ben poco...
quello che quasi certamente ti capitera' sara' di dover allocare
dinamicamente lo spazio.
Poi se pensi che il costo di tante malloc o di una realloc non sia
accettabile puoi simulare il comportamento della malloc a mano (per
intenderci, come fa' il K&R con la sua alloca o alloc, non ricordo il
nome esatto) e in tal caso eviti il costo della system call associata.
-- 
Mox

 Quasi certamente NON crasha (soprattutto se sfori di pochi elementi,
Quasi certamente stai dicendo una stupidaggine. Il fatto che un
programma crashi o meno a casusa dello sfondamento dei limiti di
un array non dipende da fatto che si sfori di pochi o di molti
elementi.
Per come sono definite le variabili, probabilmente il puntatore slash
e posizionato subito dopo l'array work_dir (questo ovviamente dipende
dal compilatore e dalle ottimizzazioni, ma c'e' la possibilita' che
sia cosi) sforando l'array vai a sovrascrivere slash.
Se slash viene usato subito dopo, un crash e' quasi garantito.
La variabile Posix che indica la dimensione massima di un path e'
PATH_MAX. Sforare gli array non e' mai una cosa da fare.
C:\>iao Angelo
-- 
Posted via Mailgate.ORG Server - 
http://www.Mailgate.ORG

path lungo 102 caratteri?
In questo caso non dirmi che crasha se METTE un path... crasha magari
se cerca di usarlo, ma io non ho mai parlato di usarlo.
Se ovviamente cerchi di fare una cosa del tipo (array[x])->data, con X
maggiore dell'upper bound dell'array e passi il limite dell'array e'
molto probabile crashi.
Mox :)
-- 
Mox

(anche se non sono cosi' sicuro che heap sia maschile :P).
La linguetta significa forse che se lo heap fosse femminile ti
piacerebbe corromperlo? 8-)

tipo?
Non so se tu possa ritenerlo un metodo intelligente... ma ne ho uno un
pň barocco che avevo usato parecchio tempo fa.
Mi si č presentato esattamente il tuo problema quando ho dovuto
soddisfare la specifica di accettare da tastiera un input non limitato
a priori.
Siccome all'epoca avevo decisamente pochi strumenti a mia
disposizione, l'ho risolto usando una lista di singoli char.
Ho definito una struttura
struct Lstringa
{
  int car;
  struct Lstringa *next;
};
Ho di fatto reinventato l'acqua calda, forse in maniera discutibile
quanto a prestazioni ed utilizzo della memoria, ma per piccole
porzioni di dati (come un semplice percorso di un file, non piů grande
di qualche centinaio di byte) credo che siano problemi tranquillamente
trascurabili nella grande maggioranza dei casi.
La gestione della Lstringa (sta per Lunga stringa) avveniva mediante
l'uso di una funzione di inserimento, una Lstrlen, del tutto analoga a
quella della libreria standard string.h ed una Lstrcpy che prende come
parametri un puntatore (non costante) a char ed un puntatore a
Lstringa. La Lstrcpy semplicemente copia il contenuto della Lstringa
in un array di caratteri convenzionale, allocato dinamicamente per
l'occasione.
Ti posto il codice. Forse non č il massimo dell'eleganza, ma funziona,
magari con qualche adattamento ai tuoi scopi (per esempio puoi
aggiungere una 'Lstrcat'.
#include <stdio.h>
struct Lstringa
{
  int car;
  struct Lstringa *next;
};
struct Lstringa *ins_Lstringa(FILE *origine);
char *Lstrcpy(char *str, struct Lstringa *Lstr);
int Lstrlen(struct Lstringa *stringa);
int main(int argc, char *argv[])
{
  char *testo;
  struct Lstringa *temp_txt;
  printf("Inserisci da tastiera il testo che ti interessa\n");
  temp_txt = ins_Lstringa(stdin);	/* inserisce da tastiera il
testo (stdin) */
  testo = malloc(sizeof(char) * Lstrlen(temp_txt));	/* conta i
caratteri inseriti, ed alloca lo spazio necessario per l'array di
caratteri in cui voglio ricopiarli  */
  Lstrcpy(testo, temp_txt);	/* copia temp_txt in testo */
  printf("Il testo inserito e':\n\n%s", testo);	/* stampa */
 
  return 0;
}
struct Lstringa *ins_Lstringa(FILE *origine)
{
  struct Lstringa *start, *temp;
  char fine = 0;
  start = malloc(sizeof(struct Lstringa));
  temp = start;
  start->car = fgetc(origine);
  while(temp->car != EOF && temp->car != '\n')
  {
    temp->next = malloc(sizeof(struct Lstringa));
    temp = temp->next;
    temp->car = fgetc(origine);
  }
  if(temp == start && start->car == EOF)	/* se la stringa č
vuota, libera la memoria e restituisce NULL */
  {
    free(start);
    return NULL;
  }
  temp->car = '\0';	/* termina la stringa */
  temp->next = NULL;	/* termina la lista */
  return start;	/* restituisce la testa della lista */
}
int Lstrlen(struct Lstringa *stringa)
{
  int i = 0;
  if(stringa == NULL)
    return 0;
  while(stringa->car != '\0')
  {
    i++;
    stringa = stringa->next;
  }
  return i;
}
char *Lstrcpy(char *str, struct Lstringa *Lstr)
{
  int i = 0;
  for(i = 0; Lstr != NULL; i++)
  {
    *(str + i) = Lstr->car;
    Lstr = Lstr->next;
  }
  return str;
}
Se devi leggere da un'altra sorgente (per esempio un file su disco),
ti basta mettere il puntatore dello stream al posto di stdin
dell'esempio qui sopra riportato.

 Se slash viene usato subito dopo, un crash e' quasi garantito.
</autocite>
In ogni caso scritture in aree di memoria non allocate per il processo
sono da evitare sempre.
A meno che non si gradisca rispondere a post del tipo:
"La  nostra azienda sta' facendo il port di 25M di sorgenti.
Sotto DOS hanno funzionato benissimo per 20 anni, non riusciamo
a capire come mai compilati sotto WindowsNT il programma crasha
appena lo si avvia.
Eppure e' tutto "C" standard"
:-)


:-)
ah ah ah ah ah ah ah ah ah ah ah :)
Bellissima, questa me la segno :)
-- 
Mox

disposizione, l'ho risolto usando una lista di singoli char.
Come idea non e' male, ma secondo me hai troppo overhead (la struttura
dati dovrebbe essere meno ingombrante dei dati in linea di massima).
Riadattando il tutto per lavorare su stringhe IMHO dovrebbe rendere
meglio.
Mox
-- 
Mox

meglio.
Certo. :-)
Difatti era una soluzione che adottai quando avevo appena imparato ad
usare i puntatori e le struct, e mettevo liste dappertutto... :-))