1

文字列と qsort/bsearch の代わりに char 配列を使用する必要がある宿題に取り組んでいます。以下の bsearch への呼び出しでは、間違ったサイズの Entry を渡していることはわかっていますが、実際のサイズを取得する方法がわからないため、compareEntries 関数が正しいオブジェクトを見つけられません。

私が欠けているものを理解するのを手伝ってくれる人はいますか?

#include  <iostream>

using  namespace  std;


typedef Entry*  EntryPtr;
class  Dictionary
{
    public  :
        Dictionary( const char  *filename );
        ~Dictionary();
        const char  *lookupDefinition( const char  *word );

    private  :
        int m_numEntries;
        EntryPtr *m_entries;
        static int compareEntries(const void *leftSide, const void *rightSide);
};

int Dictionary::compareEntries(const void *leftSide, const void *rightSide)
{
    EntryPtr lside = (EntryPtr) leftSide;
    EntryPtr rside = (EntryPtr) rightSide;

    return strcmp(lside->Word, rside->Word);
}

const char *Dictionary::lookupDefinition(const char *word)
{
    if (m_numEntries == 0)
        return 0;

    EntryPtr result = (EntryPtr) bsearch(word, m_entries, 
        m_numEntries, sizeof(m_entries[0]), Dictionary::compareEntries);

    return result->Definition;
}

class Entry
{
        public:
                Entry(const char *line);
                char *Word;
                char *Definition;
};

int  main()
{
    Dictionary  dict( "C:\\path\\file.txt" );
    dict.lookupDefinition("chair");
    return  0;
}
4

5 に答える 5

2

なぜ機能しないsizeof(Entry)のですか?

再び変更 - サイズはポインターのサイズにする必要があると思います....

EntryPtr tmp = new Entry("");
tmp->Word = word;

EntryPtr result = (EntryPtr) bsearch(tmp, m_entries, 
        m_numEntries, sizeof(EntryPtr), Dictionary::compareEntries);
于 2010-03-09T22:14:21.003 に答える
0

sizeof(Entry)は機能します。ほとんどの場合、sizeofは、インスタンスではなく型で使用する必要があります。

sizeof(エントリ)

に好ましい

エントリe;
sizeof(e);

また

エントリー*e;
sizeof(* e);

すべて同じ結果になります。

#include "stdio.h"
class Entry {
  double e;
  int i;
};
int main() {
  Entry e;
  printf("%d\n", sizeof(e));
  printf("%d\n", sizeof(Entry));
  printf("%d\n", sizeof(*(&e)));
  return 0;
}
于 2010-03-09T23:11:59.533 に答える
0

マニュアルをよく読んでください。

他の人が指摘したポイントの要約と、さらにいくつかの問題:

  • sizeofの使用法は正しいです。

  • 検索するキーを含む Entry へのポインターを渡す必要があります。実際には、キーは何でもかまいません。それは最初の引数として比較関数に渡され、両方の引数を正しい型にキャストするだけで済みます。(比較関数は、アイテムがソートされた順序に対応している必要があります。)

  • 比較関数のキャストが正しくありません。比較関数は、要素へのポインターを受け取ります (この場合、これは Entry へのポインターであるため、比較関数は Entry へのポインターへのポインターを受け取ります)。

  • 結果を間違った型にキャストします。ここでも、関数は配列内の要素へのポインターを返します (エントリーへのポインターへのポインター)。

  • キーが存在しない場合、結果が NULL かどうかはチェックしません。

  • おそらく、1 レベルの間接化をあきらめることができます (エントリの配列ではなく、ポインタの配列が本当に必要ですか?)

  • 型安全性の利点について人々が話すとき、人々が何を意味するかの良い例として、これを取り上げるべきです: あなたのコードでは事実上すべての型が混同されており、間違った型で間違ったことをしているにもかかわらず、コンパイラ。void*自分が何をしているのか正確にわかっていない限り、をいじると、それが得られます。

楽しいことに、ポインターの配列を持っていると、結果を得るために途方もない量の間接化が必要になります。

#include <cstdlib>
#include <string>
#include <iostream>

int compare_string(const void* a, const void* b)
{
    return ((const std::string*)a)->compare(**(const std::string**)b);
}

int main()
{
    std::string a("a"), b("b"), c("c");
    std::string* array[3] = { &a, &b, &c };
    std::string key = "b";
    std::string** result = (std::string**)bsearch(&key, array, 3, sizeof(std::string*), compare_string);
    if (result) std::cout << **result << '\n';
}

IMO、独自のタイプ セーフな bsearch を実装するのにかかる時間は、これをすべて把握してテストおよびデバッグするのにかかる時間よりも短くなります。

于 2010-03-09T22:47:54.943 に答える