我写过这个函数isPalindrome,它意味着从一个单独的函数中获取一个字符串输入,如果它是回文,则返回1,如果不是,则返回0。输入可以是任何字符,并且可以包含大写字母,该函数用于对这些字符进行排序,并根据字母字符纯粹检查它是否是回文。
我已经有一段时间了,我无法弄清楚出了什么问题,整个功能都在下面,但我无法理解它给我的输出,有时它完全跳过了最后的其他声明,并停止循环,我不知道为什么。当连续输入两个非字母字符时,变量a或b不会递增两次,而是将其发送到最后一个else语句并返回不正确的值。
我正在尝试编写此函数,而不将任何信息复制到单独的数组中。
int isPalindrome(char s[])
{
int logic;
int a = 0;
int b = 0;
int num = 0;
int count = 0;
while ( s[b]!='\0' )
{
if ( isalpha(s[b]) != 0 )
{
num++;
}
b++;
}
b = b - 1;
printf("The number of characters is: %d\n", b);
printf("The number of alpha characters is: %d\n", num);
while ( count < num/2 )
{
if ( !isalpha(s[a]) || s[a] == ' ')
{
a++;
}
else
{
count++;
}
if ( !isalpha(s[b]) || s[b] == ' ')
{
b--;
}
if ( toupper(s[a]) == toupper(s[b]) )
{
printf("s[%d]: %c | s[%d]: %c\n", a, toupper(s[a]), b, toupper(s[b]));
a++;
b--;
if ( a == b )
{
logic = 1;
}
}
else
{
logic = 0;
break;
}
}
return logic;
}
答案 0 :(得分:2)
有多个错误 (1)逻辑必须初始化为1 (2)每次循环迭代只检查一个无效的char。
如果你删除以下代码,它应该工作(我的意思是没有有效的字符检查)。
if ( !isalpha(s[a]) || s[a] == ' ')
{
a++;
}
else
{
count++;
}
if ( !isalpha(s[b]) || s[b] == ' ')
{
b--;
}
为了删除无效字符,最好在进入循环之前执行此操作或检查'a&lt; b'而不是count / 2并继续使用无效字符,如下所示。
logic=1;
while (a<b)
{
if ( !isalpha(s[a]))
{
a++;
continue;
}
if ( !isalpha(s[b]))
{
b--;
continue;
}
if ( toupper(s[a]) == toupper(s[b]) )
{
printf("s[%d]: %c | s[%d]: %c\n", a, toupper(s[a]), b, toupper(s[b]));
a++;
b--;
}
else
{
logic = 0;
break;
}
}
return logic;
答案 1 :(得分:2)
您似乎希望您的回文测试仪仅考虑字母字符,并忽略大小写。如果是这种情况,程序的逻辑是错误的。
您有a
和b
作为字符串的索引,其中a
从头开始,b
从结尾开始。我认为最好只设置b
到最后,然后开始工作循环,而不是计算你必须做的测试次数。只要a < b
为真,循环就会继续:
int a = 0;
int b = strlen(s) - 1;
while (a < b)
{
在循环的一侧,如果a
不是字母,则应增加s[a]
;如果b
不是字母,则递减s[b]
,只要{ {1}}继续小于a
。
b
如果在调整后, while (a < b && !isalpha(s[a]))
{
++a;
}
while (a < b && !isalpha(s[b]))
{
--b;
}
仍然小于a
,那么我们可以比较b
和s[a]
,无视案例。如果它们不相等,则该字符串不是回文,因此我们可以从循环中断开。否则,s[b]
递增,a
递减,循环继续回到顶部:
b
如果循环结束且 if (a < b && toupper(s[a]) != toupper(s[b]))
{
break;
}
++a;
--b;
}
仍为真,则表示a < b
,因此该字符串不是回文,我们可以返回false。否则,它是一个回文。所以函数可以返回这个事实:
toupper(s[a]) != toupper(s[b])
答案 2 :(得分:1)
您的错误出现在导致“有效负载”回文条件检查的代码中:
if ( toupper(s[a]) == toupper(s[b]) )
该检查之前的代码应该使a
和b
处于s[a]
和s[b]
都是字母的状态。
您的代码不会这样做:具体而言,当您将字母与非字母,甚至两个非字母进行比较时,多个非字母字符的序列会将您带到某种状态。
处理此问题的一种更简单的方法是将程序分为两个阶段。第一阶段将消除输入字符串中的所有非字母;第二阶段将进行回文检查。
复制传入的字符串,然后逐个字符地复制它,只将字母复制回字符串。您最终会得到一个与原始字符串相同或更短的字符串。
现在回文检查变得微不足道:从两端开始,检查toupper
的相等性,直到两端在中间相遇。不要忘记释放你的字符串副本!
答案 3 :(得分:1)
跳过非字母字符的代码不能处理多个连续的非字母字符的情况。您从预处理过程中知道有多少个字母字符,因此您需要用if
循环替换while
语句,并使else
的正文无条件。
我自动制作的代码还有许多其他简化。
#include <ctype.h>
#include <stdio.h>
#include <string.h>
static
int isPalindrome(char s[])
{
int a = 0;
int b = 0;
int num = 0;
int count = 0;
while (s[b] != '\0')
{
if (isalpha(s[b++]))
num++;
}
printf("The number of characters is: %d\n", b);
printf("The number of alpha characters is: %d\n", num);
while (count < num/2)
{
count++;
while (!isalpha(s[a]))
a++;
while (!isalpha(s[b]))
b--;
if (toupper(s[a]) != toupper(s[b]))
return 0;
printf("s[%d]: %c | s[%d]: %c\n", a, toupper(s[a]), b, toupper(s[b]));
a++;
b--;
}
return 1;
}
int main(void)
{
char line[256];
while (fgets(line, sizeof(line), stdin) != 0)
{
line[strlen(line)-1] = '\0';
printf("Input: <<%s>>\n", line);
if (isPalindrome(line))
puts("Palindrome");
else
puts("Not a palindrome");
}
return 0;
}
这适用于字母和非字母字符的反常序列。它将空行和由所有非字母字符组成的行视为回文;如果你想让它们被拒绝,你可以通过在循环之后的字母字符数为零的情况下报告“不是回文”来对待它,该循环计算字母字符的数量。当代码检测到字符串不能成为回文时,代码会提前返回。您可以在测试之前在循环中移动print语句;然后你会看到每次比较的结果,而不仅仅是成功的比较。