【习题解析】小杨的字典

题目:小杨的字典

题目来源:2023 年 12 月 CCF GESP C++ 四级
编程题第一题

小杨的字典
题目描述:
在遥远的星球,有两个国家 A 国和 B 国,他们使用着不同的语言:A 语言和 B 语言。小杨是 B 国的翻译官,他的工作是将 A 语言的文章翻译成 B 语言的文章。
为了顺利完成工作,小杨制作了一本字典,里面记录了 个 A 语言单词对应的 B 语言单词,巧合的是,这些单词都由地球上的 26 个小写英文字母组成。
小杨希望你写一个程序,帮助他根据这本字典翻译一段 A 语言文章。
这段文章由标点符号 !()-[]{}|;:‘",./?<> 和一些 A 语言单词构成,每个单词之间必定由至少一个标点符号分割,你的程序需要把这段话中的所有 A 语言单词替换成它的 B 语言翻译。
特别地,如果遇到不在字典中的单词,请使用大写 UNK 来替换它。
例如,小杨的字典中包含 2 个 A 语言单词 abc 和 d ,它们的 B 语言翻译分别为 a 和def ,那么我们可以把 A 语言文章 abc.d.d.abc.abcd. 翻译成 B 语言文章a.def.def.a.UNK. ,其中,单词 abcd 不在词典内,因此我们需要使用 UNK 来替换它。
输入:
第一行一个整数 ,表示词典中的条目数。保证 N<=100。
接下来 N 行,每行两个用单个空格隔开的字符串 ,分别表示字典中的一个 A 语言单词以及它对应的 B 语言翻译。
保证所有 A 不重复;保证 A 和 B 的长度不超过 10。
最后一行一个字符串 S,表示需要翻译的 A 语言文章。
保证字符串 S 的长度不超过 1000,保证字符串 S 只包含小写字母以及标点符号 !()-[]{}|;:’“,./?<> 。
输出:
输出一行,表示翻译后的结果。
特别提醒
在常规程序中,输入、输出时提供提示是好习惯。但在本场考试中,由于系统限定,请不要在输入、输出中附带任何提示信息。
样例输入1:
2
abc a
d def
abc.d.d.abc.abcd.
样例输出1:
a.def.def.a.UNK.
样例输入2:
3
abc a
d def
abcd xxxx
abc,(d)d!-abc?abcd
样例输出2:
a,(def)def!-a?xxxx
样例输入3:
1
abcdefghij klmnopqrst
!()-[]{}|;:'”,./?<>abcdefghijklmnopqrstuvwxyz
样例输出3:
!()-[]{}|;:'",./?<>UNK

分析题意

题目中要求输入 N ,N 代表字典中的条目数,所以,

int N;
cin>>N;

往下 N 行,因此,

for(int i=1;i<=N;i++)
{
	
}

分析题目意思,需要将字典的内容输入,再结合样例输入,字典内容有以下的对应关系:
字典内容对应关系

要想在一个数据结构中存储两种数据,因此使用结构体。

struct zd{//zd为字典的中文缩写
	string a;//A语言
	string b;//B语言
};

题目中要求N行字典对应,所以定义一个结构体数组。

zd sr[200];//sr为输入的中文缩写,N<=100,所以设置数组元素大于100即可

结合输入。

struct zd{//zd为字典的中文缩写
	string a;//A语言
	string b;//B语言
};
zd sr[200];
int main()
{
	int N;
	cin>>N;
	for(int i=1;i<=N;i++)
	{
		//将字典进行输入
		cin>>sr[i].a;
		cin>>sr[i].b;
	}
}

最后一行的输入,则是要翻译的A语言文章,是一个字符串,由于文章不含空格,所以使用cin即可。

string awz;//awz A语言文章中文缩写
cin>>awz;

以上,输入部分完成!
输入完成后,根据题目意思,需要遍历整个文章,只要遇到字典中含有的内容,就将其翻译成对应的B语言,对应关系和翻译如下:
对应关系及翻译

研究发现,需要整体访问字符串,首先要确定整个字符串的长度。

#include<cstring>
int len=awz.length();//使用length()获取输入文章的长度,以便访问

接下来进行访问

for(int i=0;i<len;i++)
{
	
}

结合题目中的要求,保证字符串只包含小写字母以及标点符号 !()-[]{}|;:'",./?<> ,并且符号不改变,所以可以单独对小写进行进行转换。

for(int i=0;i<len;i++)
{
	if(awz[i]>='a'&&awz[i]<='z')
	{
	
	}
}

通过上面就可以将字母分离出来,分离出来的字母需要用一个容器来存储,这时候可以选择使用一个新的字符串。

string word;

再将分离出来的字母,装入到新的字符串中

if(awz[i]>='a'&&awz[i]<='z')
{
	word+=awz[i];	
}

将其分离出来之后,只需要对word字符串进行判断是否在字典中,如果在字典中,就将对应的B语言输出,即

for(int i=1;i<=N;i++)
{
	if(sr[i].a==word)//将word和字典进行对比
	{
		cout<<sr[i].b;
	}
}

结合在一起:

#include<iostream>
#include<cstring>
using namespace std;
struct zd{//zd为字典的中文缩写
	string a;//A语言
	string b;//B语言
};
zd sr[200];
string word;//最好定在全局变量
int main()
{
	int N;
	cin>>N;
	for(int i=1;i<=N;i++)
	{
		//将字典进行输入
		cin>>sr[i].a;
		cin>>sr[i].b;
	}
	string awz;//awz A语言文章中文缩写
	cin>>awz;
	int len=awz.length();//使用length()获取输入文章的长度,以便访问
	for(int i=0;i<len;i++)
	{
		if(awz[i]>='a'&&awz[i]<='z')
		{
			word+=awz[i];
		}
		for(int i=1;i<=N;i++)
		{
			if(sr[i].a==word)//将word和字典进行对比
			{
				cout<<sr[i].b;
			}
		}
	}
}

使用样例中的输入,发现结果并不正确!
样例1
样例2

只能将 abc 转换,其他的转换不了,这也证明了方法是正确的,只是没有将代码写全。
接下来的任务就是将剩余的功能写完整。
根据题目意思,如果没有符合的单词时,需要输出UNK,但如果将UNK写入其中,就会产生根据循环次数输出UNK的情况,因此可以设定一个标记,一开始标记没有找到,找到之后再进行标记。

bool find=false;

设定好标记后,对数据进行处理。

bool find=false;
for(int i=1;i<=N;i++)
{
	if(sr[i].a==word)//将word和字典进行对比
	{
		cout<<sr[i].b;
		find=true;
	}
}

设定好标记之后,还需要解决输出UNK的情况,因此需要

bool find=false;
for(int i=1;i<=N;i++)
{
	if(sr[i].a==word)//将word和字典进行对比
	{
		cout<<sr[i].b;
		find=true;
	}
}
if(find==false)
{
	cout<<"UNK";
}

这时候发现,word没有办法再次进行添加,因此需要重新将word变为空,以便进行下次判断。

word="";//word变为空,以便进行下一次

因为设定为空,所以需要提前判断word,如果word不为空,才能进行下次判断。结合前面代码写成:

#include<iostream>
#include<cstring>
using namespace std;
struct zd{//zd为字典的中文缩写
	string a;//A语言
	string b;//B语言
};
zd sr[200];
string word;//最好定在全局变量
int main()
{
	int N;
	cin>>N;
	for(int i=1;i<=N;i++)
	{
		//将字典进行输入
		cin>>sr[i].a;
		cin>>sr[i].b;
	}
	string awz;//awz A语言文章中文缩写
	cin>>awz;
	int len=awz.length();//使用length()获取输入文章的长度,以便访问
	for(int i=0;i<len;i++)
	{
		if(awz[i]>='a'&&awz[i]<='z')
		{
			word+=awz[i];
		}
		else
		{
			if(word!="")
			{
				bool find=false;
				for(int i=1;i<=N;i++)
				{
					if(sr[i].a==word)//将word和字典进行对比
					{
						cout<<sr[i].b;
						find=true;
					}
				}
				if(find==false)
				{
					cout<<"UNK";
				}
				word="";//word变为空,以便进行下一次
			}
		}
	}
}

再次代入数据进行验证。
样例1
样例2

样例3

发现除了最后一个没能正常替换,其他的都可以进行正常替换。
也没有将符号也输出,所以接下来,先需要实现符号正常输出。其实只要在遍历之后进行输出即可。

#include<iostream>
#include<cstring>
using namespace std;
struct zd{//zd为字典的中文缩写
	string a;//A语言
	string b;//B语言
};
zd sr[200];
string word;//最好定在全局变量
int main()
{
	int N;
	cin>>N;
	for(int i=1;i<=N;i++)
	{
		//将字典进行输入
		cin>>sr[i].a;
		cin>>sr[i].b;
	}
	string awz;//awz A语言文章中文缩写
	cin>>awz;
	int len=awz.length();//使用length()获取输入文章的长度,以便访问
	for(int i=0;i<len;i++)
	{
		if(awz[i]>='a'&&awz[i]<='z')
		{
			word+=awz[i];
		}
		else
		{
			if(word!="")
			{
				bool find=false;
				for(int i=1;i<=N;i++)
				{
					if(sr[i].a==word)//将word和字典进行对比
					{
						cout<<sr[i].b;
						find=true;
					}
				}
				if(find==false)
				{
					cout<<"UNK";
				}
				word="";//word变为空,以便进行下一次
			}
			cout<<awz[i];//要在else后添加,因为前面除了小写字母,剩下的就是符号了
		}
	}
}

将数据代入之后,发现符号正常输出。
但最后一位仍然没有显示,所以需要重新对后面一段word再次判断,只需要复制前面代码即可实现。

#include<iostream>
#include<cstring>
using namespace std;
struct zd{//zd为字典的中文缩写
	string a;//A语言
	string b;//B语言
};
zd sr[200];
string word;//最好定在全局变量
int main()
{
	int N;
	cin>>N;
	for(int i=1;i<=N;i++)
	{
		//将字典进行输入
		cin>>sr[i].a;
		cin>>sr[i].b;
	}
	string awz;//awz A语言文章中文缩写
	cin>>awz;
	int len=awz.length();//使用length()获取输入文章的长度,以便访问
	for(int i=0;i<len;i++)
	{
		if(awz[i]>='a'&&awz[i]<='z')
		{
			word+=awz[i];
		}
		else
		{
			if(word!="")
			{
				bool find=false;
				for(int i=1;i<=N;i++)
				{
					if(sr[i].a==word)//将word和字典进行对比
					{
						cout<<sr[i].b;
						find=true;
					}
				}
				if(find==false)
				{
					cout<<"UNK";
				}
				word="";//word变为空,以便进行下一次
			}
			cout<<awz[i];//要在else后添加,因为前面除了小写字母,剩下的就是符号了
		}
	}
	//在最后对word字符串进行判断
	if(word!="")
	{
		bool find=false; 
		for(int i=1;i<=N;i++)
		{
			if(sr[i].a==word)//将word和字典进行对比
			{
				cout<<sr[i].b;
				find=true;
			} 
		} 
		if(find==false)
		{
			cout<<"UNK";
		}
	}
	return 0;
}

代入数据验证发现输出正确,即完成。
该题解决!
PS:其实可以在对word和字典进行对比时,输出直接break跳出即可。

  • 29
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员莫小特

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值