回文字串

字串的含义是:在原串中连续出现的字符串片段。回文的含义是正着看和倒着看相同,如abba和yyxyy。在判断时,应该忽略所有标点符号和空格,且忽略大小写,但输出应保持原样(在回文串的首部和尾部不要输出多余字符)。输入字符串长度不超过5000scanf(“%s”)输入字符串,应为它碰到空格后者TAB就会停下来

第1种方法是使用fgetc(fin),它读取一个打开的文件fin,读取一个字符,然后返回一个(int)值,为什么返回的是int而不是char呢?因为如果文件结束,fgetc将返回一个特殊的标记EOF,它并不是一个char。如果把fgetc(fin)的返回值强制转换,将无法把特殊的EOF和普通字符区分开,如果要从标准输入读取一个字符,可以用getchar(),它等价于fgetc(stdin)

总结使用fgetc(fin)可以从打开的文件fin中读取一个字符。一般情况下应当检查它不是EOF后再将其转化为char。从标准输入读取一个字符可以用getchar(),它等价于fgetc(stdin)fgetc和getchar()将读取下一个字符,因此你需要知道在各种情况下应担在检查它的下一个字符是哪个.如果用scanf(“%d”,&n)读取整数n,则要是在输入123之后多加了一个空格,用getchar()读取的是这个空格,如果在“123”之后金更着换行,则读取到的将是回车符‘\n’;

注意:1这里有个潜在的陷阱:不同操作系统的回车换行符是不一致的。WINDOWS是‘\r’和‘\n’2个字符,LINUX是‘\n’,而MACOS是‘\r’;如果在windows环境下读取windows文件,fgetc()和getchar()会把‘\r’吃掉,只剩下‘\n’;但如果在linux操作系统下读取同一个文件,它们会忠实地先读取‘\r’,然后才是‘\n’,如果编程不注意,你的程序可能会再某个操作系统上是完美的,但在另一个操作系统上是错得一塌糊涂的。当然,比赛的组织方应该避免在linux下使用windows格式的文件,但选手也应该把自己的程序写得更鲁棒,及容错性更加好

2总结在使用fgetc和getchar时,应该避免写出和操作系统相关的程序。

第2种方法是在使用fgets(buf,MAXN,fin)读取完整的一行,其中buf的声明为char buf【MAXN】。这个函数读取不超过MAXN-1个字符,然后在末尾添上结束符‘\0’,因此不会出现越界的情况,因此不会出现越界的情况,之所以说可以用这个函数读取完整的一行,是应为一旦读到回车符‘\n’,读取的工作就会立刻停止,而这个‘\n’也会是buf字符串中最后一个有效字符,再往后就是字符串的结束符‘\0’了。

注意

2种方法中只有一种情况下,buf不会以‘\n’结尾;读到文件结束符,并且文件的最后一个不是以‘\n’结尾

fgetsbufMAXNfin)将读取完整的一行放在字符数组buf中,您应当保证buf足够存放下文件的一行内容,除了在文件结束前没有遇到‘\n’这种特殊情况外,buf总是以‘\n’结尾。当一个字符都没有读到时,fgets返回NULL

关于getss),没有指明读取的最大字符数,这里会导致一个潜在的问题,gets将不停地往s里塞东西,而且gets函数不管s的可用空间是多少(应为c语言并不禁止程序读取“非法内存”),例如你声明的是char s100】,你完全可以复制s1000=a’(甚至-wall也不会警告),但是后果自负。

注意c语言中getss)存在缓存区溢出漏洞,不推荐使用

解决问题有一种方法是预处理,构造一个新的字符串,不包含原来的标点符号,而且所有字符变成大写isalphac

isalphac)在ctype.h中,它用于判断字符c是否为大写字母或者小写字母。用toupperc)返回c的大写字母形式。在这样的预处理之后,buf报讯的就是原串中的所有字母了,同样c-a+A’也可以把小写字母变成大写

当任务比较复杂时,可以用预处理的方式简化输入,并提供更多的数据供使用,复杂的字符串处理题目往往可以通过合理的预处理简化任务,便于调试

补充:头文件ctype.h中定义的isalphaisdigitisprint等工具可以用来判断字符的属性,而touppertolower等工具可以用来转化大小写

S[k]的对应字符是si+j-k】,可以标记一个值ok只要一次失败就退出将ok置于0

关于写程序值得注意的地方:在实际编程时,我们经常先编写一个具备主要功能的程序,再加以完善,这样每次只添加一点点功能,而且写一点就测试一点,和一次写完整个程序相比,更加不容易出错,这种方法叫做迭代式开发。

在程序比较复杂时,除了在设计阶段可以用伪代码理清思路,编码阶段可以采用迭代开发的方法

#include <stdio.h>
#include <string.h> 
#include <ctype.h>
#define MAXN 5000+10
char buf[MAXN],s[MAXN];
int p[MAXN];
int main(){
	int n,m=0,max=0,x,y;
	int i,j;
	fgets(buf,sizeof(s),stdin);
	n=strlen(buf);
	for(i=0;i<n;i++){
		if(isalpha(buf[i])){
			p[m]=i;
			s[m++]=toupper(buf[i]);
		}
	}
	for(i=0;i<m;i++){
		for(j=0;i-j>=0&&i+j<m;j++){
			if(s[i-j]!=s[i+j]){
				break;
			}
			if(j*2+1>max){
				max=j*2+1;
				x=p[i-j];
				y=p[i+j];
			}
		}
		for(j=0;i-j>=0&&i+j+1<m;j++){
			if(s[i-j]!=s[i+j+1]){
				break;
			}
			if(j*2+2>max){
				max=j*2+2;
				x=p[i-j];
				y=p[i+j+1];
			}
		}
	}
	//printf("x=%d y=%d\n",x,y);
	for(i=x;i<=y;i++){
		printf("%c",buf[i]);
	}
	printf("\n");
	return 0;
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值