[RISOLTO][C]return di una stringa

Forum dedicato alla programmazione.

Moderatore: Staff

Regole del forum
1) Citare in modo preciso il linguaggio di programmazione usato.
2) Se possibile portare un esempio del risultato atteso.
3) Leggere attentamente le risposte ricevute.
4) Scrivere i messaggi con il colore di default, evitare altri colori.
5) Scrivere in Italiano o in Inglese, se possibile grammaticalmente corretto, evitate stili di scrittura poco chiari, quindi nessuna abbreviazione tipo telegramma o scrittura stile SMS o CHAT.
6) Appena registrati è consigliato presentarsi nel forum dedicato.

La non osservanza delle regole porta a provvedimenti di vari tipo da parte dello staff, in particolare la non osservanza della regola 5 porta alla cancellazione del post e alla segnalazione dell'utente. In caso di recidività l'utente rischia il ban temporaneo.
Avatar utente
boh
Linux 4.x
Linux 4.x
Messaggi: 1027
Iscritto il: ven 16 set 2005, 0:00
Slackware: 14.2 (x64)
Kernel: 4.4.111
Desktop: KDE 4.14.32
Località: Milano
Contatta:

[RISOLTO][C]return di una stringa

Messaggio da boh »

Scrivere un sottoprogramma che ricevute in ingresso due stringhe (e nessun altro parametro) ne crea una nuova costituita dalla concatenazione delle due ricevute in ingresso e la restituisce al chiamante.

Ora come da titolo, il problema è il return di questa stramaledetta nuova stringa!
Nella funzione ho anche creato un puntatore a char, e l'ho assegnato alla nuova stringa facendo returnare quello, ma la stringa non ce l'ho poi nel main.

Come faccio?
Ultima modifica di boh il mer 27 feb 2008, 10:55, modificato 1 volta in totale.
"Be yourself. Everyone else is already taken." ~ Oscar Wilde

Avatar utente
absinthe
Iper Master
Iper Master
Messaggi: 2354
Iscritto il: dom 15 mag 2005, 0:00
Nome Cognome: Matteo Nunziati
Slackware: 12.1 - defunct
Kernel: 2.6.32-5-amd64
Desktop: gnome
Distribuzione: debian squeeze
Località: Prato
Contatta:

Re: [C]return di una stringa

Messaggio da absinthe »

eh? non ho mica capito sai! cosa intendi: hai creato un puntatore _dentro_ la funzione di concatenazione (una funzione creata da te? strcat no?) che punta ad una stringa? come la hai allocata la stringa? e poi restituisci una variabile con riferimenti strettamente locali nel main? così restituisci l'indirizzo della stringa ma non è detto che la tringa persista, anzi! mi sa che non funziona così! posta un pò di codice!

M

PS: ma che è un esercizio di scuola e chiedi numi su slacky ? ;-)

Avatar utente
robbybby
Linux 4.x
Linux 4.x
Messaggi: 1223
Iscritto il: sab 16 dic 2006, 10:48
Slackware: 13.1 / 64 bit
Kernel: 3.3.x
Desktop: KDE 4.4.5
Località: Fra Trantor e Terminus

Re: [C]return di una stringa

Messaggio da robbybby »

C puro:

Codice: Seleziona tutto

/* assicurarsi che szSum abbia spazio almeno per iMaxLen + 1 caratteri */
void concat(const char *cszStr0, const char *cszStr1, char *szSum, int iMaxLen)
{
  assert(cszStr0);
  assert(cszStr1);
  assert(szSum);
  assert(iMaxLen > 0);

  strncpy(szSum,
                cszStr0,
                iMaxLen);
  szSum[iMaxLen] = '\0';
  strncat(szSum,
               cszStr1,
               iMaxLen - strlen(szSum));
  /* non e' necessario assicurarsi che l'ultimo carattere sia il NULL, perche' ci
      pensa la strncat (cosa che non fa la strncpy */
}
C++

Codice: Seleziona tutto

//dovrebbe bastare
string concat(const string &cstr0, const string &*cstr1)
{
  assert(&cstr0 != 0);
  assert(&cstr1 != 0);
  return cstr0 + cstr1;
}

//pero' io preferisco una cosa tipo quella in C liscio
void concat(const string &cstr0, const string &*cstr1, string *pstrSum)
{
  assert(pstrSum);
  *pstrSum = cstr0;
  *pstrSum += cstr1;
}


Avatar utente
boh
Linux 4.x
Linux 4.x
Messaggi: 1027
Iscritto il: ven 16 set 2005, 0:00
Slackware: 14.2 (x64)
Kernel: 4.4.111
Desktop: KDE 4.14.32
Località: Milano
Contatta:

Re: [C]return di una stringa

Messaggio da boh »

absinthe ha scritto: così restituisci l'indirizzo della stringa ma non è detto che la tringa persista, anzi! mi sa che non funziona così! posta un pò di codice!
Esatto era quello che pensavo!
E allora come ovviare a questo problema?

Un po' di codice:

Codice: Seleziona tutto

char * miafunz(char str1[], char str2[])
{
char str3[N+N+1]; //N è la dimensione delle due stringhe nel main

strcat(str3, str1);
strcat(str3, str2);

return //??

}
E non so cosa returnare? Più chiaro? =)

EDIT: @robbyrobby: grazie per la risposta, ma io non posso passare altri parametri oltre le due stringhe.
E poi devo far returnare qualcosa, quindi una funzione void non mi va bene ;)
"Be yourself. Everyone else is already taken." ~ Oscar Wilde

Avatar utente
robbybby
Linux 4.x
Linux 4.x
Messaggi: 1223
Iscritto il: sab 16 dic 2006, 10:48
Slackware: 13.1 / 64 bit
Kernel: 3.3.x
Desktop: KDE 4.4.5
Località: Fra Trantor e Terminus

Re: [C]return di una stringa

Messaggio da robbybby »

Non si puo' fare (in realta' si potrebbe, come suggerisco piu' sotto, ma e' un modo che non mi piace per niente), come ti ha spiegato absinthe.
L'unico modo e' qualcosa tipo quello che ti ho postato io. Oppure con una stringa globale, ma nel mondo reale andresti incostro a gravi problemi di manutenibilita' del sw :) .
Oppure in C++, li' si puo', sempre come ti ho postato io, grazie all'operator=, overloaded in std::string (mi rifiuto categoricamente di tradurre il termine in italiano! :D ) e ai copy constructor :) .
Ultima modifica di robbybby il mar 26 feb 2008, 21:07, modificato 1 volta in totale.

Avatar utente
boh
Linux 4.x
Linux 4.x
Messaggi: 1027
Iscritto il: ven 16 set 2005, 0:00
Slackware: 14.2 (x64)
Kernel: 4.4.111
Desktop: KDE 4.14.32
Località: Milano
Contatta:

Re: [C]return di una stringa

Messaggio da boh »

Se devo essere sincero immaginavo non si potesse.
Però da come interpreto io il testo parrebbe invece di si!
Anch'io avrei passato una terza stringa alla funzione...
"Be yourself. Everyone else is already taken." ~ Oscar Wilde

Avatar utente
robbybby
Linux 4.x
Linux 4.x
Messaggi: 1223
Iscritto il: sab 16 dic 2006, 10:48
Slackware: 13.1 / 64 bit
Kernel: 3.3.x
Desktop: KDE 4.4.5
Località: Fra Trantor e Terminus

Re: [C]return di una stringa

Messaggio da robbybby »

boh ha scritto:Se devo essere sincero immaginavo non si potesse.
Però da come interpreto io il testo parrebbe invece di si!
Anch'io avrei passato una terza stringa alla funzione...
In realta' un modo c'e', un po' pericoloso, ma c'e'. In genere non lo si usa nei programmi veri, ma didatticamente puo' essere valido.
Pero' te lo devi trovare da solo.
Ti do' solo un suggerimento: malloc() :)

Avatar utente
Blizzard
Master
Master
Messaggi: 1509
Iscritto il: mar 2 gen 2007, 22:53
Nome Cognome: Giovanni Santostefano
Slackware: 12.2
Kernel: 2.6.27.7-smp
Desktop: Fluxbox
Contatta:

Re: [C]return di una stringa

Messaggio da Blizzard »

[anticipato da robbybby]
ciao ragà,
forse sparo una cavolata... [CENSURA]
[/anticipato da robbybby]

[edit]
effettivamente è giusto (come dice robbybby) che trovi la soluzione da solo.... per questo l'ho rimossa... non so se si può fare... se no la rimetto
sorry
Ultima modifica di Blizzard il mar 26 feb 2008, 21:17, modificato 1 volta in totale.

Avatar utente
robbybby
Linux 4.x
Linux 4.x
Messaggi: 1223
Iscritto il: sab 16 dic 2006, 10:48
Slackware: 13.1 / 64 bit
Kernel: 3.3.x
Desktop: KDE 4.4.5
Località: Fra Trantor e Terminus

Re: [C]return di una stringa

Messaggio da robbybby »

@Blizzard
Si', ma volevo che la trovasse da se', la soluzione.
Come ho detto prima, la vedo una soluzione valida solo a scopo didattico.

Avatar utente
boh
Linux 4.x
Linux 4.x
Messaggi: 1027
Iscritto il: ven 16 set 2005, 0:00
Slackware: 14.2 (x64)
Kernel: 4.4.111
Desktop: KDE 4.14.32
Località: Milano
Contatta:

Re: [C]return di una stringa

Messaggio da boh »

Ok, sembra funzionare, posto il codice:

Codice: Seleziona tutto

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define N 30

char * concatena(char [], char []);

int main()
{
	char str1[N+1], str2[N+1];
	char *ptr;
	
	scanf("%s %s", str1, str2);
	
	ptr = concatena(str1, str2);
	
	printf("\n%s", ptr);
	
	return 0;
}

char * concatena(char str1[], char str2[])
{
	char *p;
	
	p = (char *)malloc((N+N)*sizeof(char));
	
	strcat(p, str1);
	strcat(p, str2);
	
	return p;
	
}
Grazie per i consigli :D
Ma a questo punto avrei una domanda: perchè lo spazio che ho appena allocato nella funzione non sparisce?
Non è anche quello locale?
"Be yourself. Everyone else is already taken." ~ Oscar Wilde

Avatar utente
Blizzard
Master
Master
Messaggi: 1509
Iscritto il: mar 2 gen 2007, 22:53
Nome Cognome: Giovanni Santostefano
Slackware: 12.2
Kernel: 2.6.27.7-smp
Desktop: Fluxbox
Contatta:

Re: [C]return di una stringa

Messaggio da Blizzard »

no... lo spazio allocato dalla malloc è allocato nello heap, questo significa che si tratta di un area di memoria con politiche totalmente differenti dallo stack.
Tutto ciò che è allocato nello heap deve essere deallocato manualmente.
Il che significa che se dimentichi di deallocare la memoria che hai occupato con chiamate *alloc incorri nei tanto odiati memory leak, in quanto quella memoria è praticamente perduta nell'ambito di quel processo.
dichiarazioni, invece, del tipo
int a;
char ar[DIM];
gatto *miogatto;
provocano delle allocazioni nello spazio di memoria stack e vengono automaticamente deallocate all'uscita dalla funzione.
Questo provoca che ad esempio non puoi restituire l'array ar perchè avresti un riferimento a memoria non valida.
Se da un lato potresti avere una bellissima segmentation fault dall'altro lato potresti essere così sfortunato che il programma continuerà a girare assumendo alla lunga un comportamento bizantino che ti complicherà la vita anche nella sessione di debug.
Esistono altre aree di memoria... facendo riferimento al C++ ad esempio esiste la memoria libera che è quella utilizzata quando allochi qualcosa con new ed ha più o meno le stesse politiche dello heap.
Come potrai immaginare non è affatto consigliabile allocare qualcosa con new e deallocarla con una free() o viceversa.

Di solito più o meno funziona così!
in pratica con una malloc allochi memoria raw... n byte di memoria e viene restituito l'indirizzo iniziale di questi n byte. Quindi quello che perdi quando esci dalla funzione non è la memoria allocata, bensì il puntatore che utilizzi per accedere all'area che hai allocato.

Avatar utente
boh
Linux 4.x
Linux 4.x
Messaggi: 1027
Iscritto il: ven 16 set 2005, 0:00
Slackware: 14.2 (x64)
Kernel: 4.4.111
Desktop: KDE 4.14.32
Località: Milano
Contatta:

Re: [C]return di una stringa

Messaggio da boh »

Spiegazione esemplare, grazie :D
Un'ultima cosa: per il programma che è questo penso sia ininfluente, ma dovesse capitarmi qualcosa
di più "corposo" come allocazione, allora sarebbe preferibile, dopo che nel main ho usato quella memoria, fare un bel free?

Codice: Seleziona tutto

free(ptr);
"Be yourself. Everyone else is already taken." ~ Oscar Wilde

Avatar utente
robbybby
Linux 4.x
Linux 4.x
Messaggi: 1223
Iscritto il: sab 16 dic 2006, 10:48
Slackware: 13.1 / 64 bit
Kernel: 3.3.x
Desktop: KDE 4.4.5
Località: Fra Trantor e Terminus

Re: [C]return di una stringa

Messaggio da robbybby »

@boh
In

Codice: Seleziona tutto

  p = (char *)malloc((N+N)*sizeof(char));
   
   strcat(p, str1);
   strcat(p, str2);
C'e' un errore.
A te trovarlo. :)

Il free lo devi fare sempre. Questa e' una delle ragioni per cui, in un programma vero, una funzioni siffatta non sarebbe molto bella.

Avatar utente
boh
Linux 4.x
Linux 4.x
Messaggi: 1027
Iscritto il: ven 16 set 2005, 0:00
Slackware: 14.2 (x64)
Kernel: 4.4.111
Desktop: KDE 4.14.32
Località: Milano
Contatta:

Re: [C]return di una stringa

Messaggio da boh »

Strano perchè funziona :-k

La prima cosa che mi viene in mente è che la strcat restituisce, da prototipo, un char *, e quindi sarebbe preferibile:

Codice: Seleziona tutto

p = strcat(p, str1);
p = strcat(p, str2);
EDIT: Ok ;)
"Be yourself. Everyone else is already taken." ~ Oscar Wilde

Avatar utente
Blizzard
Master
Master
Messaggi: 1509
Iscritto il: mar 2 gen 2007, 22:53
Nome Cognome: Giovanni Santostefano
Slackware: 12.2
Kernel: 2.6.27.7-smp
Desktop: Fluxbox
Contatta:

Re: [C]return di una stringa

Messaggio da Blizzard »

C'e' un errore.
A te trovarlo. :)
stavolta mi faccio i * miei!
Il free lo devi fare sempre. Questa e' una delle ragioni per cui, in un programma vero, una funzioni siffatta non sarebbe molto bella.
infatti straquoto la prima soluzione che hai postato che è senza dubbio infinitamente elegante

Rispondi