Wie kann ich die reale Größe meiner C ++ Klasse finden?
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;
}
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. NachschlagenEigentlich 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.