1

I've written this function isPalindrome that is meant to take a string input from a separate function, and return 1 if it is a palindrome, and 0 if it is not. The input would be any characters, and may have capitals in it, and the function is meant to sort through these and purely check if it is a palindrome based on the alphabetic characters.

I've been on this for a while and I can't figure out what's going wrong, the whole function is below, but I can't make sense of the output it's giving me, sometimes it completely skips the last else statement, and stops the loop, and I've no idea why. When two non alphabetic characters are entered in a row, the variable a or b does not increment twice, rather it sends it to the last else statement and returns an incorrect value.

I'm trying to write this function without copying any information into separate arrays as well.

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

4 回答 4

2

有多个错误 (1) 逻辑必须初始化为 1 (2) 每次循环迭代只检查一个无效字符。

如果您删除以下代码,它应该可以工作(我的意思是没有有效的字符检查)。

if ( !isalpha(s[a]) || s[a] == ' ')
{
    a++;
}
else
{
    count++;
}
if ( !isalpha(s[b]) || s[b] == ' ')
{
    b--;
}

要删除无效字符,最好在进入循环之前执行此操作,或者检查 'a < 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;
于 2013-09-13T02:49:07.687 回答
2

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

你有ab作为你的字符串的索引,a从头开始,b从尾开始。与其计算你必须做的测试数量,我认为最好设置b到最后,然后开始你的工作循环。只要为a < b真,循环就会继续:

int a = 0;
int b = strlen(s) - 1;

while (a < b)
{

在循环的一侧,您应该增加aifs[a]不是字母,并减少bifs[b]不是字母,只要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仍然为真,则表示toupper(s[a]) != toupper(s[b]),所以字符串不是回文,我们可以返回假。否则,它是一个回文。所以函数可以返回这个事实:

if (a < b)
{
    return false;
}
else
{
    return true;
}
// or more succinctly: return !(a < b);
于 2013-09-13T03:05:47.830 回答
1

您的错误出现在导致“有效负载”回文条件检查的代码中:

if ( toupper(s[a]) == toupper(s[b]) )

该检查之前的代码应该带有a并且b处于这样的状态,即s[a]s[b]都是字母。

您的代码不会这样做:具体而言,当您将一个字母与一个非字母甚至两个非字母进行比较时,多个非字母字符的序列会让您进入一种状态。

处理这个问题的一个更简单的方法是将你的程序分成两个阶段。第一阶段将消除输入字符串中的所有非字母;第二阶段将执行回文检查。

复制传入的字符串,然后逐个字符地检查它,只将字母复制回字符串中。您最终会得到一个较短或与原始长度相同的字符串。

现在回文检查变得微不足道:从两端开始,检查是否相等,toupper直到两端在中间相遇。不要忘记释放字符串的副本!

于 2013-09-13T02:43:58.027 回答
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 语句;然后你会看到每个比较的结果,而不仅仅是成功的比较。

于 2013-09-13T03:23:59.933 回答