判断给定字符串是否为回文字符串

3

我写了一个程序来判断输入的字符串是回文还是非回文,但它总是说它不是回文。

#include <conio.h> 
#include <graphics.h> 
#include <string.h>
void main(void)
{
    int i,len,halflen,flag=1;
    char str[50];
    clrscr();
    printf("Enter a string:\n");
    gets(str);
    len=strlen(str);
    halflen=len/2;
    for(i=0;i<halflen;i++)
    {
        if(str[i]!=str[i+halflen])
            flag=0;
        break;

    }
    if(flag)
        printf("It is a Palindrome.");
    else
        printf("It is not a Palindrome.");
    getch();
}

缩进的代码——这段代码是其必要性的很好演示。 - Jerry Coffin
通过修复问题中的一个错误,@Jerry Coffin,您将使阅读答案并理解它们正在解决的错误变得更加困难。 - Will
2
• 不要将main定义为返回void的函数。它必须始终返回int。 • 检查调用gets是否成功。 • 永远不要使用gets(str),而应该使用fgets(str, sizeof str, stdin),否则当用户输入过长的字符串时会导致未定义行为。 • 不要在main函数中进行计算,而是编写自己的函数int is_palindrome(const char *str)并将计算放入该函数中。 - Roland Illig
10个回答

10

你的中心比较存在缺陷:

if (str[i] != str[i+halflen]) 

这并不是在比较你认为的那两个字符。

尝试将"HelloHello"输入到你的程序中,它会显示它是一个回文字符串!

你需要比较这两个:

if (str[i] != str[len-i-1])

(并按照其他答案建议修复大括号)


4
应该这样写:if (str[i] != str[len-1-i]),如果不加上 -1,它会将第一个字符与结尾的 \0 进行比较,并且除了空字符串外都会失败。 - David Rodríguez - dribeas
等一下!strlen 函数也会计算 \0 吗?:S - user379888
@fahadпјҢдёҚжҳҜзҡ„гҖӮstrlenеҮҪж•°иҝ”еӣһ\0д№ӢеүҚзҡ„еӯ—з¬Ұж•°гҖӮ - Matthew Flaschen
1
@fahad,问题在于"Hello"['H','e','l','l','o',0],长度为5,正如预期的那样。如果您开始将元素0与元素len-0进行比较,则会将'H'与第6个元素(位于位置5)即'\0'进行比较。 - David Rodríguez - dribeas
是的,大家好,抱歉,应该是str[len-i-1]。 - Ned Batchelder

6
为了给你一些提示,我已经对你的代码进行了一些整理缩进:
for(i=0;i<halflen;i++)
    {
        if(str[i]!=str[i+halflen])
            flag=0;
        break;
    }

5
这就是为什么老手们会在任何地方都使用大括号,即使有些人认为它们不需要。 - Will Dean
2
这是一个问题,但不是全部问题。 - Ned Batchelder

4
您也可以使用STL检查给定字符串是否是回文,使用函数equal。假设您有一个名为xstd::string,那么以下函数调用确定x是否是回文。
equal(x.begin(), x.begin() + x.size() / 2, x.rbegin());

3

这里您需要类似于以下内容...

    if(str[i]!=str[strlen (str) - i - 1])
    {
        flag = 0;
        break;
    }
break需要放在if块中,否则它将始终被执行。在某个时刻初始化flag也是一个好主意。如果我可以发表一下自己的观点,即使只有一个语句,也要始终用花括号包含if块和else块;这样可以避免您在这里遇到的几个问题。
稍后 - 根据Rodriguez先生以下评论进行编辑。

2
再次遇到了“偏移一”的问题。你必须将右侧的术语减去1才能使其正常工作。 - David Rodríguez - dribeas
你是对的。正确地关闭括号也是很好的。 - Brian Hooper

1

来自我自己的2005版本

bool isAlphaNumeric(char c)
{
    return (iswalpha(c) || iswdigit(c));
}

bool isPalindrome(char *str)
{
    /* A man, a plan, Anal Panama!!! */
    if(*str == '\0')
    {
        return false;
    }

    int len = strlen(str);
    if(len <= 1) return true;

    char *start = str;
    char *end = start + len - 1;

    while(start < end)
    {
        if(!isAlphaNumeric(*start))
        {
            *start++;
            continue;
        }
        if(!isAlphaNumeric(*end))
        {
            *end--;
            continue;
        }
        if(towlower(*start) != towlower(*end))
        {
            return false;
        }
        *start++;
        *end--;
    }
    return true;
}

1
解决方案中有一些杂乱的 *,使其不如应该的易读... *start++*end-- 应该改为 ++start--end(编译器可以轻松省略额外的解引用,因为它知道它没有被使用,但对于我们人类来说,它只会增加混淆 - 这是我的看法。)- 我已经更正了 " => '\0',因为那肯定是一个复制错误。 - David Rodríguez - dribeas
不要使用像iswalphatowlower这样的字符测试函数,并将其用作参数的普通char。这会导致未定义行为。最好使用isalnum((unsigned char)c)。而且你为什么要使用iswalpha呢?那个函数是用于宽字符的,而你只是传递了一个简单的字符。 - Roland Illig
感谢您的建议。这是5年前的事情,距离我上次经常使用C/C++已经过去4年了。也感谢您修复了错误。我将它从我的博客中复制出来,但Wordpress的自动格式化弄乱了很多代码,把“--”变成了长破折号,并删除了其他一些字符。我以为我已经全部发现了。 - Chris Doggett

1
bool isPalindrome(char* str) {
    char* s = str;
    char* e = str;
    while(*e) e++;
    --e;
    while(s < e) {
        if(*s != *e) return false;
        ++s; --e;
    }
    return true;
}

0
一种C语言风格的解决方案 :)
bool is_palindrome(const char* s) {
    const char* p = s;
    while (*p != '\0') ++p;
    while (s < p) if (*s++ != *--p) return false;
    return true;
}

0
这是一个更短的解决方案(C ++; C 的行数相同):
bool is_p(char const * const str, ptrdiff_t n)
{
  if (n < 1) return false;

  auto p = str, q = str + n - 1;
  while (*(p++) == *(q--))
    if (p >= q)
      return true;
  return false;
}

-1
#include <stdio.h>
#include <string.h>
int main()
{
    char a[100], b[100];
    printf("Enter a string to check if it is a palindrome\n");
    gets(a);
    strcpy(b, a); 
    strrev(b); 
    if (strcmp(a, b) == 0) 
        printf("The string is a palindrome.\n");
    else
        printf("The string isn't a palindrome.\n");
    return 0;
}

-3
这里有一个更好的方法。
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
int main() {
    string input;
    cout << "Enter your text: ";
    cin >> input;
    transform(input.begin(), input.end(), input.begin(), ::tolower);
    if (input[0] == input[input.length()-1])
        cout << "Palindrome";
    else
        cout << "not palinrome";
    cin.ignore();
    cin.get();
}

2
这是一个关于C语言的问题,不是C++。 - dbush

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接