C++: string<-->char
1. char*、char[] 与 std::string 之间的区别:
char*是一个指向字符的指针,是一个内置类型。可以指向一个字符,也可以表示字符数组的首地址(首字符的地址)。我们更多的时候是用的它的第二的功能,来表示一个字符串,功能与字符串数组char ch[n]一样,表示字符串时,最后有一个 '\0'结束符作为字符串的结束标志。
#include <iostream> int main() { char ch1 = 'c'; char ch2[12] = "Hello Wrold"; char* pch1 = "string"; char* pch2 = ch2; char* pch3 = &ch1; char* pch4 = &ch2[2]; std::cout << ch2 << std::endl; // 输出ch2[0]到\0之前的所有字符 std::cout << pch1 << std::endl; // 输出ch1[0]到\0之前的所有字符 std::cout << pch2 << std::endl; // 输出ch2[0]到\0之前的所有字符 std::cout << pch4 << std::endl; // 输出ch2[2]到\0之前的所有字符 std::cout << *pch3 << std::endl; // 解引用pch3,输出pch3指向的字符 std::cout << *pch4 << std::endl; // 解引用pch4,输出pch4指向的字符 return 0; }
输出:
Hello Wrold string Hello Wrold llo Wrold c l
char p[], 表示 p 是一个字符串的数组;
std::string s, 表示 s 是一个 std::string 类的对象。
#include <iostream>
int main() { char p1[] = "12345"; char* p2 = "12345"; std::string p3 = "12345"; std::cout << "sizeof(p1) is: " << sizeof(p1) << std::endl; std::cout << "strlen(p1) is: " << strlen(p1) << std::endl; std::cout << "sizeof(p2) is: " << sizeof(p2) << std::endl; std::cout << "strlen(p2) is: " << strlen(p2) << std::endl; std::cout << "sizeof(p3) is: " << sizeof(p3) << std::endl; std::cout << "strlen(p3) is: " << strlen(p3.c_str()) << std::endl; std::cout << "length(p3) is: " << p3.length() << std::endl; std::cout << "capacity(p3) is: " << p3.capacity() << std::endl; return 0; }
输出结果如下:
sizeof(p1) is: 6 strlen(p1) is: 5 sizeof(p2) is: 8 strlen(p2) is: 5 sizeof(p3) is: 24 strlen(p3) is: 5 length(p3) is: 5 capacity(p3) is: 22
p1是 char 型数组名称,sizeof(p1)表示数组的长度(整个数组所占的字节数);
p2是指向 char 类型的指针,sizeof(p2)表示其所指向的地址值所占的字节数;
p3是 std::string 类型的对象,sizeof(p3)是 std::string 类型所占空间的大小,无论赋给它多长的字符串,sizeof(p3)都是固定值28;
strlen函数统计字符串的长度,但不包含结束符’\0’,std::string 类的 length 函数同样是统计字符串长度,std::string 类的 capacity 函数的返回值一定会大于等于字符串的长度,std::string 会预先分配一定的空间,空间不足时会重新分配。
2. char*、char[] 与 std::string 之间的转换
首先必须了解,string可以被看成是以字符为元素的一种容器。字符构成序列(字符串)。有时候在字符序列中进行遍历,标准的string类提供了STL容器接口。具有一些成员函数比如begin()、end(),迭代器可以根据他们进行定位。
注意,与char*不同的是,string不一定以NULL('\0')结束。string长度可以根据length()得到,string可以根据下标访问。所以,不能将string直接赋值给char*。
(1)string 转换成 char*
如果要将string直接转换成const char *类型,可以直接赋值,string有2个函数可以运用。一个是.c_str(),一个是data成员函数。
#include <iostream> #include <string> int main() { std::string str = "abcdeg"; const char* k = str.c_str(); const char* t = str.data(); printf("%s%s\n", k, t); std::cout << k << t << std::endl; return 0; }
如上,都可以输出。内容是一样的。但是只能转换成const char*,如果去掉const编译不能通过。
那么,如果要转换成char*,可以用string的一个成员函数copy实现。
#include <iostream> #include <string> int main() { std::string str = "abcdefg"; int len = str.length(); char* data = (char *)malloc((len + 1) * sizeof(char)); str.copy(data, len, 0); printf("%s\n", data); std::cout << data << std::endl; return 0; }
(2)string 转换成 char[]
不可以直接赋值。可以循环char*字符串逐个字符赋值,也可以使用strcpy_s等函数(需调用string对象的c_str函数,返回类型为const char* )。
这样的转换不可直接赋值。
#include <iostream> #include <string> int main() { std::string str = "dagah"; char ch[8]; int i = 0; for( ; i < str.length(); ++i) { ch[i] = str[i]; } ch[i] = '\0'; printf("%s\n", ch); std::cout << ch << std::endl; return 0; }
(3)char* 转换成 string
可以直接赋值。
#include <iostream> #include <string> int main() { char* ch = "adghrtyh"; std::string str = ch;
printf("%s\n", str.c_str()); std::cout << str << std::endl; return 0; }
不过这个是会出现问题的。
有一种情况我要说明一下。当我们定义了一个string类型之后,用printf("%s", str);输出是会出问题的。这是因为“%s”要求后面的对象的首地址。但是string不是这样的一个类型。所以肯定出错。
(4)char[] 转换成 string
这个也可以直接赋值。但是也会出现上面的问题。需要同样的处理。
(5)char* 转换成 char []
不能直接赋值,可以循环 char* 字符串逐个字符赋值,也可以使用strcpy_s等函数。
char *p="ertyu";
char r[10];
strcpy(r,p);
(6)char[] 转换成 char*
可以直接赋值。
问题:
1、char* pch = "abc"; // caution:ISO C++11 doesn't allow conversion from string literal to 'char*'
系统为可执行文件写下常量字符串,保存在可执行文件里,运行的时候加载到内存中,无法修改。
解决办法:
A、标准方法:将指针转换为char const *类型
char const* pch = "abc";
B、将字符串强制转换为char*类型
char* pch = (char*)"abc";
2、char *pch = 'a';
char *pch = &'a';
第一行由于'a'是一个char类型的字符,并不是一个有效的地址,无法用来初始化char*
第二行由于无法直接取到'a'这个char类型字符的地址。
解决办法:
A、动态内存申请:
char* pch = new char('a');
B、初始化一个新变量:
char ch = 'a';
char* pch = &ch;
注意:char *pch=ch是错误的,因为ch是一个char型变量的变量名,并不是一个有效地址。
3、Q: What is the difference between these initializations?
char a[] = "string literal";
char *p = "string literal";
My program crashes if I try to assign a new value to p[i].
A: A string literal (the formal term for a double-quoted string in C source) can be used in two slightly different ways:
As the initializer for an array of char, as in the declaration of char a[] , it specifies the initial values of the characters in that array (and, if necessary, its size).
Anywhere else, it turns into an unnamed, static array of characters, and this unnamed array may be stored in read-only memory, and which therefore cannot necessarily be modified. In an expression context, the array is converted at once to a pointer, as usual (see section 6), so the second declaration initializes p to point to the unnamed array's first element.
Some compilers have a switch controlling whether string literals are writable or not (for compiling old code), and some may have options to cause string literals to be formally treated as arrays of const char (for better error catching).
C and C++ differ in the type of the string literal. In C the type is array of char and in C++ it is constant array of char. In any case, you are not allowed to change the characters of the string literal, so the const in C++ is not really a restriction but more of a type safety thing. A conversion from const char* to char* is generally not possible without an explicit cast for safety reasons. But for backwards compatibility with C the language C++ still allows assigning a string literal to a char* and gives you a warning about this conversion being deprecated.
4、int/double 与 char*/std::string的转换
1 //------------------------------------------------- 2 // double/int --> char* 3 // itoa 不是标准库函数 4 5 // int-->char* 6 int digit1 = 167; 7 char str1[20]; 8 sprintf(str1, "%d", digit1); 9 10 // double-->char* 11 double digit2 = 168.2; 12 char str2[20]; 13 sprintf(str2, "%f", digit2); 14 15 // link 16 char* str3 = "Hello"; 17 char* str4 = "World"; 18 19 // 1 20 char str5[20]; 21 strcpy(str5, str3); 22 strcat(str5, str4); 23 24 // 2 25 char str6[20]; 26 sprintf(str6, "%s%s", str1, str2); 27 28 // 两个double转为char* 29 double digit7 = 12.3; 30 double digit8 = 23.4; 31 char str7[20]; 32 sprintf(str7, "%f%f", digit7, digit8); 33 //------------------------------------------------- 34 35 36 //------------------------------------------------- 37 // char*-->double/int 38 // atoi atof 39 // ... 40 41 double digit9 = atof("123"); 42 43 //------------------------------------------------- 44 45 46 //------------------------------------------------- 47 // double/int --> std::string 48 // std::to_string() 49 double digit11 = 451.7; 50 std::string str11 = "score" + std::to_string(digit11); 51 //------------------------------------------------- 52 53 54 //------------------------------------------------- 55 // std::string-->double/int 56 // std::stoi std::stof std::stol 57 std::string str12("123"); 58 double digit12 = std::stof(str12); 59 //-------------------------------------------------
参考:
https://stackoverflow.com/questions/28861475/conversion-from-string-literal-to-char
https://stackoverflow.com/questions/1704407/what-is-the-difference-between-char-s-and-char-s/1704433#1704433
https://stackoverflow.com/questions/164194/why-do-i-get-a-segmentation-fault-when-writing-to-a-string-initialized-with-cha
https://stackoverflow.com/questions/9650058/deprecated-conversion-from-string-literal-to-char
https://stackoverflow.com/questions/1524356/c-deprecated-conversion-from-string-constant-to-char
http://c-faq.com/decl/strlitinit.html
https://www.codeguru.com/cpp/cpp/cpp_mfc/general/article.php/c6967/Constant-Pointers-and-Pointers-to-Constants.htm
https://blog.csdn.net/doem97/article/details/51730225