方法问题:删除数组中的重复字符

时间:2013-02-04 00:38:44

标签: c++ arrays char duplicates

所以我试图在部分填充的数组中删除重复的字符。该阵列是从我PC上的文件填充的。我的数组填充方法工作正常;但是,我的重复删除方法不是。这是我的方法:

    void deleteRepeated(char array[], int* numberUsed)
{
    for (int x = 0; x < *numberUsed ; x++) 
    {
        cout << "Positions used: " << *numberUsed << endl;
        for (int y = x+1; y < *numberUsed; y++ )
        {
            cout << "Positions used: " << *numberUsed << endl;
            if (array[y] == array[x])
            {
                cout << "Positions used: " << *numberUsed << endl;
                for (int z = y; z < *numberUsed; z++)
                    array[z] = array[z+1];
                y--; 
                *numberUsed--;
                cout << "Positions used: " << *numberUsed << endl;
            }
        }
    }
}

我传递的是整个数组,以及该数组中使用的索引数。数组长度为10,而我的测试,我使用的是其中6个中的6个:{'g','g','n','o','r','e'}。我做错了什么?

注意:“cout&lt;&lt;”使用的位置:“&lt;&lt; * numberUsed&lt;&lt; endl”用于检查方法是否正确删除。在索引为z的最内层循环中,方法开始变得疯狂。

非常感谢任何帮助。

2 个答案:

答案 0 :(得分:1)

每次找到重复时,都会减少使用的字符数

*numberUsed--;

但请记住控制第一个循环索引

for (int x = 0; x < *numberUsed ; x++) 

所以试试这个

int count =*numberUsed;
for (int x = 0; x < count ; x++) 

这样你就可以访问数组中的所有原始字符。

答案 1 :(得分:1)

(在我读到你关于STL的评论不被允许之前,我写了这个答案的第一部分,但我会留下它,因为我认为这是相当简洁的代码。)

您可以使用C ++标准库提供的功能。使用std::string代替char数组(这几乎总是一个好主意),然后你可以执行以下操作(注意:C ++ 11只是因为unordered_setstd::begin):

#include <string>
#include <unordered_set>
#include <iostream>
#include <iterator>

std::string uniquechars(const std::string& s) {
    std::unordered_set<char> uniquechars(std::begin(s), std::end(s));
    std::string newstring(std::begin(uniquechars), std::end(uniquechars));
    return newstring;
}

int main() {
    std::string teststr("thisisanexamplesentence");
    std::cout << "The unique characters of " << teststr << " are " << uniquechars(teststr) << std::endl;
}

请注意,它不会保留字符的原始顺序,因此如果需要,则不起作用。


如果你必须在没有标准库的情况下工作,你必须深入挖掘一下。上面的@TimChild已经很好地开始诊断您的程序有什么问题,但是有更有效的解决方案,例如保留您已经看过哪些字符的记录。当您使用char时,我会考虑一个可以保存标记的位字段(256/8 = 32字节的额外开销)或者如果不是太多,只需要一个简单的bool数组(额外的开销256字节)。因为后者更容易实现,代码更清晰:

void deleteRepeated(char array[], int *numused) {
    bool seenthischar[256] = {false};
    char *readpointer = &array[0];
    char *writepointer = &array[0];
    int length = *numused;
    for ( ;readpointer <= &array[0] + length; readpointer++) {
      if (seenthischar[((unsigned char) *readpointer)]) {
        *numused--;
      } else {
        seenthischar[((unsigned char) *readpointer)] = true;
        *writepointer = *readpointer;
        writepointer++;
      }
    }
}

这只有一个循环,所以它只需要经过一次数组,即它的时间复杂度在输入数组的长度上是线性的。