Вы определенно НЕ должны автоматически генерировать код C ++, который жестко кодирует карту, подобную этой.Существуют библиотеки для чтения файлов json непосредственно в C ++ (см., Например, rapid json ), и их следует использовать вместо этого.Код будет компилироваться гораздо быстрее, и время, необходимое для чтения в 20 000 файлов, должно составлять порядка нескольких миллисекунд (вместо> 5 минут, которые требуются для компиляции).
Если вы хотите избежать добавления зависимости от парсера json в ваш код C ++, я рекомендую преобразовать файл JSON в более простой формат, который легче читать с C ++.
Очень очень простой формат для чтения и записи карт из файлов
Давайте возьмем простую карту:
map<string, map<string, string>> test_map {
{"Hello", {
{"A", "B"},
{"C", "D"}}},
{"World", {
{"Blarg", "glug glug glug"},
{"idek what to put here", "felt cute might delete later"}}}};
Мы собираемся записать ее в файл, используяочень простой формат.Строки будут записаны как <string length> <string text>
, а карты будут записаны как <map length> <map key-value pairs>
.Так, например, "Hello world"
будет записано как 11 Hello world
.Для приведенной выше карты соответствующий файл:
2 5 Hello2 1 A1 B1 C1 D5 World2 5 Blarg14 glug glug glug21 idek what to put here28 felt cute might delete later
У вас есть 2, что означает, что карта верхнего уровня имеет 2 элемента.Далее следует 5, что означает, что в первом ключе есть 5 символов.Далее следуют ключи и значения первой карты и т. Д.
Запись карт в файл в этом формате
Поскольку формат очень прост, это также очень просто сделать.
namespace output {
using std::map;
using std::string;
void write(FILE* file, string const& str) {
// Write the length of the string, followed by a space
fprintf(file, "%lu ", str.size());
// Write the string itself
fwrite(str.data(), 1, str.size(), file);
}
template<class Key, class Value>
void write(FILE* file, map<Key, Value> const& m) {
// Write the length of the map, followed by a space
fprintf(file, "%lu ", m.size());
for(auto& entry : m) {
// Write the key
write(file, entry.first);
// Write the value
write(file, entry.second);
}
}
}
Чтение карт из файла
Это также очень просто сделать.Например, чтобы прочитать строку, мы читаем длину, а затем читаем все символы.
namespace input {
using std::map;
using std::string;
void read(FILE* file, size_t& length) {
int result = fscanf(file, "%lu ", &length);
if(result < 0) throw std::logic_error("Couldn't read from file");
}
void read(FILE* file, string& str) {
size_t length; // Read the length
read(file, length);
str.resize(length);
size_t n_read = fread(&str[0], 1, length, file); // Read the characters
if(n_read != length) { // Handle errors
throw std::logic_error("Unable to read entirety of string from file");
}
}
template<class Key, class Value>
void read(FILE* file, map<Key, Value>& text) {
size_t length; // Read the length of the map
read(file, length);
text.clear();
for(size_t i = 0; i < length; i++) {
Key key;
read(file, key); // Read the key
read(file, text[key]); // Read the value
}
}
}
Используя этот код
Чтобы написать карту:
void write_map(string file, map<string, map<string, string>> test_map) {
auto output_file = fopen(file.c_str(), "w");
output::write(output_file, test_map);
fclose(output_file);
}
Чтобы прочитать карту:
map<string, map<string, string>> read_map(string file) {
auto input_file = fopen(file.c_str(), "r");
map<string, map<string, string>> m;
input::read(file, m);
fclose(input_file);
return m;
}
Проверка этого кода
Вы можете увидеть живую демонстрацию здесь
Эта основная функция запишет тестовую карту в файл, а затем прочитает ее обратно в другую карту, затем сравните два.
int main() {
using std::map;
using std::string;
map<string, map<string, string>> test_map {
{"Hello", {{"A", "B"}, {"C", "D"}}},
{"World", {{"Blarg", "glug glug glug"}, {"idek what to put here", "felt cute might delete later"}}}
};
{
auto output_file = fopen("example.txt", "w");
output::write(output_file, test_map);
fclose(output_file);
}
map<string, map<string, string>> map_from_file;
{
auto input_file = fopen("example.txt", "r");
try {
input::read(input_file, map_from_file);
} catch(std::logic_error& err) {
std::cerr << "Reading example.txt failed: " << err.what() << '\n';
}
fclose(input_file);
}
std::cout << std::boolalpha << "Maps equivilant? " << (test_map == map_from_file) << '\n';
for(auto pair : map_from_file) {
std::cout << '"' << pair.first << "\" -> {\n";
for(auto kv : pair.second) {
std::cout << " \"" << kv.first << "\" -> \"" << kv.second << '"' << "\n";
}
std::cout << "}\n";
}
}