C ++: Как создать многотипный и многомерный формат массива? - PullRequest
1 голос
/ 07 февраля 2011

Я пытаюсь прочитать формат массива, который использует PHP:

"data" => array(
    "keyname1" => "string", 
    "somearraykeyname" => array(
        "keyname1" => "more strings", 
        "keyname2" => "bla bla", 
        "moar" => array(
            "first" => 1, 
            "second" => 2, 
            "third" => "3",
        ),
        "keyname3" => 25,
    ), 
    "keyname2" => 13.37, 
    "keyname3" => 1337, 
    "array without keynames" => array(
        "keke", 
        "lala", 
        "lolo",
    ),
);

Но я наткнулся на проблему множественных возможных типов. Как это можно сделать в C ++ лучшим способом?

Я думал создать структуру со всеми возможными типами для каждого элемента:

struct GeneralType {
    char WhichType; // which type we are using for this value
    int IntVal;
    float FloatVal;
    string StringVal;
};

И когда я читаю элемент, я решу по значению, какой тип он получит, а затем преобразует значение в правильный тип и устанавливает его в правильную переменную (IntVal, FloatVal или StringVal). Также я буду следить за тем, какой тип значения используется в настоящее время с переменной WhichType, поэтому я могу легко выбрать правильную переменную, когда использую значение.

Это хороший подход?

Кроме того, есть еще одна проблема; Как я могу определить std :: vector, не зная глубину массива заранее? я мог бы напечатать vector<vector<GeneralType> >, если бы каждый элемент всегда был сам массив. Но не все элементы являются массивами. Итак, я не знаю, как решить эту проблему с помощью std :: vector. Это вообще возможно?

Первая идея, которая у меня возникла, состояла в том, чтобы просто превратить последовательность клавиш в строку, которая хранится в ключе std :: map, где значение std :: map будет GeneralType типа, и таким образом я буду возможность легко определить любое измерение, а также быстро получить желаемое значение, что-то вроде этого:

Mymap["data/somearraykeyname/moar"] = GeneralTypeValue; // this value not used, it will be a marker only, so i can get the first item position in the std::map easily.
Mymap["data/somearraykeyname/moar/first"] = GeneralTypeValue; // array "moar" key "first" value.

Но этот метод не позволяет мне быстро перебрать все элементы из определенного массива. Хотя ключи отсортированы, поэтому я всегда должен иметь правильный порядок; но это потребовало бы, чтобы я анализировал ключ каждый раз и проверял, изменился ли массив в следующем элементе. Это может сработать, но не очень эффективно.

Какие еще идеи могут быть для этого?

Редактировать: Я также хочу иметь возможность вызывать массив N-измерения, например: array["data"]["somearraykeyname"]["moar"]["first"] И затем, если тип значения - массив, я мог бы иметь возможность зацикливать массив, как если бы он был вектор GeneralType

Ответы [ 4 ]

4 голосов
/ 07 февраля 2011

Используйте повышение :: вариант. Он будет помнить тип внутри себя и довольно прост в использовании.

2 голосов
/ 07 февраля 2011

Вы должны рассмотреть возможность использования boost::any, который может содержать любой тип данных.

Если вы хотите, чтобы ваши элементы содержали сами массивы, вы можете заключить std::vector вboost::any и проверьте при доступе к элементам вашего массива, являются ли они сами по себе массивами.

0 голосов
/ 07 февраля 2011
struct GeneralType { };

struct IntType : public GeneralType { int IntVal; };
struct FloatType : public GeneralType { float FloatVal; };
struct StringType : public GeneralType { string StringVal; };

vector<GeneralType*> vec;
vec.push_back(new IntType);
vec.push_back(new FloatType);
vec.push_back(new StringType);

for (int i=0; i<3; ++i)
{
 IntType* type = dynamic_cast<IntType>(vec[i]);
 if (type != 0)
 {
 // using type->IntVal
 }
 else
 {
  FloatType* type = dynamic_cast<FloatType>(vec[i]);
  if (type != 0)
  {
   // using type->FloatVal
  }
  else
  {
   StringType* type = dynamic_cast<StringType>(vec[i]);
   if (type != 0)
   {
   // using type->StringVal
   }
  }
 }
}
0 голосов
/ 07 февраля 2011

используйте union, а не struct, для этого и предназначены.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...