C中回文函数的意外输出

时间:2013-09-13 02:36:23

标签: c

我写过这个函数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;
}

4 个答案:

答案 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)

您似乎希望您的回文测试仪仅考虑字母字符,并忽略大小写。如果是这种情况,程序的逻辑是错误的。

您有ab作为字符串的索引,其中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,那么我们可以比较bs[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]) )

该检查之前的代码应该使ab处于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语句;然后你会看到每次比较的结果,而不仅仅是成功的比较。