
bsteo
Tengo el siguiente código:
#include <stdio.h>
#include <string.h>
int main (void) {
char str[] = "John|Doe|Melbourne|6270|AU";
char fname[32], lname[32], city[32], zip[32], country[32];
char *oldstr = str;
strcpy(fname, strtok(str, "|"));
strcpy(lname, strtok(NULL, "|"));
strcpy(city, strtok(NULL, "|"));
strcpy(zip, strtok(NULL, "|"));
strcpy(country, strtok(NULL, "|"));
printf("Firstname: %s\n", fname);
printf("Lastname: %s\n", lname);
printf("City: %s\n", city);
printf("Zip: %s\n", zip);
printf("Country: %s\n", country);
printf("STR: %s\n", str);
printf("OLDSTR: %s\n", oldstr);
return 0;
}
Salida de ejecución:
$ ./str
Firstname: John
Lastname: Doe
City: Melbourne
Zip: 6270
Country: AU
STR: John
OLDSTR: John
¿Por qué no puedo mantener los datos antiguos ni en el str
o oldstr
¿qué estoy haciendo mal y cómo no puedo alterar los datos o conservarlos?

grijesh chauhan
Cuando tu lo hagas strtok(NULL, "|")
strtok()
encontrar token y poner null
en lugar (reemplazar token con \0
) y modifique la cadena.
usted str
se convierte en:
char str[] = John0Doe0Melbourne062700AU;
Str array in memory
+------------------------------------------------------------------------------------------------+
|'J'|'o'|'h'|'n'|0|'D'|'o'|'e'|0|'M'|'e'|'l'|'b'|'o'|'u'|'r'|'n'|'e'|0|'6'|'2'|'7'|'0'|0|'A'|'U'|0|
+------------------------------------------------------------------------------------------------+
^ replace | with \0 (ASCII value is 0)
Considere que el diagrama es importante porque char '0'
y 0
son tímidos (en la cadena 6270 son char en la figura entre paréntesis por '
para donde \0
0 es como número)
cuando imprimes str usando %s
imprime caracteres hasta el primero \0
es decir John
Para mantener su str original sin cambios, debe copiar primero str en alguna variable tempstr y luego usar eso tempstr
cadena en strtok()
:
char str[] = "John|Doe|Melbourne|6270|AU";
char* tempstr = calloc(strlen(str)+1, sizeof(char));
strcpy(tempstr, str);
Ahora usa esto tempstr
cadena en lugar de str en su código.

Pantera Rosa
Porque oldstr
es solo un puntero, una asignación no hará una nueva copia de su cadena.
Cópielo antes de pasar str al strtok
:
char *oldstr=malloc(sizeof(str));
strcpy(oldstr,str);
Su versión corregida:
#include <stdio.h>
#include <string.h>
#include<malloc.h>
int main (void) {
char str[] = "John|Doe|Melbourne|6270|AU";
char fname[32], lname[32], city[32], zip[32], country[32];
char *oldstr = malloc(sizeof(str));
strcpy(oldstr,str);
...................
free(oldstr);
return 0;
}
EDITAR:
Como mencionó @CodeClown, en su caso, es mejor usar strncpy
. Y en lugar de fijar los tamaños de fname
etc. de antemano, puede tener punteros en su lugar y asignar la memoria según sea necesario, ni más ni menos. De esa manera, puede evitar escribir en el búfer fuera de los límites …
Otra Idea: sería asignar el resultado de strtok
a punteros *fname
, *lname
, etc. en lugar de arreglos. parece que strtok
está diseñado para usarse de esa manera después de ver la respuesta aceptada.
Precaución: De esta manera, si cambia str
además, eso se reflejaría en fname
,lname
además. Porque solo apuntan a str
datos pero no a nuevos bloques de memoria. Entonces, usa oldstr
para otras manipulaciones.
#include <stdio.h>
#include <string.h>
#include<malloc.h>
int main (void) {
char str[] = "John|Doe|Melbourne|6270|AU";
char *fname, *lname, *city, *zip, *country;
char *oldstr = malloc(sizeof(str));
strcpy(oldstr,str);
fname=strtok(str,"|");
lname=strtok(NULL,"|");
city=strtok(NULL, "|");
zip=strtok(NULL, "|");
country=strtok(NULL, "|");
printf("Firstname: %s\n", fname);
printf("Lastname: %s\n", lname);
printf("City: %s\n", city);
printf("Zip: %s\n", zip);
printf("Country: %s\n", country);
printf("STR: %s\n", str);
printf("OLDSTR: %s\n", oldstr);
free(oldstr);
return 0;
}
strtok
requiere una cadena de entrada grabable y modifica la cadena de entrada. Si desea conservar la cadena de entrada, primero debe hacer una copia.
Por ejemplo:
char str[] = "John|Doe|Melbourne|6270|AU";
char oldstr[32];
strcpy(oldstr, str); // Use strncpy if you don't know
// the size of str

aggsol
Simplemente copie el puntero a la cadena, pero no la cadena en sí. Usar strncpy()
para crear una copia.
char *oldstr = str; // just copy of the address not the string itself!
xtmtrx aquí en mi respuesta escribí un código que muestra cómo
strtok()
funciona (modifica la cadena en el mismo espacio de direcciones), creo que deberías echarle un vistazo:–Grijesh Chauhan
14 de junio de 2013 a las 9:39
Espero que uno lea el código fuente de la función strtok() o lea la documentación de la función antes de hacer esa pregunta.
– PP.
14 de junio de 2013 a las 9:46
Así que aquí está el código fuente de strkok()
–Grijesh Chauhan
14 de junio de 2013 a las 9:48