Newsgroup: it.comp.lang.c
Titolo: problema con strcat

Salve
sto cercando di scrivere una function che prende in ingresso una stringa
e restituisce la medesima stringa senza gli spazi.
Il codice che ho scritto è questo :
char *toglispazi(char *s)
{
    int i;
    char *t,*j;
 
    t="";
    for (i=0;i<strlen(s);i++)
      {
         if (s[i]!=' ') t=strcat(t,s[i]);
      }
    return(t);
}
Questo codice però mi restituisce un errore di segmentation fault in 
strcat. Potreste darmi una mano a correggerlo ?
Grazie per l'attenzione.
Ciao
-- 
       _-==.==-_**_-==.==-_
         _    _   __    _
        |_)_ |_) (_  _ |_)
        | (_|| \o__)(/_| \
        (Giacomo Bellucci)
PaR._IL_BIAN...@libero.it
      Per rispondermi togliete
    _IL_BIANCONIGLIO_ dall'email


[web] 
http://www.smos.org
[ircnet] #smos

 
Ciao e grazie


 ha scritto nel
messaggio news:8mITc.43488$OH4.1...@twister1.libero.it...

Sì volendo potevi fermarti qui. Ma supponi il caso in cui hai una
stringa con una grande quantità di spazi: in quel caso allocheresti
sTmp uguale alla stringa iniziale e ne useresti solo una piccola parte
creando uno "spreco di memoria" (ingente o meno)...
Invece nel caso tipico creando la sOut allochiamo solo l'effettiva
memoria sufficiente a contenere la stringa ripulita dagli spazi e
nulla di più.
Ciao.


 strcat. Potreste darmi una mano a correggerlo ?
Ci sono due errori gravi, entrambi in grado di generare un segmentation
fault anche da soli:
1) La funzione strcat si aspetta che il primo argomento sia l'indirizzo di
un array di caratteri *scrivibile* (non const), grande almeno quanto basta
per contenere una copia della stringa passata come secondo parametro, null
terminator incluso. La variabile t punta invece alla stringa costante "",
cioè a un array const (quindi teoricamente non modificabile) contenente un
unico elemento (quindi quasi sempre troppo piccolo).
2) La funzione strcat si aspetta che il secondo argomento sia l'indirizzo di
un array (eventualmente costante) di caratteri null-terminated.
L'espressione s[i] che tu gli passi è invece un intero: il codice numerico
dell'i-esimo carattere della stringa puntata dalla variabile s. Se vuoi
l'*indirizzo* dell'i-esimo carattere della stringa s devi scrivere s + i
oppure &s[i]
Ciò detto, non sono molto bravo a mettere a posto cose scritte da altri. Io
riscriverei così:
	char * toglispazi (char * s)
	{
		register int i, j;
		for (i = j = 0; s[i] != '\0'; i++)
		{
			if (s[i] != ' ')
				s[j++] = s[i];
		}
		s[j] = '\0';
		return s;
	}
Oppure così:
	char * toglispazi (char * s)
	{
		register char * s1, * s2;
		for (s1 = s2 = s; *a != '\0'; s1++)
		{
			if (*s1 != ' ')
				*s2++ = *s1;
		}
		*s2 = '\0';
		return s;
	}
La prima implementazione (che preferisco) usa gli indici e l'altra i
puntatori; a parte questo, sono sostanzialmente equivalenti e la differenza
fra le due è pura questione di gusti.
In entrambi casi, il trucchetto è semplicissimo: l'indice in lettura (i,
corrispondente al puntatore s1 nella seconda versione) s'incrementa a ogni
giro, quale che sia il carattere, mentre l'indice in scrittura (j,
corrispondente al puntatore s2 nella seconda versione) s'incrementa solo
dentro l'if, cioè solo quando il carattere non è uno spazio.
--
Cingar
P.S.: credo che questo sia il mio primo post e ne approfitto per salutare il
NG.
--------------------------------
Inviato via 
http://arianna.libero.it/usenet/

 for (s1 = s2 = s; *a != '\0'; s1++)
Ooops! Volevo dire:
	for (s1 = s2 = s; *s1 != '\0'; s1++)
Ne approfitto per far notare un altro errore (innocuo) nella versione di
Giacomo: viene dichiarata una variabile j che poi non è utilizzata.
(Ordinaria amministrazione: è una disattenzione talmente frequente, fra i
programmatori, che quasi tutti i compilatori hanno un apposito warning per
segnalarla).
--
Cingar


 >
Se posso permettermi, volendo ottenere una stringa a partire da un'altra
togliendo gli spazi, e dichiarando la funzione come
char * funzione(char * stringa)
interpreterei tutto questo come se non si avesse l'intenzione di modificare
la stringa originaria (altrimenti la funzione 'ritornerebbe' un void).
Pertando, nel tuo codice allocherei una nuova stringa per il risultato e ne
ritornerei il puntatore.
Ciao,
Ema

 ritornerei il puntatore.
D'altra parte, il fatto che l'argomento sia di tipo (char *) e non (const
char *) suggerisce che il chiamante voglia farsi modificare la sua stringa,
non farsene generare un'altra contenente il testo modificato.
Comunque, chi ha postato il problema ha specificato chiaramente: "una
function che prende in ingresso una stringa e restituisce la MEDESIMA
stringa senza gli spazi".
Quindi, l'altra implementazione che ho visto in questo thread, che coinvolge
una malloc(), è errata in quanto "non conforme alle specifiche". (E, detto
fra noi, non leggere le specifiche è da sempre il peccato mortale del
programmatore... :-)
Quanto al valore di ritorno, credo che toglispazi() ce l'abbia per adeguarsi
alla convenzione di molte funzioni della libreria standard <string.h>, che
ritornano un puntatore al buffer modificato per permettere di concatenare
più chiamate in un'unica espressione:
    char buffer [100] = "Facciamo";
    puts(strcat(strcat(buffer, " un"), " esempio..."));
--
Cingar


     puts(strcat(strcat(buffer, " un"), " esempio..."));
Va bene. E' bello adeguarsi alle convenzioni. E tra l'altro e' uno di quegli
aspetti a cui non avevo mai dato importanza.
Pero' nel caso specifico (in cui vale:
toglispazi(toglispazi(x))=toglispazi(x) ) mi sembrava superfluo... sempre
imho.
Ciao,
Ema

 imho.
Certo, concatenazioni del genere sarebbero assurde. Quello che intendevo era
qualcosa di questo tipo:
    strcat(toglispazi(xx), toglispazi(yy));
(Che poi, a dire il vero, a me personalmente sembrano un po' assurde pure
queste... Nella programmazione reale non farei mai concatenazioni del
genere, neanche con le funzioni standard di <string.h>: preferisco mettere
ogni operazione su una riga, come istruzione a sé. Ma c'è chi ama questo
stile di programmazione, e il senso di quel valore di ritorno è proprio di
consentire questo stile.)
