String类的基本用法
auto关键字:
auto不能作为函数的参数,可以做返回值,但是建议谨慎使用.
当在同一行声明多个变量时,这些变量必须是相同的类型,否则编译器将会报错,因为编译器实际 只对第一个类型进行推导,然后用推导出来的类型定义其他变量。
auto不能直接用来声明数组.
代码如下所示:
// auto不能做参数
//void func0(auto a = 0)//error
{ }
//auto可以作返回值
int func1()
{return 10;
}
auto func2()
{return func1();
}
int main()
{int a = 10;auto b = a;auto c = 'a';auto d = func1();// 编译报错:error C3531: “e”: 类型包含“auto”的符号必须具有初始值设定项//auto e;//没有初始值cout << typeid(b).name() << endl;cout << typeid(c).name() << endl;cout << typeid(d).name() << endl;auto array[] = { 4, 5, 6 };//error ,数组不能具有其中包含“auto”的元素类型auto ret = func2();//auto可以做返回值,但需谨慎使用// auto的用武之地:auto可以简写将std::map<std::string, std::string>::iterator简写为auto//std::map<std::string, std::string>::iterator it = dict.begin();//auto it = dict.begin();return 0;
}
string有以下几种构造函数:
string() //无参构造
string (const char* s) //带参构造
string(const string &s)//拷贝构造
npos(要多长取多长)
string可以进行下标访问,代码如下所示:
void test_string()
{string s2("hello world");cout<< s2 << endl;//s2[0] = 'x';//指定位置修改,在下标为0的地方修改为x//cout << s2 << endl;//下标+[]遍历for (size_t i = 0; i < s2.size(); i++)//for循环遍历 ,自动获取大小:s2.size(){cout << s2[i] << " ";}cout << endl;
}
迭代器:
string::iterator it = s2.begin();while (it != s2.end()){//*it += 2;//hello world字符+2输出为:j g n n q " y q t n f;也就是说可以改变变量的值cout << *it << " ";++it;}
在上述代码中:begin是开始的位置,end是有效字符的下一个位置.
正向迭代器:
void test_string1()
{string s("hello world");//正向迭代器string::iterator it = s.begin();//begin是开始位置,end是有效字符下一个位置,例如字符串hello world: begin是h,end是d的下一个位置;while (it != s.end()){cout << *it << " ";++it;}
反向迭代器:
//反向迭代器:从最后一个字符开始输出string::reverse_iterator rit = s.rbegin();//rbegin是最后一个字符,rend是最开始字符的前一个while (rit != s.rend()){cout << *rit << " ";++rit;}
const迭代器:
const迭代器只能读不能写.
const string s1("hello world");//string::const_iterator cit = s3.begin();auto cit = s1.begin();//auto用法while (cit != s1.end()){//*cit += 2;//使用const会报错,cout << *cit << " ";++cit;}
范围for:
范围for:自动迭代,自动判断结束. 底层是iterator迭代器
//自动从s2中取变量给ch//for(auto ch:s2)//不加引用则不能修改值for (auto& ch : s2)//auto自动识别类型,加引用可以修改值{ch*=2;cout << ch << " ";}cout << endl;
}
reserve:
reserve提前开空间,避免扩容.
void test_string2()
{string s;s.reserve(100);//提前开100个空间size_t sz = s.capacity();cout << "capacity changed:" << sz << endl;
}
//在vs下
void test_string4()
{string s2("hello worldxxxxxxxxxxxxx");//一共有24个字符cout << s2.size() << endl;//24cout << s2.capacity() << endl << endl;//32s2.reserve(20);//当容量小于24,不会缩容cout << s2.size() << endl;cout << s2.capacity() << endl << endl;s2.reserve(28);//24<28<32,当容量在24和32之间,不会缩容cout << s2.size() << endl;cout << s2.capacity() << endl << endl;s2.reserve(40);//当40大于容量32,要2倍扩容cout << s2.size() << endl;cout << s2.capacity() << endl << endl;
}
头插和尾插:
void test_string1()
{string s("hello world");//s.push_back('x');//尾插s.push_back(' ');s.append("yyds");//尾插s += ' ';//尾插s += "city bu city";s.insert(0, "hello ");//在0的位置插入hello s.insert(5, "hello ");//在5的位置插入hello char ch = 't';s.insert(0, 1, ch);//在0的位置插入1个字符chs.insert(s.begin(), ch);cout << s << endl;
}
一般在string中,尾插使用+=;
erase;replace;find的使用:
void test_string2()
{string s("hello world");s.erase(0, 1);//在第0个位置删除1个字符s.erase(s.begin());//头删尾删s.erase(--s.end());s.erase(s.size() - 1);string s("hello world hello china");size_t pos = s.find(' ');//查找空格的位置while (pos != string::npos){s.replace(pos, 1, "%%");//在字符串中查找空格的位置一个字符替换为%%pos = s.find(' ', pos + 2);}cout << s << endl;
}
c_str返回指针,如下所示:
cin >> file;
FILE* fout = fopen(file.c_str(), "r");//c_str()是返回指针
char ch = fgetc(fout);
while (ch != EOF)
{cout << ch;ch = fgetc(fout);//读取到的字符
}
fclose(fout);
小练习(文件和路径分离)
void SplitFilename(const std::string& str)//文件路径和文件名分离
{std::cout << "Splitting: " << str << '\n';std::size_t found = str.find_last_of("/\\");//find_last_of从开始找到最后一个/或\\std::cout << " path: " << str.substr(0, found) << '\n';//substr获取从0的位置到found位置的字串std::cout << " file: " << str.substr(found + 1) << '\n';//从found+1的位置一直到最后
}