Discussion:
Cómo reducir el tamaño de un string.
(demasiado antiguo para responder)
Dani
2003-12-09 22:20:07 UTC
Permalink
Muy buenas,

A ver si algún alma caritativa me echa un cable con este problema que
para muchos debe de ser trivial:

Tengo un string de 30 caracteres de los cuales sólo 15 son caracteres
alfanuméricos, el resto son espacios en blanco. Quiero copiarlo a otro
string suprimiendo dichos espacios, para quedarme sólo con los
caracteres alfanuméricos.

Ésto es el resultado de mis intentos fallidos:

char *cadenaOrigen, *cadenaDestino;
int i=0;

do {
sprintf(cadenaDestino,"%c", *(cadenaOrigen+i));
++i;
}
while (*(p+i) != 32);


Obtengo como resultado cadenaDestino=^V.
No puedo utilizar snprintf() ya que no sé de antemano cuantos caracteres
distintos del espacio en blanco me voy a encontrar en cadenaOrigen.


Gracias por adelantado.

Saludos. Dani.
Fernando Arbeiza
2003-12-10 00:03:39 UTC
Permalink
Hola:

¿Podrías publicar un ejemplo compilable de lo que haces? Así podremos
hacernos una mejor idea de lo que estás haciendo. Con lo que das, te
Post by Dani
char *cadenaOrigen, *cadenaDestino;
int i=0;
do {
sprintf(cadenaDestino,"%c", *(cadenaOrigen+i));
Copiar un carácter de una cadena a otra es mucho más sencillo que eso:

cadenaDestino[j] = cadenaOrigen[i];
Post by Dani
++i;
}
while (*(p+i) != 32);
¿32? ¿Qué es 32? Intenta no utilizar números mágicos. Si lo que quieres
es encontrar un espacio (supongo que será ese 32) utiliza el literal
' '.

Cómo no sé qué es p, no puedo comentarte más. De todas formas,
suponiendo que p == cadenaOrigen, y antes de que publiques el código, te
comento posibles problemas:

- Escribes siempre en el mismo carácter de cadenaDestino, luego sólo
copiarías el último carácter de cadenaOrigen.

- cadenaDestino no es una cadena. No termina con '\0'

- Si cadenaOrigen no contiene ningún espacio, te saldrías de sus
límites, invocando comportamiento indefinido.

- Sólo estás copiando caracteres hasta el primer carácter 32 de
cadenaOrigen.

Un saludo.
--
Fernando Arbeiza <URL: mailto:***@ono.com>
Crea tu propio Linux: <URL: http://www.escomposlinux.org/lfs-es>
Helio.es
2003-12-10 00:10:51 UTC
Permalink
Estoy dormido, pero sería algo como:

#include <stdio.h>

int quitaespacios(char *cadenaOrigen, char *cadenaDestino) {
if (cadenaOrigen == NULL || cadenaDestino == NULL)
return -1;

while (*cadenaOrigen) {
if (*cadenaOrigen != ' ')
*cadenaDestino++ = *cadenaOrigen;
cadenaOrigen++;
}
*cadenaDestino=0;
return 0;
}

int(main) {
char origen[] = "hola que tal";
char destino[50];

quitaespacios(origen, destino);
printf("[%s] => [%s]\n", cadenaOrigen, cadenaDestino);
return EXIT_SUCCESS;
}

"Dani" <***@jazzfree.com> escribi� en el mensaje news:***@127.0.0.1...
| Muy buenas,
|
| A ver si algún alma caritativa me echa un cable con este problema
que
| para muchos debe de ser trivial:
|
| Tengo un string de 30 caracteres de los cuales sólo 15 son
caracteres
| alfanuméricos, el resto son espacios en blanco. Quiero copiarlo a
otro
| string suprimiendo dichos espacios, para quedarme sólo con los
| caracteres alfanuméricos.
|
| Ésto es el resultado de mis intentos fallidos:
|
| char *cadenaOrigen, *cadenaDestino;
| int i=0;
|
| do {
| sprintf(cadenaDestino,"%c", *(cadenaOrigen+i));
| ++i;
| }
| while (*(p+i) != 32);
|
|
| Obtengo como resultado cadenaDestino=^V.
| No puedo utilizar snprintf() ya que no sé de antemano cuantos
caracteres
| distintos del espacio en blanco me voy a encontrar en cadenaOrigen.
|
|
| Gracias por adelantado.
|
| Saludos. Dani.
Helio.es
2003-12-10 00:18:25 UTC
Permalink
Si ya digo que estoy dormido .....

"Helio.es" <***@hotmail.com> escribió en el
mensaje news:br5of5$294mpd$***@ID-165255.news.uni-berlin.de...
...
| quitaespacios(origen, destino);
| printf("[%s] => [%s]\n", cadenaOrigen, cadenaDestino);

printf("[%s] => [%s]\n", origen, destino);

| return EXIT_SUCCESS;
.....

Hasta luego!
Fernando Arbeiza
2003-12-10 10:18:40 UTC
Permalink
Sólo dos cositas para que funcione:

On Wed, 10 Dec 2003 01:10:51 +0100, Helio.es
Post by Helio.es
#include <stdio.h>
int quitaespacios(char *cadenaOrigen, char *cadenaDestino) {
if (cadenaOrigen == NULL || cadenaDestino == NULL)
return -1;
while (*cadenaOrigen) {
if (*cadenaOrigen != ' ')
*cadenaDestino++ = *cadenaOrigen;
cadenaOrigen++;
}
*cadenaDestino=0;
return 0;
}
int(main) {
^^^^^^^^^^
Ya te digo que estabas dormido ;-) No creo que haga falta que lo diga:

int main(void) {
Post by Helio.es
char origen[] = "hola que tal";
char destino[50];
quitaespacios(origen, destino);
printf("[%s] => [%s]\n", cadenaOrigen, cadenaDestino);
return EXIT_SUCCESS;
Falta incluir al principio stdlib.h que es done está definido
EXIT_SUCCESS.
Post by Helio.es
}
Un saludo.
--
Fernando Arbeiza <URL: mailto:***@ono.com>
Crea tu propio Linux: <URL: http://www.escomposlinux.org/lfs-es>
Martin J. Sanchez
2003-12-10 10:18:07 UTC
Permalink
Dani escribió en mensaje ...
Post by Dani
Muy buenas,
A ver si algún alma caritativa me echa un cable con este problema que
Tengo un string de 30 caracteres de los cuales sólo 15 son caracteres
alfanuméricos, el resto son espacios en blanco. Quiero copiarlo a otro
string suprimiendo dichos espacios, para quedarme sólo con los
caracteres alfanuméricos.
....
podrias hacer algo como:

char* cpySinEspacios( char* dest, size_t size_dest, const char* orig)
{
int i;

for( i=0; *orig && i<size_dest-1; orig++ ) {
if( *orig != ' ' )
dest[i++]= *orig;
}
orig[i]='\0';

return dest;
}

Un saludo,
Martin.
Martin J. Sanchez
2003-12-12 04:51:00 UTC
Permalink
Martin J. Sanchez escribió en mensaje ...
Post by Martin J. Sanchez
...
char* cpySinEspacios( char* dest, size_t size_dest, const char* orig)
{
int i;
for( i=0; *orig && i<size_dest-1; orig++ ) {
if( *orig != ' ' )
dest[i++]= *orig;
}
orig[i]='\0';
^^^^^^^^^^^^^

Esta linea deberia ser:
dest[i])='\0';
Post by Martin J. Sanchez
return dest;
}
De todas formas aparte de corregir el error que he señalado, la funcion
deberia controlar que size_dest no es 0 (antes del for):
if( size_dest == 0)
return 0; // devolver 'dest' es mas apropiado?

Un saludo,
Martin.
Loco
2003-12-10 15:17:17 UTC
Permalink
mira a ver si esto te sirve como apaño...

void main(){
char cad1[30]={"123456789abcdef"};
//con esto la relleno como tu la tienes, no? (15 alfanuméricos)
char cad2[30];
//sin inicializar ni nada
int i;
for(i=0;i<=30;i++){
if(cad1[i]!=" "){ //solo entra cuando no es espacio
strcat(cad2,cad1[i]); //añade desde cad1 a cad 2
}
}
}
Ojo, falta por incluir de alguna manera (que no me he querido poner a
pensar) incluir el \0 de final de cadena

Loco.
Post by Dani
Muy buenas,
A ver si algún alma caritativa me echa un cable con este problema que
Tengo un string de 30 caracteres de los cuales sólo 15 son caracteres
alfanuméricos, el resto son espacios en blanco. Quiero copiarlo a otro
string suprimiendo dichos espacios, para quedarme sólo con los
caracteres alfanuméricos.
char *cadenaOrigen, *cadenaDestino;
int i=0;
do {
sprintf(cadenaDestino,"%c", *(cadenaOrigen+i));
++i;
}
while (*(p+i) != 32);
Obtengo como resultado cadenaDestino=^V.
No puedo utilizar snprintf() ya que no sé de antemano cuantos caracteres
distintos del espacio en blanco me voy a encontrar en cadenaOrigen.
Gracias por adelantado.
Saludos. Dani.
Fernando Arbeiza
2003-12-10 15:48:58 UTC
Permalink
Post by Loco
void main(){
int main(void) {
Post by Loco
char cad1[30]={"123456789abcdef"};
//con esto la relleno como tu la tienes, no? (15 alfanuméricos)
char cad2[30];
//sin inicializar ni nada
int i;
for(i=0;i<=30;i++){
if(cad1[i]!=" "){ //solo entra cuando no es espacio
cad1[i] es un carácter y " " una cadena. Sólo hay que cambiar las
comillas: ' ' para que sea el espacio.
Post by Loco
strcat(cad2,cad1[i]); //añade desde cad1 a cad 2
Strcat espera dos punteros a carácter, pero estás pasando un puntero y
un carácter; como mucho sería cad1 + i, pero así no conseguiríamos el
objetivo.

Por cierto, para usar strcat, hay que añadir:

#include <string.h>

en el inicio.

Supongo que tu intención era hacer algo así:

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

int main(void) {
char cad1[30]={"1 23 456 789abc d ef"};
char cad2[30] = {'\0'};
size_t i;

for(i = 0;i <= strlen(cad1); i++){
if(cad1[i] != ' '){
cad2[strlen(cad2)] = cad1[i];
}
}

return 0;
}
/*****************************/

Pero Helio y Martin ya han sugerido otras formas más adecuadas de
conseguirlo.

Un saludo.
--
Fernando Arbeiza <URL: mailto:***@ono.com>
Crea tu propio Linux: <URL: http://www.escomposlinux.org/lfs-es>
ViKT0RY
2003-12-10 22:47:53 UTC
Permalink
Otra alternativa (para gustos hay colores, aquí va una de punteros a saco):

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

void limpia(char *cadena) {
char *p, *p2;
p=cadena;
p2=p;
p2++;
do { /* Recorro la cadena de izquierda a derecha */
while(*p!=' ' && *p != 0) { p++; } /* p busca el primer espacio */
while(*p2==' ' && *p2 != 0) { p2++; } /* p2 busca la primera letra que no
es un espacio*/
if(*p!=0) {
*p=*p2;
*p2=' '; /* esto evita que se repita la letra */
}
} while(*p!=0);
}

int main(void) {
char buffer[255];
printf("Escribe una cadena, yo quitare los espacios:\n");
scanf("%[^\n]", buffer);
fflush(stdin);
limpia(buffer);
printf("Resultado:\n%s", buffer);
return 0;
}
Fernando Arbeiza
2003-12-11 07:03:30 UTC
Permalink
Post by ViKT0RY
scanf("%[^\n]", buffer);
Cuidado con esto, es tan peligroso como un gets. Como mucho podrías
hacer esto:

scanf("%254[^\n]", buffer);

Pero lo mejor sería utilizar fgets.
Post by ViKT0RY
fflush(stdin);
Esto tiene un comportamiento indefinido. fflush sólo está definido para
flujos de salida.

El programa tiene un problema, no funciona si la cadena introducida no
empieza con un espacio. Quizá algo así:

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

void limpia(char *cadena) {
char *p;

while(*cadena != ' ' && *cadena != '\0') { cadena++; }
p=cadena;
p++;

do {
while(*p == ' ' && *p != '\0') { p++; }
while(*p != ' ' && *p != '\0') {
*cadena = *p;
cadena++;
p++;
}
} while(*p != '\0');

*cadena = '\0';
}

#define BUFFER_LENGTH 255

int main(void) {
char buffer[BUFFER_LENGTH];
printf("Escribe una cadena, yo quitare los espacios:\n");
fgets(buffer, BUFFER_LENGTH, stdin);
limpia(buffer);
printf("Resultado:\n%s", buffer);
return 0;
}
/*****************************/

Un saludo.
--
Fernando Arbeiza <URL: mailto:***@ono.com>
Crea tu propio Linux: <URL: http://www.escomposlinux.org/lfs-es>
ViKT0RY
2003-12-11 10:38:30 UTC
Permalink
Post by Fernando Arbeiza
Post by ViKT0RY
scanf("%[^\n]", buffer);
Cuidado con esto, es tan peligroso como un gets. Como mucho podrías
scanf("%254[^\n]", buffer);
Pero lo mejor sería utilizar fgets.
Buffer overflow, lo se.
Post by Fernando Arbeiza
Post by ViKT0RY
fflush(stdin);
Esto tiene un comportamiento indefinido. fflush sólo está definido para
flujos de salida.
Eso tiene un comportamiento controlado, limpia el buffer del teclado.
Post by Fernando Arbeiza
El programa tiene un problema, no funciona si la cadena introducida no
Yo lo he probado de diferentes maneras y sigue funcionando bien. El poner
'\0' o 0 es lo mismo. Y el '\0' final ya es copiado al ultimo espacio que
haya, si no lo hay, recuerda que al hacer un movimiento cambio el caracter
movido en la cadena original por un espacio.

Microsoft Windows XP [Versión 5.1.2600]
(C) Copyright 1985-2001 Microsoft Corp.

C:\MisProyectos\C\limpiaespacios>limpia
Escribe una cadena, yo quitare los espacios:
abcd
Resultado:
abcd
C:\MisProyectos\C\limpiaespacios>limpia
Escribe una cadena, yo quitare los espacios:
a bcd efg a b f
Resultado:
abcdefgabf
C:\MisProyectos\C\limpiaespacios>limpia
Escribe una cadena, yo quitare los espacios:
a b c d
Resultado:
abcd
C:\MisProyectos\C\limpiaespacios>
Post by Fernando Arbeiza
/*****************************/
#include <stdio.h>
#include <string.h>
void limpia(char *cadena) {
char *p;
while(*cadena != ' ' && *cadena != '\0') { cadena++; }
p=cadena;
p++;
do {
while(*p == ' ' && *p != '\0') { p++; }
while(*p != ' ' && *p != '\0') {
*cadena = *p;
cadena++;
p++;
}
} while(*p != '\0');
*cadena = '\0';
}
#define BUFFER_LENGTH 255
int main(void) {
char buffer[BUFFER_LENGTH];
printf("Escribe una cadena, yo quitare los espacios:\n");
fgets(buffer, BUFFER_LENGTH, stdin);
limpia(buffer);
printf("Resultado:\n%s", buffer);
return 0;
}
/*****************************/
Un saludo.
--
Crea tu propio Linux: <URL: http://www.escomposlinux.org/lfs-es>
Martin J. Sanchez
2003-12-11 11:31:15 UTC
Permalink
On Thu, 11 Dec 2003 11:38:30 +0100, "ViKT0RY"
Post by ViKT0RY
...
Post by Fernando Arbeiza
Post by ViKT0RY
fflush(stdin);
Esto tiene un comportamiento indefinido. fflush sólo está definido para
flujos de salida.
Eso tiene un comportamiento controlado, limpia el buffer del teclado.
No. Como te han dicho el comportamiento de fflush solo esta definidio
en streams de salida. Decho en muchos compiladores no hara nada y solo
en alguno limpia el buffer de entrada asociado a la stream, pero
ninguno (que yo conozca) limpia los buffers de entrada del SO.

Prueba lo siguiente en cualquier compilador a ver que obtienes:

int main()
{

char inputbuff[80];

printf("Intro cadena: ");
fgets( inputbuff, sizeof(inputbuff), stdin);
puts( inputbuff );

printf("pulsar algunos cars ...\n");
sleep(10); /* esperar 10 segundos */

fflush( stdin);
printf("Intro cadena2: ");
fgets( inputbuff, sizeof(inputbuff), stdin);
puts( inputbuff );

return 0;
}


Un saludo,
Martin.
Fernando Arbeiza
2003-12-11 11:42:40 UTC
Permalink
Post by ViKT0RY
Post by Fernando Arbeiza
Pero lo mejor sería utilizar fgets.
Buffer overflow, lo se.
¿Y lo sigues utilizando? ;-)
Post by ViKT0RY
Post by Fernando Arbeiza
Post by ViKT0RY
fflush(stdin);
Esto tiene un comportamiento indefinido. fflush sólo está definido para
flujos de salida.
Eso tiene un comportamiento controlado, limpia el buffer del teclado.
En tu sistema, en el mío no hace nada y en el de un amigo mío hace que
el sistema baile la macarena :-) Poco recomendable.
Post by ViKT0RY
Post by Fernando Arbeiza
El programa tiene un problema, no funciona si la cadena introducida no
Yo lo he probado de diferentes maneras y sigue funcionando bien. El poner
'\0' o 0 es lo mismo. Y el '\0' final ya es copiado al ultimo espacio que
haya, si no lo hay, recuerda que al hacer un movimiento cambio el caracter
movido en la cadena original por un espacio.
$ ./limpia
Escribe una cadena, yo quitare los espacios:
hola torpedo
Resultado:
h laotorpedo

Un saludo.
--
Fernando Arbeiza <URL: mailto:***@ono.com>
Crea tu propio Linux: <URL: http://www.escomposlinux.org/lfs-es>
Loco
2003-12-11 15:47:59 UTC
Permalink
Post by Fernando Arbeiza
Post by Loco
void main(){
int main(void) {
Post by Loco
char cad1[30]={"123456789abcdef"};
Rectifico
char cad1[30]={"1234567890abcde "};
//ahora SI tiene 15 espacios en blanco
Post by Fernando Arbeiza
Post by Loco
//con esto la relleno como tu la tienes, no? (15 alfanuméricos)
char cad2[30];
//sin inicializar ni nada
int i;
for(i=0;i<=30;i++){
if(cad1[i]!=" "){ //solo entra cuando no es espacio
cad1[i] es un carácter y " " una cadena. Sólo hay que cambiar las
comillas: ' ' para que sea el espacio.
yeah...
if(cad[i]!=' '){ //ahora si le preguntas por carácter
espacio
Post by Fernando Arbeiza
Post by Loco
strcat(cad2,cad1[i]); //añade desde cad1 a cad 2
Strcat espera dos punteros a carácter, pero estás pasando un puntero y
un carácter; como mucho sería cad1 + i, pero así no conseguiríamos el
objetivo.
A mi me explicaron que espera dos punteros a stream, de ahí el nombre que
empiece por str (=stream)
cómo funciona creo que es así: strcat(*destino,*origen);
si lo que le paso de origen es la dirección específica de un solo byte del
stream, lo que hará seá añadirlo al final de *destino (en este caso cad2)
Post by Fernando Arbeiza
#include <string.h>
Si, bueno, para quedar bien diré que lo obvié, pero no, se me olvidó, pero
por lo menos me lo sabía... :-)
Post by Fernando Arbeiza
en el inicio.
/*****************************/
#include <stdio.h>
#include <string.h>
int main(void) {
char cad1[30]={"1 23 456 789abc d ef"};
Dani (el chico que planteó el problema en cuestión) nos dijo que tenia 15
alfanuméricos y a continuación 15 en blanco, o sea, que si tenía un array de
[30], no le quedaba espacio para el carácter \0 (ó 0, como sea)
Post by Fernando Arbeiza
char cad2[30] = {'\0'};
size_t i;
for(i = 0;i <= strlen(cad1); i++){
if(cad1[i] != ' '){
cad2[strlen(cad2)] = cad1[i];
}
}
return 0;
}
/*****************************/
Pero Helio y Martin ya han sugerido otras formas más adecuadas de
conseguirlo.
Un saludo.
--
Crea tu propio Linux: <URL: http://www.escomposlinux.org/lfs-es>
Pero me gusta cómo has utilizado la asignación carácter a carácter. Yo me
lancé directamente a las funciones str.

Por cierto, lo que yo utilizo es el Borland C++ 5.1 o algo así.
Y una segunda cosa: fflush(stdin); lo que hace es limpiar el buffer de
entrada del teclado...

Loco.
Fernando Arbeiza
2003-12-11 16:21:48 UTC
Permalink
Post by Loco
Post by Fernando Arbeiza
Post by Loco
strcat(cad2,cad1[i]); //añade desde cad1 a cad 2
Strcat espera dos punteros a carácter, pero estás pasando un puntero
y un carácter; como mucho sería cad1 + i, pero así no conseguiríamos
el objetivo.
A mi me explicaron que espera dos punteros a stream, de ahí el nombre
que empiece por str (=stream)
Creo que equivocaste la pronunciación, str viene de string (cadena de
caracteres). Los parámetros son dos punteros a carácter.
Post by Loco
cómo funciona creo que es así: strcat(*destino,*origen);
si lo que le paso de origen es la dirección específica de un solo byte del
stream, lo que hará seá añadirlo al final de *destino (en este caso cad2)
No, date cuenta que strcat espera una cadena de caracteres, luego le
estás pasando la cadena que ocupa desde el lugar al que apunta origen
hasta el siguiente carácter '\0' (por la definición de string). Luego
añadirá a destino lo que haya desde el carácter al que apunta origen
hasta el final de la cadena.
Post by Loco
Dani (el chico que planteó el problema en cuestión) nos dijo que tenia 15
alfanuméricos y a continuación 15 en blanco, o sea, que si tenía un array de
[30], no le quedaba espacio para el carácter \0 (ó 0, como sea)
Dijo que tenía un array de 30 caracteres, de los cuales 15 eran
espacios. Como '\0' es un carácter, cuenta entre los treinta (pero no
vamos a discutir por eso ;-)
Post by Loco
Por cierto, lo que yo utilizo es el Borland C++ 5.1 o algo así.
Y una segunda cosa: fflush(stdin); lo que hace es limpiar el buffer de
entrada del teclado...
Veamos, fflush() de un flujo de entrada no está definido, luego que ese
comportamiento se cumple en tu sistema no quiere decir nada. Puede que
en mi sistema haga que mi teclado cambie de color, o que en el sistema
de Dani active la secuencia de autodestrucción. Así que, niños, no lo
hagáis en casa ;-)

En serio, como es un comportamiento no definido, mejor no invocarlo,
porque no se sabe cual será el resultado de la llamada.

Un saludo.
--
Fernando Arbeiza <URL: mailto:***@ono.com>
Crea tu propio Linux: <URL: http://www.escomposlinux.org/lfs-es>
Dani
2003-12-11 20:08:28 UTC
Permalink
Post by Dani
A ver si algún alma caritativa me echa un cable con este problema que
Tengo un string de 30 caracteres de los cuales sólo 15 son caracteres
alfanuméricos, el resto son espacios en blanco. Quiero copiarlo a
otro string suprimiendo dichos espacios, para quedarme sólo con los
caracteres alfanuméricos.
Muchas gracias a todos. Finalmente la solución de Martín, a falta de
estudiar las propuestas de "Helio" y "Loco", me ha aclarado el tema
perfectamente:


char* cpySinEspacios( char* dest, size_t size_dest, const char* orig)
{
int i;

for( i=0; *orig && i<size_dest-1; orig++ ) {
if( *orig != ' ' )
dest[i++]= *orig;
}
orig[i]='\0';

return dest;
}

Un saludo,
Martin.


Aunque con :

void* cpySinEspacios( char* dest, size_t size_dest, const char* orig)


sería suficiente, ¿no?. La función ya modifica dest al pasarlo como
argumento.



Para finalizar agradecerte, Fernando, tus observaciones. Me han aclarado
perfectamente algunos conceptos que tenía equivocados. En cuanto a "p"
en el código que publicaba en el mensaje original, efectivamente, se
trataba de "cadenaOrigen", un gazapo por mi parte.

Entendido también el consejo de no emplear números mágicos.
Y respecto a publicar el código, bueno, simplemente estoy empezando con
C, y de paso, para hacerlo más llevadero, empleando la librería ncurses.

El problema lo obtenía al utilizar formularios. Puedo definir los
campos como dinámicos, de tal modo que 'crezcan' hasta contener el
dato introducido. El tema es que inicialmente, debo definir el tamaño de
los campos (p.e. char[30]), con lo que si introduzco un dato de menor
tamaño la librería me lo rellena con espacios (hasta completar los 30
caracteres). Dado que dicho dato se inserta a través de una sentencia
SQL en una base de datos (Postgresql), me interesaba quitar esos
espacios en blanco.

Resumiendo, que el tema de los punteros me parece tela marinera. Ahora,
el siguiente paso será ver si acabo de comprender el concepto de
'puntero a función'.

Un saludo, y gracias de nuevo.
Dani.
Helio Tejedor
2003-12-11 20:44:42 UTC
Permalink
...
Post by Dani
El problema lo obtenía al utilizar formularios. Puedo definir los
campos como dinámicos, de tal modo que 'crezcan' hasta contener el
dato introducido. El tema es que inicialmente, debo definir el tamaño de
los campos (p.e. char[30]), con lo que si introduzco un dato de menor
tamaño la librería me lo rellena con espacios (hasta completar los 30
caracteres). Dado que dicho dato se inserta a través de una sentencia
SQL en una base de datos (Postgresql), me interesaba quitar esos
espacios en blanco.
Hombre, si es este el caso la funcion TRIM de SQL te puede ayudar
bastante. Por ejemplo:

Insert into tablita values( trim('hola ') );

Y en C:

sprintf(sql,
"insert into tablita "
"values (trim('%s'))", valor);

(bueno, ahora vendrán con el buffer overflow ;-))

Y no tendrías que montarte las historias de los punteros.

OJO! que trim solo te saca los espacios del principio y del final (que
creo que es lo que quieres).
Post by Dani
Un saludo, y gracias de nuevo.
Dani.
Hasta pronto!
Fernando Arbeiza
2003-12-11 23:31:57 UTC
Permalink
Post by Dani
void* cpySinEspacios( char* dest, size_t size_dest, const char* orig)
sería suficiente, ¿no?. La función ya modifica dest al pasarlo como
argumento.
Imagino que te referías a

void cpySinEspacios(char* dest, size_t size_dest, const char* orig)

y sin devolver ningún valor.

En este caso sí, puesto que no se hace ninguna comprobación ni se
devuelve ningún código de error. Puede haber dos razones para declararla
así (ojo, que voy a leer la mente del que escribió originalmente el
código):

- Por tradición; normalmente, las funciones de string.h devuelven un
puntero a la cadena destino.

- Por si acaso; quizá quieras devolver en algún momento NULL si se
produce un error.
Post by Dani
Y respecto a publicar el código, bueno, simplemente estoy empezando con
C, y de paso, para hacerlo más llevadero, empleando la librería ncurses.
El problema lo obtenía al utilizar formularios. Puedo definir los
campos como dinámicos, de tal modo que 'crezcan' hasta contener el
dato introducido. El tema es que inicialmente, debo definir el tamaño de
los campos (p.e. char[30]), con lo que si introduzco un dato de menor
tamaño la librería me lo rellena con espacios (hasta completar los 30
caracteres). Dado que dicho dato se inserta a través de una sentencia
SQL en una base de datos (Postgresql), me interesaba quitar esos
espacios en blanco.
Está bien que utilices ncurses y SQL si eso te hace que el aprendizaje
más llevadero; pero que no te distraigan, que el C ya es suficientemente
traicionero. Me refiero a que, quizá, te quedases mejor con los
conceptos si te concentras en el C y dejas las librerías y extensiones
para más adelante. Creo que centrándote más, podrías ir captando, por
ejemplo, el manejo de punteros.
Post by Dani
Resumiendo, que el tema de los punteros me parece tela marinera.
Ahora sí te lo parece. Pero te aseguro que un día te levantarás y, de
repente, lo verás todo mucho más claro. Y a partir de ahí, no habrá
puntero que se te resista ;-)
Post by Dani
Ahora, el siguiente paso será ver si acabo de comprender el concepto
de 'puntero a función'.
Es más fácil de lo que parece. Piensa que es una forma de meter en una
variable una función de forma que puedas aplicarla más tarde (por
ejemplo, para pasarla a una función.

Mira, por ejemplo, la función qsort. Bueno, no mires la declaración, que
puede liarte un poco; pero sería más o menos así:

void qsort(void *vector, size_t long_vector, size_t long_miembro,
funcion_t *compara);

Bien, la función qsort toma un vector que contiene long_vector
elementos, de long_miembro bytes cada uno; y los ordena.

Bien, pues además de eso, la función qsort toma como argumento el
puntero a función compara. En compara se pasa el nombre de una función
cuyo cometido será comparar los miembros, para que qsort pueda
ordenarlos.

Por ejemplo, podrías definir una función (no se define exactamente así,
pero para el ejemplo vale):

int compara_int(int *x, int *y) { return *x > *y; }

Y pasaselo a qsort:

qsort(vector, long_vector, long_miembro, compara_int);

Y entonces qsort utilizaría el argumento compara (que contendrá la
referencia a compara_int) para obtener la comparación entre elementos:

if (compara(vector + i, vector +j)) { /* ... */ }

Como el argumento compara ha almacenado la referencia a compara_int,
será como aplicar compara_int a los dos argumentos.

De esta forma, podrías ordenar en sentido contrario muy fácilmente, sólo
tendrías que definir la función compara_rev:

int compara_rev(int *x, int *y) { return *x < *y; }

Y pasárselo a qsort:

qsort(vector, long_vector, long_miembro, compara_rev);

Y ahora qsort ordenaría el vector en sentido inverso.

Bueno, creo que he acabado liándome yo sólo con tanto qsort y tanto
compara. Espero que te haya quedado un poco más claro.

Un saludo.
--
Fernando Arbeiza <URL: mailto:***@ono.com>
Crea tu propio Linux: <URL: http://www.escomposlinux.org/lfs-es>
Martin J. Sanchez
2003-12-13 05:27:28 UTC
Permalink
On Fri, 12 Dec 2003 00:31:57 +0100, Fernando Arbeiza
Post by Fernando Arbeiza
Post by Dani
void* cpySinEspacios( char* dest, size_t size_dest, const char* orig)
sería suficiente, ¿no?. La función ya modifica dest al pasarlo como
argumento.
Imagino que te referías a
void cpySinEspacios(char* dest, size_t size_dest, const char* orig)
y sin devolver ningún valor.
En este caso sí, puesto que no se hace ninguna comprobación ni se
devuelve ningún código de error. Puede haber dos razones para declararla
así (ojo, que voy a leer la mente del que escribió originalmente el
- Por tradición; normalmente, las funciones de string.h devuelven un
puntero a la cadena destino.
- Por si acaso; quizá quieras devolver en algún momento NULL si se
produce un error.
Pues si. Ambas raxones tuvieron peso al implmentarla. Me has leido la
mente ;-).

Un saludo,
Martin.

Martin J. Sanchez
2003-12-12 04:56:56 UTC
Permalink
Dani escribió en mensaje ...
Post by Dani
Muchas gracias a todos. Finalmente la solución de Martín, a falta de
estudiar las propuestas de "Helio" y "Loco", me ha aclarado el tema
char* cpySinEspacios( char* dest, size_t size_dest, const char* orig)
{
int i;
for( i=0; *orig && i<size_dest-1; orig++ ) {
if( *orig != ' ' )
dest[i++]= *orig;
}
orig[i]='\0';
^^^^^^^^^^^^

OJO, deberia ser:
dest[i]='\0';
Post by Dani
return dest;
}
void* cpySinEspacios( char* dest, size_t size_dest, const char* orig)
sería suficiente, ¿no?. La función ya modifica dest al pasarlo como
argumento.
Supongo que te refieres a declararla void. Yo opte por devolver 'dest'
por que permitiria cosas como:
printf("%s", cpySinEspacios( dest, size_dest, orig));
Post by Dani
...
El problema lo obtenía al utilizar formularios. Puedo definir los
campos como dinámicos, de tal modo que 'crezcan' hasta contener el
dato introducido. El tema es que inicialmente, debo definir el tamaño de
los campos (p.e. char[30]), con lo que si introduzco un dato de menor
tamaño la librería me lo rellena con espacios (hasta completar los 30
caracteres). Dado que dicho dato se inserta a través de una sentencia
SQL en una base de datos (Postgresql), me interesaba quitar esos
espacios en blanco.
Segun parece, deseas una funcion que elimine los espacios iniciales y
finales de la string, luego la funcion que te pasé no es apropiada por
que elimina tambien los espacios internos. Podrias hacer algo como:

char* trim( char *dest, size_t siz_dest, const char* orig)
{
int blancosFinales=0;
int i;

if( siz_dest==0 )
return 0;

/* saltar blancos iniciales */
for( ; *orig==' ' ; orig++);

/* copiar caracteres contando numero de blancos finales*/
for( i=0; *orig && i<siz_dest-1; i++, orig++ ) {
if( *orig == ' ' )
blancosFinales++;
else
blancosFinales=0;

dest[i]= *orig;
}
dest[i-blancosFinales]= '\0';
return dest;
}

Un saludo,
Martin.
David J.
2003-12-11 22:37:11 UTC
Permalink
Holas!

Ummm.....y no seria posible utilizar STRTOK ¿? para separar las partes q
llevan espacios y con STRCAT pegarla ??...No desarrollo el programa por
vagancia, aparte q hace tiempo no programo naaa y toy oxidao ;-).

Salu2.

DJ.
Loading...