如何删除空格并检查字符串是否是回文?

时间:2019-03-29 07:45:22

标签: c

我试图弄清楚如何删除空格,然后检查带有删除空格的字符串是否是回文。

我已经分别尝试了这两种方法,但是我无法让它们一起工作。

int check_palindrome(char *);

int main()
{
    char s1[20];
    printf("Enter the string...\n");
    gets(s1);

    int x;
    x=check_palindrome(s1);
    x?printf("%s = is a Palindrome\n", s1):printf("%s = is Not a Palindrome\n", s1);
}

int check_palindrome(char *s)
{
    int i,j;
    for(i=0;s[i];i++);

    for(i=i-1,j=0;i>j;i--,j++)
    {
        if(s[i]!=s[j])
        {
            return 0;
        }
    }
    if(s[i]==s[j])
    {
        return 1;
    }
}

此代码可用于检查回文,但如果输入以大写字母开头或包含空格,则该代码将无效。例如,我期望“ nurses run是回文”的输出,但是实际输出是“ nurses run不是回文”,因为它们之间的空间很大,因此“ Dad”的预期输出是“爸爸是回文集”,但返回“爸爸不是回文集”。

4 个答案:

答案 0 :(得分:3)

如果您不需要修改后的字符串,则可以节省很多工作,而在比较中只需忽略空格和大小写,例如:

int ispalindrome = 1;
while (s < e && ispalindrome) {
        while (*s == ' ') s++;
        while (*e == ' ') e--;
        if (tolower(*s++) != tolower(*e--))
                ispalindrome = 0;
}

其中s指向字符串的开头,e指向字符串的结尾(最后一个字符)。

编辑:

我刚刚意识到,如果整个字符串仅由空格组成,那么有可能发生越界数组访问的情况。然后,第二个空间跳过循环将经过数组的“左”端。因此,将其更改为

        while (*e == ' ' && e > s) e--;

请注意,在这种情况下,ispalindrome将为假。是否定义 empty 字符串是否为回文是一个定义问题。

答案 1 :(得分:1)

我将首先格式化字符串,以使其更容易分析,方法是删除所有特殊/空格字符,然后将所有字母都转换为大写或小写。

答案 2 :(得分:0)

我喜欢您的简洁风格。因此答案必须合适。

1。)大写字母颠倒了逻辑:

if(s[i]==s[j]) 
continue;
if(s[i]==s[j]+DIFF_a_A) continue;
if(s[i]+DIFF_a_A==s[j]) continue;
return false;

#define DIFF_a_A ('A' - 'a')

2。)空白 将增量放入循环中:

for(i=i-1,j=0;i>j;){
    if(s[i] == ' ') i--, continue;
    if(s[j] == ' ') j++, continue;
        ...
    i--,j++;
}

这符合您的风格吗?

答案 3 :(得分:0)

  

如何删除空格并检查字符串是否是回文?

您的问题分为两部分:(1)如何删除空格”?和(2) [如何]“ 检查字符串是否是回文?”。您应该分两个步骤解决问题。

可以通过两种不同的方式之一来删除字符串中的空格,(1)可以删除原始字符串中的空格(假设原始字符串是可变字符串而不是 String Literal )或(2),同时在第二个字符串中使用第一个非空格字符填充第二个字符串,同时保留第一个字符串不变(不管原始字符串是否可变,都可以使用) )。您最安全的选择是后者。

一个简单的函数,它提供源缓冲区和目标缓冲区作为该函数的参数,以消除空白,就像这样:

void removespace (char *dest, const char *src)
{
    size_t n = 0;
    while (*src) {
        if (!isspace(*src))
            dest[n++] = *src;
        src++;
    }
    dest[n] = *src;     /* nul-terminate */
}

移动到问题的第二部分,如果您在使用 start end 指针将字符串的末尾迭代到在中间检查字符串是否是回文,您可以对字符串索引执行相同的操作。另外,每当您需要检查某些字符是否为空格或在字符大小写之间转换时,请使用isspace()中提供的宏tolower() / toupper()ctype.h。 (否则,您将负责所需的所有条件检查)

使用字符串索引的简单checkpalindrome()实现可以是:

int checkpalindrome (const char *s)
{
    size_t n = 0, len = strlen (s);

    while (len-- > n)   /* loop over each start/end lowercase char */
        if (tolower (s[n++]) != tolower (s[len]))
            return 0;

    return 1;
}

现在实现main()并从用户 永远不要使用gets() 中读取字符串。它是如此不安全并且容易被缓冲区溢出利用,因此已从C11中的标准库中删除。参见Why gets() is so dangerous it should never be used!。只需使用fgets()并通过用 nul-termination 字符覆盖行尾来修剪fgets填充的缓冲区中的行尾。 (为此strcspn()很方便。)

将其完全放入(并使用您的三元控制"is""is not"的输出),您可以这样做:

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

#define MAXC 1024   /* if you need a constant, define one (or more) */

void removespace (char *dest, const char *src)
{
    size_t n = 0;
    while (*src) {
        if (!isspace(*src))
            dest[n++] = *src;
        src++;
    }
    dest[n] = *src;     /* nul-terminate */
}

int checkpalindrome (const char *s)
{
    size_t n = 0, len = strlen (s);

    while (len-- > n)   /* loop over each start/end lowercase char */
        if (tolower (s[n++]) != tolower (s[len]))
            return 0;

    return 1;
}

int main (void) {

    char s[MAXC], nospace[MAXC];

    fputs ("enter a string: ", stdout);
    if (!fgets (s, MAXC, stdin)) {  /* Never, Ever use gets() */
        fputs ("(user canceled input)\n", stderr);
        return 1;
    }
    s[strcspn (s, "\r\n")] = 0; /* trim line-ending */
    removespace (nospace, s);   /* remove whitespace from s */

    printf ("'%s' => %s a palindrome.\n",
            s, checkpalindrome (nospace) ? "is" : "is not");

    return 0;
}

注意: 永远不要跳过缓冲区大小!

使用/输出示例

$ ./bin/checkpalindrome
enter a string: a
'a' => is a palindrome.

(您可以根据需要更改处理单个字符串的方式)

$ ./bin/checkpalindrome
enter a string: aa
'aa' => is a palindrome.

$ ./bin/checkpalindrome
enter a string: ab
'ab' => is not a palindrome.

$ ./bin/checkpalindrome
enter a string: aba
'aba' => is a palindrome.

$ ./bin/checkpalindrome
enter a string: abc
'abc' => is not a palindrome.

$ ./bin/checkpalindrome
enter a string: A man a plan a canal Panama
'A man a plan a canal Panama' => is a palindrome.

仔细研究一下,如果您有任何疑问,请告诉我。