【C++】初步认识STL(3)


1.substr

函数原型

复制代码
string substr(size_t pos = 0, size_t count = npos) const;
  • pos:起始下标(从 0 开始)
  • npos:截取长度(不是下标)
  • count:截取字符个数
  • 省略 count:从 pos 一直截取到字符串末尾

2.find

函数原型

复制代码
// 1. 查找 string 类型子串
size_t find(const string& str, size_t pos = 0) const noexcept;

// 2. 查找 C 风格字符串(const char*)
size_t find(const char* s, size_t pos = 0) const;

// 3. 查找 C 字符串前 n 个字符
size_t find(const char* s, size_t pos, size_t n) const;

// 4. 查找单个字符
size_t find(char c, size_t pos = 0) const noexcept;

通用前提

**1.**下标从 0 开始

**2.**查找失败统一返回:string::npos

复制代码
 if(s.find("java") == string::npos)
    {
        cout << "未找到" << endl;
    }

**3.**二者不修改原字符串

**4.**支持查找:单个字符、子串

  • 作用:从左→右查找,返回第一个匹配的下标
  • pos:可选,指定开始查找的起始位置,默认从头0开始

rfind及相关函数

从后往前找,返回最后一次出现的子串 / 字符位置。

它和 find(从前往后找)正好相反,是面试和开发里超常用的函数

函数 方向 含义 一句话记忆
find_first_of 左→右 第一个是目标字符 找第一个出现的
find_last_of 右→左 最后一个是目标字符 找最后一个出现的
find_first_not_of 左→右 第一个不是目标字符 找第一个不一样的
find_last_not_of 右→左 最后一个不是目标字符 找最后一个不一样的
复制代码
s.find("ab");     // 必须找到 "ab" 才返回
s.find_first_of("ab"); // 找到 a 或 b 就返回

使用范例

示例 1:去掉字符串前后空格

复制代码
string s = "   Hello World   ";

// 找到第一个不是空格的位置
size_t start = s.find_first_not_of(" ");

// 找到最后一个不是空格的位置
size_t end = s.find_last_not_of(" ");

// 截取中间内容
string res = s.substr(start, end - start + 1);

cout << res; // Hello World

示例 2:查找第一个标点符号

复制代码
string s = "Hello,World!";

// 找第一个 逗号 或 感叹号
size_t pos = s.find_first_of(",!");
// pos = 5

3.getline

函数原型

复制代码
 getline (cin, str) (读取整行)
  • 用于读取 带空格 的完整一行
  • 从当前位置读到 ** 换行符\n** 为止
  • 包含空格,不包含最后的换行
  • 会吃掉换行符
函数 读取规则 遇到空格 / 回车 适用场景
cin >> 变量 读取****连续字符 自动停止,并丢弃换行 **读数字、**单个单词
getline (cin, 变量) 读取一整行 遇到回车才停止,保留空格 读带空格的句子
复制代码
string s;

cin >> s;      // 输入:hello world
cout << s;    // 输出:hello (只读到空格前)

getline(cin, s);  // 输入:hello world
cout << s;       // 输出:hello world (完整读取)

题目理解:

125. 验证回文串https://leetcode.cn/problems/valid-palindrome/

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

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

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

题解:

复制代码
class Solution {
public:
    bool isPalindrome(string s) {
        string w;
        
        for(int begin=0;begin<s.size();begin++)
        { 
            if(s[begin]>='A'&&s[begin]<='Z')
                {
                    s[begin]+=32;
                }
            if(s[begin]>='a'&&s[begin]<='z')
            w+=s[begin];
            if(s[begin]>='0'&&s[begin]<='9')
            w+=s[begin];
      }
        if(w[0]==NULL)
            return true;
        int begin1=0,end1=w.size()-1;
        while(w[begin1]==w[end1]&&begin1<end1)
            {
                begin1++;
                end1--;
            }
        if(w[begin1]!=w[end1])
        return false;
          return true; 
                   
    }
};

4.关系运算符重载

1.比较运算符

string 比较不是比较长度,而是:从左到右逐个字符比较 ASCII 值,谁的字符 ASCII 小,谁就更小。

ASCII 大小规律(记住就会用)

  • 数字 '0'~'9' < 大写字母 'A'~'Z' < 小写字母 'a'~'z'
  • 相同字符:继续比下一个
  • 前面都相同:短字符串更小

2."=="运算符

如果 operator== 只写成 string 的成员函数:

  • 只能支持:string 对象 == 其他类型str == "abc"
  • 完全不支持:其他类型 == string 对象"abc" == str 编译报错!

原因只有一句话:*成员函数的左操作数,必须是当前类(string)的对象,不能是别的类型(如 const char)。**

复制代码
bool string::operator==(const string& other) const {
    return 内容相等;
}

s1 == s2
s1.operator==(s2)

"hello" == s
"hello".operator==(s)//错误
"hello" 是 const char*,不是 string,根本没有 operator== 成员函数。

如果要使用,可以使用全局非成员函数


题目练习

1.反转字符串2

541. 反转字符串 IIhttps://leetcode.cn/problems/reverse-string-ii/

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

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

题解:

版本一:
复制代码
class Solution {
public:
    string reverseStr(string s, int k) {
        if (s.size() <= k) {
            reverse(s.begin(), s.end());
            return s;
        }
        if (s.size() < 2 * k) {
            reverse(s.begin(), s.begin() + k);
            return s;
        }
        int x = 2, xx = 0;
        if (s.size() >= 2 * k) {
            reverse(s.begin(),s.begin()+k);
            string::iterator it;
            for (it = s.begin()+k; it != s.end(); ++it) {
                if (xx == (x-1) * k) {
                    if(it+k<=s.end())
                    {
                        reverse(it, it + k);
                        x += 2;
                    }
                    else
                    reverse(it,s.end());
                }
                xx++;
            }
    
        }
        return s;
    }
};
版本二:
复制代码
class Solution {
public:
    string reverseStr(string s, int k) {
        for (int i = 0; i < s.size(); i += 2 * k) {
            int end = min(i + k, (int)s.size());
            reverse(s.begin() + i, s.begin() + end);
        }
        return s;
    }
};

2.反转字符串中的单词

557. 反转字符串中的单词 III

给定一个字符串 s ,你需要反转字符串中每个单词的字符顺序,同时仍保留空格和单词的初始顺序。

题解:

复制代码
class Solution {
public:
    string reverseWords(string s) {
        char* left=&s[0],*right=&s[0];
        for(int aim=2;aim<=s.size();aim++)
        {
            right++;
            if(*right==' ')
            {
                reverse(left,right);
                left=right;
                left++;
            }
        }
        reverse(left,right+1);
        return s;
    }
};

扩展:

复制代码
class Solution {

public:

string reverseWords(string s) {

istringstream iss(s); // 构建字符串流

string word;

string result = "";

复制
while (iss >> word) { // 流会自动以空格为界读取单词
    reverse(word.begin(), word.end()); // 反转当前单词
    result += word + " "; // 拼接到结果,加个空格
}

// 去掉最后多余的那个空格,并返回
return result.substr(0, result.length() - 1);
}

3.找出字符串中第一个只出现一次的字符

https://www.nowcoder.com/share/jump/4804461771777630173723https://www.nowcoder.com/share/jump/4804461771777630173723

对于给定的字符串,找出第一个只出现一次的字符。如果不存在,则输出 −1−1。

在一行上输入一个长度为 1≦len(s)≦1031≦len(s)≦103、仅由小写字母构成的字符串 ss。

如果存在只出现一次的字符,输出第一个满足条件的字符;否则,直接输出 −1−1。

题解:

版本一:
复制代码
#include <iostream>
#include <string> 
using namespace std;
int main()
{
    string str;
    while (getline(cin, str))
    {
        for (int i = 0; i < str.size(); i++)
        {
            if (str.find_first_of(str[i]) == str.find_last_of(str[i]))
            {
                cout << str[i] << endl;
                break;
            }
            if (i == str.size()-1)
                cout << -1<<endl;
        }
    }
    return 0;
}
版本二:
复制代码
#include <iostream>
using namespace std;

int main() {
  int arr[26]={0};
  string s;
  cin>>s;
  for(auto ch:s)
  {
    arr[ch-'a']++;
  }
  for(auto ch:s)
  {
    if(arr[ch-'a']==1)
    {
        cout<<ch<<endl;
        return 0;
    }
  } 
  cout<<-1<<endl;
    return 0;
}

相关推荐
玛丽莲茼蒿8 小时前
Leetcode hot100 螺旋矩阵【中等】
算法·leetcode·矩阵
Tisfy8 小时前
LeetCode 0396.旋转函数:求diff
算法·leetcode·题解·模拟·增量法
charlie1145141918 小时前
通用GUI编程技术——图形渲染实战(四十)——深度缓冲与3D变换:从平面到立体
开发语言·c++·平面·3d·图形渲染·win32
啊吧怪不啊吧8 小时前
C++之基于正倒排索引的Boost搜索引擎项目日志+server代码及详解
c++·搜索引擎·项目
小张同学8248 小时前
-RAG检索增强生成让智能体拥有企业级专属知识库
开发语言·python·架构·pycharm
DevilSeagull8 小时前
Rust 枚举(enum)深度解析:从定义到 Option 的安全之道
开发语言·后端·安全·rust·github
黎阳之光8 小时前
黎阳之光:视频孪生赋能国际盛会,定义数字孪生全球新标杆
大数据·人工智能·算法·安全·数字孪生
浩浩的科研笔记8 小时前
一篇教人如何写综述的顶刊论文—Literature review as a research methodology: An overview and guidelines 逐句精度
笔记
Ulyanov8 小时前
《现代 Python 桌面应用架构实战:PySide6 + QML 从入门到工程化》:实时时钟与数据驱动 UI —— 从“事件回调”到“状态绑定”的范式跃迁
开发语言·python·qt·ui·架构·交互