![](/img/trans.png)
[英]How to omit the dots, commas and white spaces for a string (needed for checking a palindrome)
[英]How to remove spaces and check if a string is a palindrome?
我试图弄清楚如何删除空格,然后检查带有删除空格的字符串是否是回文。
我已经分别尝试了这两种方法,但是我无法让它们一起工作。
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”的预期输出是“爸爸是回文集”,但返回“爸爸不是回文集”。
如果不需要修改后的字符串,则可以节省大量工作,而在比较中忽略空白和大小写,例如:
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
将为假。 空字符串是否是回文是定义的问题。
我将从格式化字符串开始,以便通过删除所有特殊/空格字符,然后将所有字母都转换为大写或小写,使其更易于分析。
我喜欢您的简洁风格。 因此答案必须合适。
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++;
}
这符合您的风格吗?
如何删除空格并检查字符串是否是回文?
您的问题分为两部分: (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 */
}
转到问题的第二部分,如果您在使用起始和结束指针从字符串的末端到中间进行迭代来检查字符串是否是回文式时遇到麻烦,可以执行相同的操作与字符串索引。 此外,每当您需要检查某些内容是否为空格或在字符大小写之间转换时,请使用ctype.h
提供的isspace()
或tolower() / toupper()
宏。 (否则,您将负责所需的所有条件检查)
使用字符串索引的简单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中的标准库中删除。 请参阅为什么gets()如此危险,永远不应该使用它! 。 只需使用fgets()
代替,并通过使用nul终止字符覆盖行尾来修剪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.
仔细检查一下,如果您有任何问题,请告诉我。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.