Discussion:
Ayuda con punteros
(demasiado antiguo para responder)
AnimAlf
2006-08-23 04:18:27 UTC
Permalink
Hola,

No me aclaro y no se por qué pasan estas cosas, me podeis ayudar a
terminar esta función correctamente.

Quiero que me quite los espacios en blanco del principio y del final de
una cadena.

Tal y como está ahora, funciona y hace lo que yo quiero:
DEBUG: Antes: [ cadena ]
DEBUG: return: [cadena]
DEBUG: Despues: [cadena]

pero si lo pruebo con las otras opciones (otra cadena) ... no se por
donde cogerlo. Parece que siempre se tiene que reducir el sizeoff al
retornar, pero no lo entiendo (no lo se):
DEBUG: Antes: [#______cadena______#]
DEBUG: return: [#______cadena______#]
DEBUG: Despues: [#______c]

¿Cómo puedo solucionarlo?

#include <stdio.h>
#include <string.h>

void strtrim (char **flujo){
int caracteres, espacios;
char tmpStr[255];
strcpy (tmpStr, *flujo);
while (tmpStr [0] == ' '){
strcpy (tmpStr, &tmpStr [1]);
}
do {
caracteres = strlen (tmpStr);
if (tmpStr[caracteres-1]==' ') {
espacios=1;
tmpStr [caracteres-1] = '\0';
} else { espacios = 0;}
} while (espacios);
*flujo = tmpStr;
printf ("DEBUG: return:\t[%s]\n",*flujo);
}

int main () {
char * cadena = " cadena ";
/* char * cadena = "#______cadena______#"; */
/* char * cadena = " cad "; */
/* char * cadena = "# cadena "; */
/* char * cadena = " cadena #"; */
printf ("DEBUG: Antes:\t[%s]\n",cadena);
strtrim(&cadena);
printf ("DEBUG: Despues:\t[%s]\n",cadena);
}
-------
Gracias
Bartomeu
2006-08-23 06:38:40 UTC
Permalink
El fallo principal lo tienes en el return de strtrim: Devuelves un puntero a
una cosa que, en cuanto sales de la función, ya no existe. Para solucionarlo
puedes definir tmpStr como static, definirlo como variable externa, o mejor
copiar el resultado con strncpy a flujo.
Te recomiendo la tercera. Las dos primeras soluciones son peores ya que
entonces no podrias llamar a la función dos veces seguidas en la misma
instrucción.

Otro error, que ahora no tienes, pero que tendrías con cadenas largas es en
el primer strcpy, No compruebas si flujo cabe en tmpStr. Podrías pasar un
flujo demasiado largo y provocar un desbordamiento de la pila. Es uno de los
principales causantes de los fallos de seguridad.

Finalmente dos consejos de diseño:
1º ahorrate el primer strcpy y copia los carácteres uno a uno con un
while, y aprovecha para saltarte los blancos de delante.
2º olvidate del primer consejo y en vez de utilizar un buffer interno,
ya que tienes que machacar la cadena original, utilizala como buffer,
recorrela primero quitando los blancos de atrás. Despues si el primer
caracter no es blanco ya has acabado. si es blanco buscas el primer caracter
no blanco y haces un sólo strcpy hacia delante. Te ahorras todo el problema
de comprobación de tamaños y desbordamientos de pila y la función será mucho
más rápida y eficiente. Ahora mismo estás copiando la cadena tropecientas
veces hacia delante carácter a caracter incluso los espacios de atras, para
después borrarlos.

Suerte.


"AnimAlf" <***@engendro.sytes.net> escribi� en el mensaje news:***@general.engendro.sytes.net...

#include <stdio.h>
#include <string.h>

void strtrim (char **flujo){
int caracteres, espacios;
char tmpStr[255];
strcpy (tmpStr, *flujo);
while (tmpStr [0] == ' '){
strcpy (tmpStr, &tmpStr [1]);
}
do {
caracteres = strlen (tmpStr);
if (tmpStr[caracteres-1]==' ') {
espacios=1;
tmpStr [caracteres-1] = '\0';
} else { espacios = 0;}
} while (espacios);
*flujo = tmpStr;
printf ("DEBUG: return:\t[%s]\n",*flujo);
}

int main () {
char * cadena = " cadena ";
/* char * cadena = "#______cadena______#"; */
/* char * cadena = " cad "; */
/* char * cadena = "# cadena "; */
/* char * cadena = " cadena #"; */
printf ("DEBUG: Antes:\t[%s]\n",cadena);
strtrim(&cadena);
printf ("DEBUG: Despues:\t[%s]\n",cadena);
}
Julián Albo
2006-08-23 10:21:28 UTC
Permalink
Post by AnimAlf
Quiero que me quite los espacios en blanco del principio y del final de
una cadena.
Además de lo que te dicen en otro mensaje, yo te recomendaría la técnica
"divide y vencerás". Escribe y prueba por separado una función para quitar
los espacios del principio y otra para los del final.
--
Salu2
heltena
2006-08-23 22:23:31 UTC
Permalink
Hola,
No me aclaro y no se por qué pasan estas cosas, me podeis ayudar a
terminar esta función correctamente.
Quiero que me quite los espacios en blanco del principio y del final de
una cadena.
DEBUG: Antes: [ cadena ]
DEBUG: return: [cadena]
DEBUG: Despues: [cadena]
pero si lo pruebo con las otras opciones (otra cadena) ... no se por
donde cogerlo. Parece que siempre se tiene que reducir el sizeoff al
DEBUG: Antes: [#______cadena______#]
DEBUG: return: [#______cadena______#]
DEBUG: Despues: [#______c]
¿Cómo puedo solucionarlo?
#include <stdio.h>
#include <string.h>
void strtrim (char **flujo){
int caracteres, espacios;
char tmpStr[255];
strcpy (tmpStr, *flujo);
while (tmpStr [0] == ' '){
strcpy (tmpStr, &tmpStr [1]);
}
do {
caracteres = strlen (tmpStr);
if (tmpStr[caracteres-1]==' ') {
espacios=1;
tmpStr [caracteres-1] = '\0';
} else { espacios = 0;}
} while (espacios);
*flujo = tmpStr;
printf ("DEBUG: return:\t[%s]\n",*flujo);
}
int main () {
char * cadena = " cadena ";
/* char * cadena = "#______cadena______#"; */
/* char * cadena = " cad "; */
/* char * cadena = "# cadena "; */
/* char * cadena = " cadena #"; */
printf ("DEBUG: Antes:\t[%s]\n",cadena);
strtrim(&cadena);
printf ("DEBUG: Despues:\t[%s]\n",cadena);
}
Te recomiendo que le pases dos parametros a la funcion, la string de
entrada y la de salida, como el strcpy y esas cosas. Por ejemplo:

int main()
{
char cadena[] = " cadena ";
char resultado[40];

strtrim(resultado, cadena);
printf("Antes:\t[%s]\n", cadena);
printf("Despues:\t[%s]\n", resultado);
return 0;
}

Y para evitar un buffer overflow, qué mejor que pasarle a la función
el tamaño del buffer de salida (ejemplos tienes, como por ejemplo:
strncpy). Así:

int main()
{
char cadena[] = " cadena ";
char resultado[40];

strntrim(resultado, sizeof(resultado), cadena);
printf("Antes:\t[%s]\n", cadena);
printf("Despues:\t[%s]\n", resultado);
return 0;
}

La función te quedará mucho más sencilla, te la escribo:

char* strtrim(char* out, char* in)
{
busco el primer caracter de "in" que no sea un espacio.
cuando lo encuentre voy guardandome la posición del último caracter
que no es espacio.
ahora copio los caracteres que me he encontrado (me he guardado los
indices) en "out".
retorno out por si alguien quiere usarlo como función (igual que
hace strcpy, por ejemplo).
}

La función "strntrim" te puedes imaginar que al hacer el strcpy se
usará strncpy.

Suerte!
heltena
2006-08-23 22:29:05 UTC
Permalink
Se me olvidaba, no deberías modificar valores de "cadena" porque el
contenido es constante (o debería serlo).

Osea, evita cosas como esta:

int main()
{
char cadena[] = "hola";
cadena[2] = "O";
return 0;
}

Una cosa es que modifiques el puntero (osea, cadena), otra donde apunta.
AnimAlf
2006-08-30 14:53:34 UTC
Permalink
Estoi mirando en google y veo que no se publicó ninguna de mis
respuestas. :((

Las reenvio. Y grácias a todos por la ayuda :))

El dc 23 de 08 del 2006 a les 12:21 +0200, en/na Julián Albo va
Post by Julián Albo
Post by AnimAlf
Quiero que me quite los espacios en blanco del principio y del final de
una cadena.
Además de lo que te dicen en otro mensaje, yo te recomendaría la técnica
"divide y vencerás". Escribe y prueba por separado una función para quitar
los espacios del principio y otra para los del final.
Sí, aquí me han mostrado un modo efectivo de hacerlo como comentas.

http://groups.google.es/group/es.comp.os.linux.programacion/tree/browse_frm/thread/b5fe46047b709e60/a1e6c03413f37828?rnum=1&hl=ca&_done=%2Fgroup%2Fes.comp.os.linux.programacion%2Fbrowse_frm%2Fthread%2Fb5fe46047b709e60%3Fhl%3Dca%26#doc_0161cbde71325e6a

hasta luego :))
Post by Julián Albo
Te recomiendo la tercera. Las dos primeras soluciones son peores ya que
entonces no podrias llamar a la funcin dos veces seguidas en la misma
instruccin.
Sí, pero siempre que intento utilizar la función con un destino que
sea
puntero a caracteres y no array de caracteres ... violación de
segmento.
Poco a poco creo entenderlo.
Post by Julián Albo
Otro error, que ahora no tienes, pero que tendras con cadenas largas es en
el primer strcpy, No compruebas si flujo cabe en tmpStr. Podras pasar un
flujo demasiado largo y provocar un desbordamiento de la pila. Es uno de los
principales causantes de los fallos de seguridad.
je, je, je. En el man, ante esto son un poco más frios :))

man strcpy
...
Si la cadena destino de un strcpy() no es bastante grande (esto es, si
el programador fue estúpido o perezoso, y no comprobó el tamaño
antes de
la copia) entonces puede ocurrir cualquier cosa. Provocar el
desbordamiento de cadenas de caracteres de longitud fija es una
técnica
favorita de los piratas informáticos.
...
Post by Julián Albo
1 ahorrate el primer strcpy y copia los carcteres uno a uno con un
while, y aprovecha para saltarte los blancos de delante.
while (*flujo [0] == ' '){
(*flujo)++;
}
Post by Julián Albo
2 olvidate del primer consejo y en vez de utilizar un buffer interno,
ya que tienes que machacar la cadena original, utilizala como buffer,
recorrela primero quitando los blancos de atrs. Despues si el primer
caracter no es blanco ya has acabado. si es blanco buscas el primer caracter
no blanco y haces un slo strcpy hacia delante. Te ahorras todo el problema
de comprobacin de tamaños y desbordamientos de pila y la funcin ser mucho
ms rpida y eficiente. Ahora mismo ests copiando la cadena tropecientas
veces hacia delante carcter a caracter incluso los espacios de atras, para
despus borrarlos.
sí, tiene que quedar muy guapa y rápida. Grácias.
Llevo un rato peleandome, y no se como eliminar las asignaciones
finales, si se trata de un puntero a caracteres. Me voy a aplicar con
ello.

Hasta luego

Loading...