Domanda

Sto lavorando su un compito per casa in cui sto necessario per utilizzare array char invece di stringhe e qsort / bsearch. Nella mia chiamata a bsearch sotto, I so che sto passando la taglia sbagliata di ingresso, ma non sono sicuro di come ottenere il formato reale, e la mia funzione compareEntries non è quindi trovando gli oggetti giusti .

Qualcuno può aiutarmi a capire che cosa mi manca?

#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;
}
È stato utile?

Soluzione

Perché non sizeof(Entry) lavoro?

cambiato di nuovo - credo che la dimensione dovrebbe essere la dimensione del puntatore ....

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

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

Altri suggerimenti

Il problema è che la funzione confronto utilizzato in bsearch aspetta word sia di tipo Entry* (o m_entries essere di tipo char**).

Lo sai che bsearch richiede l'input ordinato, giusto?

sizeof(m_entries[0]) sembra perfettamente bene per me.

Edit: Ora vedo il problema. La classe dizionario contiene un array di puntatori. Il problema è nella funzione compareEntries, in cui si esegue il cast passato puntatori a EntryPtr; è necessario lanciare loro di EntryPtr * invece.

Modifica 2: Come sottolineato da Amit Kumar , anche bisogno di modificare il parametro chiave si invia a bsearch, o è necessario rendersi conto che i puntatori si ricevono in compareEntries non siano rivolte agli stessi tipi e avrà bisogno di due conversioni di tipo differenti.

sizeof (Entry) avrebbe funzionato. Per lo più sizeof dovrebbe essere usato dal tipo, invece di un'istanza.

sizeof (Entry)

è preferibile

Entrata e;
sizeof (e);

o

Entrata * e;
sizeof (* e);

tutti danno lo stesso risultato.

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

Leggi il manuale attenzione.

Un riassunto dei punti fatti da altri, così come un altro paio di problemi:

  • L'utilizzo di sizeof è corretto.

  • Si dovrebbe passare un puntatore alla voce contenente la chiave che si desidera cercare. In realtà la chiave può essere qualsiasi cosa, e sarà passato alla funzione di confronto come primo argomento , e non vi resta che lanciare entrambi gli argomenti per i tipi giusti. (La funzione di confronto deve comunque corrispondere alla fine gli elementi sono stati ordinati per.)

  • I calchi in funzione di confronto non sono corretti. La funzione di confronto riceve un puntatore all'elemento (che nel tuo caso è un puntatore a voce, da qui la funzione di confronto riceve puntatori a puntatori a Entry).

  • Si lanci il risultato per il tipo sbagliato. Nuovamente la funzione restituisce un puntatore a un elemento dell'array (puntatore a puntatore a Entry).

  • Non controllare se il risultato è NULL, se la chiave non esserci.

  • Si potrebbe probabilmente rinunciare a un livello di indirezione (non si ha realmente bisogno di un array di puntatori invece di una serie di voci?)

  • Si dovrebbe prendere come un buon esempio di ciò che la gente intende quando si parla di virtù del tipo di sicurezza: nel codice praticamente tutti i tipi si confondono e si sta facendo cose sbagliate con i tipi sbagliati, ma non una sola cosa negativa dal compilatore. Questo è quello che si ottiene se si fa confusione con void*, a meno che non si sa esattamente cosa si sta facendo.

Per il gusto di farlo, avendo un array di puntatori ci vuole una quantità ridicola di riferimento indiretto per ottenere un risultato:

#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, ci sarebbe voluto meno tempo per implementare il proprio type-safe bsearch, di quello necessario per capire tutto questo e lo hanno testato e il debug.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top