目录

1.string的接口

1.1 find & substr

1.1.1 找文件名后缀

1.1.2 网址找域名

1.1.3 几道oj题目

题目1:字符串最后一个单词的长度

描述

思路:

代码

题目2:验证回文串

描述

思路

代码

题目3:字符串相加

描述:

思路:

代码:

题目4:字符串相乘

描述:

思路:

代码:


1.string的接口

1.1 find & substr

1.1.1 找文件名后缀

find可以找字符串、字符、string类型,返回值是下标

substr用来找子串,一般有两个形参,如果只填一个,那就会从当前位置开始找到最后;第二个形参是从当前位置开始往后找几个,例如:string str = "string.txt",先用find找到了.的位置,例如是pos,那么substr(str,1)就会找到'.'       substr(str,2)就会找到'.t' 

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

int main() 
{
	// find和substr接口
	string str1 = "yulei.png";
	string str2 = "yusanshi.avi";
	string str3 = "yusanpang.jpg";

	int pos1 = str1.find('.');
	int pos2 = str2.find('.');
	int pos3 = str3.find('.');
	if (pos1 != string::npos) // npos表示没找到
	{
		cout << str1.substr(pos1) << endl;
		cout << str2.substr(pos2) << endl;
		cout << str3.substr(pos3) << endl;
	}
	

}

如果一个文件使用tar压缩再打包,后缀就是.tar.zip,我只想要.zip可以怎么做呢?

使用rfind,从后往前找

1.1.2 网址找域名

网址分为:协议 + 域名(或者ip) + 资源;

协议

找:即可;

string url1 = "https://bilibili.com/profile/info";
size_t il = url1.find(":"); 
if (il != string::npos)
{
string protocal1 = url1.substr(0,il); // il是5,刚好是https的个数
cout << protocal1 << endl;
}

域名和资源怎么找:

找域名后面的/即可;

string url1 = "https://bilibili.com/profile/info";
size_t il = url1.find(":"); 
if (il != string::npos)
{
string protocal1 = url1.substr(0,il); // il是5,刚好是https的个数
cout << protocal1 << endl;
}
size_t posEnd = url1.find('/', il + 3); // com后的/
cout << url1.substr(il + 3, posEnd - (il + 3)) << endl;;// 从b开始到/
cout << url1.substr(posEnd + 1);

封装成一个函数:

// 封装url函数

void split_url(string url)
{
	size_t pos1 = url.find(':');
	string part1 = url.substr(0, pos1); // 协议
	size_t pos2 = url.find('/', pos1 + 3); // 找域名后的/
	string part2 = url.substr(pos1 + 3,pos2 - (pos1 + 3)); // 域名
	string part3 = url.substr(pos2); // 资源
	cout << "协议:" << part1 << endl;
	cout << "域名:" << part2 << endl;
	cout << "资源:" << part3 << endl;
}



int main()
{
	string url1 = "https://bilibili.com/profile/info";
	string url2 = "https://pan.baidu.com/pfile/video?path=";
	string url3 = "https://leetcode.cn/problems/first-unique-character-in-a-string/description/";
	split_url(url1);
	split_url(url2);
	split_url(url3);
}

1.1.3 几道oj题目

题目1:字符串最后一个单词的长度

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

描述

对于给定的若干个单词组成的句子,每个单词均由大小写字母混合构成,单词间使用单个空格分隔。输出最后一个单词的长度。

输入描述:

在一行上输入若干个字符串,每个字符串代表一个单词,组成给定的句子。
除此之外,保证每个单词非空,由大小写字母混合构成,且总字符长度不超过 103103 。

输出描述:

在一行上输出一个整数,代表最后一个单词的长度。

示例1

输入:

HelloNowcoder

13

在这个样例中,最后一个单词是 "HelloNowcoder""HelloNowcoder" ,长度为 1313 。

示例2

输入:

A B C D

1
思路:

        注意这是一个oj题,有刚好和空格有关,所以,这里需要使用getline进行读取一行;

①读取完毕之后,只需要从后往前找到第一个空格;

②使用size接口获得字符串后面的位置;

③再使用这个位置 - 空格之后一个位置(最后一个单词的头);

即end - (pos + 1);即可;

④需要注意的是如果没有空格,说明字符串本身就是一个单词,直接输出它的size就可以了;

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

int main() {
   string s;
//    cin >> s; // cin遇到空格就会停止
    getline(cin,s);
    size_t pos;
   if(s.rfind(' ') != string::npos)
   {
        pos = s.rfind(' ');
        cout << s.size() - (pos + 1) << endl;
   }else
   {
        // 不然就一个单词
        cout << s.size() << endl;
   }

}

题目2:验证回文串

描述

给定一个字符串 s ,验证 s 是否是 回文串 ,只考虑字母和数字字符,可以忽略字母的大小写。

本题中,将空字符串定义为有效的 回文串 

示例 1:

输入: s = "A man, a plan, a canal: Panama"
输出: true
解释:"amanaplanacanalpanama" 是回文串

示例 2:

输入: s = "race a car"
输出: false
解释:"raceacar" 不是回文串

提示:

  • 1 <= s.length <= 2 * 105
  • 字符串 s 由 ASCII 字符组成
思路

       ① 首先使用两个指针分别指向字符串的首尾,如果遇到非字符或者非数字的直接指针响中间靠拢;

        ②如果指针停下来,说明指针指向的一定是数字或者字符,此时比较如果不相等返回false;

        ③循环结束后,直接返回true;

代码

bool isCharOrNum(char ch)
{
    if((ch >= 'a' && ch <= 'z')||(ch >= '0' && ch <= '9'))
    {
        return true;
    }else
    {
        return false;
    }
}


class Solution {
public:
    bool isPalindrome(string s) {
        // 所有大写转成小写
        for(auto& ch : s)
        {
            if(ch >= 'A' && ch <= 'Z')
            {
                ch += 32; // 这里是引用,所以直接修改了
            }
        }
        int begin = 0,end = s.size() - 1;
        while(begin < end)
        {
            // 如果是字符或者数字就比对
            while(begin < end && !isCharOrNum(s[begin]))
            { 
                ++begin;
            }
            while(begin < end && !isCharOrNum(s[end]))
            {
                --end;
            }
            if(s[begin] != s[end])
            {
                return false;
            }
            ++begin;
            --end;
        }
        return true;
    }
};

题目3:字符串相加

描述:

给定两个字符串形式的非负整数 num1 和num2 ,计算它们的和并同样以字符串形式返回。

你不能使用任何內建的用于处理大整数的库(比如 BigInteger), 也不能直接将输入的字符串转换为整数形式。

示例 1:

输入:num1 = "11", num2 = "123"
输出:"134"

示例 2:

输入:num1 = "456", num2 = "77"
输出:"533"

示例 3:

输入:num1 = "0", num2 = "0"
输出:"0"

思路:

①使用两个指针,分别指向两个字符串的最后;

②如果有一个字符串指针end,>=0,那么就进入循环;

③分别取出当前指针指向的数字(如果存在);

④计算两位数的和;

⑤判断进位,若进位需要将和-10,进位为1;如果没有进位,进位是0;

⑥将结果拼到字符串末尾;

⑦出循环,判断是否还有进位,有进位就再拼一个1;

⑧将字符串逆置。

代码:
class Solution {
public:
    string addStrings(string num1, string num2) {
        int end1 = num1.size() -1;
        int end2 = num2.size() -1; // 两个字符数字的指针
        int next = 0; // 表示进位
        string strRet;
        int ret = 0;
        while(end1 >= 0 || end2 >= 0) // 有一个数字没加完
        {
            int val1 = 0,val2 = 0;
            // 取值
            if(end1 >= 0)
            {
                val1 = num1[end1] - '0';
            }
            if(end2 >= 0)
            {
                val2 = num2[end2] - '0';
            }
            // 先相加,再判断进位,因为进位是上一个循环造成的
            ret = val1 + val2 + next;
            if(ret > 9)
            {
                ret -= 10;
                next = 1;
            }else
            {
                next = 0;
            }
            // 还原到字符串
            strRet += (ret + '0');
            --end1;
            --end2;
        }

    // 如果两个数字同时end到-1,且还有进位,尾插一个1
    if(next == 1)
    {
        strRet += '1';
    } 

    // 由于是尾插,最后需要逆置
    reverse(strRet.begin(),strRet.end());
    return strRet;
    }
};

题目4:字符串相乘

描述:

给定两个以字符串形式表示的非负整数 num1 和 num2,返回 num1 和 num2 的乘积,它们的乘积也表示为字符串形式。

注意:不能使用任何内置的 BigInteger 库或直接将输入转换为整数。

示例 1:

输入: num1 = "2", num2 = "3"
输出: "6"

示例 2:

输入: num1 = "123", num2 = "456"
输出: "56088"

提示:

  • 1 <= num1.length, num2.length <= 200
  • num1 和 num2 只能由数字组成。
  • num1 和 num2 都不包含任何前导零,除了数字0本身。
思路:

        乘法:a*b,其实就是a个b相乘;

①写一个能循环a次的循环;

②每次循环+b即可;

代码:

string addStrings(string num1, string num2) {
        int end1 = num1.size() -1;
        int end2 = num2.size() -1; // 两个字符数字的指针
        int next = 0; // 表示进位
        string strRet;
        int ret = 0;
        while(end1 >= 0 || end2 >= 0) // 有一个数字没加完
        {
            int val1 = 0,val2 = 0;
            // 取值
            if(end1 >= 0)
            {
                val1 = num1[end1] - '0';
            }
            if(end2 >= 0)
            {
                val2 = num2[end2] - '0';
            }
            // 先相加,再判断进位,因为进位是上一个循环造成的
            ret = val1 + val2 + next;
            if(ret > 9)
            {
                ret -= 10;
                next = 1;
            }else
            {
                next = 0;
            }
            // 还原到字符串
            strRet += (ret + '0');
            --end1;
            --end2;
        }

    // 如果两个数字同时end到-1,且还有进位,尾插一个1
    if(next == 1)
    {
        strRet += '1';
    } 

    // 由于是尾插,最后需要逆置
    reverse(strRet.begin(),strRet.end());
    return strRet;
    }


class Solution {
public:
    string multiply(string num1, string num2) {
        // 乘法变加法
        string zero("0");
        string ret = "0";
        while(zero != num1)
        {
            ret =  addStrings(ret,num2);
            zero = addStrings(zero,"1");
        }
        return ret;
    }
};

这段代码的性能是有问题的,有没有聪明的友友,能够优化一下呢?答案将在下期揭晓。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐