c++ special variable name - c++

When I create variable I just put the a name for it, but can I create the name of the variable like this:
int var+1= 1;
So basically that should be:
int var1=1;
I know I can't use the + sign to do that but is there way to do it?
EDIT
int g=1;
string hello+g = "sdljfsdl"; // So hello+g will be hello1
So it is like mixing variable value by another variable value to get new variable name.

You can do this with macros, but you really shouldn't need dynamic variable names. It sounds like this sort of problem can be solved with an array:
int vars[5];
vars[0] = 3;
vars[1] = 4;
// etc.

It is unlikely to be desirable, but you could use token pasting in the preprocessor:
#define PASTER(x, y) x ## y
#define EVALUATOR(x, y) PASTER(x, y)
int EVALUATOR(var, 1) = 1;

you almost certainly need std::map, or, if available, unordered_map. both will allow you to construct keys however you like and set/get values for those keys e.g.
std::map<string,int mymap;
string fixed = "fixed part";
string var = " 1"; //or construct this from a number
mymap[fixed+var] = 3; //fixed+var == "fixed part 1"

Related

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";
}
}

Preprocessor directive to simulate a notation

In C++, is there a methodology by means of the preprocessor to substitute for a variable name followed by an index number by: its name followed by '[' followed by the index number, followed by ']'?
As an example, if I write:
int main(void)
{
int var[64];
var0 = 0;
var1 = 1;
var2 = 2; // etc...
return 0;
}
Translation:
int main(void)
{
int var[64];
var[0] = 0;
var[1] = 1;
var[2] = 2; // etc...
return 0;
}
#define is going to be the closest you can get.
#define var0 var[0]
#define var1 var[1]
...
However, it should be noted if you're going to use the above, you may as well just do it manually in the first place, since you're typing everything out anyway.
No. Thanks to language creators! There is no way to make syntax analysis (string parsing) inside macro definition.
It would be the real hell to read such programs.

Commands with Variables in ROOT

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();
}

How to get next value of enum

I have the following problem:
enum Language { English, French, German, Italian, Spanish };
int main() {
Language tongue = German;
tongue = static_cast<Language>(tongue + 1);
cout << tongue;
}
//it returns 3.....but i want to get the language name on index 3.....
I find that an explicit look up table works best, for both converting from enum to text and text to enum:
enum Language_Enum
{
LANGUAGE_FIRST = 0,
LANGUAGE_GERMAN = LANGUAGE_FIRST,
LANGUAGE_ENGLISH,
LANGUAGE_HOPI,
LANGUAGE_WELSH,
LANGUAGE_TEXAN,
LANGUAGE_DUTCH,
LANGUAGE_LAST
};
struct Language_Entry
{
Language_Enum id;
const char * text;
};
const Language Entry language_table[] =
{
{LANGUAGE_GERMAN, "German"},
{LANGUAGE_HOPI, "Hopi"},
{LANGUAGE_DUTCH, "Dutch"},
// ...
};
const unsigned int language_table_size =
sizeof(language_table) / sizeof(language_table[0]);
Specifying the enum along with the text, allows for the enum order to change with minimal effect to the search engine.
The LANGUAGE_FIRST and LANGUAGE_LAST identifiers allow for iteration of the enum:
Language_Enum l;
for (l = LANGUAGE_FIRST; l < LANGUAGE_LAST; ++l)
{
// ...
}
You'll have to create an array of strings which matches your enum e.g.
std::string[] LangTxt = { "English", "French", "German", "Italian", "Spanish" };
then you can reference them as follows:
cout << LangTxt[tongue];
Be careful to keep the definitions together though so they are updated side by side.
It is not so simple to print the enum name for a given enum value in C++. Instead, you can use a map or string array to hold the values, which do allow you to get both the index and the string value.
Best Way to use enum is first give initial value to your enum.
enum TestEnum
{
Zero=0,
One,
Two
}
Even you wont specify anything the default starting index is zero.
To get the value at a particular index simple do that
TestEnum(index);

How to read a character or string and automatically convert to a number (C/C++)?

Suppose I am working on a card game, and I am using the numbers 0 to 3 to represent the suits internally, as it's easier to work with numbers. So:
0 is equivalent to hearts
1 is equivalent to clubs
2 is equivalent to spades
3 is equivalent to diamonds
When I need to output the suits as strings, though, I can easily use an array of strings to convert them, like this one:
char *suits[] = {"heats","clubs","spades","diamonds"};
So that I can type:
cout << suits[card.suit]
and the output would be the exact string of the suit.
What if I want to do this the other way around though? That is, I'll be reading the suits from a file as strings, and I want to convert them to their respective numerical value (0 to 3) on the fly. How can I do it?
My initial idea was to create a very small hash table (i.e., 4 elements in this case), then hash the strings as I read them and get their respective numerical value from the hash table.
Is there an easier way I am missing (specifically in C or C++)?
std::map<std::string, int> assoc;
assoc["hears"] = 0;
assoc["clubs"] = 1;
...
char *suits[] = {"heats","clubs","spades","diamonds"};
for (char *data : suits)
{
std::cout << assoc[data];
}
Like Joachim said, I would recommend a std::map<std::string, int>.
You can then do stuff like.
std::cout << map["heart"];
I would recommend to check out the std::map class as it is quite a nice tool, but also holds some gotchas.
If you want to use it in both directions, you could also use a boost::bimap.
std::map<std::string, int id> cardsToIdMap;
int stringToCardId(std::string s) {
return cardsToIdMap[s];
}
A map is hugely overkill here:
#define SIZE(x) (sizeof (x)/sizeof(*(x)))
const char *suits[] = {"heats","clubs","spades","diamonds"};
int suit_to_int(char *s)
{
for(int x=0; x<SIZE(suits);x++)
if(strcmp(s, suits[x])==0)
return x;
return SUIT_ERR;
}
char* suit;
if (*suit == 'h') {
return 0;
} else if ...