回文 - 仅限 C 语言



我想知道为什么结果不正确。 如果我输入字符串来测试字符串是否回文, 每当我尝试时,结果都是一样的。

例如,如果我输入"爸爸"进行测试,这表明它不是回文。 但是,如果我输入"上帝",它仍然告诉我这不是回文。

我不知道如何以正确的方式解决此问题... 请让我知道我该怎么做。

谢谢。

(以下代码)

#include <stdio.h>
#include <string.h>
void isPalindrome(char *str, int n);
int main() {
char str[100];
int n = strlen(str);
char choice;
printf("Will you run this program? : ");
scanf("%c", &choice);
getchar();
while (choice == 'Y' || choice == 'y') {
isPalindrome(str, n);
printf("Retry? : ");
scanf("%c", &choice);
getchar();
}
}
void isPalindrome(char *str, int n) {
int flag = 1;
printf("Type strings : ");
gets_s(str, 100);
for (int i = 0; i < n / 2; i++) { 
if ('A' <= str[i] && str[i] <= 'Z') {
str[i] = str[i] - 'A' + 'a';
}
if (strlen(str) / 2 == 0) {
if (str[i] != str[n - i - 1]) {
flag = 0;
break;
}
} else
if (strlen(str) / 2 != 0) {
if (str[i] != str[n - i]) {
flag = 0;
break;
}
}
}
if (flag == 1) {
printf("%s is a palindrome n", str);
} else {
printf("%s is not a palindrome n", str);
}
}

对于根据 C 标准的初学者,不带参数的函数 main 应声明为

int main( void )

函数isPalindrome应该只做一件事 - 检查提供的字符串是否是回文。所有输入都应在 main 中完成。

此外,由于函数不会更改字符串本身,因此应使用限定符const声明其相应的参数。

该函数的返回类型应为int_Bool

这第二条主

char str[100];
int n = strlen(str);

没有意义,因为数组str不包含任何字符串。此外,变量n的类型应该size_T,因为它是函数strlen的返回类型。

而不是这些操作

if ('A' <= str[i] && str[i] <= 'Z')
{
str[i] = str[i] - 'A' + 'a';
}

使用标准函数tolower要好得多,并且必须同时转换字符串的两个符号。

该程序可以如下所示。

#define __STDC_WANT_LIB_EXT1__  1
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define N 100
int isPalindrome(const char s[], size_t n)
{
size_t i = 0;
while (i < n / 2 &&
tolower((unsigned char)s[i]) == tolower((unsigned char)s[n - i - 1])) ++i;
return i == n / 2;
}
int main( void )
{
char choice;
printf( "Will you run this program? : " );
scanf( " %c", &choice );
getchar();
while ( choice == 'Y' || choice == 'y' )
{
char s[N];
printf( "Type a string : " );
gets_s( s, N );
if ( isPalindrome( s, strlen( s ) ) )
{
printf( ""%s" is a palindromen", s );
}
else
{
printf(""%s" is not a palindromen", s);
}
printf( "Retry? : " );
scanf( " %c", &choice );
getchar();
}
return 0;
}

程序输出可能如下所示

Will you run this program? : y
Type a string : dad
"dad" is a palindrome
Retry? : y
Type a string : god
"god" is not a palindrome
Retry? : n

下面是一个您可以使用的示例实现,其中包括 C 编程中的良好实践,并且使用内置函数tolower()也不区分大小写:

在线试用!

#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <ctype.h>
bool isPalindrome(char*, size_t);
void printIsPalindrome(char*);
int main() {
printIsPalindrome("abba");
printIsPalindrome("abbccbba");
printIsPalindrome("aBBcCbbA");
printIsPalindrome("geeks");
printIsPalindrome("");
return 0;
}
bool isPalindrome(char* buf, size_t len) {
size_t i = 0;
size_t j = len;
char a;
char b;
while (j > i) {
a = tolower(buf[i++]);
b = tolower(buf[--j]);
if (a != b) {
return false;
}
}
return true;
}
void printIsPalindrome(char* str) {
if (isPalindrome(str, strlen(str))) {
printf("%s is a palindromern", str);
} else {
printf("%s is not a palindromern", str);
}
}

本质上,您希望将驱动逻辑与检查字符串是否为回文的实现分开。这就是为什么该功能分为isPalindrome()printIsPalindrome().

检查条件是否为真的函数不应该有输出到控制台的副作用,这通常是一个很好的做法,而不仅仅是在 C 中。

预期被重用的泛型函数(即isPalindrome()) 也不应该假定传递的缓冲区(char* buf)是 C 字符串,因此检查strlen()应该只在驱动程序代码中完成,printIsPalindrome(),而不是可移植逻辑。这样做的原因是为了避免缓冲区溢出攻击的安全漏洞,如果其他人打算在他们的程序中使用您的isPalindrome()实现作为依赖项,假设。它允许他们指定显式传递的缓冲区的大小,因此由他们来验证缓冲区是否未超出分配的内存块进行访问。

最后,任何检查缓冲区索引(ij)的东西都应该size_t,以便成为可移植代码,因为size_t保证足够大以解决所有内存空间,而int则不保证。

最新更新