1

そのため、部分的に埋められた配列で重複する文字を削除しようとしています。アレイは、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 で、私のテストでは、これらの 10 個のうち 6 個を文字 {'g', 'g', 'n', 'o', 'r', 'e'} で使用しています。私は何を間違っていますか?

注: "cout << "Positions used: " << *numberUsed << endl" は、メソッドが正しく削除されているかどうかを確認するために使用されています。インデックスが z である最も内側のループでは、メソッドが狂気になり始めます。

どんな助けでも大歓迎です。

4

2 に答える 2

1

(STLが許可されていないというあなたのコメントを読む前に、この回答の最初の部分を書きましたが、かなりきちんとしたコードだと思うので、とにかく残します。)

C++ 標準ライブラリが提供する機能を使用できます。char 配列の代わりに使用std::stringすると (ほとんどの場合、これは良い考えです)、次のことができます (注意: C++11 はunordered_setandのためのみですstd::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は、プログラムの何が問題なのかを診断する良いスタートを切っていますが、より効率的な解決策があります。たとえば、すでに見た文字の記録を保持するなどです。sを使用しているのでchar、マーカーを保持できるビット フィールド (256/8 = 32 バイトの余分なオーバーヘッド) を検討するか、それが多すぎない場合は単なるブール配列 (余分なオーバーヘッド 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++;
      }
    }
}

これにはループが 1 つしかないため、配列を 1 回通過するだけで済みます。つまり、その時間計算量は入力配列の長さに比例します。

于 2013-02-04T01:39:27.813 に答える
1

重複を見つけるたびに、使用する文字数を減らします

*numberUsed--;

ただし、最初のループ インデックスを制御することを覚えておいてください

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

だからこれを試してください

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

このようにして、配列内のすべての元の文字にアクセスします。

于 2013-02-04T01:16:30.450 に答える