concatenate string and running index into string within a loop
To use a given graphic package I need to define, book and fill histogram. How can I get the name of the histogram which is a string to concatenate with 2 integer as a string ( hts_i_j ) in 3 for loop instead. That has to be done in c++ See the exemple below
to define
TH1F* hts_5_53;
TH1F* hts_5_54;
……
TH1F* hts_5_69;
to book
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.);
to fill
hts_5_53->Fill(f)
hts_5_54->Fill(f)
……
hts_16_69->Fill(f)
Instead I would like to define, book and fill in 3 for loops. e.g .
for(int i=5, i<17, ++i){
for(int j=53, j<70, ++j){
hts_i_j
}
}
how can I get the string hts to concatenate with the indices ( i,j) in a simple short way while defining, booking and filling in 3 for loop instead
You can't construct strings in code and then use those names to get back to the variables that had those names. The compiler throws away variables' names as it builds your program into executable code.
What you're doing is probably better solved with an array. Define an array name hts
that has the dimensions you need. C++ arrays are always indexed from zero, but your lowest bound appears to be five. You can either subtract five from all your indices whenever you use them, or you can just make your array five elements longer and "throw away" the lower elements.
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.);
}
}
You have a syntax error somewhere in your make
line; I have not attempted to fix it here.
To have a minimally sized array, you'll have to massage the indices before you use them:
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.);
}
}
Another option is to use a map
from strings to your TH1F objects:
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.));
}
}
Then you can access any item you want using the name:
hts["hts_5_62"]->Fill(f);
I don't really understand your question.
What are you doing with the "books" after you declare variables for them? If you are putting them in some sort of collection it may not be necessary to have a variable declared for each one. Just declare a generic variable inside the inner for loop, assign it as needed, and put it in whatever collection you need.
Or if you have a program that just needs to work with a handful of books, then do it exactly how you're doing it now, without loops. Just declare each one manually.
In standard C++ string streams are the basic solution for string formatting:
std::ostringstream os;
os << "hts_" << i << "_" << j;
Retrieve the resulting string with os.str()
. For a discussion of alternatives see "The string formatters of Manor farm".
With the resulting string and a suitable container, your loop could e.g. become:
for (int i=5; i<17; ++i) {
for (int j=53; j<70; ++j) {
hts[i][j] = f(str);
}
}
Why however you'd need to store the indices in the string in the first place is not clear to me.
Side-note: If you are learning from a book that doesn't cover string formatting and sensible use of containers, choose a good introductory one from SOs book guide.
//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.);
I think Boost.Preprocessor is able to use it in a "loop"
However I cannot imagine what all of this can be applied for :) It's done with arrays normally
精彩评论