Espacios en concatenación strcat.

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

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

leosansan

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
pero para cada palabra puedes asignarle un espacio TOPE

Me ha gustado el uso del puntero con asignación dinámica de memoria, eso sí con lo que tan acertadamente comenta eferion respecto a dicha asignación así como el uso del bool.  ;-)

Sólo unos pequeñitos detalles:

* creo que falta la librería stdbool.h
* ¿No te sobra el "&" en los scanf al tratarse de arrays?.
* Tal como lo tienes, introduce un espacio en blanco al comienzo de la frase, cosa que no procede.
* ¿Es tan necesario el uso de memset?. Para inicializar "frase " podríamos usar calloc, en lugar de malloc, y respecto a inicializar a la variable "aux", ¿es tan necesario?. Dudas, dudas ..... :rolleyes:
* Podemos ahorrarnos uno de los scanf haciendo la pregunta al entrar la frase.

Son sólo detallitos sin mayor importancia pero creo que eferion me ha contagiado el estado "quisquilloso" hoy.  :laugh:

Pero insisto, me ha gustado la aportación, tanto que con tu permiso la modifico para tener en cuenta los pequeñitos detalles que mencioné:

Código (cpp) [Seleccionar]
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

char *funcion ( char *frase ) {
  bool cont = true ;
  char aux [ 50 ] ;
  frase = calloc ( sizeof  aux , sizeof ( char ) ) ;
  printf("\nEscribe una palabra ( n para salir ): ") ;
  scanf ( "%s" , aux ) ;
  strcpy( frase , aux ) ;
  while ( cont ) {
    printf("\nEscribe una palabra ( n para salir ): ") ;
    scanf ( "%s" , aux ) ;
    ( strlen ( aux ) == 1 && ( aux[0] == 'n' || aux[0] == 'N') ) ? cont = false : sprintf ( frase , "%s %s" , frase , aux ) ;
    frase = realloc ( frase , sizeof ( aux ) + strlen ( frase ) ) ;
  }
  return frase ;
}

int main( ) {
  char *frase ;
  printf( "\n\nLa frase es:\n\n%s" , funcion ( frase ) ) ;
  free ( frase ) ;
  return EXIT_SUCCESS ;
}


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



eferion

Cita de: Blaster en  5 Agosto 2014, 18:45 PM
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

No estoy hablando de una función concreta... hablo en general.

Porque claro, ya puestos, una vez has creado tu versión de strcat (pensando en que debe funcionar igual que la función estándar)... ¿por qué no hacer una implementación propia de strlen, strcpy, strtok, memcpy, memset... ¿eres capaz de garantizar que tus versiones van a ser igual de óptimas que las versiones estándar? estoy convencido de que no. Si miras el código fuente de algunas de estas funciones verás que están plagadas de compilaciones condicionales... precisamente para optimizar y para sortear eventualidades (no es lo mismo una arquitectura big endian que una little endian, por ejemplo)... y está claro que tú no vas a tener en cuenta estas cosas. Al final, por este camino, tu código acabaría siendo poco eficiente y no portable.... y ese no es el camino.

leosansan

Cita de: eferion en  6 Agosto 2014, 08:35 AM
No estoy hablando de una función concreta... hablo en general.

Al final, por este camino, tu código acabaría siendo poco eficiente y no portable.... y ese no es el camino.

Pues usemos dichas funciones. Como ejemplo:

Código (cpp) [Seleccionar]
char *my_strcat( char *s , char esp , char *cad ) {
  sprintf ( s , "%s %s" , s , cad)  ;
  return( s ) ;
}



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




rir3760

Cita de: leosansan en  5 Agosto 2014, 15:56 PMpara concatenar las palabras usaría la función sprintf con lo que en con sólo una función concateno las palabras:

[...]

sprintf(cad, "%s%c%s", cad, ' ', pal);
Un problema con esa llamada a sprintf es indicar que la cadena debe imprimirse sobre si misma y en caso de utilizar el par strcpy/strcat se tiene el fastidio (con la segunda) de buscar el final de la primera cadena.

En su lugar se puede aprovechar el valor de retorno de sprintf, este es el numero de caracteres generados en base a la cadena de formato sin incluir el '\0'. Un ejemplo basado en el tuyo sin validaciones ni uso de memoria dinámica:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#define MAX_PAL  50

char *funcion(char *frase);

int main(void)
{
   char frase[MAX_PAL * 20];
   
   printf("La frase es: \"%s\"\n", funcion(frase));
   
   return EXIT_SUCCESS;
}

char *funcion(char *frase)
{
   char pal[MAX_PAL];
   int nc;
   
   puts("Escribe una palabra ( n para salir ):");
   scanf("%s", pal);
   nc = sprintf(frase, "%s", pal);
   
   while (1){
      puts("Escribe una palabra (n para salir):");
      scanf("%s", pal);
     
      if (tolower(*pal) == 'n' && pal[1] == '\0')
         break;
     
      nc += sprintf(frase + nc, " %s", pal);
   }
   
   return frase;
}


Un saludo
C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly.
--
Kernighan & Ritchie, The C programming language