18 C++ string类模板
18.1 string类的构造函数
-
1.string(const char * s) ---使用'\0'结尾的字符串初始化string对象
-
2.string(size_type n, char c) ---创建一个有n个元素的string,每个元素使用c初始化
-
3.string(const string & str) ---复制构造函数,使用=将一个string对象复制给另一个string对象时使用
-
4.string() ---默认构造函数,创建一个大小为0的string对象
-
5.string(const char * s, size_type n) ---创建一个长度为n的字符串,使用'\0'结尾的字符串初始化string对象(即使s指向的字符出小于长度n)
-
6.template<class Iter>string(Iter begin,Iter end) ---将字符串对象初始化为范围[start,end)中的值,其中start和end充当指针并指定位置;[start,end)前闭后开区间。
-
7.string(const string & str,size_type pos,size_type n = npos) ---使用str初始化string对象,从str的pos位置开始,直到str结束或n长度
-
8.string(string && str) noexcept(C++11) ---使用str初始化string类,str可能是可移动的(移动构造函数)
-
9.string(initializer_list<char> il)(C++11) ---将字符串对象初始化为initializer_list列表中的字符il。
18.2 string类的输入
-
1.C风格字符串输入:
char info[100]; cin >> info; // read a word cin.getline(info, 100); // read a line, discard \n cin.get(info, 100); // read a line, leave \n in queue
添加分隔符的输入:
cin.getline(info,100,':'); // read up to :, discard :
-
2.string字符串输入
//不能使用cin.get() string stuff; cin >> stuff; // read a word getline(cin, stuff); // read a line, discard \n
添加分隔符的输入:
getline(stuff, ':'); // read up to :, discard :
-
3.C风格字符串和string类输入的不同 string是动态内存分配,可以不指定字符串长度 C风格的输入机制是使用cin类实现的,但是string的输入机制是使用友元函数实现的
-
4.string类输入的限制: (1)string类的最大允许长度string::npos,一般是最大的无符号int或无符号long数据。 (2)程序能够分配的最大内存
-
5.什么会触发string类的getline()输入停止阅读? (1)到达end-of-file,此时输入流的eofbit被设置,导致fail()和eof()都返回true (2)遇到分隔字符(默认情况是\n),分隔字符被丢弃 (3)超过string类最大允许长度或超过程序能够分配的最大内存,此时输入流的failbit会被设置,导致fail()返回true
-
6.输入流追踪标志 (1)eofbit寄存器追踪end-of-file (2)failbit寄存器追踪输入错误 (3)badbit寄存器追踪一些位置错误,比如硬件错误 (4)goodbit只是一切都很好
18.3 string类相关函数
在ASCII中,如果字符1比字符2的ASCII码小,则认为字符1<字符2.
-
1.字符串比较 允许字符串与字符串之间的对比、字符串与字符串与C风格字符串的对比和C风格字符串与C风格字符串之间的对比
-
2.字符串长度 size()和length()都能返回字符串的长度。 为什么会有两个功能一样的函数?因为length()是老版本的string的成员函数,size()是被添加来兼容STL的
-
3.字符串find
find():size_type find(const string & str, size_type pos = 0) const
---在触发字符串中,从位置pos开始,寻找子字符串str第一次出现的位置;如找到,返回str第一个字符出现的位置,反之,返回string::npos(字符串允许容纳的最大值)
size_type find(const char * s, size_type pos = 0) const
---在触发字符串中,从位置pos开始,寻找C风格子字符串s第一次出现的位置;如找到,返回s第一个字符出现的位置,反之,返回string::npos(字符串允许容纳的最大值)
size_type find(const char * s, size_type pos = 0, size_type n)
---在触发字符串中,从位置pos开始,寻找C风格子字符串s前n位第一次出现的位置;如找到,返回s第一个字符出现的位置,反之,返回string::npos(字符串允许容纳的最大值)
size_type find(char ch, size_type pos = 0) const
---在触发字符串中,从位置pos开始,字符ch第一次出现的位置;如找到,返回ch第一次出现的位置,反之,返回string::npos(字符串允许容纳的最大值)
-
rfind()
形参和find()的一样,在触发的字符串中寻找最后一次出现的子字符串或字符;如找到,返回子字符串第一个字符出现的位置,反之,返回string::npos。
注意事项:rfind()是从右往左寻找的,因此传递的pos参数要从右(字符串长度而不是0)开始。
-
find_first_of()
形参和find()一样,从左往右逐个寻找子字符串中的字符在触发字符串中第一次出现的位置,在找到一个字符存在时结束;如找到,则返回该字符在触发字符串的索引;反之,则返回string::npos。
-
find_last_of()
形参和find()一样,从左往右逐个寻找子字符串中的字符在触发字符串中最后一次出现的位置,在找到一个字符存在时结束;如找到,则返回该字符在触发字符串的索引;反之,则返回string::npos。 注意事项:find_last_of()是从右往左寻找的,因此传递的pos参数要从右(字符串长度而不是0)开始。对于寻找的字符串是从左往右检索。
-
find_first_not_of()
形参和find()一样,寻找触发字符串中第一个不在子字符串的字符并返回其索引,如果未找到,则返回string::npos。
18.4 自动内存分配的自动调整大小功能
当向一个字符串append字符串时,需要增加内存分配,但是原字符串的邻居可能已经将存储空间占用了,因此字符串需要重新寻找一个大的内存空间才可; 一些编译器为了减少这样的我呢提,首先给字符串预分配长度大于原字符串的内存空间。 capacitty():返回当前内存空间的大小(字符串为空时预留15,字符串不为空时预留) reserve(long):可以手动为字符串预留long空间(此时空间长度为:>=long)(vs2019)
18.5 string类template
模板:
template<class charT, class traits = char _traits<charT>,class Allocator = allocator<charT> > basic_string {...};
系统专门化:
typedef basic_string<char> string; typedef basic_string<wchar_t> wstring; typedef basic_string<char16_t> u16string; // C++11 typedef basic_string<char32_t> u32string ; // C++11
traits类:描述各种专门化string的操作,比如如何比较值。 针对char, wchar_t, char16_t, and char32_t类型,有traits模板预定义的专门化,这些类型也是trait模板的默认值。 Allocator类:管理内存分配,针对char, wchar_t, char16_t, and char32_t类型,有预定义的专门化,这些类型也是Allocator模板的默认值。 使用new and delete。
18.6 举例
代码:
// str1.cpp -- introducing the string class /* Project name : _19String_obj Last modified Date: 2022年4月5日11点52分 Last Version: V1.0 Descriptions: string类的一些特性 */ #include <iostream> #include <string> #include <fstream> #include <cstdlib> #include <ctime> #include <cctype> // using string constructors using namespace std; const int NUM = 26; const string wordlist[NUM] = { "apiary", "beetle", "cereal", "danger", "ensign", "florid", "garage", "health", "insult", "jackal", "keeper", "loaner", "manage", "nonce", "onset", "plaid", "quilt", "remote", "stolid", "train", "useful", "valid", "whence", "xenon", "yearn", "zippy" }; int main() { cout << "string类的构造函数***********************************************" << endl; string one("Lottery Winner!"); // ctor #1 cout << one << endl; // overloaded << string two(20, '$'); // ctor #2 cout << two << endl; string three(one); // ctor #3 cout << three << endl; one += " Oops!"; // overloaded += cout << one << endl; two = "Sorry! That was "; three[0] = 'P'; string four; // ctor #4 four = two + three; // overloaded +, = cout << four << endl; char alls[] = "All's well that ends well"; string five(alls, 20); // ctor #5 cout << five << "!\n"; string six(alls + 6, alls + 10); // ctor #6 cout << six << ", "; //string seven(five + 6, five + 10);这句是不允许的,因为string对象不像c字符串,字符串名不是第一个元素的地址 //但是下面这个就可以,因为直接给了地址 string seven(&five[6], &five[10]); // ctor #6 again cout << seven << "...\n"; string eight(four, 7, 16); // ctor #7 cout << eight << " in motion!" << endl; string piano_man = { 'L', 'i', 's','z','t' }; // ctor #8 cout << "piano_man = "<<piano_man << endl; string comp_lang{ 'L', 'i', 's', 'p' }; // ctor #8 cout << "comp_lang = " << comp_lang << endl; cout << "string类的输入*****************************************************" << endl; ifstream fin; fin.open("tobuy.txt"); if (fin.is_open() == false) //要放到项目生成文件夹下的_19String_obj文件夹才可以读取到,否则就给文件路径读取 { cerr << "Can't open file. Bye.\n"; exit(EXIT_FAILURE); } string item; int count = 0; getline(fin, item, ':'); while (fin) // while input is good { ++count; cout << count << ": " << item << endl; getline(fin, item, ':'); } cout << "Done\n"; fin.close(); cout << "字符串比较*****************************************************" << endl; string snake1("cobracobra"); string snake2("coralcoral"); char snake3[20] = "anaconda"; char snake4[20] = "Jasmine"; if (snake1 < snake2) // operator<(const string &, const string &) cout << snake1 << "<" << snake2<<endl; if (snake1 == snake3) // operator==(const string &, const char *) cout << snake1 << "==" << snake3<<endl; if (snake3 != snake2) // operator!=(const char *, const string &) cout << snake3 << "!=" << snake2<<endl; if (snake3 != snake4) cout << snake3 << "!=" << snake4<<endl; cout << "字符串长度*****************************************************" << endl; cout << "snake1.length() = " << snake1.length() << endl; cout << "snake1.size() = " << snake1.size() << endl; cout << "字符串find*****************************************************" << endl; string str = "ra"; cout << "snake2.find(str,0) = " << snake2.find(str, 0) << endl;//snake2.find(str,0) = 2 cout << "snake2.find(\"ra\",0) = " << snake2.find("ra", 0) << endl;//snake2.find("ra",0) = 2 cout << "snake2.find(\"alw\",0,2) = " << snake2.find("alw", 0,2) << endl;//snake2.find("alw",0,2) = 3 cout << "snake2.find('a',0) = " << snake2.find('a', 0) << endl;//snake2.find('a',0) = 3 cout << "字符串rfind*****************************************************" << endl; cout << "snake2.rfind(str,snake2.length()) = " << snake2.rfind(str, snake2.length()) << endl;//snake2.rfind(str,snake2.length()) = 7 cout << "snake2.rfind(\"ra\",snake2.length()) = " << snake2.rfind("ra", snake2.length()) << endl;//snake2.rfind("ra",snake2.length()) = 7 cout << "snake2.rfind(\"alw\",snake2.length(),2) = " << snake2.rfind("alw", snake2.length(), 2) << endl;//snake2.rfind("alw",snake2.length(),2) = 8 cout << "snake2.rfind('a',snake2.length()) = " << snake2.rfind('a', snake2.length()) << endl;//snake2.rfind('a',snake2.length()) = 8 cout << "字符串find_first_of*****************************************************" << endl; str = "rain"; cout << "snake2.find_first_of(str,0) = " << snake2.find_first_of(str, 0) << endl;//snake2.find_first_of(str,0) = 2 cout << "snake2.find_first_of(\"ra\",0) = " << snake2.find_first_of("ra", 0) << endl;//snake2.find_first_of("ra",0) = 2 cout << "snake2.find_first_of(\"alw\",0,2) = " << snake2.find_first_of("alw", 0, 2) << endl;//snake2.find_first_of("alw",0,2) = 3 cout << "snake2.find_first_of('a',0) = " << snake2.find_first_of('a', 0) << endl;//snake2.find_first_of('a',0) = 3 cout << "字符串find_last_of*****************************************************" << endl; str = "rain"; cout << "snake2.find_last_of(str,snake2.length()) = " << snake2.find_last_of(str, snake2.length()) << endl;//snake2.find_last_of(str,snake2.length()) = 8 cout << "snake2.find_last_of(\"ra\",snake2.length()) = " << snake2.find_last_of("ra", snake2.length()) << endl;//snake2.find_last_of("ra",snake2.length()) = 8 cout << "snake2.find_last_of(\"lac\",snake2.length(),3) = " << snake2.find_last_of("lac", snake2.length(),3) << endl;//snake2.find_last_of("lac",snake2.length(),3) = 9 cout << "snake2.find_last_of('a',snake2.length()) = " << snake2.find_last_of('a', snake2.length()) << endl;//snake2.find_last_of('a',snake2.length()) = 8 cout << "字符串find_first_not_of*****************************************************" << endl; cout << "snake2.find_first_not_of(str,0) = " << snake2.find_first_not_of(str, 0) << endl;//snake2.find_first_not_of(str,0) = 0 cout << "snake2.find_first_not_of(\"ra\",0) = " << snake2.find_first_not_of("ra", 0) << endl;//snake2.find_first_not_of("ra",0) = 0 cout << "snake2.find_first_not_of(\"lac\",0,3) = " << snake2.find_first_not_of("lac", 0, 3) << endl;//snake2.find_first_not_of("lac",0,3) = 1 cout << "snake2.find_first_not_of('a',0) = " << snake2.find_first_not_of('a', 0) << endl;//snake2.find_first_not_of('a',0) = 0 /* 一个小游戏嘿嘿 */ cout << "猜字符串游戏*****************************************************" << endl; std::srand(std::time(0)); char play; cout << "Will you play a word game? <y/n> "; cin >> play; play = tolower(play); while (play == 'y') { string target = wordlist[std::rand() % NUM]; cout << target << endl; int length = target.length(); string attempt(length, '-'); string badchars; int guesses = 6; cout << "Guess my secret word. It has " << length << " letters, and you guess\n" << "one letter at a time. You get " << guesses << " wrong guesses.\n"; cout << "Your word: " << attempt << endl; while (guesses > 0 && attempt != target) { char letter; cout << "Guess a letter: "; cin >> letter; if (badchars.find(letter) != string::npos || attempt.find(letter) != string::npos) { cout << "You already guessed that. Try again.\n"; continue; } int loc = target.find(letter); if (loc == string::npos) { cout << "Oh, bad guess!\n"; --guesses; badchars += letter; // add to string } else { cout << "Good guess!\n"; attempt[loc] = letter; // check if letter appears again loc = target.find(letter, loc + 1); while (loc != string::npos) { attempt[loc] = letter; loc = target.find(letter, loc + 1); } } cout << "Your word: " << attempt << endl; if (attempt != target) { if (badchars.length() > 0) cout << "Bad choices: " << badchars << endl; cout << guesses << " bad guesses left\n"; } } if (guesses > 0) cout << "That's right!\n"; else cout << "Sorry, the word is " << target << ".\n"; cout << "Will you play another? <y/n> "; cin >> play; play = tolower(play); } cout << "Capacity() and reserve()*****************************************************" << endl; string empty; string small = "bit"; string larger = "Elephants are a girl's best friend"; cout << "Sizes:\n"; cout << "\tempty: " << empty.size() << endl; cout << "\tsmall: " << small.size() << endl; cout << "\tlarger: " << larger.size() << endl; cout << "Capacities:\n"; cout << "\tempty: " << empty.capacity() << endl; cout << "\tsmall: " << small.capacity() << endl; cout << "\tlarger: " << larger.capacity() << endl; empty.reserve(50); cout << "empty Capacity after empty.reserve(50): " << empty.capacity() << endl; return 0; }
运行结果:
string类的构造函数*********************************************** Lottery Winner! $$$$$$$$$$$$$$$$$$$$ Lottery Winner! Lottery Winner! Oops! Sorry! That was Pottery Winner! All's well that ends! well, well... That was Pottery in motion! piano_man = Liszt comp_lang = Lisp string类的输入***************************************************** 1: sardines 2: chocolate ice cream 3: pop corn 4: leeks 5: cottage cheese 6: olive oil 7: butter 8: tofu 9: Done 字符串比较***************************************************** cobracobra<coralcoral anaconda!=coralcoral anaconda!=Jasmine 字符串长度***************************************************** snake1.length() = 10 snake1.size() = 10 字符串find***************************************************** snake2.find(str,0) = 2 snake2.find("ra",0) = 2 snake2.find("alw",0,2) = 3 snake2.find('a',0) = 3 字符串rfind***************************************************** snake2.rfind(str,snake2.length()) = 7 snake2.rfind("ra",snake2.length()) = 7 snake2.rfind("alw",snake2.length(),2) = 8 snake2.rfind('a',snake2.length()) = 8 字符串find_first_of***************************************************** snake2.find_first_of(str,0) = 2 snake2.find_first_of("ra",0) = 2 snake2.find_first_of("alw",0,2) = 3 snake2.find_first_of('a',0) = 3 字符串find_last_of***************************************************** snake2.find_last_of(str,snake2.length()) = 8 snake2.find_last_of("ra",snake2.length()) = 8 snake2.find_last_of("lac",snake2.length(),3) = 9 snake2.find_last_of('a',snake2.length()) = 8 字符串find_first_not_of***************************************************** snake2.find_first_not_of(str,0) = 0 snake2.find_first_not_of("ra",0) = 0 snake2.find_first_not_of("lac",0,3) = 1 snake2.find_first_not_of('a',0) = 0 猜字符串游戏***************************************************** Will you play a word game? <y/n> y valid Guess my secret word. It has 5 letters, and you guess one letter at a time. You get 6 wrong guesses. Your word: ----- Guess a letter: v Good guess! Your word: v---- 6 bad guesses left Guess a letter: a Good guess! Your word: va--- 6 bad guesses left Guess a letter: l Good guess! Your word: val-- 6 bad guesses left Guess a letter: s Oh, bad guess! Your word: val-- Bad choices: s 5 bad guesses left Guess a letter: d Good guess! Your word: val-d Bad choices: s 5 bad guesses left Guess a letter: i Good guess! Your word: valid That's right! Will you play another? <y/n> n Capacity() and reserve()***************************************************** Sizes: empty: 0 small: 3 larger: 34 Capacities: empty: 15 small: 15 larger: 47 empty Capacity after empty.reserve(50): 63 D:\Prj\_C++Self\_19String_obj\Debug\_19String_obj.exe (进程 15828)已退出,代码为 0。 要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。 按任意键关闭此窗口. . .