一道特殊的回文字符串处理问题

.特殊之处在于:

1.仅考虑字母的回文,而输出保留字符串中的非字母字符

2.大小写均视为相等。

举例说明:He says: Madam! I'm Adam!

输出将为——Madam! I'm Adam


这道题一开始给我带来了很大的困扰,本来考虑的是在判断回文的过程中,过滤掉非字母的角标。但是这个思路的程序边界条件太过复杂,最终我还是放弃了。(参见第二段程序,失败的部分我也贴上来已做记录)


后来受到启发,首先对字符串做一个预处理,建立一个char * pre[],来存放s[]中判断为字母的部分的地址。然后通过对pre[]中回文的判断,来确定回文的左右角标。

具体程序如下,其中的注释记录了在寻找Bug过程中的种种问题。这对于以后的学习有很大帮助!

#include<iostream>
#include<string.h>
using namespace std;
const int N=500;
char s[N];
void tst(char a)
{
	cout<<a<<';';
}
void printpalin()
{
	//预处理,过滤掉非字符。
	char* pre[N];
	int pre_i=0;

	for(int j=0;j<sizeof(s)-1;j++)
	{
		if(isalpha(s[j]))
		{
			pre[pre_i++]=&s[j];//存放原来的地址
		}
	}
	//预处理完毕。通过指针操作s中数字。
	int left,right,i=1;//边界溢出了!!经过无数次的条数:原因竟然是sizeof(pre)=2000,这是我没有想到的。因为这个错误,耽误了好长好长时间!
	while(i<pre_i)
	{	
		int move=0;
		left=i-1;right=i+1;
		while(left>=0&&right<pre_i&&(*pre[left]==*pre[right]||(*pre[left]==*pre[right]+'a'-'A')||(*pre[left]==*pre[right]+'A'-'a')))
		{
			left--;
			right++;
			move++;
		}
		if(move)
		{
			right--;
			for(char* j=pre[++left];j<=pre[right];j++)//末端处理不好,总是会多输出和下一个字母间的符号。
				//原来是因为把'--'写在了for循环里,造成了被执行多次!!!这点要注意!这个程序里各种BUG,都是意外的。
				//其实也很简单,边界条件考虑还是不周全!对sizeof还是不熟练。
				cout<<*j;
			cout<<'\n';
		}
		//另一种情况,对称字符串。
		move=0;
		left=i-1;right=i;
		while(left>=0&&right<pre_i&&(*pre[left]==*pre[right]||(*pre[left]==*pre[right]+'a'-'A')||(*pre[left]==*pre[right]+'A'-'a')))
		{
			left--;
			right++;
			move++;
		}
		if(move)
		{
			right--;
			for(char* j=pre[++left];j<=pre[right];j++)
				cout<<*j;
			cout<<'\n';
		}
		i++;
	}
}

int main()
{
	FILE *fin;
	fin=fopen("input.txt","rb");
	s[N]=fscanf(fin,"%s",s);
	printpalin();
	getchar();
}
很高兴最后这个程序没有BUG了,对于二重指针的理解也有了一些。

可见解决问题前一定要考虑好方法,下面的程序是一个失败的例子。我尝试理清其中的思路,但是最后不得不放弃。因为这段程序实在是太烂&乱了……

想法是好的,但是BUG实在太多了,可能会尝试会改一改这段,让它能正常运行。

#include<iostream>
#include<string.h>
using namespace std;
const int N=500;
char s[N];
void tst(char a)
{
	cout<<a<<';';
}
void ifpalin()//我觉得我应该用预处理。。。。。。!!!!!!已然不想写了,数据结构的重要性!
{
	int left,right,i=0;
	while(s[i])
	{
		//tst('A');
		//寻找第一个非符号点。
		while(!isalpha(s[i]))
		{
			i++;
			//tst('B');
		}
		left=i-1;right=i+1;
		while(s[left]&&(!isalpha(s[left]))&&right<sizeof(s))
		{
			left--;
			//tst('C');
		}//寻找标点左边第一个非符号点。
		while(s[right]&&(!isalpha(s[right]))&&left>=0)
		{
			right++;
			//tst('D');
		}//寻找右边第一个非符号点。

		if(isalpha(s[right])&&isalpha(s[left]))//必须是左右都有才能判断。
		{		
			while(s[left]==s[right]&&left>=0&&right<sizeof(s))
			{
				//tst('E');
				while(left>=0&&!isalpha(s[left--]));
				while(right<=sizeof(s)&&!isalpha(s[right++]));//写在while里可以多加一次
			}
			if(left!=(i-1)&&left!=right)
			{
				for(int j=++left;j<right;j++)
					cout<<s[j];
				cout<<'\n';
			}
		}
		i++;
		//两种情况。用两次。不能用if简化,没想好一串aaaaaaaaaaa时怎么处理
	}
}

int main()
{
	FILE *fin;
	fin=fopen("input.txt","rb");
	s[N]=fscanf(fin,"%s",s);
	ifpalin();
	getchar();
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值