此代码如何在字符串中找到重复的字符?

时间:2019-09-01 23:48:41

标签: c duplicates

示例:给定一个字符串(在本示例中为char *word),您想查找重复的字符(字节)。

我想知道是否有人可以向我解释以下工作原理:

    int table[256] = {0};
    for (int i = 0; i < len; i++)  table[word[i]]++;

之后,您可以检查另一个循环是否重复:

    for (int i = 0; i < len; i++) if (table[word[i]] > 1) { … }

这是如何工作的?我不明白为什么表中重复的字符> 1?

2 个答案:

答案 0 :(得分:2)

将我的评论转换为半连贯答案。

第一个循环计算每个字节值在0..255范围内的出现次数(对于找到的每个字节值,它在字节计数中增加一个);重新扫描会在字符串中找到一个以上出现的字节值-重复项的定义。

循环都假定字符串是用单字节代码集而不是像UTF-8这样的多字节代码集编码的。他们还假定纯char是无符号类型(不常见;大多数x86平台具有带符号纯char类型),或者字符串中没有任何值,其中word[i]为负(无重音字符)。

因此,出于安全考虑,代码应为:

for (int i = 0; i < len; i++)
    table[(unsigned char)word[i]]++;

for (int i = 0; i < len; i++)
{
    if (table[(unsigned char)word[i]] > 1)
    {
        …
    }
}

您可以使用word[i] & 0xFF代替演员表;它甚至具有更少的字符,但我认为演员表更清晰(字符数是红色鲱鱼,请不要追逐它)。请注意,无论普通char是带符号类型还是无符号类型,这两种变体(广播和掩码)都可以正常工作(尽管代码确实做出了CHAR_BIT为8而不是较大的数字-不能较小。)

  

但是为什么将它添加到找到的每个char值中,而不仅仅是添加到表中当前位置的那个char值中?当我打印出内存位置时,我从示例字符串"abcda"中看到,两个a在内存中是相同的。我认为在表数组中它们必须位于不同(但连续)的位置;为什么一样?

当您在字符串中找到'a'时,会有一个与该字符关联的字节值,通常为97。因此,当计数代码读取word[i]word[i]的内容为'a'时,就好像数组中有97个(实际上,数组中有97个),因此第一个循环递增table[97] -在读取a中的第一个abcda时将其从0更改为1,而在读取第二个a时将其从1更改为2。 >

在说完所有内容后,字符只是数字(但是在说完所有内容之前,可能有很多话要说;很多情况下,您不必经历所有这些事情)时间)。

答案 1 :(得分:0)

function removeDuplicates(str) {
    let result = "";
    let freq = {};
    for (let i = 0; i < str.length; i++) {
        let char = str[i];
        let smallChar = char.toLowerCase();
        let bigChar = char.toUpperCase();
        if (freq[smallChar]) {
            freq[char]++;
        } else if (freq[bigChar]) {
            freq[char]++;
        } else {
            freq[char] = 1;
            result = result + char;
        }
    }
    console.log(result);
}

removeDuplicates("ItWorks with any word");