.特殊之处在于:
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();
}