如何将std :: string转换为const char *或char *?
如何将<code>std::string转换为char*
或const char*
?
#1楼
看看这个:
string str1("stackoverflow");
const char * str2 = str1.c_str();
但是请注意,这将返回const char *
。对于char *
,请使用strcpy
将其复制到另一个char
数组中。
#2楼
char* result = strcpy((char*)malloc(str.length()+1), str.c_str());
#3楼
C ++ 17
C ++ 17 (即将发布的标准)更改了模板basic_string
的提要,增加了data()
的非const重载:
charT* data() noexcept;
返回:指针p,使得[0,size()]中每个i的p + i ==&operator。
CharT const *
来自std::basic_string<CharT>
std::string const cstr = { "..." };
char const * p = cstr.data(); // or .c_str()
CharT *
来自std::basic_string<CharT>
std::string str = { "..." };
char * p = str.data();
C ++ 11
CharT const *
来自std::basic_string<CharT>
std::string str = { "..." };
str.c_str();
CharT *
来自std::basic_string<CharT>
从C ++ 11开始,该标准规定:
basic_string
对象中的类似于char的对象应连续存储。 也就是说,对于任何basic_string
对象s
,对于所有n
值,标识&*(s.begin() + n) == &*s.begin() + n
都应成立,以使0 <= n < s.size()
。
const_reference operator[](size_type pos) const;
reference operator[](size_type pos);
返回:
*(begin() + pos)
如果pos < size()
,否则以值CharT()
引用CharT
的对象; 参考值不得修改。
const charT* c_str() const noexcept;
const charT* data() const noexcept;
返回:指针p,使得
[0,size()]
每个i
具有p + i == &operator[](i)
。
有几种可能的方法来获取非const字符指针。
1.使用C ++ 11的连续存储
std::string foo{"text"};
auto p = &*foo.begin();
专业版
- 简单而简短
- 快速(仅包含副本的方法)
缺点
- 最终的
'\\0'
不会被更改,也不一定是非常量存储器的一部分。
2.使用std::vector<CharT>
std::string foo{"text"};
std::vector<char> fcv(foo.data(), foo.data()+foo.size()+1u);
auto p = fcv.data();
专业版
- 简单
- 自动内存处理
- 动态
缺点
- 需要字符串复制
3.如果N
是编译时间常数(并且足够小) std::array<CharT, N>
请使用std::array<CharT, N>
std::string foo{"text"};
std::array<char, 5u> fca;
std::copy(foo.data(), foo.data()+foo.size()+1u, fca.begin());
专业版
- 简单
- 堆栈内存处理
缺点
- 静态的
- 需要字符串复制
4.原始内存分配和自动删除存储
std::string foo{ "text" };
auto p = std::make_unique<char[]>(foo.size()+1u);
std::copy(foo.data(), foo.data() + foo.size() + 1u, &p[0]);
专业版
- 内存占用少
- 自动删除
- 简单
缺点
- 需要字符串复制
- 静态(动态用法需要更多代码)
- 特征少于向量或数组
5.原始内存分配和手动处理
std::string foo{ "text" };
char * p = nullptr;
try
{p = new char[foo.size() + 1u];std::copy(foo.data(), foo.data() + foo.size() + 1u, p);// handle stuff with pdelete[] p;
}
catch (...)
{if (p) { delete[] p; }throw;
}
专业版
- 最大的“控制”
骗局
- 需要字符串复制
- 对错误的最大责任/敏感性
- 复杂
#4楼
对const char *
使用.c_str()
方法。
您可以使用&mystring[0]
获取char *
指针,但是有一些陷阱:您不一定会获得零终止的字符串,也无法更改字符串的大小。 您尤其要注意不要在字符串末尾添加字符,否则会导致缓冲区溢出(并可能崩溃)。
在C ++ 11之前,无法保证所有字符都将是同一连续缓冲区的一部分,但实际上,所有已知的std::string
实现都以这种方式工作; 请参见“&s [0]”是否指向std :: string中的连续字符? 。
请注意,许多string
成员函数将重新分配内部缓冲区,并使您可能保存的所有指针无效。 最好立即使用它们,然后丢弃。
#5楼
如果只想将std::string
传递给需要const char*
的函数,则可以使用
std::string str;
const char * c = str.c_str();
如果要获取可写副本,例如char *
,则可以执行以下操作:
std::string str;
char * writable = new char[str.size() + 1];
std::copy(str.begin(), str.end(), writable);
writable[str.size()] = '\0'; // don't forget the terminating 0// don't forget to free the string after finished using it
delete[] writable;
编辑 :请注意,以上内容并非异常安全。 如果在new
呼叫和delete
呼叫之间发生任何故障,您将泄漏内存,因为没有任何东西会自动为您呼叫delete
。 有两种直接的方法可以解决此问题。
boost :: scoped_array
当超出范围时, boost::scoped_array
将为您删除内存:
std::string str;
boost::scoped_array<char> writable(new char[str.size() + 1]);
std::copy(str.begin(), str.end(), writable.get());
writable[str.size()] = '\0'; // don't forget the terminating 0// get the char* using writable.get()// memory is automatically freed if the smart pointer goes
// out of scope
std :: vector
这是标准方式(不需要任何外部库)。 您使用std::vector
,它将完全为您管理内存。
std::string str;
std::vector<char> writable(str.begin(), str.end());
writable.push_back('\0');// get the char* using &writable[0] or &*writable.begin()
#6楼
给出说...
std::string x = "hello";
从“字符串”中获取“ char *”或“ const char *”
如何获得在x
保留在作用域且未进一步修改的情况下有效的字符指针
C ++ 11简化了事情; 以下所有都可以访问同一内部字符串缓冲区:
const char* p_c_str = x.c_str();
const char* p_data = x.data();
char* p_writable_data = x.data(); // for non-const x from C++17
const char* p_x0 = &x[0];char* p_x0_rw = &x[0]; // compiles iff x is not const...
以上所有指针将具有相同的值 -缓冲区中第一个字符的地址。 即使是空字符串也具有“缓冲区中的第一个字符”,因为C ++ 11保证在显式分配的字符串内容之后始终保留一个额外的NUL / 0终止符(例如std::string("this\\0that", 9)
的缓冲区将保存"this\\0that\\0"
)。
鉴于以上任何指针:
char c = p[n]; // valid for n <= x.size()// i.e. you can safely read the NUL at p[x.size()]
仅针对非const
指针p_writable_data
和&x[0]
:
p_writable_data[n] = c;
p_x0_rw[n] = c; // valid for n <= x.size() - 1// i.e. don't overwrite the implementation maintained NUL
在字符串的其他地方写入NUL 不会更改string
的size()
; string
可以包含任意数量的NUL- std::string
(在C ++ 03中相同)没有对它们进行特殊处理。
在C ++ 03中 ,事情要复杂得多(关键区别突出显示 ):
x.data()
- 将
const char*
返回到字符串的内部缓冲区,这不是标准要求以NUL结束的字符串(即可能是['h', 'e', 'l', 'l', 'o']
后跟未初始化的)或垃圾值,并且对其具有不确定行为的意外访问)。x.size()
字符可以安全读取,即x[0]
到x[x.size() - 1]
- 对于空字符串,可以确保可以安全地向其添加0的一些非NULL指针(欢呼!),但是您不应该取消引用该指针。
- 将
&x[0]
- 对于空字符串,它具有未定义的行为 (21.3.4)
- 例如,给定
f(const char* p, size_t n) { if (n == 0) return; ...whatever... }
f(const char* p, size_t n) { if (n == 0) return; ...whatever... }
不得调用f(&x[0], x.size());
当x.empty()
-仅使用f(x.data(), ...)
。
- 例如,给定
- 否则,按照
x.data()
但:- 对于非
const
x
这将产生一个非const
char*
指针; 您可以覆盖字符串内容
- 对于非
- 对于空字符串,它具有未定义的行为 (21.3.4)
x.c_str()
- 将
const char*
返回到值的ASCIIZ(NUL终止)表示形式(即['h','e','l','l','o','\\ 0'])。 - 尽管很少有实现选择这样做,但是C ++ 03 Standard的措辞是允许字符串实现自由地从
x.data()
公开的可能非NUL终止的缓冲区中动态创建独特的NUL终止的缓冲区 。x.data()
和&x[0]
x.size()
+ 1个字符可以安全阅读。- 即使对于空字符串(['\\ 0'])也保证安全。
- 将
访问外部法律索引的后果
无论采用哪种方式获取指针,都不能比上述说明中保证的字符距离指针更远。 尝试执行此操作具有不确定的行为 ,即使是读取操作,也很有可能发生应用程序崩溃和垃圾结果,此外还可能批发数据,堆栈损坏和/或写入的安全漏洞。
这些指针什么时候失效?
如果调用某个string
成员函数来修改string
或保留更多容量,则上述任何一种方法事先返回的任何指针值都将无效 。 您可以再次使用这些方法来获取另一个指针。 (规则与对string
s进行迭代的规则相同)。
另请参见即使在x
离开范围或在下面进一步修改后,如何使字符指针仍然有效。
那么,哪个更好用?
从C ++ 11开始,对于ASCIIZ数据使用.c_str()
,对于“二进制”数据使用.data()
(在下面进一步解释)。
在C ++ 03中,除非确定.data()
足够,否则使用.c_str()
, .c_str()
&x[0]
更喜欢.data()
,因为它对于空字符串是安全的。
...试图了解程序足以在适当的时候使用data()
,否则您可能会犯其他错误...
.c_str()
保证的ASCII NUL'\\ 0'字符被许多函数用作指示相关和可安全访问数据结尾的.c_str()
值。 这适用于仅C ++的函数,例如fstream::fstream(const char* filename, ...)
以及与C共享的函数,例如strchr()
和printf()
。
鉴于C ++ 03的.c_str()
关于返回的缓冲区的保证是.data()
的超集,因此您始终可以安全地使用.c_str()
,但是人们有时却不会这样做,因为:
- 使用
.data()
可以与其他读取源代码的程序员通信,即该数据不是ASCIIZ(而是您使用字符串存储数据块(有时甚至不是真正的文本)),或者将其传递给另一个将其视为“二进制”数据块的函数。 这对于确保其他程序员的代码更改继续正确处理数据至关重要。 - 仅限于C ++ 03:您的
string
实现很有可能需要做一些额外的内存分配和/或数据复制,以准备NUL终止的缓冲区
进一步提示,如果函数的参数需要( const
) char*
但不坚持获取x.size()
,则该函数可能需要ASCIIZ输入,因此.c_str()
是一个不错的选择(函数需要知道文本在何处终止,因此,如果它不是一个单独的参数,则只能是一个约定,例如长度前缀或前哨或某个固定的预期长度。
即使在x
离开范围或进一步修改后,如何使字符指针有效
你需要的内容复制 string
x
到一个新的存储区域外x
。 此外部缓冲区可能在许多地方,例如另一个string
或字符数组变量,由于处于不同的范围(例如,名称空间,全局,静态,堆,共享内存,映射的内存),它的生存期可能与x
相同或不同。文件)。
要将文本从std::string x
复制到一个独立的字符数组中:
// USING ANOTHER STRING - AUTO MEMORY MANAGEMENT, EXCEPTION SAFE
std::string old_x = x;
// - old_x will not be affected by subsequent modifications to x...
// - you can use `&old_x[0]` to get a writable char* to old_x's textual content
// - you can use resize() to reduce/expand the string
// - resizing isn't possible from within a function passed only the char* addressstd::string old_x = x.c_str(); // old_x will terminate early if x embeds NUL
// Copies ASCIIZ data but could be less efficient as it needs to scan memory to
// find the NUL terminator indicating string length before allocating that amount
// of memory to copy into, or more efficient if it ends up allocating/copying a
// lot less content.
// Example, x == "ab\0cd" -> old_x == "ab".// USING A VECTOR OF CHAR - AUTO, EXCEPTION SAFE, HINTS AT BINARY CONTENT, GUARANTEED CONTIGUOUS EVEN IN C++03
std::vector<char> old_x(x.data(), x.data() + x.size()); // without the NUL
std::vector<char> old_x(x.c_str(), x.c_str() + x.size() + 1); // with the NUL// USING STACK WHERE MAXIMUM SIZE OF x IS KNOWN TO BE COMPILE-TIME CONSTANT "N"
// (a bit dangerous, as "known" things are sometimes wrong and often become wrong)
char y[N + 1];
strcpy(y, x.c_str());// USING STACK WHERE UNEXPECTEDLY LONG x IS TRUNCATED (e.g. Hello\0->Hel\0)
char y[N + 1];
strncpy(y, x.c_str(), N); // copy at most N, zero-padding if shorter
y[N] = '\0'; // ensure NUL terminated// USING THE STACK TO HANDLE x OF UNKNOWN (BUT SANE) LENGTH
char* y = alloca(x.size() + 1);
strcpy(y, x.c_str());// USING THE STACK TO HANDLE x OF UNKNOWN LENGTH (NON-STANDARD GCC EXTENSION)
char y[x.size() + 1];
strcpy(y, x.c_str());// USING new/delete HEAP MEMORY, MANUAL DEALLOC, NO INHERENT EXCEPTION SAFETY
char* y = new char[x.size() + 1];
strcpy(y, x.c_str());
// or as a one-liner: char* y = strcpy(new char[x.size() + 1], x.c_str());
// use y...
delete[] y; // make sure no break, return, throw or branching bypasses this// USING new/delete HEAP MEMORY, SMART POINTER DEALLOCATION, EXCEPTION SAFE
// see boost shared_array usage in Johannes Schaub's answer// USING malloc/free HEAP MEMORY, MANUAL DEALLOC, NO INHERENT EXCEPTION SAFETY
char* y = strdup(x.c_str());
// use y...
free(y);
想要从string
生成char*
或const char*
其他原因
因此,在上面,您已经了解了如何获取( const
) char*
以及如何独立于原始string
来复制文本,但是您可以如何处理呢? 随机散落的例子...
- 授予“ C”代码访问C ++
string
的文本的权限,如在printf("x is '%s'", x.c_str());
- 将
x
的文本复制到函数的调用者指定的缓冲区中(例如strncpy(callers_buffer, callers_buffer_size, x.c_str())
)或用于设备I / O的易失性内存(例如for (const char* p = x.c_str(); *p; ++p) *p_device = *p;
) - 将
x
的文本追加到已经包含一些ASCIIZ文本的字符数组中(例如strcat(other_buffer, x.c_str())
)-注意不要溢出缓冲区(在许多情况下,您可能需要使用strncat
) - 从函数返回
const char*
或char*
(可能出于历史原因-客户端正在使用您的现有API-或出于C兼容性,您不想返回std::string
,但确实想复制string
的数据给呼叫者的地方)- 注意不要在指针指向的本地
string
变量离开作用域之后返回调用者可能取消引用的指针 - 一些为不同的
std::string
实现编译/链接了共享对象的项目(例如STLport和native编译器)可以将数据作为ASCIIZ传递以避免冲突
- 注意不要在指针指向的本地
#7楼
尝试这个
std::string s(reinterpret_cast<const char *>(Data), Size);
#8楼
我正在使用具有许多功能的API,将char*
作为输入。
我创建了一个小班来面对这种问题,我实现了RAII习惯用法。
class DeepString
{DeepString(const DeepString& other);DeepString& operator=(const DeepString& other);char* internal_; public:explicit DeepString( const string& toCopy): internal_(new char[toCopy.size()+1]) {strcpy(internal_,toCopy.c_str());}~DeepString() { delete[] internal_; }char* str() const { return internal_; }const char* c_str() const { return internal_; }
};
您可以将其用作:
void aFunctionAPI(char* input);// other stuffaFunctionAPI("Foo"); //this call is not safe. if the function modified the //literal string the program will crash
std::string myFoo("Foo");
aFunctionAPI(myFoo.c_str()); //this is not compiling
aFunctionAPI(const_cast<char*>(myFoo.c_str())); //this is not safe std::string //implement reference counting and //it may change the value of other//strings as well.
DeepString myDeepFoo(myFoo);
aFunctionAPI(myFoo.str()); //this is fine
我之所以称为类DeepString
是因为它正在创建现有字符串的深层且唯一的副本( DeepString
是不可复制的)。
如何将std :: string转换为const char *或char *?相关推荐
- ncnn报无法将参数 1 从“std::string”转换为“const ncnn::DataReader
详细描述 无法将参数 1 从"std::string"转换为"const ncnn::DataReader",下面代码报错 std::string param_ ...
- 如何解决error C2664: “atof”: 不能将参数 1 从“std::string”转换为“const char *”
c_str c_str函数的返回值是const char*的,不能直接赋值给char*,所以就需要我们进行相应的操作转化,下面就是这一转化过程. c++语言提供了两种字符串实现,其中较原始的一种只是字 ...
- E0413: 不存在从 “std::string“ 到 “const char *“ 的适当转换函数
问题来源:PAT乙级1048 string A, B; cin >> A >> B;if(strcmp(A,B)<0){} //错误代码: E0413: 不存在从 &qu ...
- C++ std::string 转换为 UTF-8 编码
在一次项目工程开发中,需要部署端(C++)向云端(Java)发送 HTTP POST 请求,但是在云端接受参数时出现乱码现象,故在部署端发送请求时,对请求参数进行一次 UTF-8 转码. // st ...
- 将std::string转换为LPCSTR
方法:使用LPWSTR可以更改指向字符串的内容.不能使用LPCWSTR,因为它无法改变指向的内容 LPWSTR ConvertToLPWSTR( const std::string& s ) ...
- 关于std::string和 C-style string的一些知识点备忘
C++ 中的std::string和 C-style string 是两种不同的字符串,前者是标准库中定义的一个类,后者是字符数组的别名. C-style string:通常都以\0作为结尾. std ...
- 【C++标准库】std::string用法指南源码剖析
文章目录 1.ASCII码 (1)计算机如何表达字符 2.C 语言中的字符类型 char (1)思想:char 即整数 (3)C 语言帮手函数 (4)C语言中的字符串 (4)C 语言转义符 3.C++ ...
- 关于std::string 在 并发场景下 __grow_by_and_replace free was not allocated 的异常问题
使用string时发现了一些坑. 我们知道stl 容器并不是线程安全的,所以在使用它们的过程中往往需要一些同步机制来保证并发场景下的同步更新. 应该踩的坑还是一个不拉的踩了进去,所以还是记录一下吧. ...
- 几种C++ std::string和std::wstring相互转换的转换方法
第一种方法:调用WideCharToMultiByte()和MultiByteToWideChar(),代码如下(关于详细的解释,可以参考<windows核心编程>): #include ...
最新文章
- 导致大量kworker的原因_头上白发越长越多,原因有哪些?
- 删除有序vector中的重复值c++
- Java黑皮书课后题第5章:*5.9(找出得最高分的前两个学生)编写程序,提示用户输入学生的个数、每个学生名字及分数,最后显示获得最高分的学生
- Python常见数据结构整理
- [Oracle][Corruption]究竟哪些检查影响到 V$DATABASE_BLOCK_CORRUPTION
- mysql_ping()函数的作用以及返回值的类型正确的是,[单选] mysql_ping()函数的作用以及返回值的类型正确的是:()...
- Chef宣布100%开源,要走红帽模式?\n
- jsf el 表达式_JSF表达式语言– JSF EL
- 【Prison Break】第七天(4.3)
- matlab的otdr仿真,otdr测试曲线生成软件-OTDR测试曲线图仿真软件TrcView 4.0 官方免费版 - 河东下载站...
- 游戏开发人员需要了解的5种ASO技术,苹果游戏aso优化
- 【软考:网工】协议篇(非常重要)
- PayPal 更换汇率结算方式 降低手续费,PayPal汇率结算 改为 银行汇率结算
- 浅谈塑胶件产品结构设计的几个主要原则
- 链表实现电话簿(C++)
- Computer:计算机测试理论(开发/测试/上线)之DEV、SIT、UAT、PRD四套环境(测试环境/开发环境/生产环境)详细介绍之详细攻略
- 时间序列的平稳性与差分法
- fixed 和 fixed
- oracle 获取当月的1号_Oracle 获取当前年、月、日
- 软件设计师高频考点—套路题