LINUX.ORG.RU

Выбор элемента структуры по имени

 ,


1

3

Сижу пишу на плюсах прогу, решающую газодинамику. Вывод делаю в xml-образные файлы для ParaView. Получается как-то так:

есть пачка переменных (пусть P, V, E)

открываю stringstream, пихаю в него открывающий тег, пробегаю по сетке, закрывающий тег. И так 10 раз. Потом поток уходит в файл.

Собственно, вопрос - это можно сделать более читабельным/компактным? 10 циклов отличаются 1 значением - это имя элемента структуры. Вроде в некоторых языках можно просто передать имя элемента в параметрах функции. Для плюсов такого не видел вроде (в бусте вроде было, но ну его нафиг ради одной фичи).

Понимаю, что в целом можно пихать в разные потоки, но количество переменных на вывод тоже изначально хз какое (сколько нужно - столько будет)

upd: В догонку - какой наиболее быстрый способ записи на хард если каждый цикл выплевывается файл ~ полметра размером?

★★★★★

Последнее исправление: upcFrost (всего исправлений: 1)
Ответ на: комментарий от Uter

Смещение - это ппц, не? В плане - помню там была куча проблем, особенно если параллельно считать

upcFrost ★★★★★
() автор топика
Ответ на: комментарий от upcFrost

Если типы полей одинаковы, есть пойнтер на поле структуры (с-но смещение, но безопасное).

#include <stdio.h>

struct A{
	double x, y, z;
};

void out(const A& a, double A::*p){
	printf("%g\n", a.*p);
}

int main( int argc, const char** argv ) {
	A a; a.x = 1; a.y = 2; a.z = 3;
	out(a, &A::x);
	out(a, &A::y);
	out(a, &A::z);
	return 0;
}

$ g++ test.cpp
$ ./a.out 
1
2
3

Вывод делаю в xml-образные файлы для ParaView

Уже весело. А вьювера с нормальным бинарным форматом на входе не нашлось?

открываю stringstream, пихаю в него открывающий тег, пробегаю по сетке, закрывающий тег. И так 10 раз. Потом поток уходит в файл.

О_О. А сразу fstream использовать религия не позволяет???

AIv ★★★★★
()
Ответ на: комментарий от AIv

А сразу fstream использовать религия не позволяет???

Медленнее, проверял. Когда большой объем - stringstream быстрее.

Уже весело. А вьювера с нормальным бинарным форматом на входе не нашлось?

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

upcFrost ★★★★★
() автор топика
Ответ на: комментарий от upcFrost

Медленнее, проверял. Когда большой объем - stringstream быстрее.

Гыыыы... небось <<endl юзали, которая flush вызывает?;-) Переводите строку <<«\n», и будет Вам щастье. stringstream это еще один, 1005001-й буфер. В iostream и так их наворочено...

AIv ★★★★★
()

10 циклов отличаются 1 значением - это имя элемента структуры. Вроде в некоторых языках можно просто передать имя элемента в параметрах функции

передайте указатель на структуру

struct
{
 const char *key;
 double value;
};

ищите key, и вставляйте туда найденное value.

Я бы сделал массив из 10и таких структур.

drBatty ★★
()

В C++ для этого ввели указатель на член класса (Pointer-to-member) и шаблонные функции а в C — макрос ofsetoff()

template <class T, typename tp>

void foo ( T *A, tp T::* member ) {

std::cout << A.*member;

}

anonymous
()

10 циклов отличаются 1 значением - это имя элемента структуры

map? максрос?

actics
()

с pointer to member (как ниже написали), можно так:

#include <iostream>

struct A {
  int a;
  int b;

  int& operator[](std::size_t idx) {
    static int A::*elem[2] = {
      &A::a,
      &A::b
    };
    return this->*elem[idx];
  }
};

int main() {
  A a = {1, 2};
  std::cout << a[0] << "\n" << a[1] << "\n";
  for(int i = 0; i < 2; ++i) a[i]++;
  std::cout << a[0] << "\n" << a[1] << "\n";
  return 0;
}

invy ★★★★★
()
Ответ на: комментарий от drBatty

Поиск по ИМЕНИ поля? В рантайме? Для каждой ячейки? Видно идет конкурс «самая медленная числодробилка для газовой динамики»...

AIv ★★★★★
()

хз, сделай класс какой-то типа

typedef struct{} SomeStruct; 
class Foo
{
  vector<string> _names;
  SomeStruct s;// пачка одинаковых переменных
  friend std::ostream& operator<<(std::ostream& stream, const Foo& obj) 
};
Я имею вввиду если для кучи имен одна только структура фактически, храни кучу имен, и к ним одну структуру.

Boy_from_Jungle ★★★★
()
Ответ на: комментарий от AIv

Поиск по ИМЕНИ поля? В рантайме? Для каждой ячейки?

как я понял ТСа, ему нужен поиск по имени поля в его XML. Или нужен поиск по имени поля внутри C++ компилятора?

drBatty ★★
()
Ответ на: комментарий от AIv

Внутри С++

ну если внутри - то, ИМХО, изврат. А так в цикле передаёшь указатель на структуру, оно оттуда берёт key, ищет его в XML, и пишет в value то, что нашла. Не очень понятно, зачем тут передавать именно имена C++ переменных.

drBatty ★★
()
Ответ на: комментарий от drBatty

А никто не говорит про имена. Я там выше привел же пример... иначе ф-ю out придется писать под каждое поле свою.

AIv ★★★★★
()
void* operator [] (string s) {
  if (s == "field1") {
    return &field1;
  } else if ...  
}
anonymous
()

Собственно, вопрос - это можно сделать более читабельным/компактным? 10 циклов отличаются 1 значением - это имя элемента структуры. Вроде в некоторых языках можно просто передать имя элемента в параметрах функции. Для плюсов такого не видел вроде (в бусте вроде было, но ну его нафиг ради одной фичи).

Не делай так. Сделай вместо имён элементов массив (или union и то и другое). Передавай enum индекс значения в массиве. Если все значения структуры в функции не нужны - передавай только значение. Если нужно и строковое имя поля, сотвори строковый массив и извлекай из него строковое имя по тому же индексу.

upd: В догонку - какой наиболее быстрый способ записи на хард если каждый цикл выплевывается файл ~ полметра размером?

Пиши в память лучше, в буфер. По концу цикла сбрасывай на диск. Можно попробовать создать отдельный i/o thread и параллельно записывать. Немного проиграешь в производительности.

auto12884839
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.