正确的方法来复制C字符串

时间:2012-03-06 23:55:59

标签: c++ string copy cstring

有没有简单的方法来复制C字符串?

我有const char *stringA,我希望char *stringB获取值(请注意stringB不是const)。我尝试了stringB=(char*) stringA,但这使stringB仍然指向相同的内存位置,因此当stringA稍后更改时,stringB也会这样做。

我也尝试了strcpy(stringB,stringA),但似乎如果stringB未初始化为足够大的数组,则会出现段错误。我对C字符串没有超级经验,我错过了一些明显的东西吗?如果我只是将stringB初始化为char *stringB[23],因为我知道我永远不会有超过22个字符的字符串(并允许空终止符),这是正确的方法吗?如果检查stringB是否与其他C字符串相等,那么额外的空格是否会影响任何内容?

(在这里使用字符串不是解决方案,因为我需要最少的开销并且可以轻松访问单个字符)

4 个答案:

答案 0 :(得分:16)

您可以使用strdup()返回C字符串的副本,如:

#include <string.h>

const char *stringA = "foo";
char *stringB = NULL;

stringB = strdup(stringA);
/* ... */
free(stringB);    

你也可以使用strcpy(),但是你需要先分配空间,这不是很难做到但如果没有正确完成会导致溢出错误:

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

如果您无法使用strdup(),我建议您使用strncpy()代替strcpy()strncpy()函数最多可复制 - 最多 - n个字节,这有助于避免溢出错误。但是,如果strlen(stringA) + 1 > n,您需要自己终止stringB。但是,一般来说,你会知道你需要什么尺寸的东西:

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

我认为strdup()更清洁,我自己,所以我尝试在专门处理字符串的地方使用它。我不知道POSIX /非POSIX方法是否有严重的缺点,性能方面,但我不是C或C ++专家。

请注意,我将malloc()的结果转换为char *。这是因为您的问题被标记为c++问题。在C ++中,需要从malloc()转换结果。但是,在C中,你强制转换它。

修改

你去了,有一个复杂因素:strdup()不在C或C ++中。因此,请将strcpy()strncp()与预先调整大小的数组或malloc - ed指针一起使用。无论您在哪里使用该功能,使用strncp()代替strcpy()都是一个好习惯。它将有助于减少出错的可能性。

答案 1 :(得分:3)

  

如果我只是将stringB初始化为char * stringB [23],因为我知道我永远不会有超过22个字符的字符串(并允许空终止符),这是正确的方法吗?

几乎。在C中,如果你确定字符串永远不会太长:

char stringB[MAX+1];
assert(strlen(stringA) <= MAX));
strcpy(stringB, stringA);

或者,如果字符串可能太长:

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
}

在C ++中,您应该使用std::string,除非您已经证明开销过高。许多实现都有一个“短字符串优化”,这将避免短字符串的动态分配;在这种情况下,使用C风格的数组几乎没有开销。访问单个字符与使用C风格的数组一样方便;在这两种情况下,s[i]都会将位置i的角色作为左值。复制变为stringB = stringA;,没有未定义行为的危险。

如果您确实发现std::string不可用,请考虑std::array<char,MAX+1>:包含固定大小数组的可复制类。

  

如果检查stringB是否与其他C字符串相等,那么额外的空格是否会影响任何内容?

如果您使用strcmp,它将在最短字符串的末尾停止,并且不会受到额外空间的影响。

答案 2 :(得分:2)

如果你想用纯C风格而不是:

char* new_string = strdup(old_string);
free(new_string);

如果你想用(种)C ++风格:

char* new_string = new char[strlen(old_string) + 1];
strcpy(new_string,old_string);
delete[] new_string;

答案 3 :(得分:0)

您可能正在寻找strncpy,它允许您复制字符串中的第一个n字符。只需确保在复制到字符串的位置n处添加空终止符。