【问题标题】:How to fix these error in this code palindrome problem to tell whether it is odd or even如何修复此代码回文问题中的这些错误以判断它是奇数还是偶数
【发布时间】:2019-07-06 06:12:25
【问题描述】:

给定的字符串是回文,需要说明它是偶回文(偶数长度的回文)还是奇回文(奇数长度的回文),否则返回否。

我写的这段代码没有得到真正的输出

#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

当我提供一个不超过那个的字符串时,我得到了真实的结果 但是哪里出错了。

【问题讨论】:

  • 修复代码格式 /.缩进。
  • 单字母变量名.....跳到下一个问题:(

标签: c


【解决方案1】:
  1. 创建字符串b 时忘记添加终止字符\0
  2. 在检查时是否使用h%2。但是hstrlen(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");
    }
}

忘记语法错误,只找到逻辑错误。

我觉得这种说法非常错误。除非您修复语法,否则您无法从逻辑上查看它。此外,适当的缩进确实有助于您自己调试代码和查找错误。

【讨论】:

    【解决方案2】:

    你有很多问题,但你的主要问题在于你的逆转。您尝试通过以下方式反转:

        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 将失败,不能确保 nul 终止,并且因为您使用 h=strlen(s)-1;,所以您在 if (h % 2 == 0) 中的 h 会导致 相反 确定 EVENODD。相反,您需要:

    #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) {
    

    只需选择代码的逻辑因子即可完全消除变量 td 的需要。请注意,您对n 的条件是(1)它是有效的,并且(2)它是50 或更少。这些可以组合成一张支票。在将单词读入 s 时循环 n 次也是如此。

    进行这些更改后,您的代码将简化为:

    #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;
    }
    

    现在提供您正在寻找的回文检查和ODDEVEN 长度输出,例如

    使用/输出示例

    $ echo "5 abcba abccba abcdba a aa" | ./bin/pdromerefmt
    YES ODD
    YES EVEN
    NO
    YES ODD
    YES EVEN
    

    您应该通过在"%s" 转换中包含field-width 修饰符来进一步保护s 的数组边界,例如"%99999s" 消除了检查 h &lt;= 100000 的需要(如果输入是 100000 字符或更大字符,则它已经调用了 Undefined Behavior)。无需检查 h &gt;= 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");
        }
    

    【讨论】:

      【解决方案3】:

      忘记语法错误,只找到逻辑错误。

      这就是铅笔和纸(或者你的橡皮鸭,也许)的用途,用于找出算法并在逻辑上遵循其步骤。不过,你有一个完整的程序,并且有大量的测试来尝试它。现在是时候从语法错误中根除所有可以找到的错误了, 这些错误在编译时“很容易”检测到。

      关于已发布代码中的缺陷已经有足够多的答案,但至少还有一件事尚未涵盖,但这并不是真正的错误或逻辑错误。

      发布的算法,对于每个测试用例,执行以下操作:

      • 读一个单词(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;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-02-09
        • 2014-02-12
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多