#include<iostream> using namespace std; #include<cstdio> //string就是管理字符串的类 #include<string> //库里面定义 template<class T> class basic_string { private: T* _str; //... }; //编码 --值--符号建立映射关系--编码表(用值和符号建立对应关系) // ASCILL编码表---表示英文编码 // unicode ---(包含ascill)表示全世界文字编码 //又包含utf -8,utf-16 //gbk -- 中国自己量身定做的编码表 // 汉字可以用2个字节, // //typrdef basic_string<char> string,我们用的是typedef后出来的,模板的 //int main() //{ // string s1("hello"); // char str2[] = "吃饭"; // cout << sizeof(char) << endl; // cout << sizeof(wchar_t) << endl;//2个字节,wstring // // return 0; //} //初始化 void init() { string s1;//无调用构造函数 string s2("hello world");//构造函数 string s3(s2);//拷贝构造 //cin >> s1; cout << s1 << endl; cout << s2 << endl; cout << s3 << endl; //substring (3) //string(const string & str, size_t pos, size_t len = npos); //利用字串进行初始化,pos是从0开始,从string里面先后数len个长度进行拷贝 string s4(s2, 2, 6); cout << s4 << endl;//llo wo string s5(s2, 2);//默认从坐标为2的地方往后截取所有的s2 cout << s5 << endl;//ello world //string (const char* s, size_t n); string s7("hello world", 3);//取前3个字符 cout << s7 << endl; //string(size_t n, char c);连续弄n个c string s8(3, '!');//!!! } void func() { string s1("hello"); //不计算‘\0’,这两个对于string没什么区别,size是后出现为了保证容器的一致性 cout << s1.size() << endl;//5 cout << s1.length() << endl;//5 cout << s1.max_size() << endl;//没什么意义 cout << s1 << endl; //计算容量 cout << s1.capacity() << endl;//15 s1.clear();//把有效数据都清理掉,空间保留,变成空字符串,0个字符 cout << s1 << endl; cout << s1.capacity() << endl; if (s1.empty())//判断此字符串是否为空,即是否长度为0 { cout << "not" << endl; } } //char& operator[] (size_t pos);这里的引用返回是因为这个数组是在堆上开辟的,出了作用域还在,并且可以对其中的字符进行修改,或者调用,还可以减少拷贝(不是主要目的) void operatoracess() { string s1("hello world"); for (size_t i = 0; i < s1.length(); i++) { cout << s1[i];//[]是断言终止程序,检查错误 s1[i] += 1; } cout << endl; for (size_t i = 0; i < s1.length(); i++) { s1.at(i) -= 1;//和上面是一样的 cout << s1.at(i) << endl;//at是抛异常检查错误,建议还是使用[ ] } cout << endl; } //对字符串进行尾部添加字符或字符串 void add() { string s; s.push_back('a'); s.append("bcde");//尾插bcd cout << s << endl;//abcd s += '!';//也可以利用运算符重载进行实现尾插,推荐,abcd! } //只交换字符 //abc-bcd-qwlkj变成 jkl-wqd-cbcba // class Solution { public: //计算最后一个单词的长度如“hello world ”g int lengthOfLastWord(string s) { int end=s.size()-1; while(s[end]==' ') { s.erase(end,1);//无法使用 end--; } size_t pos=s.rfind(" "); string sub=s.substr(pos+1); return sub.size(); } }; //遍历,1.迭代器2.范围for void test_string1() { string s1("hello"); string::iterator it=s1.begin();//s1.begin(),是第一个数据的地址,s1.end()是最后一个数据的后一个的地址 //这个iterator是定义在string里面,it现在指向了第一个数据的地址 //现在可以先想象成一个像指针一样的类型 // while(it!=s1.end())//直到结尾就结束了,但是不建议用< { cout<<*it<<" ";//*就是取他的数据 ++it;//到下一个地址 } cout<<endl; //除了可以读还可以写 it=s1.begin();//s1.begin(),是第一个数据的地址,s1.end()是最后一个数据的后一个的地址 //这个iterator是定义在string里面,it现在指向了第一个数据的地址 //现在可以先想象成一个像指针一样的类型 // while(it!=s1.end())//直到结尾就结束了 { *it-=1;//*就是取他的数据 ++it;//到下一个地址 } cout<<endl; //范围for,auto可以自动识别 //for(auto e:s1)//把s1里面每个字符取出来赋值给e,不需要自己++,自动判断结束 //{ // cout<<e<<" "; //} cout<<endl; //要修改就要用引用 //for(auto& e:s1) //{ // e-=1; //} cout<<endl; //反向迭代器 //倒着遍历 string::reverse_iterator rit=s1.rbegin();//rbegin(),是最后一个数据的地址 //为了简化代码也可以直接auto推到 // //auto rit=s1.rbegin() // while(rit!=s1.rend())//rend()是第一个数据的前一个地址 { cout<<*rit<<" ";//olleh,反过来遍历 ++rit;//反向迭代器的++,是往左走的 } cout<<endl; //迭代器遍历的意义是什么呢:所有的容器都可以用迭代器这种访问修改 //1.对于string类来说,利用[]都足够好用,确实可以不用迭代器 //2。对于其他容器(数据结构)也可以使用,如list,map,set,这些是不支持[],因为只有像数组一样的东西才支持[]遍历和下标, //结论::对于string得会用迭代器,但是我们还是喜欢下标加[], //还有const迭代器,普通迭代器是可读可写的 string cstr("hello world"); //funcion(cstr); string::const_iterator re=s1.begin();//只读不写,同理还有反向迭代器 //cbegin()就是const迭代器,但是我们平时都不太用, } //对于容量的函数 void test_string3() { string s1; s1.reserve(100);//可以设置容量的大小,容量就是100,加上原来的容量 string s2; s2.resize(100,'x');//也是可以设置容量的大小,同时还可以对其进行初始化,如将s1有效数据的后面全部设置成x,如果没有第二个参数,则默认是‘\0’ } //对于find,c_str ,rfind的认识与理解 void test_string2() { string s2="hello world"; cout<<s2.c_str()<<endl;//将string转变成c语言的形式字符串,char*,以\0截至 string file("test.txt"); //我们要以c语言的形式打开一个文件 //FILE* fout=fopen(s2.c_str(),"w"); //fopen第一个参数是char*,所以用这函数 //要求取出文件的后缀 size_t pos=file.find('.');//在file里面查找‘x’的位置,find的返回值是size_t,下标从0开始,查找第一个符合的坐标,否则就返回-1 string s1(file,pos); cout<<s1<<endl; if(pos!=string::npos) { string suffix=file.substr(pos); cout<<suffix<<endl; } //rfind()//可以从后面完前找,找到第一个.,方便找后缀名 //https://blog.csdn.net/m0_61567378?spm=1000.2115.3001.5343 string url("http://blog.csdn.net/m0_61567378?spm=1000.2115.3001.5343"); //找协议头 size_t pos1=url.find(':');//:前面的就是协议头 string protocol=url.substr(0,pos1-0);//取得字串就是从0开始,到pos1位置,长度为pos1的字串,也就是http cout<<protocol<<endl; //找域名, size_t pos2=url.find('/',pos1+3);//find默认从0开始找,现在我们给定他从pos1+3位置处开始找,也就是b开始,往后找,找到/的位置 string domain=url.substr(pos1+3,pos2-pos1-3); cout<<domain<<endl; //统一资源定位 string uri=url.substr(pos2+1); cout<<uri<<endl; } // void test_string4() { //insert不太推荐用,O(n),效率低 string s="hell"; s.insert(0,"owlod");//在头上插入一个owlod,是从第0个位置往后插入 s.insert(0,1,'x');//在头上插入一个x,是 s.insert(4,"xx");//从第4个位置往后插入xx cout<<s<<endl; //要挪动数据效率很低, s.erase(4,2);//从4位置,删除两个长度的字符 cout<<s<<endl; s.erase(s.size()-1,1);//尾删 s.erase(3);//第二个参数不给值就后面全部都删除了 //尾删也可以 //s.pop_back(); //输入一整行的数据,包括‘ ’ getline(cin,s);//第一个参数是流 } void test_string5() { string s1="hello"; string s2="string"; cout<<(s1<s2)<<endl;//h<s所以就是小于 cout<<("hello"<s2)<<endl;//char*的也可以比较 cout<<(string("hello")<s2)<<endl;//这样也是可以的 } //字符串与整形的转化 void test_string6() { int val=stoi("1234");//转变成int cout<<val<<endl;//1234 double val1=stod("123"); //转变成字符串 string str=to_string(12.345); string s=to_string(123456); string str = to_string(12.345); } //浅拷贝,完成值拷贝,将每个字节一起拷贝 //对于指针类型的就不可以靠浅拷贝 //浅拷贝抄作业连名字都没改,完完全全的抄 //深拷贝就是抄作业改了名字,不完全的抄 // classm my_string { private: char* _str; public: //构造函数 my_string(const char* str) :_str(new char[strlen(str)+1]) { strcpy(_str,str); } //拷贝构造要用深拷贝 my_string(const my_string& s) :_str(new char[strlen(str)+1]) { strcpy(_str,s.str); } } void test_string7() { } int main() { // init(); // func(); // operatoracess(); // add(); // Solution sl; // sl.reverseOnlyLetters("Test1ng-Leet=code-Q!"); //test_string1(); //test_string3(); //test_string2(); //test_string4(); Solution ts; string s="hello world "; //int k=ts.lengthOfLastWord(s); //cout<<k<<endl; //test_string6(); string s1 = "A man, a plan, a canal: Panama"; isPalindrome(s1); return 0; }