cstring string CString QString char*之间的联系与区别
cstring 和 string.h头文件等价,cstring是c++版本的头文件,string.h是c版本的头文件,可以理解为同一个东西,面向char*
string 头文件定义了 c++标准库 中的一个类,包含各种字符串的操作,
CString 是MFC定义的一个类
QString 是Qt的一个字符串类
std::string
basic_string和strings的关系:using string = basic_string<char, char_traits<char>, allocator<char>>;
可以看到string其实就是basic_string的一个模板特化,模板详解
一、数据类型(int、float、long等)和string互相转换
点击查看代码
//string转int等其他数据类型
std::string strInt = "123";
std::string strFloat = "12.3";
int r5 = stoi(strInt);
auto r6 = stof(strFloat);
//其他数据类型转string
int myInt = 123;
float myFloat = 12.3;
std::string r7 = std::to_string(myInt);
std::string r8 = std::to_string(myFloat); //r8 = "12.300000"
还可以利用stringstream进行数据和字符串之间的互相转换
int转char*:itoa(vc中不支持itoa,只能使用_itoa),还可以使用sprintf
二、字符串互相转换
string和QString互相转换
QString qStr = QString::fromStdString(str) //string转QString
std::string str = qStr.toStdString() //QString转string
char*和string互相转换
//string转char*
auto r1 = str1.c_str(); //r1的类型为const char*
auto r2 = str1.data();
//char*转string
std::string r3 = ch1;
std::string r4 = ch2;
auto chToStr = std::string(ch1);
string和wstring转换
-
locale:
use_facet -
Unicode和ANSI以及UTF-8互相转换(需要包含windows.h)
MultiByteToWideChar()WideCharToMultiByte()
三、查找
函数原型
size_t find (const string& str, size_t pos = 0) const noexcept;
size_t find (const char* s, size_t pos = 0) const;
size_t find (const char* s, size_t pos, size_type n) const;
size_t find (char c, size_t pos = 0) const noexcept;
查找字符串str所在的位置,返回值类型为:std::string::size_type,没有找到则返回npos
npos在源码中有如下定义static constexpr auto npos{static_cast<size_type>(-1)};
其实就是-1
示例代码
std::string str2 = "123abc456def789xyz000ab";
std::string::size_type pos1 = str2.find("ab"); //pos1 = 3,返回值为"ab"开始的位置,字符串从0开始计数,如果没有找到返回npos
auto pos2 = str2.find("ab", 8); //pos2 = 21,从第8个位置开始查找,返回的是字符串从0开始的位置,不是从第8个开始的位置
实例1:判断字符串是否包含子串
实例2:记录字符串含有多少个子串
点击查看代码
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main()
{
string s = "12a345a67b89c00a";
size_t count = 0, index = 0;
while ((index = s.find('a', index)) != s.npos) //注意括号
{
count++;
index++; //此处index必须++,不然会进入死循环
}
if (s.find("345") != s.npos)
cout << "包含该子串:345" << endl;
cout << "含有" << count << "个子串:a" << endl;
return 0;
}
四、比较(大小写转换)
-
CString有函数compareNoCase()可以不区分大小写比较,string没有可以直接不区分大小写比较的函数,可以先用transform()将字符串全部转换为大写或小写再比较。
-
string比较可以用算术运算符(>,<,==,>=,<=),也可以用函数compare()
==和compare():==其实就是调用compare(),==操作符是inline调用compare函数,效果上是一样的;效率上就看编译器是否真的inline化了,如果是则开销相同,否则==就多一次函数调用的开销。
函数原型
int compare (const string& str) const noexcept;
int compare (size_t pos, size_t len, const string& str) const;
int compare (size_t pos, size_t len, const string& str,size_t subpos, size_t sublen) const;
int compare (const char* s) const;
int compare (size_t pos, size_t len, const char* s) const;
int compare (size_t pos, size_t len, const char* s, size_t n) const;
示例代码
std::string str3 = "abcdefXXX";
std::string str4 = "ABCDEFXXX";
if (str3 == str4)
std::cout << "str3 = str4" << std::endl;
else if (str3 > str4)
std::cout << "str3 > str4" << std::endl;
else
std::cout << "str3 < str4" << std::endl;
auto r9 = str3.compare(str4); //从第一个字符开始比较,所有字符相等返回0,大于返回1,小于返回-1(比较的是ascii码)
auto r10 = str3.compare(2, 3, "cde"); //r10 = 0,从第2个字符开始,比较接下来的3个字符是否相等
auto r11 = str3.compare(6, 3, str4, 6, 3);//r11 = 0,从第6个字符开始,比较接下来的3个字符是否相等
//不区分大小写比较
std::transform(str3.begin(), str3.end(), str3.begin(), ::toupper); //小写:tolower
auto r12 = str3.compare(str4); //r12 = 0
五、长度大小
size()和length()都可以获取string的大小,且两者没有任何区别,源码如下:
点击查看代码
_NODISCARD size_type length() const noexcept {
return _Mypair._Myval2._Mysize;
}
_NODISCARD size_type size() const noexcept {
return _Mypair._Myval2._Mysize;
}
示例代码
std::string s1 = "abcd";
std::string s2 = "abcdefgh";
auto l1 = strlen(ch1); //3
auto l2 = strlen(ch2); //3
auto l3 = str1.length();//3
auto l4 = str1.size(); //3
auto l5 = sizeof(s1); //40
auto l6 = sizeof(s2); //40
auto l7 = sizeof(std::string); //40,和编译器有关,x86是28,x64是40
六、替换
函数原型
string& replace(size_t pos, size_t len, const string& str);
string& replace(const_iterator i1, const_iterator i2, const string& str);
string& replace(size_t pos, size_t len, const string& str,size_t subpos, size_t sublen);
string& replace(size_t pos, size_t len, const char* s);
string& replace(const_iterator i1, const_iterator i2, const char* s);
string& replace(size_t pos, size_t len, const char* s, size_t n);
string& replace(const_iterator i1, const_iterator i2, const char* s, size_t n);
string& replace(size_t pos, size_t len, size_t n, char c);
string& replace(const_iterator i1, const_iterator i2, size_t n, char c);
template <class InputIterator>
string& replace(const_iterator i1, const_iterator i2,InputIterator first, InputIterator last);
string& replace(const_iterator i1, const_iterator i2, initializer_list<char> il);
示例代码
std::string str5 = "ab123aab123aaabab";
std::string str6 = "987654";
str5.replace(5, 2, "xxx"); //"ab123xxxb123aaabab",从str5的第5个字符开始连续2个字符替换为"xxx",意味着多了一个字符
str5.replace(5, 2, str6, 2, 3);//"ab123765xb123aaabab",从str5的第5个字符开始连续2个字符替换为:str6的第2个字符开始连续3个字符
替换所有符合条件的字符串
std::string& replace_all(std::string& str, const std::string& old_value, const std::string& new_value)
{
while (true) {
std::string::size_type pos(0);
if ((pos = str.find(old_value)) != std::string::npos)
str.replace(pos, old_value.length(), new_value);
else break;
}
return str;
}
replace_all(str5, "ab", "@@");
七、截取子串
注意:子串是返回值,不会修改原字符串
- 函数原型:
string substr (size_t pos = 0, size_t len = npos) const;
- 示例:
std::string str7 = str5.substr(2,3);//截取从第2(起始为0)个字符开始连续3个字符,第二个参数可选,没有则截取从第一个参数之后的所有字符
八、删除字符
函数原型
basic_string& erase(size_type pos = 0, size_type len = npos);
iterator erase(iterator p);
iterator erase(iterator first, iterator last);
示例代码
std::string str10("abcdefg");
str10.erase(str10.begin() + 2); //abdefg 删除从开始位置的第三个字符
str10.erase(4); //abde 删除从第四个位置开始后的所有字符
std::string str11("abcdefghijk");
str11.erase(2, 5); //abhijk 删除从第二个位置开始连续的五个字符
删除字符串中的空格
#include <iostream>
#include <string>
#include <cctype>
//删除字符串中的所有空格,返回一个新的字符串,源字符串不变
const std::string delete_all_space_new(const std::string& _str)
{
std::string str;
for (auto& c : _str)
{
if (!isblank(c))
str += c;
}
return str;
}
//删除字符串中的所有空格,返回原字符串(在原字符串的基础上删除空格)
const std::string delete_all_space_old(std::string& _str)
{
size_t index = 0;
while ((index = _str.find(' ', index)) != std::string::npos)
{
_str.erase(index, 1);
}
return _str;
}
//删除字符串首尾空格,返回原字符串
const std::string delete_headtail_space(std::string& _str)
{
_str.erase(0, _str.find_first_not_of(' '));
_str.erase(_str.find_last_not_of(' ') + 1);
return _str;
}
int main()
{
std::string s1(" a b c d e ");
std::string s2(" 1 234 5 6 7 890 ");
std::string s3(" 123 45 67 89 a b ");
std::cout << delete_all_space_new(s1) << std::endl;
std::cout << delete_all_space_old(s2) << std::endl;
std::cout << delete_headtail_space(s3) << std::endl;
return 0;
}
cctype用法,还可以用空字符串替换字符串中所有的空格来达到删除字符串中所有空格的目的
string根据分隔符转换为vector
vector<string> stringToVector(string str, char delim)
{
vector<string> vec;
size_t pos = 0;
while ((pos = str.find(delim, pos)) < str.npos)
{
vec.emplace_back(str.substr(0,pos));
str = str.substr(pos + 1);
}
return vec;
}
int main()
{
string s("aa,bb,cc,dd");
auto ret = stringToVector(s, ',');
system("pause");
return 0;
}
九、格式化
sprintf
点击查看代码
std::string & std_string_format(std::string & _str, const char * _Format, ...) {
std::string tmp;
va_list marker = NULL;
va_start(marker, _Format);
size_t num_of_chars = _vscprintf(_Format, marker);
if (num_of_chars > tmp.capacity()) {
tmp.resize(num_of_chars + 1);
}
vsprintf_s((char *)tmp.data(), tmp.capacity(), _Format, marker);
va_end(marker);
_str = tmp.c_str();
return _str;
}
十、其他常用函数
函数 | 用法 |
---|---|
char& at (size_t) | 返回具体位置的单个字符,也可以用数组形式 |
reverse(begin(),end()) | 翻转 |
swap(string&) | 交换 |
empty() | 判空 |
find_first_of(str) | 返回和str任意一个字符匹配的第一个字符位置 |
find_first_not_of(str) | 返回和str中任意一个字符都不匹配的第一个字符位置 |
find_last_of(str) | 返回和str任意一个字符匹配的最后一个字符位置 |
find_last_not_of(str) | 返回最后一个和str任意一个字符都不匹配的字符的位置 |
size_t find_last_of (const char* s, size_t pos, size_t n) const;
s:要查找的子字符串 pos:结束的位置(从原字符串的第几个位置开始往前查找),n:要查找的子字符串s的大小(如果为0,函数始终返回npos)
size_t find_first_of (const char* s, size_t pos, size_t n) const;
s:要查找的子字符串 pos:开始查找的位置(从原字符串中第几个位置开始查找),n:要查找的子字符串s的大小(如果为0,函数始终返回npos)
示例
string str("abcdbegbh");
auto ret7 = str.find_first_of('b', 3); // 4
auto ret2 = str.find_last_of('b', 4); // 4
完整代码:
点击查看代码
#include <iostream>
#include <string>
#include <algorithm> //transform
std::string& replace_all(std::string& str, const std::string& old_value, const std::string& new_value)
{
while (true) {
std::string::size_type pos(0);
if ((pos = str.find(old_value)) != std::string::npos)
str.replace(pos, old_value.length(), new_value);
else break;
}
return str;
}
int main()
{
char ch1[] = "abc";
//char ch0[3] = "abc"; //错误,abc后面还有一个\0,因此此处的3因该为4(大于4也可以)
const char* ch2 = "bcd";
std::string str1 = "abc";
//string转char*
auto r1 = str1.c_str(); //r1的类型为const char*
auto r2 = str1.data();
//char*转string
std::string r3 = ch1;
std::string r4 = ch2;
auto chToStr = std::string(ch1);
//获取长度
std::string s1 = "abcd";
std::string s2 = "abcdefgh";
auto l1 = strlen(ch1); //3
auto l2 = strlen(ch2); //3
auto l3 = str1.length();//3
auto l4 = str1.size(); //3
auto l5 = sizeof(s1); //40
auto l6 = sizeof(s2); //40
auto l7 = sizeof(std::string); //40,和编译器有关,x86是28,x64是40
//string转int等其他数据类型
std::string strInt = "123";
std::string strFloat = "12.3";
int r5 = stoi(strInt);
auto r6 = stof(strFloat);
//其他数据类型转string
int myInt = 123;
float myFloat = 12.3;
std::string r7 = std::to_string(myInt);
std::string r8 = std::to_string(myFloat); //r8 = "12.300000"
//查找
std::string str2 = "123abc456def789xyz000ab";
std::string::size_type pos1 = str2.find("ab"); //pos1 = 3,返回值为"ab"开始的位置,字符串从0开始计数,如果没有找到返回npos
auto pos2 = str2.find("ab", 8); //pos2 = 21,从第8个位置开始查找,返回的是字符串从0开始的位置,不是从第8个开始的位置
//find
std::string str8 = "0123456789";
auto rr1 = str8.find_first_of("75"); //5
auto rr2 = str8.find_first_not_of("75"); //0
auto rr3 = str8.find_last_of("75"); //7
auto rr4 = str8.find_last_not_of("75"); //9
//比较
std::string str3 = "abcdefXXX";
std::string str4 = "ABCDEFXXX";
if (str3 == str4)
std::cout << "str3 = str4" << std::endl;
else if (str3 > str4)
std::cout << "str3 > str4" << std::endl;
else
std::cout << "str3 < str4" << std::endl;
auto r9 = str3.compare(str4); //从第一个字符开始比较,所有字符相等返回0,大于返回1,小于返回-1(比较的是ascii码)
auto r10 = str3.compare(2, 3, "cde"); //r10 = 0,从第2个字符开始,比较接下来的3个字符是否相等
auto r11 = str3.compare(6, 3, str4, 6, 3);//r11 = 0,从第6个字符开始,比较接下来的3个字符是否相等
//不区分大小写比较
std::transform(str3.begin(), str3.end(), str3.begin(), ::toupper); //小写:tolower
auto r12 = str3.compare(str4); //r12 = 0
//替换
std::string str5 = "ab123aab123aaabab";
std::string str6 = "987654";
str5.replace(5, 2, "xxx"); //"ab123xxxb123aaabab",从str5的第5个字符开始连续2个字符替换为"xxx",意味着多了一个字符
str5.replace(5, 2, str6, 2, 3);//"ab123765xb123aaabab",从str5的第5个字符开始连续2个字符替换为:str6的第2个字符开始连续3个字符
replace_all(str5, "ab", "@@");
std::string str9(" ab c d e ");
replace_all(str9, " ", ""); //删除字符串中的所有空格
//反转
reverse(str5.begin(), str5.end());
//交换
str5.swap(str6);
//判空
str5.empty(); //字符串为空返回true,不为空返回false
//截取字串
std::string str7 = str5.substr(2, 3); //截取从第3个字符开始连续3个字符,第二个参数可选,没有则截取从第一个参数之后的所有字符
std::string str10("abcdefg");
str10.erase(str10.begin() + 2); //abdefg 删除从开始位置的第三个字符
str10.erase(4); //abde 删除从第四个位置开始后的所有字符
std::string str11("abcdefghijk");
str11.erase(2, 5); //abhijk 删除从第二个位置开始连续的五个字符
system("pause");
return 0;
}