如何在C++中将字符串转换为字符数组?

136

我想要将 string 转换为 char 数组,但不是 char*。我知道如何将 string 转换为 char*(通过使用 malloc 或我在代码中发布的方式),但这不是我想要的。我只想将 string 转换为 char[size] 数组。这可能吗?

#include <iostream>
#include <string>
#include <stdio.h>
using namespace std;

int main()
{
    // char to string
    char tab[4];
    tab[0] = 'c';
    tab[1] = 'a';
    tab[2] = 't';
    tab[3] = '\0';
    string tmp(tab);
    cout << tmp << "\n";

    // string to char* - but thats not what I want

    char *c = const_cast<char*>(tmp.c_str());
    cout << c << "\n";

    //string to char
    char tab2[1024];
    // ?

    return 0;
}

3
可能是 std::string to char* 的重复问题。 - cegprakash
11个回答

166

我能想到的最简单的方法是:

string temp = "cat";
char tab2[1024];
strcpy(tab2, temp.c_str());

为了安全起见,您可能更喜欢:

string temp = "cat";
char tab2[1024];
strncpy(tab2, temp.c_str(), sizeof(tab2));
tab2[sizeof(tab2) - 1] = 0;

或者可以这样:

string temp = "cat";
char * tab2 = new char [temp.length()+1];
strcpy (tab2, temp.c_str());

11
使用 strncpy 的问题在于,如果它在找到源字符串中的空字符之前就达到了目标大小,那么它不会添加空字符作为结尾。因此,在使用时需要小心! - Fred Larson
1
是的,我认为这是一个合理的处理方式。 - Fred Larson
1
strncpy是为了安全起见,因为它不会越界你给它的缓冲区。此外,strcpy_s不在C99中,但它最近已经被添加到C11中。 - bames53
9
我喜欢人们滥用“安全”这个词的方式......哦,字符串没有足够的空间,所以让我们将其截断...哦,我们不小心删除了患者生命威胁性药物过敏的信息...但是我们不再有缓冲区溢出了。好吧,我它是“安全”的... - Karoly Horvath
5
@KarolyHorvath - 不同领域的安全性。显然,你需要检查你的功能要求并避免做愚蠢的事情。但是如果你越过缓冲区,你失去了任何知道会发生什么的保证。正确编码确保程序在您的操作系统上运行是“安全”的。正确的“思考”确保程序在执行用户所需的操作时是“安全”的。 - Chowlett
显示剩余7条评论

81

好的,我很震惊没有人真正给出一个好的答案,现在轮到我了。有两种情况:

  1. 如果一个常量字符数组对你来说足够好,那么就使用它:

    const char *array = tmp.c_str();
    
  2. 或者你需要修改字符数组,所以常数不可以,那么就使用这个方法

  3. char *array = &tmp[0];
    

两者都仅仅是赋值操作,并且在大多数情况下,这就是您所需要的。如果确实需要一个新副本,请参考其他人的答案。


7
他想要一个字符数组,而不是一个字符指针。 - harogaston
17
他创建的指针其实就是一个字符数组。在 C 和 C++ 中,一个数组变量本质上就是指向该数组第一个元素的指针。 - JustinCB
5
@JustinC.B.并不是完全正确!在C++中,数组变量可能会退化为指针,但它们与指针并不相同。例如,当elem是一个char数组时,C++中的std::size(elem)是定义良好的,但是当elem是一个char*const char*时,它将无法编译。您可以在这里看到。 - aniliitb10
如果tmp是堆栈分配的并且超出范围,但数组的生命周期更长,那么#2会导致问题(悬空指针)吗? - William Bradley
@WilliamBradley 是的,你将访问无效的内存。 - Bersan

20
str.copy(cstr, str.length()+1); // since C++11
cstr[str.copy(cstr, str.length())] = '\0';  // before C++11
cstr[str.copy(cstr, sizeof(cstr)-1)] = '\0';  // before C++11 (safe)

在C++中最好避免使用C语言代码,因此应该选择std::string::copy而不是strcpy


16

最简单的方法是这样的

std::string myWord = "myWord";
char myArray[myWord.size()+1];//as 1 char space for null is also required
strcpy(myArray, myWord.c_str());

20
在C++中,数组大小必须是编译时常量。 - interjay
1
@PhaniRithvij,除非你只针对允许此语言扩展的编译器,否则这是错误的,即使是在这种情况下,这仍然是不良实践。 - interjay

6

只需使用 strcpy 将字符串复制到数组中即可。


5
尝试这种方法,它应该能够工作。
string line="hello world";
char * data = new char[line.size() + 1];
copy(line.begin(), line.end(), data);
data[line.size()] = '\0'; 

4
尝试使用strcpy(),但正如Fred所说,这是C++,不是C。

3

如果你不知道字符串的大小,你可以动态地分配一个数组:

auto tab2 = std::make_unique<char[]>(temp.size() + 1);
std::strcpy(tab2.get(), temp.c_str());

3
您可以使用strcpy()函数,如下所示:
strcpy(tab2, tmp.c_str());

注意缓冲区溢出。


1
如果您使用的是C++11或更高版本,我建议使用std::snprintf而不是std::strcpystd::strncpy,因为它更安全(即您可以确定写入缓冲区的字符数),并且它会为您添加字符串的空终止符(所以您不必担心它)。代码示例如下:
#include <string>
#include <cstdio>

std::string tmp = "cat";
char tab2[1024];
std::snprintf(tab2, sizeof(tab2), "%s", tmp.c_str());

在C++17中,你有这个替代方案:

#include <string>
#include <cstdio>
#include <iterator>

std::string tmp = "cat";
char tab2[1024];
std::snprintf(tab2, std::size(tab2), "%s", tmp.c_str());

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接