Pergunta

Eu estou trabalhando em C, e eu tenho que concatenar algumas coisas.

Agora eu tenho este:

message = strcat("TEXT ", var);

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

Agora, se você tem experiência em C Eu tenho certeza que você percebe que isso lhe dá uma falha de segmentação quando você tenta executá-lo. Então, como faço para resolver isso?

Foi útil?

Solução

Em C, "strings" são apenas matrizes char simples. Portanto, você não pode concatenar-los diretamente com outros "strings".

Você pode usar a função strcat, que acrescenta o string apontada por src ao final do string apontada por dest:

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

Aqui está um href="http://www.cplusplus.com/reference/clibrary/cstring/strcat.html" rel="noreferrer"> exemplo :

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

Para o primeiro parâmetro, você precisa fornecer o destino tampão si. O buffer de destino deve ser um tamp de matriz de char. Ex .: char buffer[1024];

Certifique-se que o primeiro parâmetro tem espaço suficiente para armazenar o que você está tentando copiar para ele. Se estiver disponível para você, é mais seguro para utilizar funções como: strcpy_s e strcat_s onde explicitamente tem que especificar o tamanho do buffer de destino.

Nota : Um literal cadeia não pode ser usado como um tampão, uma vez que é uma constante. Assim, você sempre tem que alocar uma matriz de char para o buffer.

O valor de retorno de strcat pode simplesmente ser ignorado, ele simplesmente retorna o mesmo ponteiro como foi passado como o primeiro argumento. É lá por conveniência, e permite que você cadeia as chamadas em uma linha de código:

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

Então, o problema poderia ser resolvido da seguinte forma:

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

Outras dicas

Evite usar strcat em código C. O mais limpo e, mais importante, a maneira mais segura é usar snprintf :

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

Alguns comentadores levantou uma questão que o número de argumentos pode não corresponder à string de formato e o código ainda irá compilar, mas a maioria dos compiladores já emitir um aviso se este for o caso.

Folks, uso str n cpy (), str n gato (s), ou n printf ().
exceder seu espaço de buffer irá lixo tudo aquilo que segue na memória!
(E lembre-se de deixar espaço para a fuga nulo '\ 0'!)

Além disso malloc e realloc são úteis se você não sabe de antemão como muitas cordas estão sendo concatenados.

#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);
}

Strings também podem ser concatenados em tempo de compilação.

#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 */ 
                ;

Não se esqueça de inicializar o buffer de saída. O primeiro argumento para strcat deve ser uma cadeia terminada nula com espaço extra suficiente alocado para a seqüência resultante:

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

O primeiro argumento de strcat () precisa ser capaz de manter espaço suficiente para a cadeia concatenada. Portanto, alocar um buffer com espaço suficiente para receber o resultado.

char bigEnough[64] = "";

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

/* and so on */

strcat () irá concatenar o segundo argumento com o primeiro argumento, e armazenar o resultado no primeiro argumento, o caractere retornado * é simplesmente este primeiro argumento, e apenas para sua conveniência.

Você não ter uma seqüência de recém-alocado com o primeiro e segundo argumento concatenado, que eu acho que você espera com base em seu código.

Como as pessoas apontou manipulação de strings melhorou muito. Então você pode querer aprender como usar o C ++ biblioteca de cadeia em vez de cordas de estilo C. No entanto, aqui é uma solução em puro C

#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;
}

Eu não tenho certeza se ele está correto / seguro, mas agora eu não poderia encontrar uma maneira melhor de fazer isso em ANSI C.

Melhor maneira de fazer isso sem ter um tamanho da memória intermédia é limitada usando asprintf ()

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

É um comportamento indefinido para tentar modificar strings literais, que é o que algo como:

strcat ("Hello, ", name);

tentará fazer. Ele vai tentar tack na corda name ao final do "Hello, " literal string, que não está bem definido.

Tente algo disso. Ele consegue o que você parece estar tentando fazer:

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

Isso cria uma área tampão que é autorizados a ser modificado e, em seguida, cópias tanto o literal de cadeia eo outro texto a ele. Basta ter cuidado com estouros de buffer. Se você controla os dados de entrada (ou verificar antes de mão), não há problema em usar buffers de tamanho fixo como eu tenho.

Caso contrário, você deve usar mitigação estratégias, tais como alocação de memória suficiente da pilha para garantir que você pode lidar com isso. Em outras palavras, 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.

Você pode escrever sua própria função que faz a mesma coisa que strcat() mas isso não muda 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;
}

Se ambas as cordas juntos, são mais de 1000 caracteres, ele vai cortar a corda em 1000 caracteres. Você pode alterar o valor de MAX_STRING_LENGTH para atender às suas necessidades.

Supondo que você tenha um char [fixed_size] em vez de um char *, você pode usar um único, macro criativa para fazer tudo de uma vez com uma ordenação <<cout<<like ( "ao invés% do desarticulada% s \ n", "do que ", "formato de estilo printf"). Se você estiver trabalhando com sistemas embarcados, este método também permitirá que você deixar de fora malloc e da grande família *printf de funções como snprintf() (Isso mantém dietlibc de reclamando * printf também)

#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, você normalmente não usaria argv [0] como este - apenas um exemplo
  • Nota 2, você pode usar qualquer função que saídas de um char *, incluindo funções fora do padrão como itoa () para converter números inteiros para tipos string.
  • Nota 3, se você já está usando em qualquer lugar printf em seu programa, não há razão para não usar snprintf (), uma vez que o código compilado seria maior (mas inlined e significativamente mais 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;
}

Você está tentando copiar uma string em um endereço que é alocado estaticamente. Você precisa de gato em um buffer.

Especificamente:

... snip ...

destino

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

... snip ...

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

Há um exemplo aqui também.

Se você tem experiência em C você vai notar que as cordas são matrizes única de char onde o último caractere é um caractere nulo.

Agora que é bastante inconveniente como você tem que encontrar o último caractere, a fim de acrescentar algo. strcat vai fazer isso por você.

Assim strcat pesquisas através do primeiro argumento para um caractere nulo. Em seguida, ele irá substituir isso com o conteúdo do segundo argumento (até que termina em um nulo).

Agora vamos passar por seu código:

message = strcat("TEXT " + var);

Aqui você está adicionando algo para o ponteiro para o "texto" texto (o tipo de "texto" é const char *. Um ponteiro.).

Isso geralmente não funcionam. Também modificar a matriz "TEXT" não irá funcionar, uma vez que é geralmente colocado num segmento constante.

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

Esse trabalho seria melhor, exceto que você está novamente tentando modificar textos estáticos. strcat não está alocando nova memória para o resultado.

Eu proporia a fazer algo parecido com isto em vez disso:

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

Leia a documentação de sprintf de verificar por sua opções.

E agora um ponto importante:

Certifique-se de que o buffer tem espaço suficiente para armazenar o texto e o caractere nulo. Há um par de funções que podem ajudá-lo, por exemplo, strncat e versões especiais de printf que alocar o buffer para você. Não garantindo o tamanho do buffer vai levar à corrupção de memória e erros exploráveis ??remotamente.

Esta foi a minha solução

#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;
}

mas você precisa especificar quantas cordas você está indo para concatenar

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

Tente algo semelhante a isto:

#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 em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top