Discussione:
[principiante] problema con stringa di lunghezza arbitraria.
(troppo vecchio per rispondere)
mdema@diesel
2008-09-13 22:20:42 UTC
Permalink
Salve a tutti.
Premetto che sono un principiante in C.
Io ho la necessita di creare una stringa di lunghezza arbitraria (che
non sia limitata insomma da alcuna lunghezza limite).
Leggendo un po' in rete e sviluppando quello che ho trovato, ho scritto
il seguente codice:

int getString(char *s){
unsigned long i=0;
char c;

if(!(s=(char*)malloc(sizeof(char))))
{
return -1;
}

while(isspace(c = getchar())); // ignora eventuali spazi iniziali

do // cicla finchè non incontra uno spazio
{
s[i]=c;
i++;
if(!(s=(char*)realloc(s, i)))
{
return -1;
}

}while(!(isspace(c=getchar())));

s[i]='\0';
return 0;

}

void main(){

char *stringa;
int a,b;

scanf("%d %d",&a,&b);
getString(stringa);

printf("%d %d %s",a,b,stringa);

}

Il mio problema è che non stampa la stringa immessa da scehrmo! Ho
provato a mettere vari printf dentro alla funzione getString e ho
verificato che, alla fine dell'esecuzione, in s c'è effettivamente la
stringa immessa in input....solo che poi non riesco a passarla al main.
Qualcuno mi spiega dove sto sbagliando??
Grazie mille.
Pleg
2008-09-14 00:50:08 UTC
Permalink
Post by ***@diesel
int getString(char *s){
unsigned long i=0;
char c;
if(!(s=(char*)malloc(sizeof(char))))
Questo sembra un modo molto contorto di dire "s = malloc(1)": la dimensione del char e' sempre 1 byte, ed e' sconsigliato castare il tipo restituito da malloc (che e' void* e si "casta da solo" al tipo corretto). Cmq, hai allocato un byte e dato la posizione a 's'.
Post by ***@diesel
{
return -1;
}
while(isspace(c = getchar())); // ignora eventuali spazi iniziali
do // cicla finchè non incontra uno spazio
{
s[i]=c;
i++;
if(!(s=(char*)realloc(s, i)))
'i' valeva 0. Adesso vale 1: dovrai allocare 2 byte ora, non 1: "realloc(s, i+1)".
Post by ***@diesel
{
return -1;
}
}while(!(isspace(c=getchar())));
s[i]='\0';
return 0;
Perche' restituire 0? Innanzitutto, se non ti serve restituire niente puoi dichiarare la funzione come "void getString(...)" e non mettere return. Ma qui TI SERVE! Insomma, hai creato la stringa, caricato il testo... e poi la butti via? Quandi allochi memoria col malloc/realloc la funzione ti restituisce un puntatore alla zona di memoria dove hai memorizzato la striga: ma questo valore devi passarlo indietro al main, se no come fa il main a sapere dove sta la stringa?
Quindi: non ti serve passare 's'/'stringa' per valore alla funzione; ti serve invece che la funzione lo restituisca al main:


char *getString(void) {
char *s;
...
return s;
}


e nel main:

stringa = getString();




Pleg
?manu*
2008-09-14 06:33:01 UTC
Permalink
Post by Pleg
Quindi: non ti serve passare 's'/'stringa' per valore alla funzione;
Anzi è proprio sbagliato. Infatti il valore di s che viene passato alla
funzione viene perso, e chi ha chiamato la funzione non ha modo di
recuperare la stringa allocata.

E.
Andrea Laforgia
2008-09-14 11:56:33 UTC
Permalink
Post by ***@diesel
Leggendo un po' in rete e sviluppando quello che ho trovato, ho scritto
Ci sono molti errori in questo codice.
Post by ***@diesel
int getString(char *s){
Qui stai passando il puntatore per valore, il che vuol dire che
qualsiasi modifica farai a questo valore verrà persa, all'uscita dalla
funzione. Inoltre, se la funzione non deve restituire valori,
dichiarala "void". L'alternativa è far restituire un puntatore alla
funzione oppure passare il puntatore per indirizzo:

1) char *getString()
2) void getString(char **ps)
Post by ***@diesel
if(!(s=(char*)malloc(sizeof(char))))
Il cast sul valore di ritorno di malloc non va usato in C e
sizeof(char) è sempre uguale a 1. In ogni caso, questo tuo codice non
ha molto senso. Non è pensabile fare riallocazioni successive di 1
byte. Molto meglio allocare memoria a blocchi. A volte la crescita
ammortizzata è una buona soluzione per tecniche dinamiche (i.e: parto
con 10, espando a 20, espando a 40, espando ad 80, ecc...).
Post by ***@diesel
while(isspace(c = getchar())); // ignora eventuali spazi iniziali
Fai letture successive con fgets(), non con getchar(), per il discorso
di cui sopra. Dichiara un buffer di, supponiamo, 128 caratteri e leggi
a blocchi con fgets().
Post by ***@diesel
if(!(s=(char*)realloc(s, i)))
La realloc() non va mai usata a questo modo: bisogna prima verificare
che il risultato non sia NULL e solo dopo aver verificato che non è
NULL assegnarlo al puntatore riallocato.
Post by ***@diesel
void main(){
Ricordati che main(), per essere portabile, deve restituire un int.
Continua a leggere su narkive:
Loading...