문제

나는 문자열과 qsort/bsearch 대신 숯 배열을 사용해야하는 숙제 할당을 연구하고 있습니다. 아래에서 bsearch에 대한 나의 부름에서, i 알다 입력의 잘못된 크기를 전달하지만 실제 크기를 얻는 방법을 잘 모르겠습니다. 따라서 ComparentRies 기능은 올바른 개체를 찾지 못합니다.

누구든지 내가 놓친 것을 이해하도록 도와 줄 수 있습니까?

#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;
}
도움이 되었습니까?

해결책

왜 그렇지 않습니다 sizeof(Entry) 일하다?

다시 변경 - 크기가 포인터의 크기라고 생각합니다 ....

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

EntryPtr result = (EntryPtr) bsearch(tmp, m_entries, 
        m_numEntries, sizeof(EntryPtr), Dictionary::compareEntries);

다른 팁

문제는 비교 기능이 사용된다는 것입니다 bsearch 기대합니다 word 유형이 될 수 있습니다 Entry* (또는 m_entries 유형이 될 수 있습니다 char**).

당신은 그것을 알고 있습니다 bsearch 정렬 된 입력이 필요합니까?

sizeof(m_entries[0]) 나에게 완벽하게 좋아 보인다.

편집 : 이제 문제가 있습니다. 사전 클래스에는 다양한 포인터가 포함되어 있습니다. 문제는 Compareentries 기능에있어서 전달 된 포인터를 EntryPtr; 당신은 그들을 던져야합니다 EntryPtr * 대신에.

편집 2 : 지적한대로 Amit Kumar, 너 또한 BSEARCH에 보내는 주요 매개 변수를 변경해야합니다. 그렇지 않으면 ComparentErries에서받는 포인터가 동일한 유형을 가리키지 않으며 두 개의 다른 타입 캐스트가 필요하다는 것을 알아야합니다.

크기 (Entry)의 크기가 작동합니다. 인스턴스 대신 유형에서 대부분 Sizeof를 사용해야합니다.

Sizeof (Entry)

바람직합니다

입력 E;
크기 (e);

또는

진입* e;
크기 (*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;
}

읽기 수동 주의하여.

다른 사람이 만든 요점에 대한 요약과 몇 가지 더 많은 문제가 있습니다.

  • 귀하의 사용법 크기 맞다.

  • 찾아보고 싶은 키가 포함 된 항목에 대한 포인터를 전달해야합니다. 실제로 열쇠는 무엇이든 될 수 있으며, 첫 번째 인수로서 비교 함수로 전달되며, 두 인수를 올바른 유형에 시전하면됩니다. (비교 함수는 여전히 항목이 정렬 한 순서에 해당해야합니다.)

  • 비교 함수의 캐스트는 올바르지 않습니다. 비교 함수는 요소에 대한 포인터를 수신합니다 (귀하의 경우 입력에 대한 포인터이므로 비교 함수는 입력 포인터에 포인터를받습니다).

  • 결과를 잘못된 유형으로 시전합니다. 다시 함수는 배열의 요소에 대한 포인터를 반환합니다 (입력 포인터에 대한 포인터).

  • 키가 없으면 결과가 null인지 확인하지 않습니다.

  • 당신은 아마도 한 수준의 간접 수준을 포기할 수 있습니다 (실제로 항목 배열 대신 많은 포인터가 필요합니까?)

  • 당신은 사람들이 유형 안전의 미덕에 대해 이야기 할 때 의미하는 바에 대한 좋은 예로 받아야합니다. 코드에서 거의 모든 유형이 혼합되고 잘못된 유형으로 잘못된 일을하고 있지만 단일 불만은 아닙니다. 컴파일러. 그게 당신이 엉망이면 당신이 얻는 것입니다 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를 구현하는 데 시간이 덜 걸립니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top