1. char*胳螟、char[] 與 std::string 之間的區(qū)別
char*是一個(gè)指向字符的指針糖耸,是一個(gè)內(nèi)置類型嘉竟【腧剑可以指向一個(gè)字符审丘,也可以表示字符數(shù)組的首地址(首字符的地址)滩报。我們更多的時(shí)候是用的它的第二的功能,來表示一個(gè)字符串可训,功能與字符串?dāng)?shù)組char ch[n]一樣握截,表示字符串時(shí),最后有一個(gè) '\0'結(jié)束符作為字符串的結(jié)束標(biāo)志胯努。
#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 是一個(gè)字符串的數(shù)組脊另;
std::string s, 表示 s 是一個(gè) std::string 類的對(duì)象。
#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;
}
輸出結(jié)果如下:
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 型數(shù)組名稱,sizeof(p1)表示數(shù)組的長(zhǎng)度(整個(gè)數(shù)組所占的字節(jié)數(shù));
p2是指向 char 類型的指針反粥,sizeof(p2)表示其所指向的地址值所占的字節(jié)數(shù);
p3是 std::string 類型的對(duì)象,sizeof(p3)是 std::string 類型所占空間的大小尾组,無論賦給它多長(zhǎng)的字符串,sizeof(p3)都是固定值28;
strlen函數(shù)統(tǒng)計(jì)字符串的長(zhǎng)度,但不包含結(jié)束符’\0’,std::string 類的 length 函數(shù)同樣是統(tǒng)計(jì)字符串長(zhǎng)度咆耿,std::string 類的 capacity 函數(shù)的返回值一定會(huì)大于等于字符串的長(zhǎng)度,std::string 會(huì)預(yù)先分配一定的空間,空間不足時(shí)會(huì)重新分配吻商。
2. char*艾帐、char[] 與 std::string 之間的轉(zhuǎn)換
首先必須了解捎稚,string可以被看成是以字符為元素的一種容器。字符構(gòu)成序列(字符串)腥泥。有時(shí)候在字符序列中進(jìn)行遍歷,標(biāo)準(zhǔn)的string類提供了STL容器接口。具有一些成員函數(shù)比如begin()、end()孩等,迭代器可以根據(jù)他們進(jìn)行定位。
注意权她,與char*不同的是,string不一定以NULL('\0')結(jié)束步清。string長(zhǎng)度可以根據(jù)length()得到询微,string可以根據(jù)下標(biāo)訪問书聚。所以,不能將string直接賦值給char*。
2.1. string 轉(zhuǎn)換成 char*
如果要將string直接轉(zhuǎn)換成const char *類型鸽心,可以直接賦值太闺,string有2個(gè)函數(shù)可以運(yùn)用蟀淮。一個(gè)是.c_str(),一個(gè)是data成員函數(shù)逃延。
#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;
}
如上讽膏,都可以輸出。內(nèi)容是一樣的拄丰。但是只能轉(zhuǎn)換成const char*府树,如果去掉const編譯不能通過。
那么料按,如果要轉(zhuǎn)換成char*奄侠,可以用string的成員函數(shù)copy實(shí)現(xiàn)。
#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.2. string 轉(zhuǎn)換成 char[]
不可以直接賦值载矿÷⒊保可以循環(huán)string字符串逐個(gè)字符賦值,也可以使用strcpy_s等函數(shù)(需調(diào)用string對(duì)象的c_str函數(shù)闷盔,返回類型為const char* )弯洗。
這樣的轉(zhuǎn)換不可直接賦值。
#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;
}
2.3. char* 轉(zhuǎn)換成 string
可以直接賦值逢勾。
#include <string>
int main()
{
char* ch = "adghrtyh";
std::string str = ch;
printf("%s\n", str.c_str());
std::cout << str << std::endl;
return 0;
}
不過牡整,當(dāng)我們定義了一個(gè)string類型之后,用printf("%s", str);輸出是會(huì)出問題的溺拱。這是因?yàn)椤?s”要求后面的對(duì)象的首地址逃贝,但是string不是這樣的一個(gè)類型。所以肯定出錯(cuò)迫摔。
2.4. char[] 轉(zhuǎn)換成 string
這個(gè)也可以直接賦值秋泳。但是也會(huì)出現(xiàn)上面的問題。需要同樣的處理攒菠。
2.5. char* 轉(zhuǎn)換成 char []
不能直接賦值迫皱,可以循環(huán) char* 字符串逐個(gè)字符賦值,也可以使用strcpy_s等函數(shù)。
char *p="ertyu";
char r[10];
strcpy(r,p);
2.6. char[] 轉(zhuǎn)換成 char*
可以直接賦值卓起。
3. 問題
1和敬、char* pch = "abc"; // caution:ISO C++11 doesn't allow conversion from string literal to 'char*'
系統(tǒng)為可執(zhí)行文件寫下常量字符串,保存在可執(zhí)行文件里戏阅,運(yùn)行的時(shí)候加載到內(nèi)存中昼弟,無法修改。
解決辦法:
- A奕筐、標(biāo)準(zhǔn)方法:將指針轉(zhuǎn)換為char const *類型
char const* pch = "abc";
- B舱痘、將字符串強(qiáng)制轉(zhuǎn)換為char*類型
char* pch = (char*)"abc";
2、
char* pch = 'a';
char* pch = &'a';
第一行由于'a'是一個(gè)char類型的字符离赫,并不是一個(gè)有效的地址芭逝,無法用來初始化char*
第二行無法直接取到'a'這個(gè)char類型字符的地址。
解決辦法:
-A渊胸、動(dòng)態(tài)內(nèi)存申請(qǐng):
char* pch = new char('a');
-B旬盯、初始化一個(gè)新變量:
char ch = 'a';
char* pch = &ch;
注意:char *pch=ch是錯(cuò)誤的,因?yàn)閏h是一個(gè)char型變量的變量名翎猛,并不是一個(gè)有效地址胖翰。
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的轉(zhuǎn)換
//-------------------------------------------------
// double/int --> char*
// itoa 不是標(biāo)準(zhǔn)庫函數(shù)
// int-->char*
int digit1 = 167;
char str1[20];
sprintf(str1, "%d", digit1);
// double-->char*
double digit2 = 168.2;
char str2[20];
sprintf(str2, "%f", digit2);
// link
char* str3 = "Hello";
char* str4 = "World";
// 1
char str5[20];
strcpy(str5, str3);
strcat(str5, str4);
// 2
char str6[20];
sprintf(str6, "%s%s", str1, str2);
// 兩個(gè)double轉(zhuǎn)為char*
double digit7 = 12.3;
double digit8 = 23.4;
char str7[20];
sprintf(str7, "%f%f", digit7, digit8);
//-------------------------------------------------
//-------------------------------------------------
// char*-->double/int
// atoi atof
// ...
double digit9 = atof("123");
//-------------------------------------------------
//-------------------------------------------------
// double/int --> std::string
// std::to_string()
double digit11 = 451.7;
std::string str11 = "score" + std::to_string(digit11);
//-------------------------------------------------
//-------------------------------------------------
// std::string-->double/int
// std::stoi std::stof std::stol
std::string str12("123");
double digit12 = std::stof(str12);
//-------------------------------------------------
5. 參考
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