Newsgroup: it.comp.lang.c
Titolo: Aiutatemi sono diventato un pollo

Come da subj, mi sento una pippa.
Non riesco a trovare l'errore, anche se TRE giorni fa ho scritto un pezzo di
programma praticamente identico (cambiano i nomi delle variabili...) che
funziona a meraviglia, ora non trovo il bandolo della matassa;
considerate queste 5 righe
int main(void)
{ 
char *dom="
pippo.pippo.com
"
char test[5];
test=strtok(dom,".");
printf("%s",test);
}
una volta compilato senza errore e lanciato va in seg.fault
(indovinate a quale riga...)
Il problema e' che non capisco percheeeeee'
Ho provato a fare delle varizioni sull'allocazione di test ma nisba.
vi prego aiutatemi a togliermi questo dilemma dalla mente...
Vi][oZ
-- 
          We are the true believers
       It's our turn to show the world
 In the fire of heavy metal we were burned
         It's more than our religion
          It's the only way to live
           But the enemies of metal
              We can't forgive

 test=strtok(dom,".");
ciao,
prima cosa, penso che qui devi usare strcpy .... non puoi "assegnare"
una stringa, 
ma la devi copiare ...
secondo :
io non ho mai usato la funzione strtok e cosi',per curiosita', sono
andato a
vedere la pagina man ....
ti riporto testualmente ....
BUGS
Never use this function. This function modifies its first argument.
The identity of the delimiting character is lost.
This function cannot be used on constant string.
sara' forse questo ?
ciao ciao ...
-- 
Antonio barbone ......
Outside of a dog, a book is man's best friend.
Inside of a dog, it's too dark to read.
		-- Groucho Marx

 <snip>
Magari con <char test[6];> funziona...
Visto che un token della tua stringa e' lungo 6 caratteri (5 + il
famosissimo '\0')
Andrea
 ('< ----------------+-------------------+-----------------
 /V\   Andrea        | arimicci @@       | Inet Abuse Dept.
<(_)        Rimicci  |      aritaly. com |     AR Italy
--~~-+---------------+-------------------+-----------------
     |     Phone & Fax 
+39-019-489197
      /__ /\
_____#__ Male, 33, Italian, C programmer__](__=_`)apx______

 test=strtok(dom,".");
Quest'assegnazione non si può fare in quanto test non è un l-value. Devi
usare strcpy():
strcpy( test, strtok( dom, "." ) );
EMG


char test[5]  e' un' array di char quindi un lvalue non modificabile.Mi sembra
strano che il tuo compilatore sia stato zitto nel parsare:
test=strtok(dom,".")
Prova cosi':
int main(void)
{
char dom[]="
pippo.pippo.com
"
char *test;
test=strtok(dom,".");
printf("%s",test);
}
Ivan Molella


Esatto, questa e' la conclusione a cui ero giunto stamani, pero' ora mi
viene un dubbio: Tempo fa era passato sul ng un thread lunghissimo sulla
differenza tra dichiarare 
char *pippo="literal"
char pippo[]="literal"
Ed in effetti sul K&R come sempre appare la soluzione, che io da studente
reietto avevo scordato => faccio ammenda pubblica (con i ginocchi sui ceci)
ed ammetto di essere un pollo...
grazie mille, mi hai fatto ricordare la disuguaglianza array!=puntatore.



Come prima, e' sbagliato se dichiaro test come char test[6].
grazie 


Come da subj, mi sento una pippa.
/* pippa.c */
#include <stdio.h>
#include <string.h>
int main()
{
    char *dom = "
pippo.pippo.com
" ;
    char test[5] = {0} ;
    strncpy( test, strtok( dom, "." ), sizeof test - 1 ) ;
    printf( "%s", test ) ;
    return 0 ;
}

char pippo[]="literal"
La differenza tra il primo e' il secondo caso e' notevole.
Nel primo caso la stringa di caratteri (che spesso sono definiti
costanti) viene allocata in memoria e al suo indirizzo viene fatto
puntare pippo.
Nel secondo caso (che ricade in uno dei tre in cui un vettore NON
decade nel puntatore al suo primo elemento) e' come se intendessimo :
char pippo[] = { 'l','i','t','e','r','a','l','\0' } ;
Formalmente, nel primo caso, scrivere :
pippo[3] = 'c' ;
potrebbe anche generare un errore, in quanto i caratteri vengono
assunti costanti (anche se nella maggior parte dei casi non e' cosi').
Nel secondo caso no.

 Come prima, e' sbagliato se dichiaro test come char test[6].
Non è affatto sbagliato! La dimensione potrebbe essere ancora
insufficiente (dipende dalla lunghezza del token letto) ma è il sistema
migliore per utilizzare la strtok() (che comunque non è un granché come
funzione proprio a causa della static utilizzata).
EMG

 }
  Scusa se insisto, ma il comportamento della strncpy in questione ha un
comportamento indefinito continuando a dichiarare p come puntatore a
char e non come array di char,quindi questo codice potrebbe crasciare in
determinati ambienti.
Con la strtok voglio acquisire la stringa pippo non pipp, che nell
'esempio su riportato andrebbe peraltro a creare una no null termitated
string, con la conseguente causa di poter creare altri crash.
Ivan Molella

   <snip>
Tagliamo, come si dice, la testa al toro e facciamo quindi un esempio
dove tutti noi possiamo essere daccordo.
#include <stdio.h>
#include <string.h>
int main(void)
{
  char dom[21];
  char test[9];
  char *next;
  strcpy(dom,"pippo.pluto.paperino");
  strcpy( test, strtok( dom, "." )) ;
  printf( "%s\n", test ) ;
  while ((next = strtok( NULL, "." )) != NULL)
    {
      strcpy( test, next) ;
      printf( "%s\n", test ) ;
    }
  return 0 ;
}
Questo esempio dovrebbe spiegare come funziona 'strtok' nella sua
completezza.
---------------------------------------------------------------   .--')
Andrea Rimicci (Male, 33)           _,.--""--.,,_               .' .-'
             ,       ,   _,,_ _,.--''             `""-._       / .'
arimicci @@  \`'-""-' |-"    `           ,     _.-.,_   `-, _.' /
 
aritaly.com
 | e  e        ,    .      /    ';-..._ `'-,_ ` _.'
           _..\      /       )    \ _,.-'.     \    `)  | ```
  __,.--"'`   _\_Y_ /.___,.-'   _.'`      `>   /    /  / Inet Abuse 
(((_.--'--""``  '--'__.-'  __.-'      .---'   / .--' .'     Dept,
   +39,019,489197 (((_..--'          ((_(_.-'` ((_(.'jgs  AR Italy

string, con la conseguente causa di poter creare altri crash.
"test", nel mio esempio, e' una stringa di 4 caratteri piu' uno zero
terminale tutti messi a 0 (vedi inizializzazione).
Lo scopo di tale inizializzazione e' proprio quella di creare una NULL
terminated string.


scrivere char test[5] = { 0 } a mio avviso non significa inizializzare un
array di char a 0,ma soltanto il primo elemento.
Con la tua strncpy dici di copiare l'area restituita da strtok(...) in test
per un massimo di 4 caratteri,e dato che "pippo0" sono piu' di 4 caratteri la
strncpy non mettera' il
carattere terminatore alla fine di test che non essendo inizializzato
"correttamente" potrebbe contenere qualunque cosa.
Ivan Molella

array di char a 0,ma soltanto il primo elemento.
Assolutamente no.
Assegnando al primo carattere 0, si fa in modo che tutti i restanti
caratteri siano inizializzati a 0. Vedi lo standard per maggiori
informazioni.

 le implementazioni devono adeguarsi. 
  La forma idiomatica
	char *string="This is a string";
assegna al puntatore /string/ il valore di una locazione di memoria
nella quale risiedono i caratteri della stringa "This is a string",
definita dallo standard come "costante di tipo stringa".  
  Purtroppo, lo stesso standard C89 non e` sufficientemente chiaro sul
significato del termine "costante" o, meglio, lo e` nella misura in cui
si associa questo termine al fatto che il contenuto degli apici doppi e`
un simbolo "letterale" (come un intero o un numero in virgola mobile) e,
quindi, non necessariamente che il contenuto dell'oggetto sia
memorizzato in una zona particolare della memoria (ad esempio, una zona
a sola lettura, come accade per gli oggetti di classe di memoria
/const/).
  Una certezza, invece, c'e`, ed e` il fatto che l'area di memoria che
contiene la stringa e` specificata /static/ e, come tale, mantiene il
suo "valore anche fra l'uscita e ed il successivo rientro da funzioni e
blocchi" [1]. 
  Ora, noi sappiamo che strtok() *modifica* il suo primo argomento ma
non possiamo sapere, data la sua dipendenza dall'implementazione, come
questa modifica avvenga. 
  Non credo che quello osservato sia un comportamento standard ma e`
abbastanza "comprensibile". La soluzione, ovviamente, e` utilizzare un
vettore di caratteri invece che un puntatore, ovvero non usare strtok()
[2]. ;)
	Alla prossima,
		Marco
[1] Kernighan, B. W., Ritchie, D. M., "Il linguaggio C. Seconda
edizione", A4.1, pag. 253.

 memoria /const/).
  D'altra parte, il seguente programma
<code>
	#include <string.h>
	char *string="This is a string";
	int main()
	{
        	strcpy(string,"Blah");
	        return 0;
	}
</code>
si compila tranquillamente *ma* va drammaticamente in /crash/ in
esecuzione. ;)
	Alla prossima,
		Marco

esecuzione. ;)
Sul mio sistema (C++ Builder 5.0 sotto WindowsNT) funziona
perfettamente.

/const/).
Tratto dall'ANSI C Rationale :
3.1.4  String literals
----------------------
String literals are specified to be unmodifiable.  This specification
allows implementations to share copies of strings with identical text,
to place string literals in read-only memory, and perform certain
optimizations.  However, string literals do not have the type array of
const char, in order to avoid the problems of pointer type checking,
particularly with library functions, since assigning a pointer to
const char to a plain pointer to char is not valid.  Those members of
the Committee who insisted that string literals should be modifiable
were content to have this practice designated a common extension.

 array di char a 0,ma soltanto il primo elemento.
In C++ significa proprio inizializzare tutto l'array, in C forse solo il
primo elemento.
EMG

 wrote:


No, anche in C il risultato è quello di inizializzare tutto l'array a 
zero, ma forse vale la pena spiegare: il punto è che quando il numero 
degli inizializzatori è minore del numero degli elementi del vettore,
quelli in eccesso tra questi ultimi sono inizializzati a zero.
Per cui inizializzare esplicitamente a zero solo il primo elemento ha 
come risultato quello di inizializzare a zero tutto il vettore.
Ciao ciao,
Andrea
-- 
"...Unix, MS-DOS, and Windows NT (also known as the Good, the Bad, and 
 the Ugly)."
(by Matt Welsh)