Newsgroup: it.comp.lang.c
Titolo: funzione che restituisce stringa

Salve a tutti!
ho un problema per scrivere una funzione che deve restituire una 
stringa
se faccio cosi non funziona
char *restCodice(int num)
{
 char stringa[50];
 sprintf(stringa,"Numero: %d",num);
 return stringa;
}
potrei usare una variabile globale, ma poi avrei altri problemi; ad es. 
scrivendo;
sprintf(stringa2, "%s; %s", restCodice(6), restCodice(5));
pero' e' lo stesso problema che si ha con la funzione fcvt di stdlib.h
The return value of fcvt points to static data whose content is 
overwritten by each call to fcvt and ecvt.
finora ho utilizzato solo soubroutine del tipo: void restCodice(int 
num, char *stringa)

 return stringa;
MAI fare una cosa del genere. Lo spazio per 'stringa' � allocato sullo
stack. All'uscita da restCodice, quello spazio viene invalidato, per
cui il puntatore che restituisci punta ad un'area non pi� valida.
Dovresti invece allocare memoria mediante malloc() & C. e deallocarla
all'esterno della funzione, una volta usata la stringa per i tuoi
scopi.

 
...che ï¿œ imho la cosa piï¿œ sensata(*); al massimo, se preferisci, puoi 
fare qualcosa del tipo:
char *restCodice(int num, char *stringa)
{
	sprintf(...);
	return stringa;
}
che estetica a parte ha il vantaggio che non rischi di dimenticarti una 
delle chiamate
char a[100], b[100];
restCodice(n1, a);
// restCodice(n2, b); questo lo dimentico!
funz(a, b);
(*) Non che l'idea di Andrea Laforgia sia male, ï¿œ una mia preferenza 
personale: l'idea ï¿œ di non mescolare malloc (e gestione dei suoi 
fallimenti) e formattazione, anche perchï¿œ di solito faccio cose del 
genere sol in buffer temporanei, per formattare un messaggio; se mi 
serve una copia c'ï¿œ strdup, ma di solito non mi serve perchï¿œ salvo in 
memoria il dato grezzo e stringhifico solo quando serve.
Di nuovo, ï¿œ *solo* una preferenza personale.

Di nuovo, � *solo* una preferenza personale.
Concordo. Anche a me non piace molto dover separare le fasi di
allocazione/deallocazione. Sicuramente � meglio allocare fuori dalla
funzione, passare alla funzione, e lasciare il compito di deallocare a
chi ha allocato. Concordo con te, meno che sullo "stringhifico" :)

 funz(a, b);
col c++ ho anche utilizzato la seguente:
AnsiString restCodice(int num)
{
 char stringa[50];
 sprintf(stringa,"Numero: %d",num);
 return AnsiString(stringa);
}
da utilizzare nel seguente modo
sprintf(stringa2, "%s; %s", restCodice(6).c_str(), 
restCodice(5).c_str());

 > ...che è imho la cosa più sensata(*); al massimo, se preferisci, puoi fare

L'equivalente C sarebbe qualcosa del tipo:
char *restCodice(int num)
{
    char stringa[50];
    ...
    return strdup(stringa);
}
ma ovviamente il chiamante dovrebbe deallocare la memoria quando
finisce, visto che non hai distruttori o garbage collectors che lo
facciano al posto suo.
Comunque, di solito, come già ti hanno suggerito, la soluzione
elegante è la
char *restCodice(int, char *);
per aumentare l'eleganza, se volessi seguire una specie di convenzione
de-facto delle librerie GNU, potresti fare due funzioni distinte, una
con storage statico e una rientrante:
char *restCodice(int); /* restituisce lo statico */
char *restCodice_r(int, char *); /* lavora sul parametro */
Ciao!

 }
E' bene specificare che AnsiString non � una classe C++, ma � distribuita
con C++ Builder. L'equivalente standard sarebbe std::string. Da
sottolineare che il metodo che tu hai usato � estremamente inefficiente,
perch� costruisci un intero oggetto da restituire. Meglio avere un
riferimento alla stringa da valorizzare, come parametro. Ma siamo OT.
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it

 
questa non l'ho capita!
ci sono diverse opzioni io farei allocazione dinamica sullo heap anche 
se poi devi stare un pï¿œ attento alla deallocazione!
una cosa tipo:
char *restCodice(int num)
{
     char* stringa = malloc(50);
     sprintf(stringa,"Numero: %d",num);
     return stringa;
}
void main(){
     char* s = restCodice(10);
     free(s);
}
 

void main(){
Meglio abituarsi a scrivere il valore int come ritorno di main().

 sforare i 50 mallocati...
S�? e tu come lo sai? Sai qual � la lunghezza in bit dell'int su quella
macchina? sai quant'� lungo il valore massimo esprimibile?
In ogni caso non hai compreso bene il senso di ci� che ho scritto. Non
bisogna MAI dare per scontato che verr� occupata solo una parte di un
certo buffer preallocato. Bisogna SEMPRE garantire che solo una parte
venga occupata, senza sforamenti. Funzioni come strncpy() nascono apposta
per questi scopi.



Premesso che sono d'accordissimo con quello che hai detto,
probabilmente nel caso di portare un codice su macchina in cui esiste
un int esprimibile su più di 50 caratteri in notazione decimale il
fatto che il buffer sia corto sarebbe l'ultimo dei problemi :D
E cmq, al di là degli scherzi: probabilmente è meglio cercare un modo
(elegante) per far schiantare il programma in caso un numero non sia
outputtabile (scusate il termine) nel buffer - meglio far schiantare
il programma che restituire un valore errato/incompleto! Quindi -
definitivamente - controllare sempre se si è sforato, e soprattutto
fare l'operazione giusta al variare dei casi ;-)
Ciao!

 fatto che il buffer sia corto sarebbe l'ultimo dei problemi :D
Per 50 cifre, se non erro, servono 167 bit. Un futuro neanche troppo
lontano :)


Andrea Laforgia ha scritto:

oddio era uno stralcio giusto per... non pretendevo mica fosse un codice 
perfetto... speravo di rendere evidente il problema pi� grosso poi 
ovviamente c'� un p� di alt ri problemi.