我试图弄清楚如何删除空格,然后检查带有删除空格的字符串是否是回文。
我已经分别尝试了这两种方法,但是我无法让它们一起工作。
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”的预期输出是“爸爸是回文集”,但返回“爸爸不是回文集”。
答案 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.
仔细研究一下,如果您有任何疑问,请告诉我。