复制C字符串的正确方法

问题描述 投票:11回答:4

是否有简单的方法来复制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字符串的相等性,那么多余的空间会影响什么吗?

((这里仅使用字符串不是解决方案,因为我需要最小的开销并易于访问单个字符。)

c++ string copy c-strings
4个回答
18
投票

您可以使用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()是一个好习惯。这将有助于减少潜在的错误。


3
投票

如果我只是将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;,它将停止在最短字符串的结尾,并且不受多余空间的影响。


2
投票

如果您想以纯C样式执行此操作,则:

std::string

如果您想使用(某种)C ++样式:

std::array<char,MAX+1>

1
投票

您可能正在寻找strcmp,它使您可以从字符串中复制前char* new_string = strdup(old_string); free(new_string); 个字符。只需确保在复制到的字符串的位置n处添加空终止符即可。

© www.soinside.com 2019 - 2024. All rights reserved.