• string类(一)


    目录

    一、 string类对象的常见构造

    二、string类对象的容量操作

     2.1 size(返回字符串有效字符长度)

    2.2 capacity(返回空间总大小) 

     2.3 reserve扩空间​编辑

    2.4 resize初始化不会覆盖本来的空间​编辑

    2.5 对于test_string7中每一句代码进行调试运行

    三、string类对象的访问及遍历操作

     3.1 operator[]

     3.2 迭代器

    四、笔试题

    1.关于代码输出正确的结果是( )

     2.关于代码输出正确的结果是( )

    3.关于代码输出正确的结果是( )

    4. 把字符串转换成整数_牛客题霸_牛客网 (nowcoder.com)

    5.917. 仅仅反转字母 - 力扣(Leetcode)

    6.541. 反转字符串 II - 力扣(Leetcode)

    7.125. 验证回文串 - 力扣(Leetcode)  

    一、 string类对象的常见构造

     string初始化:

    1. #define _CRT_SECURE_NO_WARNINGS 1
    2. #include
    3. #include
    4. using namespace std;
    5. //string管理动态增长的字符数组,这个字符串以\0结尾
    6. int main()
    7. {
    8. std::string s;
    9. //string初始化
    10. string s1;//构造空的string类对象s1
    11. cout << "s1: " << s1 << endl;
    12. string s2("hello world");
    13. s2 += "!!!!";
    14. cout << "s2: " << s2 << endl;
    15. string s3(s2);
    16. cout << "s3: " << s3 << endl;
    17. string s4 = s2;//拷贝构造
    18. cout << "s4: " << s4 << endl;
    19. string s5("https://blog.csdn.net/weixin_57604904?spm=1000.2115.3001.5343", 4);
    20. cout << "s5: " << s5 << endl;
    21. string s6(6, 'C');
    22. cout << "s6: " << s6 << endl;
    23. string s7(s2, 6, 5);//第6个字符往后,不包括第6个,5个字符进行初始化
    24. cout << "s7: " << s7 << endl;
    25. string s8(s2, 6, 4);
    26. cout << "s8: " << s8 << endl;
    27. string s9(s2, 1, 100);//不会报错,会到\0截止
    28. cout << "s9: " << s9 << endl;
    29. string s10(s2, 6);//从s2的第六个字符往后直接到\0
    30. cout << "s10: " << s10 << endl;
    31. string s11(s2, 1);
    32. cout << "s11: " << s11 << endl;
    33. string s12(s2, 10);
    34. cout << "s12: " << s12 << endl;
    35. return 0;
    36. }

     s1可修改:

    1. void test_string()
    2. {
    3. string s1("hello");
    4. string s2("xxxx");
    5. s1 = s2;
    6. s1 = "xxx";
    7. s1 = 'y';
    8. cout << s1 << endl;
    9. cout << s2 << endl;
    10. }
    11. int main()
    12. {
    13. test_string();
    14. return 0;
    15. }

    二、string类对象的容量操作

     2.1 size(返回字符串有效字符长度)

     

    1. 1. size()与length()方法底层实现原理完全相同,
    2. 引入size()的原因是为了与其他容器的接口保持一致,
    3. 一般情况下基本都是用size()。

    2.2 capacity(返回空间总大小) 

    1. void test_string6()
    2. {
    3. string s("helloworld");
    4. size_t sz = s.capacity();//空间总大小
    5. cout << sz << endl;
    6. //s.reserve(1000);//扩空间
    7. //s.resize(1000, 'x');//扩空间+初始化
    8. for (int i = 0; i < 1000; i++)
    9. {
    10. s.push_back('c');//尾插
    11. if (sz != s.capacity())//尾插后,容量如果满了,容量会变
    12. {
    13. sz = s.capacity();//变了后就有新的sz
    14. cout << "capacity changed: " << sz << "\n";
    15. }
    16. }
    17. }
    18. int main()
    19. {
    20. test_string6();
    21. return 0;
    22. }

    初始size与capacity:

    字符串有效字符长度与空间总大小:

     

     

     尾插push_back,空间满了就扩容:

     第一次扩容:

     运行结果:

     2.3 reserve扩空间

    2.4 resize初始化不会覆盖本来的空间

     注意:观察如下代码:

    1. void test_string7()
    2. {
    3. string s("hello");
    4. s.reserve(100);
    5. s.resize(100, 'x');//注意不会改变hello,只是让size=100,后面补x
    6. s.reserve(10);//说明reserve会扩不会缩
    7. //s[9] = 'y'//会报断言错误
    8. s.resize(10, 'x');//但是resize使得size= 10//s[9] = 'x'
    9. s[9] = 'y';//不会报错
    10. }
    11. int main()
    12. {
    13. test_string7();
    14. return 0;
    15. }

    2.5 对于test_string7中每一句代码进行调试运行

    1.capacity变为111

     2.size变为100,补x

     3. capacity没有变(reserve不会缩只会扩)

     4.resize会改变size,从100->10

     5.改变s[9],不会报错

    1. 3. resize(size_t n) 与 resize(size_t n, char c)都是将字符串中有效字符个数改变到n个,
    2. 不同的是当字符个数增多时:
    3. resize(n)用0来填充多出的元素空间,
    4. resize(size_t n, char c)用字符c来填充多出的元素空间。
    5. 注意:resize在改变元素个数时,如果是将元素个数增多,可能会改变底层容量的大小,如果是将元素个数减少,底层空间总大小不变。
    6. 4. reserve(size_t res_arg=0):为string预留空间,不改变有效元素个数,
    7. 当reserve的参数小于string的底层空间总大小时,reserve不会改变容量大小。

    三、string类对象的访问及遍历操作

     3.1 operator[]

    返回位于字符串中指定位置的字符:

    1. 对于operator[],字符串中的第一个字符用值0(而不是1)表示,
        s1.operator[](i)//返回位于字符串中指定位置i的字符。
        如果字符串对象是const限定的,则该函数返回const char&。否则,它返回char&。
        char& operator[] (size_t pos);const char& operator[] (size_t pos) const;

    2. 为什么不能返回char?
        1).返回的是位于字符串指定位置pos的字符,return str[pos]
        其因为是在堆区开辟的,出了作用域还在,所以按常规操作肯定是返回char&别名更合适,减少拷贝;
        2).这样引用返回可以使得返回值可修改,因为如果是char返回,返回是先创建临时变量,返回的是临时变量,而临时变量具有常性,const权限放大,不能赋值和修改,而char&不会,可以修改。

    1. void test_string2()
    2. {
    3. string s1("hello");//初始化
    4. s1.at(1) = 'x';
    5. //s1[6];//会报错assert判断的
    6. cout << s1.size() << endl;//s1.size()返回有效字符个数,不包含\0
    7. for (size_t i = 0; i < s1.size(); i++)
    8. {
    9. cout << s1[i] << " ";
    10. }
    11. cout << endl;
    12. }
    13. int main()
    14. {
    15. test_string2();
    16. return 0;
    17. }

     3.2 迭代器

    reverse_iterator rbegin();

    const_reverse_iterator rbegin() const;

    1. void test_string4()
    2. {
    3. string s = "helloworld";
    4. string::reverse_iterator rit = s.rbegin();
    5. while (rit != s.rend())
    6. {
    7. cout << *rit << " ";
    8. rit++;
    9. }
    10. cout << endl;
    11. }
    12. void test_string5()
    13. {
    14. const string s = "helloworld";
    15. string::const_reverse_iterator rit = s.rbegin();
    16. while (rit != s.rend())
    17. {
    18. cout << *rit << " ";
    19. rit++;
    20. }
    21. cout << endl;
    22. }
    23. int main()
    24. {
    25. test_string4();
    26. test_string5();
    27. return 0;
    28. }

    四、笔试题

    1.关于代码输出正确的结果是( )

    1. 关于代码输出正确的结果是( )
    2. int main(int argc, char *argv[])
    3. {
    4. string a="hello world";
    5. string b=a;
    6. if (a.c_str()==b.c_str())
    7. {
    8. cout<<"true"<
    9. }
    10. else
    11. cout<<"false"<
    12. string c=b;
    13. c="";
    14. if (a.c_str()==b.c_str())
    15. {
    16. cout<<"true"<
    17. }
    18. else
    19. cout<<"false"<
    20. a="";
    21. if (a.c_str()==b.c_str())
    22. {
    23. cout<<"true"<
    24. }
    25. else
    26. cout<<"false"<
    27. return 0;
    28. }
    29. A.false false false
    30. B.true false false
    31. C.true true true
    32. D.true true false
    1. 分析:a 和 b的值虽然相同,
    2. 但是a.c_str()==b.c_str()比较的是存储字符串位置的地址,
    3. a和b是两个不同的对象,内部数据存储的位置也不相同,因此不相等,
    4. 后面c="",a=""与b对象都没有任何的影响,所以都不相等
    5. 故答案为:A

     2.关于代码输出正确的结果是( )

    1. 下面程序的输出结果正确的是( )
    2. int main()
    3. {
    4. string str("Hello Bit.");
    5. str.reserve(111);
    6. str.resize(5);
    7. str.reserve(50);
    8. cout<size()<<":"<capacity()<
    9. return 0;
    10. }
    11. A.10 50
    12. B.5 50
    13. C.5 111
    14. D.10 111
    1. 分析:
    2. str.reserve(111); //调整容量为 111
    3. str.resize(5); //调整元素个数为 5
    4. str.reserve(50); //调整容量为 50,由于调整的容量小于已有空间容量,故容量不会减小
    5. 所以size=5 capacity=111
    6. 故答案为: C

    3.关于代码输出正确的结果是( )

    1. 下面程序的输出结果正确的是( )
    2. int main(int argc, char *argv[])
    3. {
    4. string strText = "How are you?";
    5. string strSeparator = " ";
    6. string strResult;
    7. int size_pos = 0;
    8. int size_prev_pos = 0;
    9. while((size_pos=strText.find_first_of(strSeparator, size_pos)) != string::npos)
    10. {
    11. strResult = strText.substr(size_prev_pos, size_pos-size_prev_pos);
    12. cout<" ";
    13. size_prev_pos = ++size_pos;
    14. }
    15. if(size_prev_pos != strText.size())
    16. {
    17. strResult = strText.substr(size_prev_pos, size_pos-size_prev_pos);
    18. cout<" ";
    19. }
    20. cout<
    21. return 0;
    22. }
    23. A.Howareyou?
    24. B.How Are You?
    25. C.How are
    26. D.How are you?
    1. 分析:程序的目的是以字符串strSeparator = " "作为分隔符,
    2. 对字符串string strText = "How are you?";进行分割,每分割出一个单词就进行一次打印
    3. 故答案为 D

    实际的 find_first_of函数的作用是:
            在一个字符串中进行查找,返回值是第一个与指定字符串中任何字符匹配的字符位置;
    如果没有找到匹配的内容,就返回 string::npos。
     

    注意与find的区别:发现find是返回-1,说明找不到。

     find:

    substr:

    1. substr(size_type _Off = 0,size_type _Count = npos)
    2. 参数:
    3. _Off——所需的子字符串的起始位置。字符串中第一个字符的索引为 0,默认值为0
    4. _Count——复制的字符数目
    5. 返回值——一个子字符串,从其指定的位置开始
    6. 假设string s(“student12”);
    7. string x=s.substr() //默认时的长度为从开始位置到尾
    8. string y=s.substr(5) //获得字符串s中 从第5位开始到尾的字符串
    9. string z=s.substr(5,3); //获得字符串s中 从第5位开始的长度为3的字符串

     具体解析:

    1. int main()
    2. {
    3. string strText = "How are you?";
    4. string strSeparator = " ";
    5. string strResult;
    6. int size_pos = 0;
    7. int size_prev_pos = 0;
    8. //找不到就返回npos
    9. //在strText中找空格,返回位置为3,因为是从0开始。
    10. //找不到就返回string::pos
    11. //只要strText.find_first_of(strSeparator, size_pos)) != string::npos就说明
    12. //找到了空格,找到了空格就返回所在位置或者说是下标size_pos
    13. while ((size_pos = strText.find_first_of(strSeparator, size_pos)) != string::npos)
    14. //在strText的第0开始找strSeparator也就是空格,返回的位置只要不是-1,就进入循环,
    15. //如果在一个字符串strText中查找另一个字符串strSeparator,
    16. //如果strText1中含有strSeparator中的任何字符,则就会查找成功
    17. {
    18. //从0开始找(3-0)个元素,找到How
    19. strResult = strText.substr(size_prev_pos, size_pos - size_prev_pos);
    20. cout << strResult << " ";//再输出一个空格
    21. size_prev_pos = ++size_pos;//然后同时++,都变成4
    22. //之后size_pos = 4,从位置4开始找空格,到了位置7,7-4=3
    23. //size_prev_pos = size_pos = 8
    24. //之后就找不到空格了,跳出循环,size_pos = -1,size_prev_pos = 8
    25. }
    26. if (size_prev_pos != strText.size())//已知size = 12,8!=12进入if
    27. //只要不和size相等就进入循环
    28. {
    29. strResult = strText.substr(size_prev_pos, size_pos - size_prev_pos);
    30. //从8开始找到-9,就相当于找到底
    31. cout << strResult << " ";
    32. }
    33. cout << endl;
    34. return 0;
    35. }

    4. 把字符串转换成整数_牛客题霸_牛客网 (nowcoder.com)

    描述

    将一个字符串转换成一个整数,要求不能使用字符串转换整数的库函数。 数值为 0 或者字符串不是一个合法的数值则返回 0

    1. class Solution
    2. {
    3. public:
    4. int StrToInt(string str)
    5. {
    6. if (str == "")//如果没有字符串返回0
    7. return 0;//输入一个字符串,包括数字字母符号,可以为空
    8. int ret = 0;
    9. int flag = 1;
    10. if (str[0] == '-')
    11. {
    12. str[0] = '0';
    13. flag = -flag;
    14. }
    15. if (str[0] == '+')
    16. {
    17. str[0] = '0';
    18. }
    19. for (int i = 0; i < str.size(); ++i)
    20. {
    21. if (str[i] < '0' || str[i] > '9')
    22. //注意:字符串中可能出现任意符号,出现除 +/- 以外符号时直接输出 0
    23. {
    24. return 0;
    25. }
    26. if (str[i] >= '0' && str[i] <= '9')
    27. //比如str是0123,str[1] = 1,ret = 0+1
    28. //str[2] = 2,ret = 1*10+2=12
    29. //str[3] = 3,ret = 12*10+3=123
    30. {
    31. ret = ret*10 + str[i] - '0';//‘0’ascii码值是48
    32. //字符'1'的ascii码值是49,49-48 =1,从字符1变成整数1
    33. }
    34. }
    35. if (flag == -1)
    36. {
    37. ret *= -1;//如果flag等于-1,那么ret就要乘上-1
    38. }
    39. return ret;
    40. }
    41. };

    5.917. 仅仅反转字母 - 力扣(Leetcode)

    给你一个字符串 s ,根据下述规则反转字符串:

    • 所有非英文字母保留在原有位置。
    • 所有英文字母(小写或大写)位置反转。

    返回反转后的 s 。

    1. class Solution {
    2. public:
    3. bool isLetter(char ch)
    4. {
    5. if(ch >= 'A' && ch <= 'Z')
    6. {
    7. return true;
    8. }
    9. else if(ch >= 'a' && ch <= 'z')
    10. {
    11. return true;
    12. }
    13. else
    14. {
    15. return false;
    16. }
    17. }
    18. string reverseOnlyLetters(string s)
    19. {
    20. string::iterator left = s.begin();
    21. string::iterator right = s.end()-1;
    22. while(left < right)
    23. {
    24. while(leftisLetter(*left))
    25. //是字母就为true,取反为0
    26. //不是字母就返回false,取反为1
    27. left++;//说明不是字母就++
    28. while(leftisLetter(*right))
    29. right--;
    30. swap(*left,*right);//是字母就进行交换
    31. left++;
    32. right--;
    33. }
    34. return s;
    35. }
    36. };

    6.541. 反转字符串 II - 力扣(Leetcode)

    给定一个字符串 s 和一个整数 k,从字符串开头算起,每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符。

    如果剩余字符少于 k 个,则将剩余字符全部反转。
    如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。

    1. class Solution {
    2. public:
    3. void reverse(string& s, int left, int right)
    4. {
    5. while (left < right)
    6. {
    7. swap(s[left], s[right]);
    8. left++;
    9. right--;
    10. }
    11. }
    12. string reverseStr(string s, int k)
    13. {
    14. //从字符串开头算起,每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符。
    15. //每次i向前移动2k个字符
    16. for (int i = 0; i < s.size(); i += 2 * k)
    17. {
    18. //x为走了2k步后的剩余字符,如果k<= x <2k,那么反转前k个数
    19. //那么s.size()>=(k+2k),就反转前k个数
    20. if (s.size() >= (i + k))
    21. {
    22. reverse(s, i, i + k - 1);
    23. continue;//反转前k个数后,调到for循环,继续向后走2k步,如果还大于,接着反转前k个数
    24. }
    25. //如果x
    26. reverse(s, i, s.size() - 1);
    27. }
    28. return s;
    29. }
    30. };

    7.125. 验证回文串 - 力扣(Leetcode)  

    如果在将所有大写字符转换为小写字符、并移除所有非字母数字字符之后,短语正着读和反着读都一样。则可以认为该短语是一个 回文串 。

    字母和数字都属于字母数字字符。

    给你一个字符串 s,如果它是 回文串 ,返回 true ;否则,返回 false 

    1. class Solution {
    2. public:
    3. char func(char c)
    4. {
    5. if (('0' <= c && c <= '9') || ('a' <= c && c <= 'z'))
    6. return c;//数字0~9或a~z无需转换
    7. else if ('A' <= c && c <= 'Z')
    8. return c + 'a' - 'A'; //所有大写转小写,A~Z转化为对应a~z
    9. else
    10. {
    11. return ' '; //其他字符转换为空格符' '
    12. }
    13. }
    14. bool isPalindrome(string s)
    15. {
    16. if (s.size() == 0 || s.size() == 1)
    17. return true;//空字符和一个字符都是回文结构
    18. string::iterator left = s.begin();
    19. string::iterator right = s.end() - 1;
    20. char c1, c2;
    21. while (left < right)
    22. {
    23. c1 = func(*left); //调用转化函数
    24. c2 = func(*right); //调用转化函数
    25. if (c1 == ' ')
    26. {
    27. left++;
    28. }
    29. if (c2 == ' ')
    30. {
    31. right--;
    32. }
    33. //c1和c2如果是空格,说明是别的字符且已经转换了
    34. if (c1 != ' ' && c2 != ' ')
    35. {
    36. if (c1 != c2)
    37. {
    38. return false;
    39. }
    40. left++; right--;
    41. }
    42. }
    43. return true;
    44. }
    45. };

  • 相关阅读:
    【C++题解】1715. 输出满足条件的整数5
    4 -25
    字符串压缩(三)之短字符串压缩
    【踩坑纪实】URL 特殊字符 400 异常
    C# .Net MAUI 从入门到入土
    shell脚本基础教程,快速上手
    30.链表练习题(1)(王道2023数据结构2.3.7节1-15题)
    Java学习笔记(8)
    Pytorch训练神经网络完整步骤:搭建一个完整的神经网络(以用于Mnist手写数字识别的卷积神经网络为例)
    binary tree Leetcode 二叉树算法题
  • 原文地址:https://blog.csdn.net/weixin_57604904/article/details/127998278