我有以下功能,我想测试两个字符串是否是字谜。我想做的一种方法是将字符串中每个字符的值相加,然后比较它们的值。
但是,当我尝试运行程序时,我在两个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;
}
答案 0 :(得分:3)
在for
循环中,您必须检查
*p != '\0'
*q != '\0'
这是seg-fault的原因。
此外,即使修复了,该代码也会给你误报:
“bc”字谜“广告”
我建议你采用不同的方法:
制作两个int
大小为256的数组,初始化为零。
让每个数组的每个项目保持每个字符串的每个字母(字符)的计数。
最后比较两个数组是否相同。
我将代码写入你的任务。
答案 1 :(得分:1)
" p!= 0"应该是" * p!= 0",因为现在你正在等待指针变为空。
答案 2 :(得分:1)
以下是您问题的完整解决方案:
#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;
}
答案 3 :(得分:1)
由于我们已经就更好的方法给出答案,所以这是我的:
获取(最好是小的)素数列表。对于输入字符串的每个可能字符都需要一个,因此当您想要检查仅包含数字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)
时间和恒定的空间复杂度。