Pergunta

Eu estou trabalhando em uma tarefa de casa em que eu sou obrigado a matrizes uso de char em vez de cordas e qsort / bsearch. Na minha chamada para bsearch abaixo, eu sei eu estou passando o tamanho errado de entrada, mas não tenho certeza de como obter o tamanho real, e minha função compareEntries não é, portanto, encontrar os objetos certos .

Alguém pode me ajudar a entender o que eu estou perdendo?

#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;
}
Foi útil?

Solução

Por que não funciona sizeof(Entry)?

mudou de novo - Eu acho que o tamanho deve ser o tamanho do ponteiro ....

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

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

Outras dicas

O problema é que a função do comparador utilizado em espera bsearch word para ser do tipo Entry* (ou m_entries para ser do tipo char**).

Você sabe que bsearch requer entrada classificada, certo?

aparência sizeof(m_entries[0]) perfeitamente bem para mim.

Edit: Agora eu vejo o problema. Sua classe dicionário contém uma matriz de ponteiros. O problema está na função compareEntries, onde você elenco passou ponteiros para EntryPtr; você precisa lançá-los para EntryPtr * vez.

Edit 2: Como apontado por Amit Kumar , você também necessidade de alterar a chave de parâmetros que você enviar para bsearch, ou você precisa perceber que os ponteiros que você recebe em compareEntries não estão apontando para os mesmos tipos e vai precisar de dois typecasts diferentes.

sizeof (Entry) iria funcionar. Principalmente sizeof deve ser usado com o tipo, em vez de uma instância.

sizeof (Entry)

É preferível

Entrada e;
sizeof (e);

ou

Entrada * e;
sizeof (* e);

todos dão o mesmo resultado.

#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;
}

Leia a manual do cuidado.

Um resumo dos pontos feitos por outras pessoas, bem como mais algumas questões:

  • O uso de sizeof está correto.

  • Você deve passar um ponteiro para a entrada que contém a chave que você deseja procurar. Na verdade, a chave pode ser qualquer coisa, e ele vai ser passado para a função de comparação como o primeiro argumento , e você só precisa lançar ambos os argumentos de direito tipos. (A função de comparação ainda deve corresponder à ordem os itens foram classificadas segundo.)

  • Os moldes da função de comparação não estão corretas. A função de comparação recebe um ponteiro para o elemento (que no seu caso é um ponteiro para entrada, portanto, a função de comparação recebe ponteiros para ponteiros para Entry).

  • Você converter o resultado para o tipo errado. Mais uma vez a função retorna um ponteiro para um elemento na matriz (ponteiro para a entrada de ponteiro).

  • Você não verificar se o resultado é NULL, se a chave não estar lá.

  • Você provavelmente poderia desistir de um nível de engano (você realmente precisa de uma matriz de ponteiros em vez de um conjunto de entradas?)

  • Você deve tomá-lo como um bom exemplo do que as pessoas querem dizer quando falam sobre as virtudes do tipo de segurança: em seu código praticamente todos os tipos se misturam e você está fazendo coisas erradas com tipos errados, contudo não uma única queixa do compilador. Isso é o que você ganha se você mexer com void*, se você não sabe exatamente o que você está fazendo.

Para se divertir, ter uma matriz de ponteiros é preciso uma quantidade ridícula de engano para obter um resultado:

#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, que levaria menos tempo para implementar seu próprio bsearch tipo seguro, do que leva a descobrir tudo isso e tê-lo testado e depurado.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top