объединить строку и запустить индекс в строку внутри цикла - PullRequest
0 голосов
/ 03 мая 2010

Чтобы использовать данный графический пакет, мне нужно определить, записать и заполнить гистограмму. Как я могу получить имя гистограммы, которая представляет собой строку для объединения с 2 целыми числами в виде строки (hts_i_j) в 3 для цикла вместо. Это должно быть сделано в C ++ Смотрите пример ниже

определить

TH1F* hts_5_53;
TH1F* hts_5_54;
……
TH1F* hts_5_69;

забронировать

hts_5_53= HDir.make<TH1F>("hts_5_53")," Title", 100,0.,100.);
hts_5_54->HDir.make<TH1F>("hts_5_54")," Title", 100,0.,100.);
……
hts_16_69->HDir.make<TH1F>("hts_16_69")," Title", 100,0.,100.);

для заполнения

hts_5_53->Fill(f)
hts_5_54->Fill(f)
……
hts_16_69->Fill(f)

Вместо этого я хотел бы определить, забронировать и заполнить 3 для циклов. например .

for(int i=5, i<17, ++i){
  for(int j=53, j<70, ++j){

   hts_i_j 

 } 
}

как мне получить строку hts для объединения с индексы (i, j) простым коротким способом при определении, бронирование и заполнение 3 за цикл вместо

Ответы [ 4 ]

1 голос
/ 03 мая 2010

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

То, что вы делаете, возможно, лучше решить с помощью массива . Определите имя массива hts, которое имеет необходимые вам размеры. Массивы C ++ всегда индексируются с нуля, но ваша нижняя граница равна пяти. Вы можете либо вычесть пять из всех ваших индексов, когда бы вы их ни использовали, либо вы можете просто увеличить массив на пять элементов и «выбросить» нижние элементы.

TH1F* hts[17][70];
for (int i = 5; i < 17; ++i) {
  for (int j = 53; j < 70; ++j) {
    ostringstream name;
    name << "hts_" << i << "_" << j;
    hts[i][j] = HDir.make<TH1F>(name.str()), " Title", 100, 0., 100.);
  }
}

У вас есть синтаксическая ошибка где-то в вашей строке make; Я не пытался исправить это здесь.

Чтобы иметь массив минимального размера, вам придется помассировать индексы, прежде чем использовать их:

int const Offset1 = 5;
int const Offset2 = 53;
TH1F* hts[17-Offset1][70-Offset2];
for (int i = Offset1; i < 17; ++i) {
  for (int j = Offset2; j < 70; ++j) {
    ostringstream name;
    name << "hts_" << i - Offset1 << "_" << j - Offset2;
    hts[i][j] = HDir.make<TH1F>(name.str()), " Title", 100, 0., 100.);
  }
}

Другой вариант - использовать map из строк для ваших объектов TH1F:

std::map<std::string, TH1F*> hts;
for (int i = 5; i < 17; ++i) {
  for (int j = 53; j < 70; ++j) {
    ostringstream name;
    name << "hts_" << i << "_" << j;
    hts.insert(name.str()), HDir.make<TH1F>(name.str()), " Title", 100, 0., 100.));
  }
}

Затем вы можете получить доступ к любому элементу, который хотите, используя имя:

hts["hts_5_62"]->Fill(f);
0 голосов
/ 12 мая 2010
//string concat with a macro
#define HTS_(i,j) hts_##i##_##j

//usage
//declare variables    
    TH1F* HTS_(5,53);
    TH1F* HTS_(5,54);
    //but note that the following produces variable hts_k_l, not hts_8_9;
    int k = 8;
    int l = 9;
    TH1F* HTS_(k,l);
    //use your variables
    hts_5_53 = HDir.make<TH1F>("hts_5_53")," Title", 100,0.,100.);
    hts_5_54 =HDir.make<TH1F>("hts_5_54")," Title", 100,0.,100.);

Я думаю, что Boost.Preprocessor может использовать его в «цикле»

Однако я не могу себе представить, для чего все это можно применить :) Обычно это делается с массивами

0 голосов
/ 03 мая 2010

Я не очень понимаю ваш вопрос.

Что вы делаете с «книгами» после того, как объявляете переменные для них? Если вы помещаете их в какую-то коллекцию, может быть необязательно иметь переменную, объявленную для каждой из них. Просто объявите переменную общего типа во внутреннем цикле for, присвойте ее по мере необходимости и поместите в любую нужную коллекцию.

Или если у вас есть программа, которая просто должна работать с несколькими книгами, то делайте это в точности так, как вы делаете это сейчас, без циклов. Просто объявите каждый вручную.

0 голосов
/ 03 мая 2010

В стандартном C ++ строковые потоки являются основным решением для форматирования строк:

std::ostringstream os;
os << "hts_" << i << "_" << j;

Получите полученную строку с помощью os.str(). Для обсуждения альтернатив см. " Строка форматеров усадьбы фермы " .

С полученной строкой и подходящим контейнером ваш цикл может, например, стать:

for (int i=5; i<17; ++i) {
    for (int j=53; j<70; ++j) {
       hts[i][j] = f(str); 
    } 
}

Почему, в первую очередь, вам нужно хранить индексы в строке, мне неясно.

Примечание: Если вы учитесь из книги, которая не охватывает форматирование строк и разумное использование контейнеров, выберите хороший вводный из справочника SO .

...