12.26课程复盘(C++ string类型的使用)

题目一 敲笨钟

微博上有个自称“大笨钟V”的家伙,每天敲钟催促码农们爱惜身体早点睡觉。为了增加敲钟的趣味性,还会糟改几句古诗词。其糟改的方法为:去网上搜寻压“ong”韵的古诗词,把句尾的三个字换成“敲笨钟”。例如唐代诗人李贺有名句曰:“寻章摘句老雕虫,晓月当帘挂玉弓”,其中“虫”(chong)和“弓”(gong)都压了“ong”韵。于是这句诗就被糟改为“寻章摘句老雕虫,晓月当帘敲笨钟”。

现在给你一大堆古诗词句,要求你写个程序自动将压“ong”韵的句子糟改成“敲笨钟”。

输入格式:

输入首先在第一行给出一个不超过 20 的正整数 N。随后 N 行,每行用汉语拼音给出一句古诗词,分上下两半句,用逗号 , 分隔,句号 . 结尾。相邻两字的拼音之间用一个空格分隔。题目保证每个字的拼音不超过 6 个字符,每行字符的总长度不超过 100,并且下半句诗至少有 3 个字。

输出格式:

对每一行诗句,判断其是否压“ong”韵。即上下两句末尾的字都是“ong”结尾。如果是压此韵的,就按题面方法糟改之后输出,输出格式同输入;否则输出 Skipped,即跳过此句。

输入样例:

5
xun zhang zhai ju lao diao chong, xiao yue dang lian gua yu gong.
tian sheng wo cai bi you yong, qian jin san jin huan fu lai.
xue zhui rou zhi leng wei rong, an xiao chen jing shu wei long.
zuo ye xing chen zuo ye feng, hua lou xi pan gui tang dong.
ren xian gui hua luo, ye jing chun shan kong.

输出样例:

xun zhang zhai ju lao diao chong, xiao yue dang lian qiao ben zhong.
Skipped
xue zhui rou zhi leng wei rong, an xiao chen jing qiao ben zhong.
Skipped
Skipped

主要思路 

利用for循环逐句读取string,检索其中有无输入的目标字符,若有则将末尾三个字替换成qiao ben zhong,无则整体替换为Skipped。

注意!查找字符串a是否包含子串b,不是用strA.find(strB) > 0 而是 strA.find(strB) != string:npos。其中string:npos是个特殊值,说明查找没有匹配。

总代码

#include <iostream>
using namespace std;

int main()
{
    int n;
    string str[22];
    string s="qiao ben zhong.";
    string t="Skipped"; 
    cin >> n;
    getchar();   
    for(int i=0;i<n;i++)    
    {
        getline(cin,str[i]);  
        if(str[i].find("ong,")!=string :: npos)
        {
            if(str[i].rfind("ong.")!=string :: npos) 
            {
                int k=0,f=0; 
                unsigned int j=str[i].size();  
                for(;j>0;j--)
                {
                    if(k==3)   
                        break;
                    else
                        if(str[i][j]==' ')  
                        k++;
                    f++;   
                }
                str[i].replace(j+2,f,s);  
            }
            else
                str[i].replace(0,str[i].length(),t); 
        }
        else
            str[i].replace(0,str[i].length(),t); 
    }
    for(int i=0;i<n;i++) 
    {
        cout << str[i] << endl;
    }
    return 0;
}

getchar()的用法

在给定的代码中,getchar() 函数的作用是为了消耗在使用 cin >> n 读取整数 n 后留在输入缓冲区中的换行符。

当使用 cin >> n 读取整数时,它会从输入流中读取一个整数,但它会在输入缓冲区中留下换行符(Enter 键)。这个换行符可能会被误读为下一个输入操作(例如 getline(cin, str[i])),导致它读取一个空行。

为了避免这个问题,getchar() 函数被用来在进入使用 getline() 读取行的循环之前消耗换行符。这确保了换行符不会被误读为空行。

cin >> n;
getchar(); // 消耗换行符

for (int i = 0; i < n; i++)    
{
    getline(cin, str[i]);  // 读取一行
    // ...(代码的其余部分)
}

string的函数的用法  

声明一个C++字符串

string str:生成空字符串

string s(str):生成字符串为str的复制品

string s(str, strbegin,strlen):将字符串str中从下标strbegin开始、长度为strlen的部分作为字符串初值

string s(cstr, char_len):以C_string类型cstr的前char_len个字符串作为字符串s的初值

string s(num ,c):生成num个c字符的字符串

string s(str, stridx):将字符串str中从下标stridx开始到字符串结束的位置作为字符串初值

eg:


    string str1;               //生成空字符串
    string str2("123456789");  //生成"1234456789"的复制品
    string str3("12345", 0, 3);//结果为"123"
    string str4("012345", 5);  //结果为"01234"
    string str5(5, '1');       //结果为"11111"
    string str6(str2, 2);      //结果为"3456789"

读取一行文本并赋值:getline()函数

 string line;
// 从标准输入读取一行文本并赋值给line
getline(cin, line); 

获取字符串长度

 1.str.length()

string str = "Hello World!";
cout << str.length() << endl;
//输出:12

2.str.size()

string str = "Hello World!";
cout << str.size() << endl;
//输出:12

3.使用C风格的字符串函数strlen()(需要包含cstring头文件)

#include<cstring>
const char* cstr = "Hello world!";
cout << strlen(cstr) << endl;
//输出:12

访问字符串内的元素

通过索引访问字符串,用for循环遍历输出

string str = "abcd1234";
//输出:abcd1234
for (int i = 0; i < str.size(); i++) { //这里使用str.length()也是可以的
	cout << str[i];
}
cout << endl;

 通过迭代器访问字符串

①直接使用auto替代繁琐的类型声明:  (方便)

string str = "abcd1234";
//输出:abcd1234
for (auto it : str) {
	cout << it;
}
cout << endl;

②声明类型 

string str = "abcd1234";
//输出:abcd1234
for (string::iterator it = str.begin(); it != str.end(); it++) {
	out << *it;
}
cout << endl;

③或者用auto代替string,效果也是一样的: 

string str = "abcd1234";
//输出:abcd1234
for (auto it = str.begin(); it != str.end(); it++) {
	cout << *it;
}
cout << endl;

插入字符串

在字符串开头插入

索引为0的位置插入

//向字符串索引为0的位置插入"1234",就是在字符串的开头添加"1234"
str.insert(0, "1234"); 

或者直接使用+

string str = "abcdefg";
str = "1234" + str;

在字符串末尾添加

索引,在str.size()处

//向字符串索引为str.size()的位置插入"1234",就是在字符串的末尾添加"1234"
str.insert(str.size(), "1234");

直接使用+

string str = "abcdefg";
str = str + "1234"; //或者str += "1234";

 连接字符串

1.直接使用+

2.通过append()连接字符串

string str = "abcdefg";
str.append("1234");
//输出:abcdefg1234
cout << str << endl;

删除、修改、替换字符串中的元素

删除:erase函数

string str = "0123456789";
//从索引为2的位置开始(包括2),删除3个字符
str.erase(2, 3);
//输出:0156789
cout << str << endl;
 
string str = "0000123456789";
//从索引为0的位置开始(包括0),删除3个字符
str.erase(0, 3);
//输出:0123456789
cout << str << endl;

通过索引修改

string str = "0123456789";
str[0] = 'a';
str[1] = 'b';
str[2] = 'c';
//输出:abc3456789
cout << str << endl;

 通过replace()函数

string str = "0123456789";
//替换str中从索引1(包括1)开始的3个字符为"abcde"
str.replace(1, 3, "abcde");
//输出:0abcde456789
cout << str << endl;

查找字符串中的元素/查找子串 

find()函数

如果能找到,返回子串第一个字符所在的索引;如果找不到,返回-1,不会报错; 

string str = "Hello, world!";
	// 查找子串的位置
int pos = str.find("world"); 
	//输出:7
cout << pos << endl;

int pos1 = str.find("llo");
	//输出:2
cout << pos1 << endl;

rfind()函数

该函数从字符串的末尾开始查找子串

与find()函数类似,只是find()函数从字符串开头开始查找

截取子串:substr()函数

string str = "0123456789";
//截取字符串从索引3开始的,长度为5的子串
string sub = str.substr(3, 5); 
//输出:34567
cout << sub << endl;

转换为其他数据类型 

字符串转整数:stoi() 函数

	string str = "123";
	int num = stoi(str);
	//输出:123
	cout << num << endl;

字符串转浮点数:stof()函数   类似stoi()函数

字符串转双精度浮点数:stod()函数

大小写转换

转小写:tolower();转大写:toupper();用法相似。

string str= "THIS IS A STRING";
for (int i=0; i <str.size(); i++)
   {
   str[i] = tolower(str[i]);
   }

 string的排序:sort(s.begin(),s.end()) 

string s = "cdefba";
sort(s.begin(),s.end());
cout<<"s:"<<s<<endl;     // 结果:abcdef

题目二 特立独行的幸福

对一个十进制数的各位数字做一次平方和,称作一次迭代。如果一个十进制数能通过若干次迭代得到 1,就称该数为幸福数。1 是一个幸福数。此外,例如 19 经过 1 次迭代得到 82,2 次迭代后得到 68,3 次迭代后得到 100,最后得到 1。则 19 就是幸福数。显然,在一个幸福数迭代到 1 的过程中经过的数字都是幸福数,它们的幸福是依附于初始数字的。例如 82、68、100 的幸福是依附于 19 的。而一个特立独行的幸福数,是在一个有限的区间内不依附于任何其它数字的;其独立性就是依附于它的的幸福数的个数。如果这个数还是个素数,则其独立性加倍。例如 19 在区间[1, 100] 内就是一个特立独行的幸福数,其独立性为 2×4=8。

另一方面,如果一个大于1的数字经过数次迭代后进入了死循环,那这个数就不幸福。例如 29 迭代得到 85、89、145、42、20、4、16、37、58、89、…… 可见 89 到 58 形成了死循环,所以 29 就不幸福。

本题就要求你编写程序,列出给定区间内的所有特立独行的幸福数和它的独立性。

输入格式:

输入在第一行给出闭区间的两个端点:1<A<B≤104。

输出格式:

按递增顺序列出给定闭区间 [A,B] 内的所有特立独行的幸福数和它的独立性。每对数字占一行,数字间以 1 个空格分隔。

如果区间内没有幸福数,则在一行中输出 SAD

输入样例 1:

10 40

输出样例 1:

19 8
23 6
28 3
31 4
32 3

注意:样例中,10、13 也都是幸福数,但它们分别依附于其他数字(如 23、31 等等),所以不输出。其它数字虽然其实也依附于其它幸福数,但因为那些数字不在给定区间 [10, 40] 内,所以它们在给定区间内是特立独行的幸福数。

输入样例 2:

110 120

输出样例 2:

SAD

总代码

#include <iostream>
#include <vector>
#include <cmath>
using namespace std;

struct HAPPY_NUMBER{
    int number;//幸福数
    int independece;//独立性
};
//判断n是否是素数
bool isPrime(int n){
     for(int i=2;i<=sqrt(n);i++)
        if(n%i==0)
            return false;
    return true;
}
//对n做一次迭代,算平方数
int interateNumber(int n){
    int m=0;
    while(n>0){ 
        m+=pow(n%10,2);
        n/=10;
    }
    return m;
}

//判断n是否是幸福数,如果是,就返回链条上的所有数,否则返回size==0的vector
vector<int> isHappy(int x){
    vector<int> happy;
    while(x!=1){
        x=interateNumber(x);
        size_t j;
        for(j=0;j<happy.size();j++){
            if(x==happy[j])
                break;
        }
        if(j<happy.size())
            break;
        else
            happy.push_back(x);
    }
    if(x!=1)
        happy.clear();
    return happy;
}

vector<HAPPY_NUMBER> work(int m,int n){
    vector<HAPPY_NUMBER> specialHappy;
    vector<int> globalHappy;
    for(int i=m;i<=n;i++){
        //判断i是否是幸福数,如果是就放入specialHappy,并将链条上的数全部放到globalHappy
        vector<int> happy =isHappy(i);
        if(happy.size()>0){
            HAPPY_NUMBER hn;
            hn.number= i;
            if(isPrime(hn.number))
                hn.independece=happy.size()*2;
            else
                hn.independece=happy.size();
            specialHappy.push_back(hn);
            globalHappy.insert(globalHappy.end(),happy.begin(),happy.end());
        }
    }
    //将specialHappy里面在globalHappy出现过的删除
    for(int i=specialHappy.size()-1;i>=0;i--){
        for(size_t j=0;j<globalHappy.size();j++){
            if(specialHappy[i].number==globalHappy[j]){
                specialHappy.erase(specialHappy.begin() + i);
                break;
            }
        }
    }
    return specialHappy;
}

int main()
{
    int m,n;
    vector<HAPPY_NUMBER> specialHappy;
    cin>>m>>n;
    specialHappy =  work(m,n);
    if(specialHappy.size()>0)
    {
        for(HAPPY_NUMBER h:specialHappy)//遍历specialHappy,并将每个元素赋值给变量h。
        //HAPPY_NUMBER是自定义的数据类型
        {
            cout<<h.number<<" "<<h.independece<<endl;
        }
    }else 
        cout<<"SAD"<<endl;
    system("pause");
    return 0;
}

 vector的使用

[详解-vector] C++必知必会 vector常用各种操作解析 - 知乎

size_t

size_t 是一些C/C++标准在stddef.h中定义的,size_t 类型表示C中任何对象所能达到的最大长度,它是无符号整数。

size_t 在数组下标和内存管理函数之类的地方广泛使用。例如,size_t 用做sizeof 操作符的返回值类型,同时也是很多函数的参数类型,包括malloc 和strlen。

在声明诸如字符数或者数组索引这样的长度变量时用size_t 是好的做法。它经常用于循环计数器、数组索引,有时候还用在指针算术运算上。

  • 19
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值