C++ string类模板

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。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jasmine-Lily

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值