尝试通过使用字符串来检查数字是否为回文

Trying to check if a number is a palindrome through the use of strings

我正在尝试检查输入的数字是否为回文。我是通过字符串而不是整数来完成的。所以,我正在接收一个字符串并将其反转为另一个字符串。但是,当我使用字符串比较函数时,它没有给我 0,说明字符串不相同。即使当我输入例如“1001”时,输入字符串和反向字符串都显示 1001。我已经用其他方法解决了这个问题,但我试图具体了解这个方法有什么问题。

#include <stdio.h>
#include <string.h>

int main(void)
{
    char input[100];
    char reverse[100];

    int numLen = 0;

    printf("Enter a number\n");
    fgets(input, 100, stdin);
    printf("The number is: %s\n", input);

    numLen = strlen(input) - 1;
    printf("Length of string is: %d\n", numLen);

    for (int i = 0; i < numLen; i++)
    {
        reverse[i] = input[numLen - 1 - i];

        if (i == numLen - 1)
        {
            reverse[i + 1] = '[=10=]';
        }
    }

    printf("The reverse number is: %s\n", reverse);
    printf("The original number is: %s\n", input);

    int result = strcmp(input, reverse);
    printf("Result of strcmp gives us: %d\n", result);

    if (strcmp(input, reverse) == 0)
    {
        printf("These numbers are palindromes\n");
    }
    else
    {
        printf("These numbers are not palindromes\n");
    }

    return 0;
}

问题是您没有正确处理字符串。你应该用 [=17=].

覆盖 '\n'
    ...
    char input[100];
    char reverse[100];

    int numLen = 0;

    printf("Enter a number\n");
    fgets(input, 100, stdin);
    printf("The number is: %s\n", input);
    input[strcspn(input,"\n")]='[=10=]'; // getting the length of the 
                                     // string without `\n` 
                                     // and overwriting with `[=10=]`
    numLen = strlen(input) ;  // now you don't need to put the -1
    printf("Length of string is: %d\n", numLen);

    for (int i = 0; i < numLen; i++)
    {
        ....

除了这两个变化之外,其他一切都保持不变。你把它完全颠倒过来了。然后你正确地使用了 strcmp。但是我显示的代码中删除了额外的 \n

(仍然)为什么有效?

现在给你一个更好的主意。你很好地形成了反转的字符串。但是原始字符串本身有 \n

printf("The reverse number is: (%s)\n", reverse);
printf("The original number is: (%s)\n", input);

在前面的程序中你只写了这两行。你会明白哪里错了。

在给出输入 1001Enter 时给出此输出。

The reverse number is: (1001)
The original number is: (1001
)

strcspn在做什么?

我使用 strcspn 函数得到了没有 \n 的长度,并用 [=17=] 覆盖了它。

0 1 2 3  4  5   --> indices
1 0 0 1 \n [=13=]   --> strcspn(input,"\n") returns 4.
1 0 0 1 [=13=] [=13=]   --> input[strcspn(input,"\n")]='[=13=]'

你可以像这样简单地做,而不需要复制和其他任何东西。

无需额外内存 - 进行回文检查

bool checkPal(const char *s){
    for(int i = 0, j= strlen(s)-1; i< strlen(s) && j>=0 ; i++)
        if(s[i] != s[j])
            return false;
    return true;
}
int main(void)
{
    char input[100];
    char reverse[100];

    
    printf("Enter a number\n");
    if( fgets(input, 100, stdin) )
    printf("The number is: %s\n", input);
    
    input[strcspn(input,"\n")]='[=14=]';
    int numLen = strlen(input) ;
    printf("Length of string is: %d \n", numLen);
  
    printf("These numbers are %spalindromes\n", checkPal(input)?"not ":"");
    return 0;
}

checkPal() 更简洁的写法是,

bool checkPal(const char *first){
    const char *last = first + strlen(first);
    while (first < last) {
       if (*first++ != *--last) {
           return false;
       }
   }
   return true;
}

last 指向 [=17=] 字符。在我们开始比较之前,减法是必要的。要清楚地了解发生了什么,您必须知道优先级和一些规则。

first<last 部分很明显。我们一直比较到 first > last(对于偶数长度的字符串)或 first = last(对于奇数长度的字符串)。

if 有点棘手。 *first++ 涉及两个运算符。 *(间接)和++(post增量)。

并且 ++ 的优先级高于取消引用 *

所以 *first++ 将是 - 首先递增。然后你可能会认为我们第一次漏掉了一个字符,但事实并非如此。 postfix 表达式的值是我们执行 first++ 之前的值。所以现在你有了第一个角色。

同理*--last除了前缀表达式的值为运算后的值外,效果相同。所以你在考虑最后一个字符。

如果匹配,我们继续。 firstlast 已包含修改后的值。我们对较小的子字符串中的其余字符重复相同的逻辑。

如果出现不匹配,我们会立即 return。 (因为它不是回文)。

对不起,我的错。试试这个:

#include <stdio.h>
#include <string.h>

// A function to check if a string str is palindrome
void isPalindrome(char str[])
{
    // Start from leftmost and rightmost corners of str
    int l = 0;
    int h = strlen(str) - 1;

    // Keep comparing characters while they are same
    while (h > l)
    {
        if (str[l++] != str[h--])
        {
            printf("%s is Not Palindromen", str);
            return;
        }
    }
    printf("%s is palindromen", str);
}

// Driver program to test above function
int main()
{
    isPalindrome("abba");
    isPalindrome("abbccbba");
    isPalindrome("geeks");
    return 0;
}

这个有用吗?

一个变体,递归版本,没有更多的字符串作为参数(或原始字符串的副本)

int pal(char *s) {
    int n = strlen(s);
    if (n <= 1) return 1;
    if (s[0] != s[n-1]) return 0;
    s[n-1] = '[=10=]';
    return pal(++s);
}

return 0:不是回文,1:是回文

请注意字符串已更改,因此如果有问题(或者如果字符串是在静态区域中创建的),您可以这样调用它

char *copy = malloc(strlen(string)+1); // string is original string
strcpy(copy, string);
int ispal = pal( copy );

printf("Is %s a palindrome\n", ispal ? "":"not");