机试指南练习总结第八章
机试指南练习总结第八章-标准模板库STL
熟悉STL中常用的string
,map
等数据结构的使用
- 对于
string
对象,可以直接使用=
实现深拷贝,同时对于string
还有以下几个需要熟悉的函数
str.size(); //求字符串的大小
str1 = str1 + "a"; //直接拼接字符串
str.insert(index, str1); //在index的位置插入字符串str1
str.insert(index, count, s); //在index的位置插入cout个字符s
str.erase(index, cout); //从index位置开始删除cout个字符
str.find(str1, startPos); //从startPos位置开始查找字符串str1,若找到则返回第一次出现的下标,若不能找到,则返回string::npos
- STL中map模板的使用
map<string, int> mp; //初始化
mp.clear(); //清空map
mp.find(b); //查找mp中使用有b的映射,如果有的话返回对应的迭代器,如果没有的话返回mp.end()
mp.cout(b); //查找元素b,是否存在,有0,1两个值
例8.1:字符串的查找删除
未找到提交OJ
题目描述
给定一个短字符串(不含空格),再给定若干字符串,在这些字符串中删除所含有的短字符串
输入描述
输入只有1组数据。
输入一个短字符串(不含空格),再输入若干字符串直到文件结束为止。
输出描述:
删除输入的短字符串(不区分大小写)并去掉空格,输出
示例1
输入:
in
#include
int main()
{
printf(" Hi ");
}
输出:
#clude
tma()
{
prtf("Hi");
}
解题思路
本题主要有两个难点,第一个是数据的读入,可知本题中输入数据是一行一行读入的,可以使用getline(cin, str)
,或者gets(str)
,第一个函数是C++中的,第二个函数是C中的(str必须是字符指针)
第二个难点就是要忽略大小写,这一点就使得不能直接使用string
中的find
函数来进行查找。我的解决思路就是直接回归最原始方法,一个一个遍历字符来查找字符串,同时在查找到之后对字符串进行删除。代码如下:
#include <iostream>
#include <stdio.h>
#include <string>
#define MAX 1000
using namespace std;
//判断是否到文件结尾
int main()
{
string str;
cin>>str;
cin.ignore(1);
int s1 = str.size();
string tar;
int i, j;
while(!cin.eof())
{
getline(cin, tar);
int s2 = tar.size();
j = 0;
for(i=0; i<s2; i++)
{
while(tar[i] == str[j] || 'A' + (tar[i] - 'a') == str[j] || 'a' + (tar[i] - 'A') == str[j])
{
if(j == s1 - 1)
{
int temp1 = i - (s1 - 1);
i = temp1;
tar.erase(temp1, s1);
s2 = tar.size();
j = 0;
continue;
}
i++;
j++;
}
if(tar[i] != str[j] && 'A' + (tar[i] - 'a') != str[j] && 'a' + (tar[i] - 'A') == str[j])
i--;
j = 0;
}
s2 = tar.size();
for(i=0; i<s2; i++)
{
if(tar[i] == ' ')
tar.erase(i, 1);
}
cout<<tar<<endl;
}
return 0;
}
其他思路
- 对于忽略大小写的处理方式,书中的处理方式也值得借鉴,不容易出错。书中是将字符串拷贝一份,然后将目标字符串和拷贝的字符串都全部转为小写字母,在这两个字符串之间做查找,然后在原来的字符串中做删除,这样的话也就能够达到忽略大小写查找删除的目的。
需要总结的一些知识点
- C/C++中自带的字母大小写转换函数,
tolower(),toupper()
,包含在头文件<ctype.h>
或者< cctype >
中,能够把单个字符转换为大写或者小写,如果要转换字符串,则需要使用循环。
练习题1:单词替换
题目描述
输入一个字符串,以回车结束(字符串长度<=100)。该字符串由若干个单词组成,单词之间用一个空格隔开,所有单词区分大小写。现需要将其中的某个单词替换成另一个单词,并输出替换之后的字符串。
输入描述
多组数据。每组数据输入包括3行, 第1行是包含多个单词的字符串 s, 第2行是待替换的单词
a,(长度<=100) 第3行是a将被替换的单词b。(长度<=100) s, a, b 最前面和最后面都没有
空格.
输出描述:
每个测试数据输出只有 1 行, 将s中所有单词a替换成b之后的字符串。
示例1
输入:
You want someone to help you
You
I
输出:
I want someone to help you
解题思路
本题我是直接使用string
类中的erase
和find
函数来解决的,解题过程中碰到两个坑点
- 需要注意题目中是将一个单词替换为另一个单词,同时单词和单词之间有空格分隔,这就意味着当CCC是CC的前缀表达式时不能被替换
string
类中find
函数返回值的问题,string
中find
函数在没有找到目标时返回的是string::npos
,要注意的是,这个数的类型是string::size_type
,不能使用unsigned int
或者int
来存,要不然就会出错。我一开始使用unsigned int
来保存,在本题测试没问题,但是提交到OJ上之后就一直报数组越界,就是由于当使用unsigned int
保存时会使t != string::npos
失效。
#include <iostream>
#include <stdio.h>
#include <string>
using namespace std;
//发生越界错误
int main()
{
string str, str1, str2;
while(!cin.eof())
{
getline(cin, str);
getline(cin, str1);
getline(cin, str2);
str.insert(0, " ");
str = str + " ";
string::size_type t = str.find(" " + str1 + " ", 0);
while(t != str.npos)
{
if(str.size() == 0 || str1.size() == 0)
break;
str.erase(t, str1.size() + 2);
str.insert(t, " " + str2 + " ");
t = str.find(" " + str1 + " ");
}
str.erase(0, 1);
str.erase(str.size() - 1, 1);
cout<<str<<endl;
}
return 0;
}
其他思路
- 也可以直接使用
string
中的replace
函数来进行字符串替换
需要总结的一些知识点
string
中find
函数返回值的问题,不能使用int
,或者unsigned int
来保存,否则不同编译器可能在判断该值是否等于string::npos
时会出现问题,最保险的办法有两种
参考博客:https://blog.csdn.net/qq_33933704/article/details/79188028
//1,使用string::size_type类型来保存,然后在判断
string::size_type t = str.find(a);
while(t != string::npos)
//2,在判断是否为string::npos之后再使用int保存
while(str.find(a) != string::npos)
{
int t = str.find(a);
}
string
中replace
函数的使用问题,函数原型为:string& replace (size_t pos, size_t len, const string& str);
可以用str
来替换字符串中从pos
位置开始的len
个字符
参考博客:https://blog.csdn.net/cai_niaocainiao/article/details/81260902