Forma adequada de copiar os textos em C
tenho const char *stringA
, e quero char *stringB
tomar o valor (note que stringB
não é const
). Eu tentei stringB=(char*) stringA
, mas isso faz stringB
ainda apontar para o mesmo local de memória, então quando stringA
mais tarde muda, stringB
também muda.
Eu também tentei strcpy(stringB,stringA)
, mas parece que se stringB
não foi inicializado para uma grande variedade o suficiente, há uma segfault. Não tenho muita experiência com C-strings, estou a perder algo óbvio? Se eu ... inicializar {[[2]} como char *stringB[23]
, Porque eu sei que nunca terei um texto maior que 22
caracteres (e permitindo o terminador nulo), é esse o caminho certo? Se stringB
for verificado a igualdade com outras cadeias de caracteres C, o espaço extra irá afectar alguma coisa?
(e só usar strings não é uma solução aqui, pois eu preciso de sobrecarga mínima e acesso fácil a caracteres individuais) {[[16]}
4 answers
Podias usar strdup()
para devolver uma cópia de uma cadeia C, como em:
#include <string.h>
const char *stringA = "foo";
char *stringB = NULL;
stringB = strdup(stringA);
/* ... */
free(stringB);
Você também pode usar strcpy()
, mas você precisa alocar espaço primeiro, o que não é difícil de fazer, mas pode levar a um erro de excesso, se não for feito corretamente:
#include <string.h>
const char *stringA = "foo";
char *stringB = NULL;
/* you must add one to cover the byte needed for the terminating null character */
stringB = (char *) malloc( strlen(stringA) + 1 );
strcpy( stringB, stringA );
/* ... */
free(stringB);
Se não puder utilizar strdup()
, recomendaria a utilização de strncpy()
em vez de strcpy()
. A função strncpy()
copia até - e apenas até - n
bytes, o que ajuda a evitar erros de excesso de fluxo. No entanto, se strlen(stringA) + 1 > n
teria de acabar contigo. Mas, geralmente, você saberá que Tamanhos você precisa para as coisas:
#include <string.h>
const char *stringA = "foo";
char *stringB = NULL;
/* you must add one to cover the byte needed for the terminating null character */
stringB = (char *) malloc( strlen(stringA) + 1 );
strncpy( stringB, stringA, strlen(stringA) + 1 );
/* ... */
free(stringB);
Eu próprio acho que strdup()
é mais limpo, por isso tento usá-lo onde se trabalha exclusivamente com cordas. Não sei se há desvantagens graves na abordagem POSIX/não-POSIX, em termos de desempenho, mas não sou um especialista em C ou C++.
Note que eu lancei o resultado de malloc()
para char *
. Isto é porque a sua pergunta está marcada como uma pergunta c++
. Em C++, é necessário lançar o resultado de malloc()
. No entanto, em C, não lançarias isto.
EDITAR
Aqui está, há uma complicação: strdup()
não está em C ou C++. Então use strcpy()
ou strncp()
com uma matriz pré-dimensionada ou um ponteiro malloc
-ed. É um bom hábito usar strncp()
em vez de strcpy()
, onde quer que você possa usar essa função. Ajudará a reduzir o potencial de erros.
Quase. Em C, se tiver a certeza de que o texto nunca será muito longo:Se Eu apenas inicializar stringB como char * stringB [23], Porque eu sei que nunca vou ter uma string mais de 22 caracteres (e permitindo o terminador nulo), é esse o caminho certo?
char stringB[MAX+1];
assert(strlen(stringA) <= MAX));
strcpy(stringB, stringA);
Ou, se houver uma possibilidade de que a corda possa ser demasiado longa:
char stringB[MAX+1];
strncpy(stringB, stringA, MAX+1);
if (stringB[MAX] != '\0') {
// ERROR: stringA was too long.
stringB[MAX] = '\0'; // if you want to use the truncated string
}
Em C++, deve usar std::string
, a menos que tenha provado que a sobrecarga é proibitiva. Muito implementações têm uma "otimização de cadeia curta", que evitará alocação dinâmica para cadeias curtas; nesse caso, haverá pouca ou nenhuma sobrecarga sobre o uso de um array de estilo C. O acesso a caracteres individuais é tão conveniente como com uma matriz de estilo C; em ambos os casos, s[i]
dá o carácter na posição i
como um value. A cópia torna-se stringB = stringA;
sem perigo de comportamento indefinido.
Se realmente achar que std::string
está inutilizável, considere std::array<char,MAX+1>
: um copiável classe que contém uma matriz de tamanho fixo.
Se o stringB for verificado pela igualdade com outras cadeias de C, o espaço extra irá afectar alguma coisa?
Se você usar strcmp
, então ele vai parar no final do texto mais curto, e não será afetado pelo espaço extra.
Se o quiseres fazer em puro estilo C que:
char* new_string = strdup(old_string);
free(new_string);
Se o quiser fazer em (Tipo de) estilo C++:
char* new_string = new char[strlen(old_string) + 1];
strcpy(new_string,old_string);
delete[] new_string;
strncpy
, o que lhe permite copiar os primeiros caracteres n
de um texto. Certifique-se apenas de adicionar o terminador nulo na posição n do texto copiado para.