是否有简单的方法来复制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字符串的相等性,那么多余的空间会影响什么吗?
((这里仅使用字符串不是解决方案,因为我需要最小的开销并易于访问单个字符。)
您可以使用strdup()
返回C字符串的副本,如:
strdup()
您也可以使用#include <string.h>
const char *stringA = "foo";
char *stringB = NULL;
stringB = strdup(stringA);
/* ... */
free(stringB);
,但您需要先分配空间,这并不难,但如果执行不正确,则会导致溢出错误:
strcpy()
如果无法使用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()
函数最多可复制—个,最多只能复制strncpy()
个字节,这有助于避免溢出错误。但是,如果strcpy()
,则需要您自己终止strncpy()
。但是,通常,您会知道东西需要什么尺寸:
n
我个人认为strlen(stringA) + 1 > n
更干净,所以我尝试在专门处理字符串的地方使用它。从性能的角度来看,我不知道POSIX / non-POSIX方法是否存在严重的缺点,但我不是C或C ++专家。
注意,我将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()
问题。在C ++中,需要从malloc()
强制转换结果。但是,在C语言中,您将not强制转换。
编辑
[走,有一个复杂的问题:char *
不在C或C ++中。因此,将c++
或malloc()
与预大小数组或strdup()
-ed指针一起使用。在任何可能使用该功能的地方,都使用strcpy()
而不是strncp()
是一个好习惯。这将有助于减少潜在的错误。
如果我只是将stringB初始化为char * stringB [23],因为我知道我的字符串永远不会超过22个字符(并且允许使用空终止符),这是正确的方法吗?
几乎。在C中,如果您确定知道字符串永远不会太长:
malloc
或者,如果字符串可能太长:
strncp()
在C ++中,除非已证明开销过高,否则应使用strcpy()
。许多实现都有“短字符串优化”,这将避免动态分配短字符串。在这种情况下,使用C样式数组几乎没有开销。访问单个字符就像使用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
}
处的字符作为lvalue给出。复制成为std::string
,没有不确定行为的危险。
如果确实发现s[i]
不可用,请考虑i
:包含固定大小数组的可复制类。
如果检查stringB与其他C字符串是否相等,多余的空间会影响什么吗?
如果使用stringB = stringA;
,它将停止在最短字符串的结尾,并且不受多余空间的影响。
如果您想以纯C样式执行此操作,则:
std::string
如果您想使用(某种)C ++样式:
std::array<char,MAX+1>
您可能正在寻找strcmp
,它使您可以从字符串中复制前char* new_string = strdup(old_string);
free(new_string);
个字符。只需确保在复制到的字符串的位置n处添加空终止符即可。