【问题标题】:C - Passing an int value from a char stringC - 从 char 字符串传递一个 int 值
【发布时间】:2016-06-17 10:55:00
【问题描述】:

我有以下函数,我想测试这两个字符串是否是字谜。我想到的一种方法是将字符串中每个字符的值相加,然后比较它们的值。

但是,当我尝试运行我的程序时,我在两个 for 循环中都遇到了分段错误。我没有正确理解这一点,我的代码中有什么不正确的地方吗?

int anagram(char *a, char *b)
{
    int sum1 = 0;
    int sum2 = 0;
    char *p, *q;

    for (p=a; p != '\0'; p++) {
        sum1 += *p - 'a';
    }

    for (q=b; q != '\0'; q++) {
        sum2 += *q - 'a';
    }

    if ( sum1 == sum2 )
        return 1;
    else 
        return 0;
}

【问题讨论】:

  • 应该是*p != '\0' 和*q != '\0'。由于 p 和 q 不是 NULL 指针,因此您的循环是无限循环。
  • @Barmar 我的意思是,如果我为字符串 a 输入 hello,为字符串 b 输入 loleh,我将返回 1
  • 复制字符串,对它们进行排序,然后查看它们是否相等。
  • 或使用counting sort。换句话说,创建每个单词中字母的直方图,然后验证直方图是否相同。
  • 不要求和,计数字符的出现并比较计数。另一种方法是将素数与每个字符相关联,然后将它们相乘。不过,为此,使用 C 内置数据类型肯定不够大。

标签: c string char segmentation-fault int


【解决方案1】:

在您的for 循环中,您必须检查

*p != '\0'

*q != '\0'

这是段错误的原因。


此外,即使是固定的,该代码也会给您带来误报:

“广告”的“bc”字谜

我建议您采用不同的方法:

制作两个大小为 256 的 ints 数组,初始化为零。

让每个数组的每一项都保持每个字符串的每个字母(char)的计数。

最后比较两个数组是否相同。

我把编写代码的任务留给你。

【讨论】:

  • @chqrlie 他使用总和来测试字谜的整个想法是错误的,但这不是问题所要问的。
  • 他的问题很令人困惑......但我更喜欢解决大多数问题(如果不是全部问题)的答案。
【解决方案2】:

“p !=0”应该是“*p != 0”,因为现在您正在等待指针变为空。

【讨论】:

    【解决方案3】:

    既然我们已经给出了关于更好方法的答案,这里是我的:

    获取(最好是小的)素数列表。对于输入字符串的每个可能字符,您都需要一个,因此,当您要检查仅包含数字 0 到 9 的字符串时,您需要 10 个素数。让我们拿这些:

    static unsigned const primes[10] = {
      2, 3, 5, 7, 11, 13, 17, 19, 23, 29};
    

    现在,由于每个数字都只有一个素数分解,并且由于乘法是可交换的,因此您可以为字符串的每个字符构建素数的乘积。如果它们相同,则对于每个字符来说,它在两个字符串中的次数相同。因此,两个字符串都是彼此的字谜。

    unsigned long prime_product(char const * str) {
      assert(str != NULL);
      unsigned long product = 1;
      for (; *str != '\0'; ++str) {
        assert(*str >= '0');
        assert(*str <= '9');
        product *= primes[*str - '0'];
      }
      return product;
    }
    
    char is_anagram(char const * one, char const * two) {
      return prime_product(one) == prime_product(two);
    }
    

    当产品溢出时,这甚至应该在某种程度上起作用,尽管这样可能会出现误报(尽管在比较两个字符串的长度时它们的可能性会大大降低)。

    可以看出,此版本具有O(n) 时间和恒定空间复杂度。

    【讨论】:

    • 不错,但需要uint128_t 来处理 26 个不同的符号。
    【解决方案4】:

    这里是您问题的完整解决方案:

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    int cmp(const void *str1, const void *str2) {
        return (*((char*)str1) - *((char*)str2));    
    }
    
    bool areAnagram(char *str1, char *str2) {
        int n1 = strlen(str1);
        int n2 = strlen(str2);
    
        if (n1 != n2)
          return false;
    
        qsort(str1, n1, 1, &cmp);
        qsort(str2, n2, 1, &cmp);
    
        for (int i = 0; i < n1;  i++)
           if (str1[i] != str2[i])
             return false;
    
        return true;
    }
    
    int main()
    {
        char str1[] = "test";
        char str2[] = "tset";
        if (areAnagram(str1, str2))
          printf("The two strings are anagram of each other");
        else
          printf("The two strings are not anagram of each other");
    
        return 0;
    }
    

    【讨论】:

    • @chux:谢谢,我没有运行它。只是凭记忆写的。用你的建议换行。
    猜你喜欢
    • 1970-01-01
    • 2011-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-10
    • 1970-01-01
    • 2019-09-28
    相关资源
    最近更新 更多