String类 [上]

一、编码的基础介绍

编码:是信息从一种形式或格式转换为另一种形式的过程。

ASCLL 编码表:主要表示的是英文的编码表

Unicode:是为了解决传统的字符编码方案的局限而产生的,它为每种语言中的每个字符设定了统一并且唯一的二进制编码二进制编码二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求

GBK:可以说是为中文量身定做的一种编码

 二、String 类的介绍

在C 语言中,字符串是以 '\0' 结尾的一些字符的集合,为了操作方便, C 标准库中提供了一些 str 系列的库函数, 但是这些库函数与字符串是分离开的,不太符合OOP(即面向对象程序设计 )的思想,而且底层空间需要用户自己管理,稍不留神可 能还会越界访问。

而在C++中的string是表示字符串的字符串类,该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作。string在底层实际是:basic_string模板类的别名,typedef basic_string<char, char_traits, allocator> string;并且不能操作多字节或者变长字符的序列。String类可以管理字符串,大大减少了人工管理所存在的问题。

但需要注意的是:使用string类时,必须包含#include头文件以及using namespace std;

三、string类的常用接口

3.1 构造函数

 String类的构造函数有7个,主要是以下三个,分别是默认构造,拷贝构造以及带参的构造

“首先cin的输入有一个特点,在遇到‘ ’(空格)或换行时,会结束输入,因为cin以空格和换行为间隔,区分前后的输入,而cin.get()则将‘ ’也作为了一个字符放到输入里。”

然而上面的三个构造函数是非常重要的,需要着重掌握,其次我们也可以了解一下

 这个构造函数的作用是用str对象从第pos个位置开始npos个长度去构造新的对象

其中npos为缺省值,默认为-1,又因为是size_t类型,所以是整形的最大值,即表示如果你没有给长度的时候,会使用这个缺省值,又因为size_t类型,所以从第pos位置开始有多少拷贝多少

 npos是静态成员变量也是size_t类型,即表示整形的最大值

 

 作用:拷贝s的前三个字符

需要与上面

区别的是:一个是const char* 指针,一个是const string& str对象

 

作用:用n个c字符去初始化

3.2 析构函数

 系统会自动调用析构函数

3.3  string 的容量操作

size 用于返回字符串有效字符长度,不包含'\0',作为下标是最后一个数据的下一个位置

length  用于返回字符串有效字符长度,不包含'\0'

 max_size 返回字符串最大长度

 capacity 返回空间的分配大小

 clear 清理空间数据

 empty 检测字符串释放为空串,是返回true,否则返回false

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

遍历string方式一  :  char&返回不是为了减少拷贝,是为了支持修改返回对象,返回的是pos位置的字符的引用,

即可以对pos位置的值进行修改

遍历string 方式2 :迭代器 可以把it理解成指针

 

 方式3:范围for:每次自动识别每个字符赋值给e,自动往后迭代,自动判断结束

可读可写:

 迭代器:

对于string,[ ]+下标的方式已经很好来访问和修改了,为什么还要用正向迭代器和反向迭代器呢?

对于string,下标和[ ]是足够好用,可以不同迭代器,但是对于其他的容器呢?

所以使用迭代器的原因是所有的容器都可以用迭代器去访问和修改。

 除了3.4第二种方式里面使用的正向迭代器外还有反向迭代器

带有const 的正向和反向迭代器

 at 与operator[]的作用差不多,但是他们的区别在于当发生错误的时候,at是进行抛异常,operator[]是进行断言

 back : 用于返回字符串尾上的字符

 front:用于返回字符串头上的字符

3.5 string类对象的修改操作

push_back   在字符串后尾插字符 c
append    在字符串后追加一个字符串

operator+= ( 重点 ) 在字符串后追加字符串 str(可以直接适用上面俩个情况,推荐)

 牛刀小试:

力扣https://leetcode.cn/problems/reverse-only-letters/

思路:与快排相似,设置头和尾的俩个下标,头和尾下标都是字母则进行交换,如果有一个不是则再while循环中进行寻找,直到是字母,然后再进行交换,然后继续迭代

运行今日学习的方方:比如string类中的swap模板,size等等

class Solution {
public:
    string reverseOnlyLetters(string s) 
    {
        int begin = 0;
        int end = s.size()-1;
        while(begin < end)
        {
            //如果不是字母就跳过,都是字母就交换,如果一直都不是字母呢?不就一直++了吗,所以也要进行begin<end判断
            while(begin < end && !isalpha(s[begin]))
            {
                begin++;//直到找到是字母,然后交换
            }
            while(begin < end && !isalpha(s[end]))
            {
                end--;
            }
            //交换
            swap(s[begin],s[end]);
            //交换之后继续迭代
            ++begin;
            --end;
        }
         return s;
    }
};

力扣https://leetcode.cn/problems/first-unique-character-in-a-string/submissions/

思路:相当于计数排序,用数组的方式,时间复杂度为o(n)

因为只有26个小写字母,可以设置大小为26的整形数组(因为里面存放的是每个字母出现的次数),对字符串中的字母进行统计,从'a'为0下标开始,依次将每个字母出现的次数放在对应的下标下,然后再对字符串进行遍历即对应带对应的数组里面的次数,出现第一次次数为1的即为不重复的字母,返回它的下标,否则返回-1

class Solution {
public:
    int firstUniqChar(string s) 
    {
        //用数组的方式,相似与计数排序
        int array[26] = {0};//因为只有小写字母
       for(int  i = 0; i < s.size();i++)
       {
           array[s[i] - 'a']++;//从a为0下标开始,依次对应的字母次数放在对应的下标下
       }
       for( int j= 0; j< s.size();j++)
       {
           if(array[s[j] - 'a'] == 1)//s[j]-'a'是按照字符串中的顺序,先出现1的就是不重复的
           {
               return j;
           }
       }
       return -1;

    }
};

 利用reserve(直接开好空间)提高插入数据的效率,避免增容带来的开销

 reserve和resize的区别

 reverse和resize,如果string s1("hello world");s1有元素,那么都相当于扩容

resize如果申请的个数比s1里面的数少,那么会多余的数会删除

c_str:返回C格式字符串

查找:

find:   size_type find (charT c, size_type pos = 0) const;

查找什么字符,从pos开始找,默认pos下标为0,从左往右找第一次出现的

如果想找最后一次出现的后缀,则可以从右往左找,rfind

size_type rfind (charT c, size_type pos = npos) const;

 取url中的各个段

插入

删除

 

 牛刀小试:

字符串最后一个单词的长度_牛客题霸_牛客网

#include <iostream>
#include <string>
using namespace std;

int main()
{
    string s1;
    //因为cin遇到空格和换行结束,所以获取整个字符串的方式一:
    char ch = cin.get();//每次获取一个字符
    while(ch != '\n')//整个字符串以换行结束
    {
        s1 += ch;
        ch = cin.get();
    }
    
    //方式二:
    getline(cin,s1);//cin的字符串放到s1中去
    size_t pos = s1.rfind(' ');//从后往前找,最后一个单词

    if(pos == string::npos)
    {
        cout << s1.size()<< endl;
    }
    else
    {
        size_t length = s1.size() - (pos+1);
        cout << length << endl;
    }
    
    return 0;
}

string的比较重载函数:

 

字符串转换成整形等:

 整形等转换成字符串:

力扣https://leetcode.cn/problems/valid-palindrome/

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

class Solution 
{
public:
    bool is_alph_word(char c)
    {
        if((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >='A' && c <= 'Z'))
        {
            return true;
        }
        else
        {
            return false;
        }
    }
    bool isPalindrome(string s) 
    {
        //1.字符串是否为空
        //2.大写字符转换为小写字符,是否为字母或数字
        //3.左右俩个指针
        if(s.empty())
        {
            return true;
        }
        for(int i = 0;i < s.size();i++)
        {
            s[i] = tolower(s[i]);//忽略大小写
        }
        int left = 0;
        int right = s.size()-1;
        while(left < right)
        {
           while(left < right && !is_alph_word(s[left]))
           {
               left++;
           }
           while(left < right && !is_alph_word(s[right]))
           {
               right--;
           }
           if(s[left] == s[right])
           {
               left++;
               right--;
           }
           else
           {
               return false;
           }
        }
        return true;
    }
};

力扣icon-default.png?t=N3I4https://leetcode.cn/problems/add-strings/submissions/

给定两个字符串形式的非负整数 num1 和num2 ,计算它们的和并同样以字符串形式返回。你不能使用任何內建的用于处理大整数的库(比如 BigInteger), 也不能直接将输入的字符串转换为整数形式。
如:

class Solution {
public:
    string addStrings(string num1, string num2) 
    {
        string s1;
        //设置俩个指针end1与end2
        int end1 = num1.size()-1;
        int end2 = num2.size()-1;
        int value1 = 0;
        int value2 = 0;
        int next = 0;
        //只要有一个没结束就继续
        while(end1 >= 0 || end2 >= 0 )
        {
            //如果end1没有结束
            if(end1 >= 0)
            {
                //把其变成数
                value1 = num1[end1] -'0';
                end1--;
            }
            else
            {
                 value1 = 0;
            }
            if(end2 >= 0)
            {
                value2 = num2[end2] - '0';
                end2--;
            }
            else
            {
                value2 = 0;
            }
            int ret = value1 + value2 + next;
            if(ret > 9)
            {
                next = 1;
                ret %= 10;
            }
            else
            {
                next = 0;
            }
            s1 += (ret + '0');
        }
        //如果俩个都结束了,但是相加的值大于9了,则还需要在最前面+'1'
        if(next == 1)
        {
            s1 += '1';
        }
        reverse(s1.begin(),s1.end());
        return s1;

    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值