Newsgroup: it.comp.lang.c
Titolo: togliere lo \t da una stringa

ciao a tutti, ho una stringa con un tab davanti e devo toglierlo per
ottenere la stringa senza tab, se io faccio...
char *senza_tab(char *stringa)
{      
        char *stringa_formattata;
        char vettore[50];
        char memo[50];
        int i,k;
        i=k=0;
        strcpy(vettore;stringa);
        while(*stringa)
       {
                 if (vettore[i] != '\t') 
                   memo[k++] = vettore[i++];
                stringa++;
       }
    stringa_formattata=malloc(strlen(memo));
    return(stringa_formattata);
}
il problema e' che mi trova il carattere '\t solo al carattere zero, non al secondo al terzo e cosi' via, cosi' non so quanti caratteri togliere alla stringa!
chi puo' darmi un consiglio???
ciao


Vado al volo... (non ho compilato) :
#include <string.h>
...
char *senza_tab(char *stringa)
{
     int len = strlen( stringa ) ;
     for ( ; stringa[0] ; len-- )
     {
           if ( stringa[0] == '\t' ) 
              memmove( stringa, &stringa[1], len ) ;
     }
}
--
Andrea Laforgia - walkietalkie(at)
libero.it
#exclude <windows.h>

     }
Sorry... e' sbagliato... non c'e' condizione d'uscita :)


ottenere la stringa senza tab, se io faccio...
Se vuoi togliere tutti i tab basta usare l'approccio leggi-scrivi:
  void togli_tab(char *stringa)
  {
    char *leggi=stringa,*scrivi=stringa;
    do
    {
      if (*leggi!='\t')
        *scrivi++=*leggi;
    } while (*leggi++);
  }
In pratica usi due puntatori che lavorano sulla stessa area:
quello di lettura si incrementa sempre... quello di scrittura
solo quando hai un carattere che ti interessa tenere (in
questo caso tutti tranne i tab).
Il loop a condizione finale e' comodo perche' cosi' viene
compiato anche lo '\0' finale.
Se invece il tuo problema e' togliere solo i tab *iniziali*:
  void togli_tab_iniziali(char *stringa)
  {
    char *leggi=stringa;
    while (*leggi=='\t')
      leggi++;
    while((*stringa++ = *leggi++)!='\0')
      ;
  }
In questo caso fai un loop iniziale cercando quanti sono i
tab da eliminare e poi fai una copia della parte restante
(anche in questo caso torna comodo controllare di aver
incontrato lo '\0' *dopo* aver fatto la copia del carattere).
HTH
Andrea
--
Andrea Griffini, Programmer
http://www.netservers.com/~agriff

ottenere la stringa senza tab, se io faccio...
Questa è giusta?
char *senza_tab(char *stringa)
{
        int len= strlen(stringa);
        char *stringa_formattata;
        stringa_formatta = (char*) malloc(len * (char) -1) ;
        int i,a;
if (stringa[0] == '\t')
{
        for(i=1,a=0; i<=len;i++,a++)
            {
                        stringa_formattata[a]=stringa[i];
            }
} else
            { strcpy(stringa_formattata,"");
                return(stringa_formattata);
            }
    return(stringa_formattata);
}


Web Site: 
http://asterix75.capri.it
Secret MS Windows code:
while (1) { if (num_process > 1) bluescreen(rand()); }

 Sorry... e' sbagliato... non c'e' condizione d'uscita :)
Cosa volevi fare con il ciclo for?
Se il tab e` il primo carattere:
if (*stringa == '\t')
	memmove(stringa, &stringa[1], len );
ciao
Kronos
-- 
Home: 
http://kronoz.cjb.net
Non sempre quello che viene dopo e` progresso.
Alessandro Manzoni

Se il tab e` il primo carattere:
Gia', e se il secondo e' ancora un tab ?


        for (; *s && (*s == '\t'); s++)
Qui hai un bel "memory leak"...


        stringa_formatta = (char*) malloc(len * (char) -1) ;
A parte che il cast sul ritorno di malloc non ci va, immagino tu volessi
scrivere "sizeof(char)" invece che "char"; peraltro, sizeof(char) è
sempre uguale a 1, e quindi è superfluo.
-- 
Saluti,
    Mardy

scalare l'array stesso con memmove?
E` giusto, purché non venga utilizzato questo puntatore per un'eventuale
chiamata a free(); bisogna che il chiamante preservi il valore di "s",
se intende deallocare la sua memoria.
Chiaramente se la stringa non è stata allocata con malloc() allora non
c'è alcun problema.
-- 
Saluti,
    Mardy

}
"C, C++ e Java sono ricchi di operatore ed espressioni sintattiche,
per cui è facile eccedere nel loro utilizzo. Alcune espressioni sono
compatte, ma contengono troppi operatori dentro una singola istruzione
[...] L'infinita energia creativa dei programmatori spesso si riversa
nello scrivere codice nel modo più coinciso possibile o nel trovare
strade ingegnose allo scopo di ottenere il scopo di ottenere il
risultato. Tuttavia l'obiettivo è scrivere un codice chiaro e non un
codice ingegnoso"
B.W. Kernighan - R. Pike, Programmazione nella pratica, pag 8
Anto
--
Antonio Cuni, 19 anni, studente
Brainbench C++ Master: 4.6, higher than 98% of all previous test takers.
C Language: 3.32, higher than 79% of all previous test takers.
Guida C/C++ di Programmazione.it: 
http://cpp.programmazione.it

 B.W. Kernighan - R. Pike, Programmazione nella pratica, pag 8
E' un bellissimo libro che possiedo e che continuo a studiare. Il fatto e' 
che hai dimenticato di citare gli esempi che intendono mostrare il codice 
ingegnoso ma poco chiaro di cui si parla:
*x += (*xp=(2*k < (n-m) ? c[k+1] : d[k--]));
e
subkey = subkey >> (bitoff - ((bitoff >> 3) << 3));
L'espressione che ho scritto non mi sembra poco chiara, e' soltanto un 
approccio che puo' essere utilizzato in C per trattare le stringhe. 
for (; *s && (*s == '\t'); s++)
        ;
Di cose del genere ne e' pieno il K&R:
void strcpy(char *s, char *t)
{
        while (*s++ = *t++)
                ;
}
int strcmp(char *s, char *t)
{
        for ( ; *s == *t; s++, t++)
                if (*s == '\0')
                        return 0;
        return *s - *t;
}
pp. 134 e 135.


codice ingegnoso"
Codivido in pieno :)
Una frase carina che ho letto (credo sia di Kernighan ma non
ne sono sicuro) e' che per fare il debug o manutenzione di
un frammento del codice e' necessaria una abilita' doppia
con il linguaggio rispetto all'abilita' necessaria per
scrivere il codice stesso. Chi scrive al limite della sua
comprensione del linguaggio sta scrivendo codice di cui lui
stesso non riuscira' a fare manutenzione.


Di cose del genere ne e' pieno il K&R:
No, il tuo codice non e' corretto, nel senso che restituisce un
puntatore a una zona di memoria che non e' quella originariamente
passata.  Il K&R non lo fa in nessuno dei suoi esempi.


 passata.  Il K&R non lo fa in nessuno dei suoi esempi.
Qui hai ragione, infatti, ho postato anche la seconda funzione che 
restituisce lo stesso puntatore passato.
Intendevo solo dimostrare che non si trattava di codice poco chiaro come 
sintassi...


sintassi...
No, per chi conosce il C :)


 erano inutili.
beh... alla fine dei conti l'unica espressione inutile era quel *s


 No, per chi conosce il C :)
Stavo per cominciare a credere il contrario... :-)


beh... alla fine dei conti l'unica espressione inutile era quel *s
E l'operatore "&&" usato per la condizione. Anche la scelta
di usare un for con una parte di inizalizzazione vuota e una
parte di body vuota e' secondo me discutibile. Non offre nulla
in piu' del while risultando semplicemente meno chiara.


 No, per chi conosce il C :)
Io invece sono d'accordo con Andrea Griffini: un codice del genere,
anche se conosci bene il C, non lo puoi considerare chiaro e te ne
accorgerai nel momento in cui ci devi rimettere le mani. Pensa non ad
esempietti del genere ma ad un intero programma di centinaia o migliaia
di righe di codice scritto tutto in quel modo. Da far rizzare i capelli!
E pensa anche al cliente che ti sta chiedendo cose assurde situate
comunque ad un livello di astrazione completamente diverso...
EMG

in piu' del while risultando semplicemente meno chiara.
ed era proprio questo il motivo per cui avevo postato la citazione.
Sempre  Kernighnan e Pike consigliano di "programmare nel mainstream",
ovvero utilizzare le espressioni idiomatiche tipiche del linguaggio
utilizzato: usare un for "deficiente" (nel senso etimologico del
termine, ovvero che manca di una sua parte) IMHO non è una espressione
idiomatica. Inoltre spesso spezzare su più righe il codice contenuto
in una sola porta ad una maggiore chiarezza.


 in una sola porta ad una maggiore chiarezza.
...in questo non posso che essere d'accordo con te...
Piu' per gioco che per altro ho fatto questa piccola statistica: nei 
sorgenti di Apache il for "deficiente" e' usato 52 volte su 727 cicli for 
utilizzati in totale...
:-)
$ cd /usr/src/apache_1.3.20
$ egrep -r "for *\( *;"  ./* | egrep -v "for *\( *; *; *\)" | wc -l
     52
$ egrep -r "for *\(" ./* | wc -l
    727
In quel 52 non viene conteggiato l'uso dell'espressione idiomatica for(;;) 
che realizza un ciclo infinito...


    727
penso che sarebbe ora che io iniziassi a studiarmi un po' di grep...
non capisco le regexp che hai usato ma mi fido ;-) 
