给定的字符串是回文,您需要声明它是偶数回文(长度为偶数的回文)或奇数回文(长度为奇数的回文),否则返回No。
我编写此代码,但未获得真实输出
#include<string.h>
#include <stdio.h>
int main(){
int n ;
char s[100000],b[100000];
int count=0,d,h,i,t,j;
if(count<1)
{
scanf("%d", &n);
if(n<=50)
{
for(t=1;t<=n;t++)
{
i=0,j=0,h=0;
scanf("%s", s);
h=strlen(s)-1;
if(h>=1&&h<=100000)
{
for(i=0,j=h;i<=h&&j>=0; j--,i++)
{
b[i]=s[j];
}
if(strcmp(s,b)==0)
{
if(h%2==0)
{
printf("YES EVEN");
printf("\n");
}
else
{
printf("YES ODD");
printf("\n");
}
}
else{
printf("NO");
printf("\n");
}
}
}
}
count++;
}
return 0;
}
#include<string.h>
#include <stdio.h>
int main(){
int n ;
char s[100000],b[100000];
int count=0,d,h,i,t,j;
if(count<1)
{
scanf("%d", &n);
if(n<=50)
{
for(t=1;t<=n;t++)
{
i=0,j=0,h=0;
scanf("%s", s);
h=strlen(s)-1;
if(h>=1&&h<=100000)
{
for(i=0,j=h;i<=h&&j>=0; j--,i++)
{
b[i]=s[j];
}
if(strcmp(s,b)==0)
{
if(h%2==0)
{
printf("YES EVEN");
printf("\n");
}
else
{
printf("YES ODD");
printf("\n");
}
}
else{
printf("NO");
printf("\n");
}
}
}
}
count++;
}
return 0;
}
忘记语法错误,只会发现逻辑错误。
我希望输出是
输入
3
abc
abba
aba
您代码的输出
NO
YESODD
NO
预期正确输出
NO
YESEVEN
YESODD
当我提供不超过一个的字符串时,我得到真实的结果 但是哪里出错了?
答案 0 :(得分:0)
b
时,您忘记添加终止字符\0
h%2
。但是h
是strlen(s)-1
。因此,如果h%2 == 0
相关更改如下所示
for(i=0,j=h;i<=h&&j>=0; j--,i++)
{
b[i]=s[j];
}
b[h+1] = '\0';
if(strcmp(s,b)==0)
{
if(h%2!=0)
{
printf("YES EVEN");
printf("\n");
}
else
{
printf("YES ODD");
printf("\n");
}
}
忘记语法错误,只会发现逻辑错误。
我发现这种说法非常错误。除非您修复语法,否则您将无法从逻辑上对其进行查看。另外,适当的缩进确实有助于调试代码并自行查找错误。
答案 1 :(得分:0)
您有很多问题,但是主要问题在于您的冲销。您尝试通过以下方式进行逆转:
h=strlen(s)-1;
if(h>=1&&h<=100000){
for(i=0,j=h;i<=h&&j>=0; j--,i++) {
b[i]=s[j];
}
这将strlen(s) == 1
失败,不能确保终止,并且因为您使用h=strlen(s)-1;
,所以h
中的if (h % 2 == 0)
会导致相反{> EVEN
和ODD
的确定。相反,您需要:
#define MAXC 100000 /* if you need a constant, #define one (or more) */
...
h = strlen (s); /* h must be strlen(s) - not - 1 */
if (h >= 1 && h < MAXC) { /* now loop j=h-1; j < h times */
for (i = 0, j = h-1; i < h && j >= 0; j--,i++)
b[i] = s[j];
b[i] = 0; /* and ensure b is nul-terminated */
(注意:适当间隔的代码更易于阅读和调试)
接下来,您将无法验证每次对scanf
的调用的返回,而是盲目地使用变量而没有任何指示输入是否成功的提示-未定义行为的秘诀。您必须验证每个用户输入,例如
if (scanf ("%d", &n) != 1 || n > 50) {
fputs ("error: invalid integer or out-of-range.\n", stderr);
return 1;
}
while (n-- && scanf ("%s", s) == 1) {
只需选择代码的逻辑因式,就完全不需要变量t
和d
。请注意,您在n
上的条件是(1)有效,并且(2)不超过50
。这些可以合并为一张支票。将单词读入n
时,s
循环执行同样的操作。
进行这些更改后,您的代码可简化为:
#include <stdio.h>
#define MAXC 100000 /* if you need a constant, #define one (or more) */
int main (void)
{
char s[MAXC];
int n;
if (scanf ("%d", &n) != 1 || n > 50) {
fputs ("error: invalid integer or out-of-range.\n", stderr);
return 1;
}
while (n-- && scanf ("%s", s) == 1) {
char b[MAXC]; /* b is only needed within loop */
int h = strlen (s), i = 0, j; /* as are h, i, j, no - 1 for h */
if (h >= 1 && h < MAXC) { /* now loop j=h-1; j < h times */
for (i = 0, j = h-1; i < h && j >= 0; j--,i++)
b[i] = s[j];
b[i] = 0; /* and ensure b is nul-terminated */
if (strcmp (s, b) == 0) {
if (h % 2 == 0)
printf ("YES EVEN\n");
else
printf ("YES ODD\n");
}
else
printf ("NO\n");
}
}
return 0;
}
现在可以提供您所需要的回文检查和ODD
或EVEN
长度的输出,例如
使用/输出示例
$ echo "5 abcba abccba abcdba a aa" | ./bin/pdromerefmt
YES ODD
YES EVEN
NO
YES ODD
YES EVEN
您应该通过为s
转换添加 field-width 修饰符来进一步保护"%s"
的数组范围,例如"%99999s"
消除了检查h <= 100000
的需要(如果输入的字符为100000
或更大,则已经检查了 Undefined Behavior )。无需检查h >= 1
,因为循环限制对h = 0
不起任何作用,但可以确保为空字符串。
通过进一步的调整和数组边界保护,您的循环简化为:
while (n-- && scanf ("%99999s", s) == 1) {
char b[MAXC]; /* b is only needed within loop */
int h = strlen(s), i = 0, j = h;/* as are h, i, j, no -1 for h */
while (j--) /* must loop j times, regardless */
b[i++] = s[j]; /* reversing characters in s in b */
b[i] = 0; /* and ensure b is nul-terminated */
if (strcmp (s, b) == 0) {
if (h % 2 == 0)
printf ("YES EVEN\n");
else
printf ("YES ODD\n");
}
else
printf ("NO\n");
}
答案 2 :(得分:0)
忘记语法错误,只会发现逻辑错误。
这就是铅笔和纸(或者也许是橡皮鸭)的用途,目的是找出一种算法并从逻辑上遵循其步骤。但是,您有一个完整的程序,并有大量测试可以尝试。现在是时候消除您可以找到的每个错误,从语法错误开始,这些错误在编译时可以“轻松”检测到。
已经有足够的答案来解决发布的代码中的缺陷,但是至少还没有涉及到一件事,但这实际上不是错误或逻辑错误。
对于每个测试用例,发布的算法都将执行以下操作:
读一个单词(用scanf
)。
查找尺寸(使用strlen
)。
创建一个反向副本(使用for
循环)。
将副本与原始副本进行比较以检查回文率(使用strcmp
)。
为什么所有这些副本和数组遍历?一旦知道了单词的长度,就可以将字符串的左侧与右侧进行比较。
#include <stdio.h>
#include <stdbool.h>
#include <assert.h>
#define MAX_CHARS_IN_STR 100000
#define MAX_N_TESTS 50
// Performs the check without copying the the string
// length: size of the word
bool is_palindrome(size_t length, const char *str);
#define STRINGIFY_IMPL(x) #x
#define STRINGIFY(x) STRINGIFY_IMPL(x)
#define STR_WIDTH_FMT(x) "%" STRINGIFY(x) "s"
int main(void)
{
int n_words;
if ( scanf("%d", &n_words) != 1 || n_words < 1 || n_words > MAX_N_TESTS)
{
fprintf(stderr, "Error: the input is not a valid integer between 1 and %d.",
MAX_N_TESTS);
return 1;
}
int n_chars;
// Allocates an array big enough (including the null-terminator)
char word[MAX_CHARS_IN_STR + 1];
// It will use an array of two pointers instead of another if-else
const char *even_or_odd_str[] = { "IS EVEN", "IS ODD" };
while ( n_words-- )
{
// consume whitespace characters left in the input
scanf(" ");
// reads the string up to its maximum width or until the first whitespace.
// The macro expands to "%100000s" and that literal will be concatenated to "%n",
// which returns the number of characters read.
if ( scanf(STR_WIDTH_FMT(MAX_CHARS_IN_STR) "%n", word, &n_chars) != 1 )
{
fputs("Error: unable to read word.", stderr);
break;
}
if ( is_palindrome(n_chars, word) )
puts(even_or_odd_str[n_chars % 2]);
else
puts("NO");
}
}
bool is_palindrome(size_t n, const char *str)
{
assert(n && str);
size_t i = 0, j = n - 1;
while ( i < j && str[i] == str[j] )
{
++i;
--j;
}
// It's a palindrome only if the two indices met halfway
return i >= j;
}