Commands with Variables in ROOT - c++

I am trying to create a simple loop that calls data from sequential channels. I have channels numbered 1-8 (named qL1 - qL8) and need to call the qL*->Draw(); command for all of them.
Is there a way to use a loop to continually update the number in the command? I believe the equivalent code in a c shell would be:
for {set i 1} {$i <= 8} {incr i} {
qL$i->Draw();
}
As stated in the title, I am trying to write a macro for ROOT. Thanks.

put everything into an array/vector
well, you can fill your channels (I assume TH1 here, but it should work similarly for TGraph, TTree, etc) into an array/vector first, since they are pointers anyhow:
TH1* qL[9]; // nine elements to have indices matching
qL[1] = qL1;
qL[2] = qL2;
qL[3] = qL3;
qL[4] = qL4;
qL[5] = qL5;
qL[6] = qL6;
qL[7] = qL7;
qL[8] = qL8;
for (int i = 1 ; i <= 8 ; i++) { qL[i]->Draw() ; }
though that probably doesn't gain you much.
use ROOT's directory mechanism and use string manipulation
What might be better suited is to work with root's directory management (if you anyhow get your channels from an input file, that should be a straight forward solution):
for (int i = 1 ; i <= 8 ; i++) {
TH1* localhist = (TH1*) gDirectory->Get(Form("qL%d",i));
localhist->Draw();
}
Here, Form(...) is a cstring and the syntax for Form is the same as for printf (google is your friend). And Get looks for an object of which the name is the cstring provided. (be aware of the room for confusion in TH1* variablename = new TH1F( NAME, TITLE , ...), what matters is the NAME and not the variablename)
preprocessor macros
you can use a preprocessor (e.g. boost) to concatenate the string part (qL) of your variable with a number and use this in a preprocessor macro which takes the number as argument.
#include <boost/preprocessor/cat.hpp>
#define qL(i) BOOST_PP_CAT(qL, i)
TH1* qL1 = new TH1F("test","test",1,0,1);
qL(1)->GetName();
The problem with this is, that the argument must be known at compile time, if you put this in a for loop, you'll get errors because qLi is not known.
Which can be done in preprocessor, though not sure if this will greatly work out on the long run
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
#define HHHHH(z,n,zz) BOOST_PP_CAT(qL, n) zz
BOOST_PP_REPEAT_FROM_TO(1,3,HHHHH,->Draw();)

No. If only your channels names were an array, e.g. qL[N], where N=0, 1, ..., 7, that would be possible with something like
for (Int_t i=0; i<8; i++)
{
qL[i]->Draw();
}

Related

Edit string by calling it using concatenation in C++

I'm a very new C++ user (and a new StackOverflow user at that), and I'm trying to code a very basic Tic-Tac-Toe (Naughts and Crosses) game. I'm not sure how to render the board as it is updated.
My main question is if it is possible to call a string using concatenation. I have an array set up that indexes the states of the 9 spaces of the board using a 0 for empty, a 1 for an X, and a 2 for an O. If I set up 9 variables in a user-defined renderBoard() function named bit1, bit2, etc; Can I call them this way:
void renderBoard()
{
int i = 1;
string bit1;
string bit2;
string bit3;
string bit4;
string bit5;
string bit6;
string bit7;
string bit8;
string bit9;
while (i < 10)
{
if (Spaces[i] = 0)
{
(bit + i) = * //This is the main bit I'm wondering about
}
else
{
//Check for 1, 2, and edit the string bits accordingly
}
++i;
}
//Put all of the strings together, as well as some more strings for adding the grid
//Output the whole concatenated string to the command line
}
If anyone knows of a better way to do this, please let me know. I've tried Googling and rifling through various C++ help websites, but I find it difficult to express my particular case through anything other than a long-winded and specific explanation.
Thanks for you help!!
If I correctly understood your problem, your problem is that you want to access the strings named bit1, bit2, etc using a variable i like bit + i.
And no, you cannot do that!
It will throw a compile time error.
Please correct me if I didn't get what you are looking for.
But one question is still in my mind that why are you using string variables bit1, bit2 etc?
I think you just want to store single digit value in those strings. If this is the case, you can just use a single string of length 9.
You can do this as follows:
int i = 0; //because string indices start from 0 and also array indices.
string bit(9, ' '); //declare a string of length 9 with default value of a space (you can modify it with your default value)
while (i < 9) { // i < 9 because highest index will be 8
if (Spaces[i] == 0) {
bit[i] = '*';
} else {
}
++i;
}
Declaring 9 variables like this is apparently wrong. What you are looking for is an array.
std::array<std::string, 9> bits;
(You need #include <array> and #include <string>.)
Then, you can traverse the string using a for-loop: (in C++, arrays are indexed starting from zero, not one)
for (std::size_t i = 0; i < 9; ++i) {
// operate on bits[i]
}
In the for-loop, you can use the subscript operator to access the element: bits[i].
Finally, to put all the strings together, use std::accumulate:
std::accumulate(bits.begin(), bits.end(), std::string{})
(You need #include <numeric>.)

Change alias after declaration

I'm quite new in C++ programming. So I tried to define an alias and change it later, but I'm not sure if it is possible and (if it's possible) how to do it:
using Alpha = Alphabet::DNA
//I don' need the Alpha here, but I have to define it before the scope,
//because afaik if I define it inside the scope,
//it'll be lost outside the scope
for(int i = 0 ; i < argc ; ++i){
if(argv[i] == "-d"){
Alpha = Alphabet::DNA;
}else if(argv[i] == "-r"){
Alpha = Alphabet::RNA;
}
}
Sequence<Alpha> seq;
I need to do this because I only know from the arguments which Alpha I have to use. Alphabet is already a namespace and DNA and RNA are "subtypes" of it.
Sequence is just a template class representing the sequence of molecules fro DNA or RNA.
Thanks for your help
The answer is NO.
For every type (alias or not), cpp compiler have to determine its "real type" in compile time.
For instance,
constexpr int N = 3;
using FixedBitset = std::bitset<N>;
is valid. While
int N = 3;
using FixedBitset = std::bitset<N>;
is definitely invalid because the value N cannot be checked out in compile time.

Putting multiple calculations into a for-loop that uses variables based on iteration number

What is the best way to organize the following into a for loop that iterates X times, but requires updating the variables (velocity, currentPose, targetPoint) depending on the iteration number?
velocity1 = computeVelocity(currentPose1, targetPoint1);
velocity2 = computeVelocity(currentPose2, targetPoint2);
...
velocityX = computeVelocity(currentPoseX, targetPointX);
The for loop would ideally look something like this:
for (int i=0; i<X; i++)
{
velocity_i = computeVelocity(currentPose_i, targetPoint_i);
}
Since for each velocity, there will be an associated (and possibly distinct) currentPose and targetPoint, one way to do it it to have all these variables as std::vectors, or std::array if you know at compile time how many items you will have to store. Then your loop could look like this:
for (int i=0; i<X; i++)
{
velocity[i] = computeVelocity(currentPose[i], targetPoint[i]);
}
I don't think that wanting the i to be a part of the variables' name is doable (although there might be some way to do it using preprocessor macros and the # concatenation operator, I have not thought about it), nor would it be usual C++ code.
For a C++ programmer the vector/array approach is the more natural one.

How to use variable this way c++

Im making a c++ program wherein there are multiple variables for example:
var1, var2, var3, var4;
i want to use it for a for loop like:
for(int x; x<=5; x++){
if(var1==1){cout << "hi";}
}
But instead of typing var1 i want to make it var"x" where x is equal to 1.
I remember from my batch programming days(not exact) i can use this like:
set x=1
echo var%x%
then the output will be var1.
You can do this, using macros, but I really don't think it is a good idea. Why not use arrays instead? With arrays you can reference the index you want, so instead of var1, var2, var3, ... it will be var[0], var[1], var[2], ... Much more C++ like, anyway.
When using arrays, I would even recommend thinking in one of the container classes C++ offers, such as std::vector, or std::array. To have a simple array of integer variables in a vector, simply declare one such as: std::vector<int> intVec, to extract a specific element use the at function, such as intVec.at(0) which will extract the first element. Really use, almost any other approach, than macros.
Having said that, to do it in a macro you would need to make a macro like this:
#define var(x) var##x
var(1) = 2; // resolves to var1 = 2;
Macros are compile time however, so using them in a loop, by passing a variable to it, will not work the way you would expect. So calling int x = 1; var(x) = 2; would not set var1 to 2, but rather attempt to set varx to 2.
The macro solution comes with a number of disadvantages, one is making your less readable, another is making your code more error prone, and lastly, why stir away from the "C++ way"?
You can make use of command line arguments while invoking your program executable.
prog.exe 3 4 1 6
This way your program will receive 5 command line arguments, the first being the program name itself.
The code will look something like this:
int main(int argc, char *argv[]) {
// For the above example, argc = 5
for (int i = 1; i < argc; ++i) {
// make use of argv[i]
}
}
This may not be exactly what you want to do, but confirms to your idea of multiple variables var1 i.e. argv[1]
It is possible to this in many script programming but unfortunately no direct support is available in C++.
Some ways around are use of arrays (if possible) or an array of pointers to actual variables.
int vars[5] = {...};
for(int x = 0; x < 5; x++){
if(var[x]==1){cout << "hi";}
}
or
int var0 = 2, var1 = 42, var2 = 7;
int *const pvars[] = {&var0, &var1, &var2};
for(int x = 0; x < 3; x++) {
if(*(pvars[x]) == 1)
{
cout << "hi";
}
}
or as mentioned in this comment
int var0 = 2, var1 = 42, var2 = 7;
for(auto &var = {var0, var1, var2}) {
if(var == 1)
{
cout << "hi";
}
}

Iterate through Enums in C++

C++ enum question.
So I have a list of files, and their IDs that I need to iterate over, and do stuff to. Most of the stuff is the same, but there are a few file-specific things that need to be done. I tried putting the file IDs in an enum, and iterating over that. Howver, the fileIDs are non contiguous, and jump around.
Currently, I have something akin to this
for(int i = 0; i < FILE_ENUM_MAX; i++)
{
currentFile = myEnum(i);
// do stuff
}
enum myEnum {
file1 = 0x1111,
file2 = 0x8000,
file3 = 0x75,
file4 = 0x120,
FILE_ENUM_MAX = 4
}
This doesn't work; I just go through files 0, 1, 2, and 3. I get the idea that I can't just get the Nth item in an enumeration by asking for item N. So what would be the best way to iterate over this enum? Or should I just get rid of it? I probably could put the items in numerical order, but I'd prefer a solution to where order didn't matter.
Unfortunately, C++ does not provide a way to iterate through enums like you want.
I guess the low-tech answer might be to skip the enum, and just create a static array:
#define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0]))
int FILE_ENUM[] = { 0x1111, 0x8000, 0x75, 0x120 };
for(int i = 0; i < ARRAYSIZE(FILE_ENUM); i++) {
currentFile = myEnum[i];
// do stuff
}
TJ
I have two suggestions:
Use a std::vector to contain the enums.
Use a std::map to contain the
enums.
Solution 2 offers a benefit where the key is the file ID and the value can be the name of the file (or an object containing attributes of the file, such as a file handle or pointer).
i <= FILE_ENUM_MAX and it will iterate with 4th file. Sorry if this is an old thread but maybe someone will still need an answer trying to find it here.