【问题标题】:strcmp returning only 0 (palindrom algo bug)strcmp 仅返回 0(回文算法错误)
【发布时间】:2017-01-14 09:15:05
【问题描述】:

您好,我在课堂上了解了 string.h 库,特别是用于比较字符串的 strcmp 函数。 如果第一个字符串首先出现在字典中,它将返回一个大于 0 的数字,如果第二个字符串大于第一个字符串,它将返回一个小于 0 的数字,如果它们相等,则它应该返回一个 0。 我是这样使用它的:

strcmp(strArr , strrev(strArr));

请随时教育我。

代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_LENGTH 100
#define PALINDROM_TRUE 0//because in strcmp if both strings compared are equile the strcmp will return 0.
int main(void)
{
    char strArr[MAX_LENGTH];
    printf("Enter string (max length 100 chars): ");
    fgets(strArr , MAX_LENGTH , stdin);
    int pali = strcmp(strArr , strrev(strArr));
    if(pali == PALINDROM_TRUE)
    {
        printf("Palindrom\n");
    }
    else
    {
        printf("Not Palindrom\n");
    }
    system("PAUSE");
    return 0;
}

我的问题是,当我输入下面的代码时,即“abc”它会打印到屏幕 Palindrom 它应该打印 Not Palindrom ,它从不打印 不是回文

【问题讨论】:

  • 您是否尝试打印出strArr 和strrev(strArr) 的值以确保它们具有您期望的值?
  • 该死的,我设法使 pali 成为 'int' ,对此感到抱歉。
  • 您对strcmp() 工作方式的“修复”是一个潜在的混淆源。相反,尝试类似#define strequal(x, y) (strcmp((x), (y)) == 0) 然后if (strequal(x, y) == true) ...
  • 这一行:#define PALINDROM_TRUE 0//because in strcmp if both strings compared are equile the strcmp will return 0. 将包含使用宏的注释:PALINDROM_TRUE。这意味着使用该宏的行的其余部分都将被视为注释。强烈建议将评论放在单独的一行
  • 在调用 fgets() 以从字符串中删除任何(可能的)换行符序列后,发布的代码缺少几行。

标签: c strcmp string.h


【解决方案1】:

原因是你调用了 strrev()。 strrev() 函数就地工作。换句话说,strrev 在与原始数组相同的缓冲区(即 strArr 数组)上工作,并且不会为反转的字符串分配新空间。结果,一旦你用 strArr 调用 strrev(),strArr 中的字符串就会反转,你所做的只是比较两个相同的字符串:strArr 中的一个,strArr 中的一个,现在两者都是逆转。 (请注意,“both”一词可能具有误导性。实际上,只有一个缓冲区,并且 strcmp 的两个参数都指向该缓冲区。)

纠正此问题的一种方法是分配第二个数组 strArr2 并将字符串复制到其中。然后,反转strArr2中的字符串,用strArr和strArr2调用strcmp。下面是这个解决方案在代码中的样子。

    ...
    char strArr2[MAX_LENGTH];
    ...
    strcpy(strArr2, strArr);
    strrev(strArr2);
    int pali = strcmp(strArr , strArr2);
    if(pali == PALINDROM_TRUE)
    {
        printf("Palindrom\n");
    }
    else
    {
        printf("Not Palindrom\n");
    }
    ...

请注意,由于您采用特定的输入方法,您可能还必须检查 strArr 的结尾是否有任何尾随空白字符。任何此类尾随空格字符都可能通过影响比较结果而使您的反转和比较策略变得无用。

如果您没有那么多空间,或者如果 MAX_SPACE 值太大,另一种方法是使用自定义比较函数来检查字符串是否为回文,而不必使用 strcmp 或 strrev。

【讨论】:

  • @ilim 仍然不工作,现在它只打印 Not Palindrom。我尝试打印这两个字符串,并且在它们之间以 3 行间距打印它,即使我根本没有使用 \n。
  • @ilim 无论如何都要在用户输入空格时使此代码工作??
  • @spyc 为了处理带有空格字符的输入,根据您的输入规范,您应该查看 scanf 格式字符串的详细信息,或者尝试使用 getchar。话虽这么说,您最初的问题是关于 strcmp 的工作原理,我应该查看之前关于 SO 在接受输入时处理空间的问题。
【解决方案2】:
int pali = strcmp(strArr , strrev(strArr));

这条线显然是问题所在。

对strrev(strArr) 的调用与strArr 相反,所以在调用strcmp 之后,您是否期望strArr 会有所不同?但它是同一个变量...

您必须创建另一个char 数组来存储反转的字符串。

编辑:

#include <stdio.h>
#include <string.h>

#define MAX_LENGTH 100

int main(void)
{
    char str[MAX_LENGTH];
    char rev[MAX_LENGTH];

    puts("Enter string (max length 100 chars): ");
    scanf("%s", str); 

    strcpy(rev, str);
    strrev(rev);

    if(strcmp(str, rev) == 0) {
        puts("Palindrom"); 
    } else {
        puts("Not Palindrom");
    }
}

【讨论】:

  • 喜欢吗? 'strcpy(strArrRev, strArr);strrev(strArrRev);int pali = strcmp(strArr, strArrRev);'
  • @spyc 乍一看还不错,是的。
  • 使用 change 编译时,它永远不会显示为回文,当我打印这两个时,它们会在和之间显示三行空格,即 abc cba。但是当我执行 aabbaa 时,它会显示 aabbaa 并且它仍然写道它不是 pali。
  • 请不要说我故意避免 scanf ,因为最近发现它会引入安全问题(让你重写内存,超出分配给你的内存)。
  • 考虑写scanf("%99s", str);以避免潜在的缓冲区溢出,并检查scanf()的返回值以避免未定义的行为。
【解决方案3】:

我已经添加了

strArr[strcspn(strArr, "\n")] = 0;

之后

fgets(strArr , MAX_LENGTH , stdin);

它起作用了,它基本上重写了最后的 (null)。这搞乱了相反的情况,在字符串的开头包含 null (0)。 谢谢大家。

完成代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_LENGTH 100
#define PALINDROM_TRUE 0//because in strcmp if both strings compared are equile the strcmp will return 0.
int main(void)
{
    char strArr[MAX_LENGTH], strArrRev[MAX_LENGTH];
    printf("Enter string (max length 100 chars): ");
    fgets(strArr , MAX_LENGTH , stdin);
    strArr[strcspn(strArr, "\n")] = 0;
    strcpy(strArrRev, strArr);
    int pali = strcmp(strArr , strrev(strArrRev));
    if(pali == PALINDROM_TRUE)
    {
        printf("Palindrom\n");
    }
    else
    {
        printf("Not Palindrom\n");
    }
    system("PAUSE");
    return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多