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.
Related
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";
}
}
There's already a question about adressing variables with strings in Arduino, but the answers given didn't apply to my problem.
I have multiple sensors (around 14 and the number might increase) connected to my Arduino, I also have relays, engines and RFIDs. I'm creating a function that checks if all of the sensors are active.
The idea is basically this:
#define Sensor_1 2
#define Sensor_2 3
#define Sensor_3 4
#define Sensor_4 5
#define Sensor_5 6
int checkSensors(){
int all_active = 0;
int num_sens = 5;
int n;
int active_sens = 0;
for(n= 1; n <= num_sens; n++) {
if( !digitalRead("Sensor_" + n)) {
active_sens= active_sens+ 1;
}
else {
all_active = 0;
return ( all_active);
}
}
if(active_sens== num_sens) {
all_active = 1;
return(all_active);
}
}
The problem is: I want to address the variable Sensor_n, but I can't find out a way to do it. The error message I get is referring to the digitalRead("Sensor_" + n ) command.
error: invalid conversion from 'const char*' to 'uint8_t {aka unsigned char}' [-fpermissive]
I already tried to use "Sensor_" in a String = "Sensor_", I've tried to force a typecast to uint8_t, but the error message says that it loses precision.
I also tried the .toCharArray command, but it failed as well.
Is there a way to access a variable through a string + int?
I'm more familiar with the "loose" variables in PHP, so this is giving me a lot of trouble.
There are a few issues with your code. First you can't get the value of a variable or a define by dynamically using a string that is the name of the variable. It doesn't work that way in C. The easiest approach is to use an array and then just index through it. To make this work well I've changed the for loop to count from 0 since the array is indexed starting at 0. I changed the all_active logic assuming that at some point later you are going to want to know how many sensors are active instead of just whether they are all active or not. If you don't want that, then your logic is also more complicated than needed. It could just return 1 at the end of the for loop since all must have passed the test to get there.
#define Sensor_1 2
#define Sensor_2 3
#define Sensor_3 4
#define Sensor_4 5
#define Sensor_5 6
int sensors[] = {Sensor_1, Sensor_2, Sensor_3, Sensor_4, Sensor_5};
int checkSensors(){
int all_active = 1;
int num_sens = 5;
int n;
int active_sens = 0;
for(n= 0; n < num_sens; n++){
if( !digitalRead(sensors[n])){
active_sens= active_sens+ 1;
}
else {
all_active = 0;
}
}
return all_active;
}
In C this line will not work
if( !digitalRead("Sensor_" + n))
you cannot build a string like this in C. Since you didn't post the function digitalRead() I presume it takes a char* type, here a string, which in C you could build like this
char senstr[50];
sprintf(senstr, "Sensor_%d", n);
...
if (!digitalRead(senstr)) { ...
As a side issue, please get used to iterating loops from 0. You add 1 to interface with humans.
I was just curious to know if there is way to create a new variable with a new name every time a loop is executed.
For example:
#include <iostream>
int main()
{
for (int x = 1 ; x<=5 ; x++)
int a_x;
return 0;
}
5 new variables should be created with names a_1, a_2, ..., a_5
The above code just shows what I am looking for and is not the answer.
Is this possible without using arrays?
No, there is no way to do what you've outlined (directly). Here are several possible alternatives:
First off, if you do not need the "variables" to be accessible outside the loop, just use a normal local variable:
for (int x = 1; x <= 5; ++x) {
int a = whatever; // This will be freshly redeclared & reinitialised in each iteration
}
If the bounds of the iteration are known at compile time, you can use an array:
std::array<int, 5> a;
for (int x = 0; x < a.size(); ++x) {
a[x];
}
If the bounds are only known at runtime, use a dynamic array:
std::vector<int> a(the_runtime_size);
for (int x = 0; x < a.size(); ++x) {
a[x];
}
If you really need individual variables for some reason (and you know the number at compile time), you could resort to preprocessor tricks with Boost.Preprocessor. But that is far above beginner level:
#include <boost/preprocessor>
#define DECLARE_MY_VARIABLE(z, idx, name) \
int BOOST_PP_CAT(name, BOOST_PP_CAT(_, idx));
BOOST_PP_REPEAT(5, DECLARE_MY_VARIABLE, a)
The code above will expand to:
int a_0; int a_1; int a_2; int a_3; int a_4;
You could of course take this several steps further, to have each of the variables of a different type, or name them by names instead of by indices. It will just require more macro magic.
Disclaimer: Do NOT use this approach unless you very clearly know you need it. Even then, reconsider twice before you actually do that. And if you still do, document it heavily. Stuff like this should generally be hidden deep inside a library under a nice & clean user-friendly interface.
No you can't do that in C++.
The best thing to do in this case would be to create an array of ints and use the for loop to populate them.
int a_x[5];
for (int x = 1 ; x<=5 ; x++)
a_x[x - 1] = /*ToDo - something*/
Note that
arrays are zero-based: can you see how I've used x - 1. The normal thing to do would be to rebase x in the for loop though: for (int x = 0 ; x < 5; ...
arrays are not initialised. You must populate the contents.
While many will assume that this is impossible, it can be achieved with the preprocessor. It is necessary that the loop count is known at compile time. Here I use the Boost Preprocessor Library. The example for PP_REPEAT does almost exactly what you want.
#include <boost/preprocessor/repetition/repeat.hpp>
#define DECL(z, n, text) text ## n = n;
int main()
{
BOOST_PP_REPEAT(5, DECL, int a_) // expands to int a_0 = 0; int a_1 = 1; ...
return 0;
}
Please remember: this is certainly not what you want. You probably want to use an array. Do only use this if you are absolutely certain that you need it.
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"
int main()
{
int var = 0;; // Typo which compiles just fine
}
How else could assert(foo == bar); compile down to nothing when NDEBUG is defined?
This is the way C and C++ express NOP.
You want to be able to do things like
while (fnorble(the_smurf) == FAILED)
;
and not
while (fnorble(the_smurf) == FAILED)
do_nothing_just_because_you_have_to_write_something_here();
But! Please do not write the empty statement on the same line, like this:
while (fnorble(the_smurf) == FAILED);
That’s a very good way to confuse the reader, since it is easy to miss the semicolon, and therefore think that the next row is the body of the loop. Remember: Programming is really about communication — not with the compiler, but with other people, who will read your code. (Or with yourself, three years later!)
I'm no language designer, but the answer I'd give is "why not?" From the language design perspective, one wants the rules (i.e. the grammar) to be as simple as possible.
Not to mention that "empty expressions" have uses, i.e.
for (i = 0; i < INSANE_NUMBER; i++);
Will dead-wait (not a good use, but a use nonetheless).
EDIT: As pointed out in a comment to this answer, any compiler worth its salt would probably not busy wait at this loop, and optimize it away. However, if there were something more useful in the for head itself (other than i++), which I've seen done (strangely) with data structure traversal, then I imagine you could still construct a loop with an empty body (by using/abusing the "for" construct).
OK, I’ll add this to the worst case scenario that you may actually use:
for (int yy = 0; yy < nHeight; ++yy) {
for (int xx = 0; xx < nWidth; ++xx) {
for (int vv = yy - 3; vv <= yy + 3; ++vv) {
for (int uu = xx - 3; uu <= xx + 3; ++uu) {
if (test(uu, vv)) {
goto Next;
}
}
}
Next:;
}
}
I honestly don't know if this is the real reason, but I think something that makes more sense is to think about it from the standpoint of a compiler implementer.
Large portions of compilers are built by automated tools that analyze special classes of grammars. It seems very natural that useful grammars would allow for empty statements. It seems like unnecessary work to detect such an "error" when it doesn't change the semantics of your code. The empty statement won't do anything, as the compiler won't generate code for those statements.
It seems to me that this is just a result of "Don't fix something that isn't broken"...
Obviously, it is so that we can say things like
for (;;) {
// stuff
}
Who could live without that?
When using ;, please also be aware about one thing. This is ok:
a ? b() : c();
However this won't compile:
a ? b() : ; ;
There are already many good answers but have not seen the productive-environment sample.
Here is FreeBSD's implementation of strlen:
size_t
strlen(const char *str)
{
const char *s;
for (s = str; *s; ++s)
;
return (s - str);
}
The most common case is probably
int i = 0;
for (/* empty */; i != 10; ++i) {
if (x[i].bad) break;
}
if (i != 10) {
/* panic */
}
while (1) {
; /* do nothing */
}
There are times when you want to sit and do nothing. An event/interrupt driven embedded application or when you don't want a function to exit such as when setting up threads and waiting for the first context switch.
example:
http://lxr.linux.no/linux+v2.6.29/arch/m68k/mac/misc.c#L523