题目描述:给出一串“可忽略关键词”(如of、and、the等)和一串“标题”(如The Old Man And The Sea等),两者用“::”分隔。任务是输出一列标题。具体要求是:所有标题中出现的“可忽略关键词”之外的单词都是“关键词”,输出的标题需按关键词的字典序排列,如果有多个标题使用同一关键词,则按标题出现的顺序依次打印。除此之外,还要求打印出的标题除了关键词大写外,其他均小写。
如:
the old MAN and the sea
the friendship between a MAN and a dog
travel to the MOON
TRAVEL to the moon
关键的知识点:字符大小写转换函数toupper和tolower;判断字母函数isalpha;sscanf中%n的用法;strcpy和strcmp函数的反复使用;给字符串排序的qsort函数。
解题思路:首先要读入“可忽略关键词”,保存在数组ignore中,然后读入“标题”,保存在title中。(注意用全局变量,否则可能空间不够!)
并且,读入“可忽略关键词”之后应该用一个getchar()消去多余的回车,否则fgets会仅仅读入一个回车。
我们选择一个一个处理字符。用sscanf时需要使用格式符%n来帮助确定指针,读入后存在数组s中,(注意s在本题中要及时清零)顺便统一转小写。若遇空格或回车,首先判断s是否是“可忽略关键词”,方法比较原始,只能逐个比较。若是,则令flag=0,清空s,continue;若不是,则与sort中已有的单词比较,若有相同的,则在num数组中保存句子序号、单词在句子中开始的序号、单词在句子中结束的序号三个信息。其中num【k】【0】保存数组长度,若没有相同的,则将单词加入sort,这里不再赘述。处理完后将sort整体复制到sorted,调用qsort函数,将字符串排为字典序。然后将sorted从上到下进行检索,目的是在sort中找出与之相同的单词,然后可以找到对应的num(序号相同),由于保存时就是按句子顺序排列的,所以也顺便符合题目中“多个标题使用同一关键词”的要求。打印时,判断“指针”p是否落在关键词的区间里,若是,则输出大写,若不是,则输出小写。不用添加printf("\n"),因为在fgets读入的时候,已经读入了回车符。
具体程序如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
char s[15]="",ignore[55][15]={""},sort[3000][15]={""},sorted[3000][15]={""},title [210][310]={""};
int num[3000][630]={0};
int cmp_string(const void*_a,const void*_b);
int main(void)
{
int i=0,j=0,k=0,ignum=0,tinum=0,n=0,ch=0;
for(i=0;i<3000;i++)
num[i][0]=1;
i=0;
while(scanf("%s",s)==1&&isalpha(s[0]))
{
strcpy(ignore[i++],s);
memset(s,'\0',sizeof(s));
}
getchar();
while(fgets(title[j],310,stdin)!=NULL)
j++;
ignum=i;tinum=j;
memset(s,'\0',sizeof(s));
for(j=0;j<tinum;j++)
{
char *p=title[j];
int count=-1,temp,q=0;
while(sscanf(p,"%c%n",&ch,&n)==1)
{
count++;
p+=n;
if(isalpha(ch)) s[q++]=tolower(ch);
if(ch==' '||ch=='\n')
{
int flag=1,judge=1,len=q;
q=0;
for(i=0;i<ignum;i++)
if(strcmp(ignore[i],s)==0) {flag=0;break;}
if(!flag) {memset(s,'\0',sizeof(s));continue;}
for(i=0;i<k;i++)
if(strcmp(sort[i],s)==0)
{
temp=num[i][0];
num[i][temp]=j;
num[i][temp+1]=count-len;
num[i][temp+2]=count-1;
num[i][0]+=3;
judge=0;
break;
}
if(judge)
{
temp=num[k][0];
num[k][temp]=j;
num[k][temp+1]=count-len;
num[k][temp+2]=count-1;
num[k][0]+=3;
strcpy(sort[k++],s);
}
memset(s,'\0',sizeof(s));
}
if(ch=='\n') break;
}
}
for(i=0;i<k;i++)
strcpy(sorted[i],sort[i]);
qsort(sorted,k,sizeof(sorted[0]),cmp_string);
for(i=0;i<k;i++)
for(j=0;j<k;j++)
if(strcmp(sorted[i],sort[j])==0)
{
int t=1;
while(t<num[j][0])
{
int p=0;
while(title[num[j][t]][p]!='\0')
{
if(p>=num[j][t+1]&&p<=num[j][t+2])
printf("%c",toupper(title[num[j][t]][p]));
else
printf("%c",tolower(title[num[j][t]][p]));
p++;
}
t+=3;
}
}
return 0;
}
int cmp_string(const void*_a,const void*_b)
{
char*a=(char*)_a;
char*b=(char*)_b;
return strcmp(a,b);
}