Основная проблема, кажется, в том, что вы накапливаете много дезинформации. Я попытаюсь прояснить некоторые вещи:
- Использование последовательностей или нет не имеет абсолютно никакого отношения к возможности изменять существующие значения или добавлять новые значения в файл. Проблема в том, что вы добавляете файл, используя
std::ios::app
, который всегда создает новую запись. Вместо этого вы должны загрузить файл в узел YAML, изменить содержимое этого узла и затем записать весь узел обратно. - Файл YAML без заданной вами последовательности, безусловно, не выполняет то, что вы думаете, он делает поскольку вы размещаете
? GyroOffset
на той же глубине, что и Headset2:
, что делает его родным братом Headset2
. Также обратите внимание, что смешивание неявных (foo:
) с явными (? foo
) ключами в одном и том же отображении является своего рода угловым случаем, который может сбить с толку некоторые реализации. Файл YAML может выглядеть просто так:
Headset2:
IdentificationNumber: b630cc42-9a03-42da-a039-0e023cf5b090
GyroOffset:
GyroX:
Value: -0.012388126
GyroY:
Value: -0.0155748781
GyroZ:
Value: -0.0115196211
Чтобы сделать ваш код более читабельным, я предлагаю использовать вспомогательные классы для доступа к вашим значениям. Предполагая, что приведенный выше код представляет собой весь файл YAML, он может выглядеть следующим образом:
struct Value {
YAML::Node data;
// access existing node
explicit Value(YAML::Node data): data(data) {
assert(data.IsMapping());
}
// create new node
explicit Value(float value) {
data["Value"] = value;
}
float get() { return data["Value"].as<float>(); }
void set(float value) { data["Value"] = value; }
};
struct GyroOffset {
YAML::Node data;
explicit GyroOffset(YAML::Node data): data(data) {
assert(data.IsMapping());
}
GyroOffset(float x, float y, float z) {
data["GyroX"] = Value(x).data;
data["GyroY"] = Value(y).data;
data["GyroZ"] = Value(z).data;
}
Value gyroX() { return Value(data["GyroX"]); }
Value gyroX() { return Value(data["GyroY"]); }
Value gyroZ() { return Value(data["GyroZ"]); }
};
struct Headset {
YAML::Node data;
Headset(YAML::Node data): data(data) {
assert(data.IsMapping());
}
Headset(const char *id) {
data["IdentificationNumber"] = id;
// initialize with zero values
data["GyroOffset"] = GyroOffset(0, 0, 0).data;
}
std::string id() { return data["IdentificationNumber"].as<std::string>(); }
void setId(const char *value) { data["IdentificationNumber"] = value; }
GyroOffset gyroOffset() { return GyroOffset(data["GyroOffset"]); }
}
Теперь поиск GyroOffset данного идентификационного номера выглядит следующим образом (я показываю простую функцию, потому что я не знаю вашего поля класса, поскольку вы их не отображаете):
// write found values to output of found
bool findHedasetGyroOffset(Yaml::Node &input /* the file as shown above */, const char *id, GyroOffset &output) {
for (auto it = input.begin(); it != input.end(); ++it) {
Headset hs(it->second);
if (hs.id() == id) {
output = hs.gyroOffset();
return true;
}
}
return false;
}
Поскольку YAML::Node
в основном является ссылкой, при изменении значений внутри возвращенного GyroOffset
исходные данные изменяются. Затем можно записать узел root обратно в файл ( не добавить его) и получить обновленный файл.
Добавление новой гарнитуры будет выглядеть следующим образом:
void addCalibrationToConfigFile(Yaml::Node &file, const char* identificationNumber, const float* in) {
Headset newHs(identificationNumber);
auto go = newHs.gyroOffset();
go.gyroX().set(*in);
go.gyroY().set(*(in + 1));
go.gyroZ().set(*(in + 2));
// note that this will overwrite an existing Headset2
file["Headset2"] = newHs.data;
}
Пока я пытался придерживаться структуры, которую вы показываете, у меня есть ощущение, что фактический ключ в отображении должен быть не Headset2
, а IdentificationNumber:
b630cc42-9a03-42da-a039-0e023cf5b090:
Name: Headset2
GyroOffset:
GyroX:
Value: -0.012388126
GyroY:
Value: -0.0155748781
GyroZ:
Value: -0.0115196211
Так как вы делаете поиск на основе идентификатора, это будет иметь больше смысла. Кроме того, создание новой конфигурации действительно будет работать (в настоящее время из-за жестко заданного значения "Headset2"
она всегда будет перезаписывать эту гарнитуру, если она существует).
Осторожно, я написал код в качестве демонстрации и не тестировал Это; могут быть ошибки.