Frage

Ich arbeite gerade an einer Hausaufgabe, in dem ich erforderlich ist char-Arrays anstelle von Strings und qsort / bsearch zu verwenden. In meinem Ruf unten an bsearch, I weiß Ich bin die falsche Größe des Eintrags vorbei, aber ich bin nicht sicher, wie die reale Größe zu bekommen, und meine compareEntries Funktion findet daher nicht die richtigen Objekte .

Kann mir jemand helfen zu verstehen, was ich fehle?

#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;
}
War es hilfreich?

Lösung

Warum funktioniert nicht sizeof(Entry)?

wieder geändert - ich denke, die Größe sollte die Größe des Zeigers sein ....

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

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

Andere Tipps

Das Problem ist, dass die Komparator-Funktion in bsearch verwendet word vom Typ Entry* wird erwartet (oder m_entries vom Typ char** sein).

Du weißt, dass bsearch erfordert sortierten Eingang, nicht wahr?

sizeof(m_entries[0]) sieht für mich völlig in Ordnung.

Edit: Jetzt sehe ich das Problem. Ihre Klasse Dictionary enthält ein Array von Zeigern. Das Problem ist in der compareEntries Funktion, wo Sie Zeiger Stimmen gefasst EntryPtr; Sie müssen sie werfen, anstatt EntryPtr *.

Edit 2: Wie Amit Kumar Sie auch müssen Sie den Schlüssel Parameter, den Sie bsearch senden ändern, oder Sie müssen erkennen, dass die Zeiger Sie in compareEntries erhalten nicht die gleichen Typen weisen und müssen zwei verschiedene Typumwandlungen.

sizeof (Entry) funktionieren würde. Meist sollte sizeof vom Typ anstelle einer Instanz verwendet werden.

sizeof (Entry)

vorzuziehen

Eintrag e;
sizeof (e);

oder

Eintrag * e;
sizeof (* e);

alle das gleiche Ergebnis.

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

Lesen Sie die Handbuch sorgfältig.

Eine Zusammenfassung der von anderen gemacht Punkten, sowie ein paar mehr Probleme:

  • Ihre Nutzung von sizeof ist richtig.

  • Sie sollten einen Zeiger auf den Eintrag übergeben Sie die gewünschte Taste enthält. Nachschlagen Eigentlich kann der Schlüssel sein, etwas, und es wird auf die Vergleichsfunktion als erstes Argument übergeben werden und Sie müssen nur beide Argumente zu richtigen Arten werfen. (Die Vergleichsfunktion noch die Reihenfolge entsprechen sollte die Einträge nach sortiert wurden.)

  • Die Abgüsse in der Vergleichsfunktion nicht korrekt ist. Die Vergleichsfunktion empfängt einen Zeiger auf das Element (die in Ihrem Fall ein Zeiger auf Eintrag ist, daher die Vergleichsfunktion empfängt Zeiger auf Zeiger auf Eintrag).

  • Sie werfen das Ergebnis an den falschen Typ. Wiederum gibt die Funktion einen Zeiger auf ein Element in dem Array (Zeiger zu Eintrag Zeiger).

  • Sie können überprüfen, ob das Ergebnis NULL ist, sollte der Schlüssel nicht da sein.

  • Sie könnten wahrscheinlich ein Dereferenzierungsebene aufgeben (brauchen Sie wirklich ein Array von Zeigern anstelle eines Arrays von Einträgen?)

  • Sie sollten es als ein gutes Beispiel für das, was die Leute meinen, wenn sie über die Vorzüge von Typsicherheit sprechen: im Code praktisch alle Arten gemischt und Sie falsche Dinge mit falschen Arten tun, noch nicht eine einzige Beschwerde vom Compiler. Das ist, was Sie, wenn Sie mit void* bekommen, es sei denn, Sie wissen genau, was Sie tun.

Für den Spaß an der Sache, ein Array von Zeigern, die es dauert eine lächerliche Menge Indirektionsebene ein Ergebnis zu erhalten:

#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, würde es weniger Zeit in Anspruch nehmen Sie Ihre eigene typsichere bsearch zu implementieren, als es dies alles, um herauszufinden, dauert und hat es getestet und korrigiert.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top