NOIP学习小站
西安交通大学附属中学航天学校

字符串例题——删除单词后缀

问题:给定一个单词,如果单词以er、ly或者ing后缀作为结尾,则删除该后缀,否则不做任何处理。输出单词删除er、ly、ing后缀的结果(输入保证保证删除后缀后的单词长度不为0)。

分析:将单词存储在字符数组中,判断字符数组尾部的2个字符或者3个字符是否是后缀,如果是可以设置后缀第一个字符为字符串结束标志'\0'

#include<iostream>
#include<cstring>
using namespace std;
char s[1001];
int main()
{
    cin>>s;
    int len = strlen(s);
    if(len>=3 && s[len-1]=='g' && s[len-2]=='n' && s[len-3]=='i'){
        //手动设置存储字符串的字符数组某个元素为终止字符,会改变字符串的长度             
        s[len-3]='\0';
    }
    if(len>=2 && (s[len-1]=='y' && s[len-2]=='l' || s[len-1]=='r' && s[len-2]=='e')){
        s[len-2]='\0';
    }
    cout<<s;
    return 0; 
}

问题变形:上面的问题提出新的要求,删除后缀之后继续判断是否存在后缀,如果存在删除后缀,一直这样处理直到没有后缀为止。

分析:通过循环处理依次所有的后缀,使用标记变量标记某一次是否找到后缀,如果找到后缀,那么还需要继续执行循环;如果没有找到后缀,那么就可以退出循环了。

#include<iostream>
#include<cstring>
using namespace std;
char s[1001];
int main()
{
	cin>>s;
	int len = strlen(s);
	bool find = true;	//记录是否发现要删除的后缀,初始值为true 
	while(find){
		find = false;	//判断前默认没有发现,设置为false 
		if(len>=3 && s[len-1]=='g' && s[len-2]=='n' && s[len-3]=='i'){
			len -= 3; 
			s[len] = '\0';
			find = true;	//本次发现后缀 
		}
		if(len>=2 && (s[len-1]=='y' && s[len-2]=='l' || s[len-1]=='r' && s[len-2]=='e')){
			len -= 2;
			s[len] = '\0';
			find = true;	//本次发现后缀 
		}
		//执行到这里,如果find == true(也就是本次发现了要删除的后缀),那么循环还会继续执行(因为循环的条件就是find == true)
		//否则(find == false),那就没有发现要删除的后缀了,会自动跳出循环 
	}	
	cout<<s;
	return 0; 
}

当然也可以使用while(true)死循环,在循环体中没有发现后缀的时候使用break跳出循环:

#include<iostream>
#include<cstring>
using namespace std;
char s[1001];
int main()
{
    cin>>s;
    int len = strlen(s);
    while(true){
        bool find = false;    //判断前默认没有发现,设置为false 
        if(len>=3 && s[len-1]=='g' && s[len-2]=='n' && s[len-3]=='i'){
            len -= 3;
            s[len] = '\0'; 
            find = true;    //本次发现后缀
        }
        if(len>=2 && (s[len-1]=='y' && s[len-2]=='l' || s[len-1]=='r' && s[len-2]=='e')){
			len -= 2;
			s[len] = '\0';
			find = true;	//本次发现后缀 
		}
        //本次没有发现后缀,break强制退出循环 
        if(!find) break;
    }    
    cout<<s;
    return 0; 
}

也可以使用C++的string来解决问题:

#include<iostream>
#include<string>
using namespace std;
int main()
{
	string s;
	cin>>s;
	while(true){
		bool find = false; 
		if(s.length()>=2 && (s.rfind("er")==s.length()-2 || s.rfind("ly")==s.length()-2)){
			s = s.substr(0,s.length()-2);
			find = true;
		}
		if(s.length()>=3 && s.rfind("ing")==s.length()-3){
			s = s.substr(0,s.length()-3);
			find = true;
		}
		if(!find) break;
	}
	cout<<s<<endl;
	return 0;
} 

上面程序中,代码 s.rfind("er") 是用来逆向查找字符串"er"在字符串 s 中出现的位置,很显然,如果s.rfind("er")==s.length()-2,那么字符串肯定是以"er"结尾的("er"是字符串 s 的后缀)。s.substr(start,n)用来获取字符串s中从 start 开始的 n 个字符的子串。