Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/58.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 如何修复此代码回文问题中的这些错误,以判断它是奇数还是偶数_C - Fatal编程技术网

C 如何修复此代码回文问题中的这些错误,以判断它是奇数还是偶数

C 如何修复此代码回文问题中的这些错误,以判断它是奇数还是偶数,c,C,给定的字符串是回文,您需要声明它是偶数长度的偶数回文回文或奇数长度的奇数回文回文,否则返回否 这段代码是我写的,但没有得到真正的输出 #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", &

给定的字符串是回文,您需要声明它是偶数长度的偶数回文回文或奇数长度的奇数回文回文,否则返回否

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

#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;
}
代码的输出

NO
YESODD
NO
预期正确输出

NO
YESEVEN
YESODD
当我提供的字符串不超过这个值时,我得到了真正的结果 但错误在哪里呢

创建字符串b时,您忘记添加终止字符\0 在检查是否使用h%2时。但h是strlens-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");
    }
}
忘记语法错误,只查找逻辑错误


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

您有许多问题,但主要问题在于您的错误。您尝试使用以下方法进行反转:

    h=strlen(s)-1;
    if(h>=1&&h<=100000){
     for(i=0,j=h;i<=h&&j>=0; j--,i++) {
        b[i]=s[j];
    }
注意:足够间距的代码更易于阅读和调试

接下来,您无法验证对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或更少。这些可以合并成一张支票。将单词读入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;
}
    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");
    }
您应该通过为%s转换包括字段宽度修饰符来进一步保护s的数组边界,例如%9999s,这样就不需要检查h=1,因为循环限制对h=0没有任何作用,但要确保字符串为空

通过进一步调整和阵列边界保护,您的循环简化为:

#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;
}
    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");
    }
忘记语法错误,只查找逻辑错误

这就是铅笔和纸或者你的橡皮鸭,用来找出一个算法并逻辑地遵循它的步骤。不过,您有一个完整的程序和大量的测试来尝试它。现在是时候根除您能找到的每一个bug了,从语法错误开始,这些错误在编译时很容易被检测到

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

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

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

修复代码格式设置/。缩进。单字母变量名称…..跳到下一个问题:
#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;
}