Как я могу найти реальный размер моего класса C ++? - PullRequest
1 голос
/ 10 марта 2010

Я работаю над домашним заданием, в котором мне нужно использовать массивы символов вместо строк и qsort / bsearch. В моем вызове bsearch ниже я знаю Я передаю неверный размер Entry, но я не уверен, как получить реальный размер, и поэтому моя функция compareEntries не находит нужные объекты.

Может кто-нибудь помочь мне понять, чего мне не хватает?

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

Ответы [ 5 ]

2 голосов
/ 10 марта 2010

Почему sizeof(Entry) не работает?

Изменилось еще раз - я думаю, что размер должен быть размер указателя ....

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

EntryPtr result = (EntryPtr) bsearch(tmp, m_entries, 
        m_numEntries, sizeof(EntryPtr), Dictionary::compareEntries);
1 голос
/ 10 марта 2010

Проблема в том, что функция сравнения, используемая в bsearch, ожидает, что word будет иметь тип Entry* (или m_entries будет иметь тип char**).

1 голос
/ 10 марта 2010

Вы знаете, что bsearch требует отсортированного ввода, верно?

sizeof(m_entries[0]) выглядит прекрасно для меня.

Редактировать: теперь я вижу проблему. Ваш класс Dictionary содержит массив указателей. Проблема в функции CompareEntries, где вы передаете переданные указатели на EntryPtr; вместо этого вам нужно привести их к EntryPtr *.

Редактировать 2: Как указывает Амит Кумар , вам также необходимо изменить параметр ключа, который вы отправляете в bsearch, или вы должны понимать, что указатели, которые вы получаете в CompareEntries не указывают на одни и те же типы и требуют двух разных типов типов.

0 голосов
/ 10 марта 2010

sizeof (Entry) будет работать. Преимущественно sizeof следует использовать для типа вместо экземпляра.

SizeOf (запись)

предпочтительнее

Вступление e;
SizeOf (е);

или

Вступление * e;
SizeOf (* е);

все дают одинаковый результат.

#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;
}
0 голосов
/ 10 марта 2010

Внимательно прочитайте руководство .

Сводка замечаний, высказанных другими, а также еще пара вопросов:

  • Ваше использование sizeof правильно.

  • Вы должны передать указатель на Entry, содержащую ключ, который вы хотите найти. На самом деле ключ может быть любым, и он будет передан функции сравнения в качестве первого аргумента, и вам просто нужно привести оба аргумента к нужным типам. (Функция сравнения должна соответствовать порядку сортировки элементов.)

  • Неверные значения в функции сравнения. Функция сравнения получает указатель на элемент (который в вашем случае является указателем на Entry, следовательно, функция сравнения получает указатели на указатели на Entry).

  • Вы приводите результат к неверному типу. Опять же, функция возвращает указатель на элемент массива (указатель на указатель на Entry).

  • Вы не проверяете, равен ли NULL результат, если ключа там нет.

  • Возможно, вы могли бы отказаться от одного уровня косвенности (вам действительно нужен массив указателей вместо массива Entries?)

  • Вы должны взять это за хороший пример того, что люди имеют в виду, когда говорят о достоинствах безопасности типов: в вашем коде практически все типы смешаны, и вы делаете неправильные вещи с неправильными типами, но ни единой жалобы от компилятора. Это то, что вы получаете, если связываетесь с 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, для реализации вашего собственного безопасного поиска типа потребуется меньше времени, чем для выяснения всего этого, проверки и отладки.

...