Pregunta

Estoy trabajando en C, y tengo para concatenar un par de cosas.

Ahora tengo este:

message = strcat("TEXT ", var);

message2 = strcat(strcat("TEXT ", foo), strcat(" TEXT ", bar));

Ahora, si usted tiene experiencia en C estoy seguro de que te das cuenta de que esto le da un fallo de segmentación cuando intenta ejecutar.Entonces, ¿cómo puedo evitar eso?

¿Fue útil?

Solución

En C, las "cadenas" son simplemente char las matrices.Por lo tanto, directamente no se puede concatenar con otras "cadenas".

Usted puede utilizar el strcat la función, que se anexa a la cadena apuntada por src al final de la cadena apuntada por dest:

char *strcat(char *dest, const char *src);

Aquí es un ejemplo de cplusplus.com:

char str[80];
strcpy(str, "these ");
strcat(str, "strings ");
strcat(str, "are ");
strcat(str, "concatenated.");

Para el primer parámetro, usted necesita proporcionar el búfer de destino en sí mismo.El búfer de destino debe ser una matriz de char buffer.E. g.: char buffer[1024];

Asegúrese de que que el primer parámetro tiene suficiente espacio para almacenar lo que usted está tratando de copiar en él.Si están disponibles para usted, es más seguro usar funciones como: strcpy_s y strcat_s donde explícitamente se tiene que especificar el tamaño del búfer de destino.

Nota:Un literal de cadena no puede ser utilizado como un tampón, ya que es una constante.Por lo tanto, usted siempre tiene que asignar una matriz de char para el búfer.

El valor de retorno de strcat puede ser simplemente ignorado, simplemente devuelve el mismo puntero a medida que se pasa como primer argumento.Es allí, por conveniencia, y le permite a la cadena de las llamadas en una línea de código:

strcat(strcat(str, foo), bar);

Así que su problema podría ser resuelto de la siguiente manera:

char *foo = "foo";
char *bar = "bar";
char str[80];
strcpy(str, "TEXT ");
strcat(str, foo);
strcat(str, bar);

Otros consejos

Evite usar strcat en el código C. La forma más limpia y, lo más importante, la más segura es usar snprintf :

char buf[256];
snprintf(buf, sizeof buf, "%s%s%s%s", str1, str2, str3, str4);

Algunos comentaristas plantearon un problema de que el número de argumentos puede no coincidir con la cadena de formato y el código aún se compilará, pero la mayoría de los compiladores ya emiten una advertencia si este es el caso.

Gente, use str n cpy (), str n cat () o s n printf ().
¡Superar su espacio de búfer destruirá todo lo que sigue en la memoria!
(¡Y recuerde dejar espacio para el carácter nulo '\ 0' final!)

También malloc y realloc son útiles si no sabe de antemano cuántas cadenas se concatenan.

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

void example(const char *header, const char **words, size_t num_words)
{
    size_t message_len = strlen(header) + 1; /* + 1 for terminating NULL */
    char *message = (char*) malloc(message_len);
    strncat(message, header, message_len);

    for(int i = 0; i < num_words; ++i)
    {
       message_len += 1 + strlen(words[i]); /* 1 + for separator ';' */
       message = (char*) realloc(message, message_len);
       strncat(strncat(message, ";", message_len), words[i], message_len);
    }

    puts(message);

    free(message);
}

Las cadenas también se pueden concatenar en tiempo de compilación.

#define SCHEMA "test"
#define TABLE  "data"

const char *table = SCHEMA "." TABLE ; // note no + or . or anything
const char *qry =               // include comments in a string
    " SELECT * "                // get all fields
    " FROM " SCHEMA "." TABLE   /* the table */
    " WHERE x = 1 "             /* the filter */ 
                ;

No olvides inicializar el búfer de salida. El primer argumento para strcat debe ser una cadena terminada en nulo con suficiente espacio extra asignado para la cadena resultante:

char out[1024] = ""; // must be initialized
strcat( out, null_terminated_string ); 
// null_terminated_string has less than 1023 chars

El primer argumento de strcat () necesita poder contener suficiente espacio para la cadena concatenada. Asigne un búfer con suficiente espacio para recibir el resultado.

char bigEnough[64] = "";

strcat(bigEnough, "TEXT");
strcat(bigEnough, foo);

/* and so on */

strcat () concatenará el segundo argumento con el primer argumento, y almacenará el resultado en el primer argumento, el char * devuelto es simplemente este primer argumento, y solo para su conveniencia.

No obtiene una cadena recién asignada con el primer y segundo argumento concatenados, lo que supongo que esperaba en función de su código.

Como la gente señaló, el manejo de la cuerda mejoró mucho. Por lo tanto, es posible que desee aprender a usar la biblioteca de cadenas de C ++ en lugar de las cadenas de estilo C. Sin embargo, aquí hay una solución en C puro

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

void appendToHello(const char *s) {
    const char *const hello = "hello ";

    const size_t sLength     = strlen(s);
    const size_t helloLength = strlen(hello);
    const size_t totalLength = sLength + helloLength;

    char *const strBuf = malloc(totalLength + 1);
    if (strBuf == NULL) {
        fprintf(stderr, "malloc failed\n");
        exit(EXIT_FAILURE);
    }

    strcpy(strBuf, hello);
    strcpy(strBuf + helloLength, s);

    puts(strBuf);

    free(strBuf);

}

int main (void) {
    appendToHello("blah blah");
    return 0;
}

No estoy seguro de si es correcto / seguro, pero en este momento no podría encontrar una mejor manera de hacerlo en ANSI C.

La mejor manera de hacerlo sin tener un tamaño de búfer limitado es utilizando asprintf ()

char* concat(const char* str1, const char* str2)
{
    char* result;
    asprintf(&result, "%s%s", str1, str2);
    return result;
}

Es un comportamiento indefinido intentar modificar los literales de cadena, que es algo así como:

strcat ("Hello, ", name);

intentará hacer. Intentará agregar la cadena name al final del literal de cadena "Hello, ", que no está bien definido.

Intenta algo así. Logra lo que parece estar tratando de hacer:

char message[1000];
strcpy (message, "TEXT ");
strcat (message, var);

Esto crea un área de búfer que tiene permitido modificar y luego copia tanto el literal de cadena como otro texto. Solo tenga cuidado con los desbordamientos del búfer. Si controla los datos de entrada (o los verifica de antemano), está bien usar buffers de longitud fija como yo.

De lo contrario, debe usar estrategias de mitigación como asignar suficiente memoria del montón para asegurarse de que puede manejarlo. En otras palabras, algo como:

const static char TEXT[] = "TEXT ";

// Make *sure* you have enough space.

char *message = malloc (sizeof(TEXT) + strlen(var) + 1);
if (message == NULL)
     handleOutOfMemoryIntelligently();
strcpy (message, TEXT);
strcat (message, var);

// Need to free message at some point after you're done with it.

Puede escribir su propia función que haga lo mismo que strcat() pero que no cambie nada:

#define MAX_STRING_LENGTH 1000
char *strcat_const(const char *str1,const char *str2){
    static char buffer[MAX_STRING_LENGTH];
    strncpy(buffer,str1,MAX_STRING_LENGTH);
    if(strlen(str1) < MAX_STRING_LENGTH){
        strncat(buffer,str2,MAX_STRING_LENGTH - strlen(buffer));
    }
    buffer[MAX_STRING_LENGTH - 1] = '\0';
    return buffer;
}

int main(int argc,char *argv[]){
    printf("%s",strcat_const("Hello ","world"));    //Prints "Hello world"
    return 0;
}

Si ambas cadenas juntas tienen más de 1000 caracteres, cortará la cadena a 1000 caracteres. Puede cambiar el valor de MAX_STRING_LENGTH para satisfacer sus necesidades.

Suponiendo que tiene un char [tamaño_ fijo] en lugar de un char *, puede usar una sola macro creativa para hacerlo todo de una vez con un orden <<cout<<like (" en lugar de% s el% s desunido \ n " ;, " que " ;, " formato de estilo printf "). Si está trabajando con sistemas integrados, este método también le permitirá omitir malloc y la gran familia de funciones *printf como snprintf() (Esto evita que dietlibc se queje de * printf también)

#include <unistd.h> //for the write example
//note: you should check if offset==sizeof(buf) after use
#define strcpyALL(buf, offset, ...) do{ \
    char *bp=(char*)(buf+offset); /*so we can add to the end of a string*/ \
    const char *s, \
    *a[] = { __VA_ARGS__,NULL}, \
    **ss=a; \
    while((s=*ss++)) \
         while((*s)&&(++offset<(int)sizeof(buf))) \
            *bp++=*s++; \
    if (offset!=sizeof(buf))*bp=0; \
}while(0)

char buf[256];
int len=0;

strcpyALL(buf,len,
    "The config file is in:\n\t",getenv("HOME"),"/.config/",argv[0],"/config.rc\n"
);
if (len<sizeof(buf))
    write(1,buf,len); //outputs our message to stdout
else
    write(2,"error\n",6);

//but we can keep adding on because we kept track of the length
//this allows printf-like buffering to minimize number of syscalls to write
//set len back to 0 if you don't want this behavior
strcpyALL(buf,len,"Thanks for using ",argv[0],"!\n");
if (len<sizeof(buf))
    write(1,buf,len); //outputs both messages
else
    write(2,"error\n",6);
  • Nota 1, normalmente no usaría argv [0] de esta manera, solo un ejemplo
  • Nota 2, puede usar cualquier función que genere un char *, incluidas funciones no estándar como itoa () para convertir enteros en tipos de cadena.
  • Nota 3, si ya está utilizando printf en cualquier parte de su programa, no hay razón para no usar snprintf (), ya que el código compilado sería más grande (pero en línea y significativamente más rápido)
int main()
{
    char input[100];
    gets(input);

    char str[101];
    strcpy(str, " ");
    strcat(str, input);

    char *p = str;

    while(*p) {
       if(*p == ' ' && isalpha(*(p+1)) != 0)
           printf("%c",*(p+1));
       p++;
    }

    return 0;
}

Está intentando copiar una cadena en una dirección que está asignada estáticamente. Debes colocar el gato en un búfer.

Específicamente:

... recortar ...

destino

Pointer to the destination array, which should contain a C string, and be large enough to contain the concatenated resulting string.

... recortar ...

http://www.cplusplus.com/reference/clibrary/cstring /strcat.html

También hay un ejemplo aquí.

Si tiene experiencia en C, notará que las cadenas son solo matrices de caracteres donde el último carácter es un carácter nulo.

Ahora, eso es bastante inconveniente, ya que tienes que encontrar el último personaje para agregar algo. strcat lo hará por usted.

Entonces strcat busca en el primer argumento un carácter nulo. Luego reemplazará esto con el contenido del segundo argumento (hasta que termine en un valor nulo).

Ahora revisemos su código:

message = strcat("TEXT " + var);

Aquí está agregando algo al puntero al texto " TEXT " (el tipo de " TEXT " es const char *. Un puntero).

Eso generalmente no funcionará. También modificando & Quot; TEXT & Quot; La matriz no funcionará, ya que generalmente se coloca en un segmento constante.

message2 = strcat(strcat("TEXT ", foo), strcat(" TEXT ", bar));

Eso podría funcionar mejor, excepto que nuevamente está intentando modificar textos estáticos. strcat no está asignando nueva memoria para el resultado.

En su lugar, propondría hacer algo como esto:

sprintf(message2, "TEXT %s TEXT %s", foo, bar);

Lea la documentación de sprintf para verificar sus opciones.

Y ahora un punto importante:

Asegúrese de que el búfer tenga suficiente espacio para contener el texto Y el carácter nulo. Hay un par de funciones que pueden ayudarlo, por ejemplo, strncat y versiones especiales de printf que le asignan el búfer. No garantizar que el tamaño del búfer provocará daños en la memoria y errores explotables de forma remota.

Esta fue mi solución

#include <stdlib.h>
#include <stdarg.h>

char *strconcat(int num_args, ...) {
    int strsize = 0;
    va_list ap;
    va_start(ap, num_args);
    for (int i = 0; i < num_args; i++) 
        strsize += strlen(va_arg(ap, char*));

    char *res = malloc(strsize+1);
    strsize = 0;
    va_start(ap, num_args);
    for (int i = 0; i < num_args; i++) {
        char *s = va_arg(ap, char*);
        strcpy(res+strsize, s);
        strsize += strlen(s);
    }
    va_end(ap);
    res[strsize] = '\0';

    return res;
}

pero debe especificar cuántas cadenas va a concatenar

char *str = strconcat(3, "testing ", "this ", "thing");

Pruebe algo similar a esto:

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

int main(int argc, const char * argv[])
{
  // Insert code here...
  char firstname[100], secondname[100];
  printf("Enter First Name: ");
  fgets(firstname, 100, stdin);
  printf("Enter Second Name: ");
  fgets(secondname,100,stdin);
  firstname[strlen(firstname)-1]= '\0';
  printf("fullname is %s %s", firstname, secondname);

  return 0;
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top