Espacios en concatenación strcat.

Iniciado por programator11, 5 Agosto 2014, 13:17 PM

0 Miembros y 1 Visitante están viendo este tema.

programator11

Buenas que tal.

Mi problema es el siguiente, quiero hacer un programa que vaya concatenando las palabras que yo vaya introduciendo por teclado, el problema es que no se como hacer para que se concatenen con un espacio cada palabra (aaa bbb en lugar de aaabbb)

He probado a concatenar un espacio a cada palabra que se introduzc pero no obtengo resultado,aqui mi codigo;


..........
.........
void funcion()
   {
    char cad[100],pal[18];
    char seg;
    int cont=0;
do
    {
      if (cont==0)
      {
      printf ("\nIntroduzca la primera palabra\n\n");
      scanf ("%s",&pal);
        strcat (cad,pal);
      cont++;
      }
     
      else
      {
      printf ("\nIntroduzca la siguiente palabra de la frase:\n");
      scanf ("%s",&pal);
      strcat (cad,pal);
      }
        printf( "\nSi quieres seguir alargando la frase pulsa S, sino pulsa cualquier otra letra:\n" );
    fflush(stdin);
        scanf( "%c", &c);
   } while ( c == 's' );
    printf ("\n\nLa frase final es \n\n%s",cad);



Gracias de antemano  :)

eferion

#1
Que tal algo del tipo...


char buffer[ 100 ];
strcat( buffer, "palabra1" );
strcat( buffer, " " );
strcat( buffer, "palabra2" );


Por cierto, esta línea, por ejemplo:

scanf ("%s",&pal);

Está mal... pal es de por sí un puntero, si pasas la referencia en vez del puntero vas a escribir donde no debes.

Además:


char cad[ 100 ];
// ...
strcat( cad, pal );


¿Dónde has inicializado "cad"?? strcat concatena a partir del final de cadena, es decir, de que encuentra el carácter nulo... si la cadena no está inicializada vas a tener basura y la función va a concatenar donde le de la gana... y seguro que no coincide con el sitio donde tú quieres que escriba.

leosansan

#2
Cita de: programator11 en  5 Agosto 2014, 13:17 PM
Buenas que tal.

Mi problema es el siguiente, quiero hacer un programa que vaya concatenando las palabras que yo vaya introduciendo por teclado, el problema es que no se como hacer para que se concatenen con un espacio cada palabra (aaa bbb en lugar de aaabbb)


Además de la solución que te dio eferion te propongo otra alternativa.

Para empezar sacaría el primer scanf del do-while, ya que la primera palabra y la segunda son escaneadas impepinablemente siendo ya optativas las siguientes. Con eso ahorras la variable cont y te evitas el if-else del do-while.

Y para concatenar las palabras usaría la función sprintf con lo que en con sólo una función concateno las palabras:

Código (cpp) [Seleccionar]
/***************************************************/

 char c , cad[100] = "" , pal[18] ;

 printf ( "\nIntroduzca la primera palabra\n\n" ) ;
 scanf ( "%s"  ,pal ) ;
 sprintf ( cad , "%s%s" , cad  , pal ) ;

 do {
   printf ( "\nIntroduzca la siguiente palabra de la frase:\n" ) ;
   scanf ( "%s" , pal) ;
   sprintf ( cad , "%s%c%s" , cad , ' ' , pal ) ;
   printf( "\nSi quieres seguir alargando la frase pulsa S, sino pulsa cualquier otra letra:\n" ) ;
   scanf( " %c", &c) ; /* Observa el espacio en blanco antesde %c para limpiar el '\n' del scanf previo */
 } while ( c == 's' ) ;

  printf ( "\n\nLa frase final es \n\n%s" , cad ) ;

/********************************************************/


Y respecto al uso de scanf y  fflush (stdin) te aconsejaría leer lo que no hay que hacer en C/C++. Nivel basico.

En cualquier caso si veo necesario el uso de una condición que controle el tamaño de la cadena "cad" tal que si se supere su tamaño aborte el ciclo y no permita añadir más palabras pues en caso contrario se iría más allá de la dimensión de la mencionada cadena cad.También es necesario controlar que la variable "palabra" introducida sucesivamente no supere en cada caso su tamaño y tienes ejemplo de eso en el enlace anterior. Eso ya te lo dejo a ti aunque es sencillito.  ;)

¡¡¡¡ Saluditos! ..... !!!!



Blaster

#3
O podrías implementar tu propia versión de strcat así para ajustarlo a tus necesidades y evitar tantas llamadas de la versión estándar :

Código (cpp) [Seleccionar]
char *my_strcat(char *s, char esp, char *cad)
{
   char *save = s;

   for (; *s; ++s);
*s = esp;
   while ((*++s = *cad++) != '\0');

   return(save);
}

int main(void)
{
   char s[80] = "hola";
   char p[80] = "mundo";
   
   my_strcat(s, ' ', p);
   
   printf("%s", s);

   return 0;
}


Saludos

eferion

#4
Cita de: Blaster en  5 Agosto 2014, 16:55 PM
O podrías implementar tu propia versión de strcat así para ajustarlo a tus necesidades y evitar tantas llamadas de la versión estándar :

Código (cpp) [Seleccionar]
char *my_strcat(char *s, char esp, char *cad)
{
   char *save = s;

   for (; *s; ++s);
*s = esp;
   while ((*++s = *cad++) != '\0');

   return(save);
}

int main(void)
{
   char s[7] = "hola";
   char p[] = "mundo";
   
   my_strcat(s, ' ', p);
   
   printf("%s", s);

   return 0;
}


Saludos

Eres consciente que tu ejemplo escribe fuera del buffer, no?? ... o perdón, hablando con propiedad... provoca buffer overflow.

A ver, ya puestos, no tiene mucho sentido que el "remedio" consista en crear una versión de strcat que permita concatenar dos cadenas por vez en vez de una...

Si pretendemos ahorrar llamadas al menos tenemos que intentar hacerlo con un poco de sentido... no viene a cuento reinventar la rueda... ten por seguro que la implementación de la librería estándar es, en el peor de los casos, igual de eficiente que la tuya... lo lógico es que esa versión tienda a ser más eficiente que la tuya. Y aunque esta no fuese razón suficiente, piensa que la librería estándar va a tener muchos menos errores de código que tu versión... además que te evitas tener que mantener ese código.

Código (cpp) [Seleccionar]

char* my_strcat( char*s, const char*cad )
{
 if ( *s != 0 )
   strcat( s, " " );

 strcat( s, cad );

 return s;
}


Pd.: tampoco he entendido muy bien la utilidad de la variable "save";


Blaster

#5
Cita de: eferion en  5 Agosto 2014, 17:12 PM
Eres consciente que tu ejemplo escribe fuera del buffer, no?? ... o perdón, hablando con propiedad... provoca buffer overflow.

Uff es que lo estaba probando y olvide ponerle el tamaño actual gracias por la observación

Saludos

eferion

Cita de: Blaster en  5 Agosto 2014, 17:25 PM
Uff es que lo estaba probado y olvide ponerle el tamaño actual gracias por la observación

Saludos

Son cosas que pasan... es que lo he visto nada más ver el código... que, dicho sea de paso, no es culpa de la función sino de cómo ha sido declarada la variable.

Swain

Si no sabes el largo que va a tomar la frase tienes que usar punteros
pero para cada palabra puedes asignarle un espacio TOPE



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

char *funcion(){
char *frase;
bool cont = true;  // CONDICIONAL PARA CONTINUAR O SALIR
char aux[50]; /// MAXIMO 50 CARACTERES POR PALABRA
frase = (char *)malloc(sizeof(aux));// INICIO CON AL MENOS CON 1 PALABRA
memset(frase,'\0',strlen(frase));
while(cont){
memset(aux,'\0',sizeof(aux)); //LIMPIO AUXILIAR ANTES DE COMENZAR
printf("escribe palabra: ");
scanf("%s",&aux);
sprintf(frase,"%s %s",frase,aux); //CONCATENO FRASE ARMADA + PALABRA
printf("Dese continuar?(y/n)");
memset(aux,'\0',sizeof(aux));
scanf("%s",&aux);
if(aux[0] == 'n' || aux[0] == 'N') //SI EMPIEZA CON N o n SALGO
cont = false;
       frase = (char *)realloc(frase,sizeof(aux)+strlen(frase)); //PIDO MAS ESPACIO
}

return frase; // DEVUELVO LA FRASE TERMINADA
}


int main(){

printf("la frase es: %s\r\n",funcion());
return 0;
}
No me sigas.

eferion

Cita de: Swain en  5 Agosto 2014, 17:51 PM
Si no sabes el largo que va a tomar la frase tienes que usar punteros

... y si sabes la longitud ... también.

Las cadenas de caracteres van siempre con punteros.

PD.: lo siento hoy estoy quisquilloso... te falta un free so pena de tener lagunas de memoria.

PD2.: hay que tener cuidado con las reservas de memoria ( malloc, calloc, realloc ). Estas funciones están pensadas para hacer reservas grandes de memoria... con reservas pequeñas son bastante ineficientes... además, realloc tiene el problema añadido de mover información de una posición de memoria a otra... luego andar haciendo realloc cada dos por tres no parece una opción muy atractiva... casi es mejor hacer realloc de forma exponencial... reservando bloques cada vez más grandes de memoria precisamente para realizar la menor cantidad de llamadas posibles. Escatimar recursos a este nivel solo es útil en sistemas empotrados o con recursos escasos, en el resto de casos no merece la pena.

Blaster

#9
Cita de: eferion en  5 Agosto 2014, 17:12 PM
ten por seguro que la implementación de la librería estándar es, en el peor de los casos, igual de eficiente que la tuya... lo lógico es que esa versión tienda a ser más eficiente que la tuya. Y aunque esta no fuese razón suficiente, piensa que la librería estándar va a tener muchos menos errores de código que tu versión... además que te evitas tener que mantener ese código.

Dudo que la versión estándar sea tan diferente, es mas apostaría que es igual a:

Código (cpp) [Seleccionar]
char *strcat(char *s, const char *cad)
{
   char * save = s;
   for (; *s; ++s);
   while ((*s++ = *cad++) != '\0');

   return (save);
}


Y la verdad no sé que la hace tan "eficiente" ya que ni siquiera realiza la validación
pertinente para asegurar que la cadena destino sea lo suficientemente grande para
luego concatenarle la cadena indicada.

Saludos