Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как лучше хранить дерево. 
:(
    Опции темы
a1ien
Дата 1.4.2011, 14:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 23
Регистрация: 2.6.2008

Репутация: нет
Всего: нет



Есть данные которые представляют из себя что-то типа дерева.
Вобще это что-то типа
QMap<Qstring,QMap<Qstring,....>>> и вот глубена неизвестна как такое хранилище реализовать, при этом конечный тип это скорее всего QVariant
хочу как в интерпретируемых языках иметь доступ таким образом
Код
data["user"]["settings"]["mail"]["inbox"]=some valuse
data["user"]["name"]=some valuse

PM MAIL   Вверх
borisbn
Дата 1.4.2011, 15:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 48
Всего: 135



используя в качестве значения map'а "себя" всё более или менее получается:

Код

class Settings
{
public:
    Settings & operator[]( const QString & idx ) {
        return m_map[ idx ];
    }
    Settings & operator=( QVariant v ) {
        val = v;
        return *this;
    }
    QVariant val() {
        return m_value;
    }
private:
    typedef QMap< QString, Settings > map_t;
    map_t m_map;
    QVariant m_value;
};

Settings data;
data["user"]["settings"]["mail"]["inbox"] = 42;
int x = data["user"]["settings"]["mail"]["inbox"].val().toInt();




--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
a1ien
Дата 1.4.2011, 15:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 23
Регистрация: 2.6.2008

Репутация: нет
Всего: нет



хммм. да должно работать спасибо большое.
PM MAIL   Вверх
a1ien
Дата 3.4.2011, 00:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 23
Регистрация: 2.6.2008

Репутация: нет
Всего: нет



Да вобщем то-что нужно. Но может можно как-то избавится от 
Код

    Settings & operator=( QVariant v ) {
        val = v;
        return *this;
    }
    QVariant val() {
        return m_value;
    }
 и QVariant m_value;

Пробовал просто отнаследоватся от QVariant но что-то не так выходит(
PM MAIL   Вверх
borisbn
Дата 3.4.2011, 11:04 (ссылка) |  (голосов:3) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 48
Всего: 135



Цитата(a1ien @  3.4.2011,  00:21 Найти цитируемый пост)
Но может можно как-то избавится от 

зачем  smile не вижу смысла

от оператора присвоения можно избавится, добавив ф-цию присвоения
Код

void set( const QVariant & v ) {
    m_value = v;
}

но тогда вызов будет выглядеть не так элегантно
Код

data["user"]["settings"]["mail"]["inbox"].set( 42 );


от QVariant val() можно избавиться, добавив
Код

operator QVariant () const {
    return m_value;
}

но не советую, т.к. операторы приведения - зло

от QVariant m_value вообще не избавишься, т.к. хранить данные где-то надо...


и ещё, я пропустил... в операторе присвоения Settings & operator= лучше использовать константную ссылку на QVariant, а не передачу по значению
Код

Settings & operator=( const QVariant & v ) {
        val = v;
        return *this;
    }


 smile 
P.S. Название у темы прикольное. Так и хочется ответить: "замотай корни в мокрую тряпку и храни при температуре 0...7 град" smile smile smile

Это сообщение отредактировал(а) borisbn - 3.4.2011, 11:13


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
a1ien
Дата 3.4.2011, 11:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 23
Регистрация: 2.6.2008

Репутация: нет
Всего: нет



Цитата

QVariant m_value вообще не избавишься, т.к. хранить данные где-то надо...

А почему нельзя отнаследовать от QVariant ?

Это сообщение отредактировал(а) a1ien - 3.4.2011, 11:33
PM MAIL   Вверх
borisbn
Дата 3.4.2011, 11:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 48
Всего: 135



Цитата(a1ien @  3.4.2011,  11:21 Найти цитируемый пост)
А почему нельзя отнаследовать от QVariant ?

технически можно, но не советую, потому, что


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
a1ien
Дата 3.4.2011, 11:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 23
Регистрация: 2.6.2008

Репутация: нет
Всего: нет



еще за одно. )
приходится вот таким извратом заниматся
Код

 QString key = readString();

    while(key!="") {
        QVariant r=readData();
        switch(r.type()){
        case QVariant::String   : { (*data)[key] =r.toString(); break;}
        case QVariant::Int   : { (*data)[key] =r.toInt(); break;}
        case QVariant::LongLong   : { (*data)[key] =r.toLongLong(); break;}
        case QVariant::Double   : { (*data)[key] =r.toLongLong(); break;}
        default                 : (*data)[key] = r.value<Data>();
    }

        //(*data)[key] = readData();
        key = readString();
    }

иначе когда пишешь data["currentUser"]["currentstatus"].val().toString() возврящает пустую строку. Ну и с другими типами анологично
PM MAIL   Вверх
borisbn
Дата 3.4.2011, 11:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 48
Всего: 135



a1ien, не понял, откуда этот изврат код ? в какой ф-ции приходится так писать ? 
почему, в каких случаях
Цитата(a1ien @  3.4.2011,  11:33 Найти цитируемый пост)
data["currentUser"]["currentstatus"].val().toString() возврящает пустую строку




--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
a1ien
Дата 3.4.2011, 12:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 23
Регистрация: 2.6.2008

Репутация: нет
Всего: нет



Приведу чутка больше кода. Может бысть скажете еще где я неправ )) Это код моего AMF парсера.
Код

QVariant AMFDeserializer::readData(AMFType typeMarker)
{

    if (typeMarker==DT_UNDEFINED) {
        data->readRawData((char *)&typeMarker,1);
    }

    switch (typeMarker) {

    case DT_UNDEFINED  : return NULL;
    case DT_NULL       : return NULL;
    case DT_BOOL_FALSE : return false;
    case DT_BOOL_TRUE  : return true;
    case DT_INTEGER    : return readInteger();
    case DT_NUMBER     : { double i; *data>>i; return i;}
    case DT_STRING     : return readString();
    case DT_XML        : return readString();
    case DT_ARRAY      : return readArray();
    case DT_OBJECT     : return readObject();
    case DT_XMLSTRING  : 
    case DT_BYTEARRAY  : return readString();
    default            : return false;


}

грубо говоря readObject() это основная функция. Самым первым типом почти всегда идет DT_OBJECT.
Вот части readObject().
Код

QVariant AMFDeserializer::readObject()
{
    qint32 objInfo = readInteger();
    bool storedObject = (objInfo & 0x01)==0;
    objInfo = objInfo >> 1;
....
if (storedObject) {
        qint32 objectReference = objInfo;
        if (storedObjects.count()<objectReference) { // storedObjects -  QList<AMFData*> - AMFData - Это и есть предмет обсждения
            //TODO ERROR
        } else {
            rObject = storedObjects[objectReference];
        }
    } else {
        bool storedClass = (objInfo & 0x01)==0;
        objInfo= objInfo >> 1;
     if (storedClass) {

            qint32 classReference = objInfo;
            if (storedClasses.count()<classReference) { // storedClasses -  QList< QMap<QString,QVariant>* >
                //TODO ERROR
            } else {
                encodingType = (*storedClasses[classReference])["encodingType"].toInt();
                propertyNames = (*storedClasses[classReference])["propertyNames"].toStringList();
                className = (*storedClasses[classReference])["className"].toString();

            }

        } else {

            className = readString();
            encodingType = objInfo & 0x03;
            objInfo = objInfo >> 2;

        }
        rObject=new AMFData();
        storedObjects.append(rObject); 
.....
if (!storedClass) {
                    qint32 propertyCount = objInfo;
                    for(int i=0;i<propertyCount;i++) {

                        propertyNames.append(readString());


                    }
                    map=new QMap<QString,QVariant>();
                    (*map)["className"]=className;
                    (*map)["encodingType"]=encodingType;
                    (*map)["propertyNames"]=propertyNames;
                    storedClasses.append(map);

                }

                foreach(QString propertyName,propertyNames) {

                    properties[propertyName] = readData(); 
   // Опять вызываем и получаем рекурсия(объекты могут содержать объекты)

                }

 foreach(QString k,properties.keys())
            {
                QVariant data=properties.value(k);
                switch(data.type()){
                case QVariant::String   : { (*rObject)[k] =data.toString(); break;}
                case QVariant::Int   : { (*rObject)[k] =data.toInt(); break;}
                case QVariant::LongLong   : { (*rObject)[k] =data.toLongLong(); break;}
                case QVariant::Double   : { (*rObject)[k] =data.toLongLong(); break;}
                default                 : (*rObject)[k] = data.value<AMFData>();
            }
                //(*rObject)[className][k] = properties.value(k);
            }  //вот тут и этот код.
........
return QVariant(AMFData::Type(),rObject); // AMFData::Type() -     static int Type()
 //   {
 //      return qRegisterMetaType<AMFData>("AMFData");
//    }
// также  Q_DECLARE_METATYPE(AMFData) после описания класса.
}

и использование 
Код

 QDataStream *dat=new QDataStream(file.readAll());
    AMFDeserializer *ds=new AMFDeserializer(dat);
    AMFData data=ds->readAMFData().value<AMFData>();

..
ui->AMFd->appendPlainText(
            tr("res=%3").
            .arg(data["responseTick"].val().toLongLong())); 
// Вот тут если в readObject не делать определения то возвращает либо 0 если числовое значение, либо пустую строку



Это сообщение отредактировал(а) a1ien - 3.4.2011, 12:09
PM MAIL   Вверх
borisbn
Дата 3.4.2011, 12:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 48
Всего: 135



Цитата(a1ien @  3.4.2011,  12:07 Найти цитируемый пост)
 //(*rObject)[className][k] = properties.value(k);

если так и было, то и при вызове нужно
Цитата

ui->AMFd->appendPlainText(
            tr("res=%3").
            .arg(data[className]["responseTick"].val().toLongLong()));

и почему %3, а не %1 ?

В общем, сделай простенький тест, и если не будет работать - тогда будем разбираться, а если у тебя в большой и сложной программе где-то что-то не отрабатывает, а в простом примере работает, то тут уж ... да поможет тебе отладчик smile


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
a1ien
Дата 3.4.2011, 12:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 23
Регистрация: 2.6.2008

Репутация: нет
Всего: нет



 %3 - просто это я когда тут постил удалил первые 2 длинны параметра. )
(*rObject)[className][k]
нет там className уже ненужен 

UPD:
код теперь такой 
Код

            foreach(QString k,properties.keys())
            {
                (*rObject)[k] = properties.value(k);
            }

Есть строка
Код

ui->AMFd->appendPlainText(
            tr("Mission %1/%2| res=%3").
            arg(data["currentUser"]["currentMissionsCount"].val().typeName() )
.arg(data["currentUser"]["missionsLimit"].val().typeName())
.arg(data["responseTick"].val().typeName() ));

Mission /| res=double - это вывод

Это сообщение отредактировал(а) a1ien - 3.4.2011, 13:05
PM MAIL   Вверх
mes
Дата 3.4.2011, 12:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 7
Всего: 250



Цитата(borisbn @  1.4.2011,  14:10 Найти цитируемый пост)

   map_t m_map;
   QVariant m_value;

Цитата(a1ien @  3.4.2011,  10:21 Найти цитируемый пост)
А почему нельзя отнаследовать от QVariant ?


 smile, зачем все это ? ,когда есть:

Цитата

QMap<QString, QVariant>    toMap () const
QMap<QString, QVariant> QVariant::toMap () const




--------------------
PM MAIL WWW   Вверх
borisbn
Дата 3.4.2011, 13:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 48
Всего: 135



a1ien
Цитата(a1ien @  3.4.2011,  12:51 Найти цитируемый пост)
(*rObject)[k] = properties.value(k);

здесь у тебя получается не дерево, а просто ствол одноуровневый map. Почему ["currentUser"]["currentMissionsCount"] должен что-то возвращать ?
Вот если бы ты записал в (*rObject) сначала ["currentUser"], а затем в этот полученый класс в ["currentMissionsCount"] записал что-то, то смог бы и вытащить. А у тебя получилось, что ты записал что-то сначала в (*rObject)["currentUser"], а затем в (*rObject)["currentMissionsCount"]. Будь добр так и вытаскивай: 

Код

ui->AMFd->appendPlainText(
            tr("%1 %2").
            arg( data["currentUser"].val().typeName() )
           .arg( data["currentMissionsCount"].val().typeName() )
);


Цитата(mes @  3.4.2011,  12:57 Найти цитируемый пост)
, зачем все это ? ,когда есть:

этот вариант видел, но так меньше завязка на КуТю. Заменив QMap на std::map, QString на std::string и QVariant на TVariant, можно в (прости меня Господи) Билдере использовать




--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
a1ien
Дата 3.4.2011, 13:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 23
Регистрация: 2.6.2008

Репутация: нет
Всего: нет



Цитата

десь у тебя получается не дерево, а просто ствол одноуровневый map. Почему ["currentUser"]["currentMissionsCount"] должен что-то возвращать ?

Потому-что выше  properties[propertyName] = readData(); у нас в рекурсии все это идет тоесть readData() возвращает мапу.
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С/С++: Кроссплатформенное программирование, QT/Gtk+/wxWidgets"
JackYF
Любитель
  • В заголовке темы в квадратных скобках обозначьте используемую вами библиотеку, например: [QT],[GTK],[wx].
  • Если вопрос актуален только для некоторой версии библиотеки, либо, если вы пользуетесь не самой последней версией, укажите это. Например: [QT4], [GTK2].
  • Все начинающие изучать Qt - не забудьте зайти сюда.
  • Проставьте несколько ключевых слов темы, чтобы её можно было легче найти.
  • В вопросе укажите полную версию версию библиотеки, а также все дополнительные используемые программные пакеты.
  • Не забывайте пользоваться кнопкой "Код".
  • Телепатов на форуме нет! Задавайте чёткий, конкретный и полный вопрос. Указывайте полностью ошибки компилятора и компоновщика.
  • Новое сообщение должно иметь прямое отношение к тематике этого раздела. Флуд, флейм, оффтопик запрещены.
  • Категорически запрещается обсуждение вареза, "кряков", взлома программ и т.д.

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, Любитель.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | С/С++: Кроссплатформенное программирование, Qt/Gtk+/wxWidgets | Следующая тема »


 




[ Время генерации скрипта: 0.0958 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.