I came across a statement which I didn’t understand. Can anyone explain me please.
It is a C++ program to sort data.
#define PRINT(DATA,N) for(int i=0; i<N; i++) { cout<<"["<<i<<"]"<<DATA[i]<<endl; } cout<<endl;
And also when I tried to rearrange the statement in the below format,I got compilation error!
#define PRINT(DATA,N)
for(int i=0; i<N; i++)
{
cout<<"["<<i<<"]"<<DATA[i]<<endl;
}
cout<<endl;
It's a macro, each time you write PRINT(DATA,N) the pre-processor will substitute it for the entire for loop, including the variables.
You're missing \ signs at the end of each line. This tells it the Macro continues to the next line. (Look at Multi-statement Macros in C++
If you use macro, use brackets around any variables (DATA) and (N). The substitution is literal and this will allow usages like PRINT(data, x+1) which otherwise cause unexpected results.
Don't use macro unless you REALLY must, there are many problems that can arise from this, it doesn't have a scope and so on. You can write an inline method or use std::copy_n like Nawaz proposed
It can be used if you properly define it. But .... just because it can be used, does not mean that it should be used.
Use std::copy_n:
std::copy_n(data, n, std::stream_iterator<X>(std::cout, " "));
That will print all the n items from data to the stdout, each separated by a space. Note that in the above code, X is the type of data[i].
Or write a proper function (not macro) to print in your own defined format. Preferably a function template with begin and end as function parameters. Have a look at how algorithms from the Standard library work and are implemented. That will help you to come up with a good generic design of your code. Explore and experiment with the library generic functions!
This isn't something you want to use a macro for.
Write a template function that does the exact same thing:
template<typename T>
void PRINT(const T &data, size_t n){
for (size_t i=0;i<n;++i)
cout << "["<<i<<"]"<<data[i]<<endl;
}
You should really avoid using macros. The only reason I find you NEED macros is when you need to use the name of the input (as string), or location (LINE or FILE) e.g.:
#define OUT(x) #x<<"="<<x<<"; "
#define DEB std::cerr<<"In "<<__FILE__<<":"<<__LINE__<<": "
for use in printing like this:
DEB << OUT(i)<<OUT(val[i])<<OUT(some_func(val[i],3))<<endl;
Which will print
In file.cc:153: i=4; val[i]=10; some_func(val[i],3)=4.32;
This is a functionality you can't do without macros. Anything you CAN do without macros you SHOULD
Related
I'm trying to define macros to read and print matrices in C++, but I'm trying something different, and it's not working:
#define rm(A, m, n, type)
for(int i = 0; i < m; i++)
for(int j = 0; j < n; j++)
scanf("%##type##", &A[i][j]);
A is the matrix (int or char)
I want to write d or c to read int or char, but this code isn't working and I don't even know why, I just tried to use the concat ## symbol to create the string that scanf receive as argument, but it bugs.
My questions are:
1 - why is it wrong?
2 - how can I make this macro work fine?
(if necessary, the solution may contain 1 or 2 macro declarations, but short ones, otherwise I wouldn't ask and I could just create a macro for int and other for char.
PS: this macro is written one line, the algorithm above is just to show what it does.
Thanks
If you really must make a macro for this - which, as others have pointed out, is a Really Bad Idea and Not The Right Way To Do This - the issue that you're encountering is that macros are interpreted by the preprocessor, which treats line breaks as as the end of a macro replacement. To fix this, you'll need to introduce some escape sequences at the ends of the lines:
#define rm(A, m, n, type) \
for(int i = 0; i < m; i++) \
for(int j = 0; j < n; j++) \
scanf("%" #type, &A[i][j]);
Notice that I've factored out your use of the token-pasting operator from the inside of the string, since the preprocessor doesn't fill in string literals for you, and instead opted to use the stringizing operator # to convert the type to a string literal. Since the compiler automatically concatenates adjacent string literals together, there's no need to paste anything. I should repeat that this is a really bad idea in that it hurts code readability and doesn't offer anything you can't already do with a regular C++ function.
You've tagged this question as C++, though, so I should point out that scanf has all sorts of type safety issues that can come up, so it's almost certainly safer to use the iostream library, which for all its faults does catch a ton of possible errors at compile-time.
Fundamentally, though, you shouldn't use macros for this. Just write a regular old function. Here's one way to do this, which has the added benefit that it automatically infers the sizes of arrays:
template <typename T, size_t m, size_t n>
void readArray(T (&array)[m][n], std::istream& source = std::cin) {
for (size_t i = 0; i < m; i++) {
for (size_t j = 0; j < n; j++) {
source >> array[i][j];
}
}
}
Now, you can say something like this:
double arr[137][42];
readArray(arr);
to read an array of doubles from cin, or
int arr[5][5];
ifstream input("my-file.txt");
readArray(arr, input);
to read an array of ints from an external file. This is type-safe and will raise a compiler error if you try reading in a case where the array size isn't defined or where the type can't be read. This prevents all sorts of possible problems. Compare this with your macro, where I could do something like this:
int arr[5][5];
rm(arr, 6, 6, f);
Oops - I just used the wrong array size and the wrong scanf specifier. Any time you can offload work to the compiler that saves you from having to make code changes across lots of places, it's worth considering!
I have this snippet of C++ code from an exam. We are just suppose to write out what the output of the program is, I assumed the output would be '20', but the output is '10'. Why is this?
#define func(x) (x*x)-x
int i=3;
int main() {
cout << func(i+2) << endl;
}
If I put the i+2 in brackets like so:
cout << func( (i+2) ) << endl;
The output is '20' as assumed it would be.
How does C++ process this code that makes it return 10 not 20?
That's just how macros work. It's pure text substitution. So func(i+2) expands as:
(i+2*i+2)-i+2
which is to say:
2*i + 4
This is why typically macros would be written by excessively parenthesizing the arguments:
#define func(x) (((x)*(x))-(x))
But really, this is why you should strongly prefer functions to macros. While parenthesizing the arguments would fix the usage in func(i+2), it still wouldn't fix the usage in func(++i) - which while being a straightforward expression if func were a function is undefined behavior with the macro.
Because the brackets aren't there.
The macro expands to
(i+2*i+2)-i+2
And it all goes wrong from there. An inline function instead of a macro would just work.
Lessons to be learned: (1) Always parenthesise inside macro definitions. (2) DON'T USE MACROS IN C++!
In java you can do something like:
Scanner sc = new Scanner(System.in);
int total = 0;
for(int i = 0; i<something;i++){
total+=sc.nextInt(); // <<< Doesn't require an extra variable
}
And my question is: can you do something similar in C or C++ ? and if there is, is it better?
This is what I currently do:
int total;
int aux; // <<< Need an extra variable to read input
for(int i = 0; i<something;i++){
scanf("%d",&aux);
total+=aux; // <<< and add the read value here
}
The obvious way to do it in C++ would be something like this:
int total = std::accumulate(std::istream_iterator<int>(std::cin),
std::istream_iterator<int>(),
0);
As it stands, this reads all the ints it can from the input file rather than requiring a separate specification of the number of input values. You could specify an N if you wanted to badly enough, but at least in my experience, you're not very likely to want that.
If you really want to specify N directly, the cleanest way to handle the situation would probably be to define an accumulate_n that works about like std::accumulate:
template <class InIt, class T>
T accumulate_n(InIt in, size_t n, T init) {
for (size_t i=0; i<n; i++)
init += *in++;
return init;
}
You'd use this about like the previous version, but (obviously enough) specifying the number of values to read:
int total = accumulate_n(std::istream_iterator<int>(std::cin),
something,
0);
I suppose I should add that (especially for production code) you'd probably want to add some constraints on the template parameters in the accumulate_n definition above. I also haven't tried to do anything about the possibility of bad input, such as containing something other than a number, or simply containing fewer items than specified. These can be dealt with, but offhand I don't remember how Java deals with them; I'd probably have to do some thinking/research to find/figure out exactly what reaction to such problems would be most appropriate.
Reading a number of variables from an input stream in c++ usually looks like follows (regarding your sample):
int total = 0;
int aux;
while(std::cin >> aux) {
// break on 'something' condition
total += aux;
}
So, I don't see a way how to do it without an auxiliary variable, that actually receives the value read from the std::istream, unless you provide a wrapper class yourself, that just provides that java like behavior.
"can you do something similar in C or C++ ? and if there is, is it better?"
I doubt it's worth to write such wrapper class for std::istream in c++ (You can just consider to use the std::accumulate() algorithm as mentioned in #JerryCoffin's answer).
For c language, there's no alternate choice, I actually can see/know about.
I would like to print : table_name[variable_value]
by giving ONE input : table_name[variable_name]
Let me explain a simpler case with a toy solution based on a macro:
int i = 1771;
I can print the variable_name with
#define toy_solution(x) cout << #x ;
If I execute
toy_solution(i);
"i" will be printed.
Now, imagine there is a well-allocated table T.
I would like to write in the program:
solution(T[i]);
and to read on the screen "T[1771]".
An ideal solution would treat the two cases, that is :
ideal_solution(i) would print i.
ideal_solution(T[i]) would print T[1771].
It is not important to me to use a macro or a function.
Thanks for your help.
#define toy_solution(x, i) cout << #x << "[" << i << "]"
I would like to print : table_name[variable_value]
by giving ONE input : table_name[variable_name]
well, as you did not understand my comment, I'll say out loud in an answer:
what you want to do is not possible
You have to choose between either #Alin's solution or #lizusek.
I think that #lizusek's solution is better because you're writing C++ code, so if you can do something that gives the same result than with using macros, you should use plain C++ code.
edit: let my try to explain why this is not possible
so what you want is:
f(T[i]) -> T, i
The only way you could write that so it would make sense in preprocessor is:
#define f(T[i]) cout<<#T#<<#i#
but then the preprocessor will give an error, because you can't index an array as a function (even a macro function) parameter:
test.c:5:12: error: expected comma in macro parameter list
#define f(T[i]) cout<<#T#<<#i#
^
If you try to do the same thing using a C++ function, then it's even more non-sense, as a function call such as:
toy_solution(t[i]);
would actually be translated to the value t[i] points to at runtime, so inside the function you'll never be able to known that the given value was actually in an array. So what you want is wrong, and you should stick to good coding practices: using a function and if what you want is:
toy_solution(t[i]);
then use:
toy_solution("t", i);
Possible solutions that you should never use
well, when I say it's not possible, it's that the only solutions I can think off are so twisted that you'd be insane to actually use them in your code… And if you do, I hope I'll never read one of your code or I may become violent :-) That's why I won't show you how or give you any code that could help do what I'm about to tell you.
use a template system
You could either write your code using your own template system or use one commonly used for HTML processing to process your source code through it and apply a transformation rule such as:
toy_solution(t[i]) -> toy_solution("t", t[i])
it's definitely possible, but it makes your build chain even more complicated and dependant on more tools. C/C++ build toolchain are complicated enough, please don't make it worst.
Or you code make your own fork of C and of a C compiler to change the syntax rules so what you want becomes possible. Though, I personnally would never use your fork, and then I'd go trolling and flaming about this on HN, deeply regretting to have given you such a bad idea :-)
use a custom class to encapsulate your arrays in
if you do something like:
template<T>
class Element {
T value;
List<T> _owner;
[…]
}
template<T>
class List {
Element<T> values[];
std::string _name;
[…]
}
so that when you call the function
toy_solution(T[i]);
the implementation would look like:
void toy_solution(Element<T> e) {
std::cout<<e.get_list_name()<<" "<<e.get_value()<<std::endl;
}
but that's sooo much boilerplate and overhead just to avoid doing a simple function definition that does not look as nice as you dream of, that I find it really stupid to do so.
You can write a function as simple as that:
void solution( std::string const& t, int i) {
std::cout << t << "[" << i << "]";
}
usage:
int i = 1771;
solution( "T", i);
You can also write a macro, but be aware that this is not type safe. Function should be preferred.
For some kinds of programs I need to use a constant high value to indicate some properties of some variables. I mean let color[i] = 1000000; if the i node in a tree is unexplored. But I quite often miswrite the number of 0s at the end, so I just wondered whether is it better to do it this way:
#define UNEXPLORED 1000000;
color[i] = UNEXPLORED;
I remember that somewhere I have read that it's much better to avoid using #define. Is it right? How would you tackle this problem?
For simple constants, you can use either const or the new constexpr:
constexpr unsigned int UNEXPLORED = 1000000;
In a case like this, it's no difference between using const and constexpr. However, "variables" marked constexpr are evaluated at compile-time and not at run-time, and may be used in places that otherwise only accepts literals.
For example use constants.
const unsigned int UNEXPLORED = 1000000;
or enums
enum { UNEXPLORED = 1000000 };
In the use of constants the two answers above are correct, however #define is not limited to that use alone. Another example of the use of #define is macros.
Macros
Macros are preprocessor-utilised pieces of code, and they work exactly like other #define declarations in that regard. The preprocessor will literally swap out the occurrence of your defined symbol with the code of the macro. An example:
#define HELLO_MAC do{ std::cout << "Hello World" << std::endl; }while(false)
int main(int argc, char** argv)
{
HELLO_MAC;
}
That will literally swap out the HELLO_MAC symbol with the code I declared. If it were a constant it would do the exact same thing. So you can think of #defines for constants as a particular kind of macro.
With macros you can also pass parameters, and it is especially useful I find for enforcing logging/exception policies over code.
For example
#define THROW_EXCEPT( ex_type, ex_msg ) /
do{ throw ex_type( buildExString( (ex_msg), __LINE__, __FILE__ ) ); }while(false)
...
// somewhere else
THROW_EXCEPT( std::runtime_error, "Unsupported operation in current state" );
That code allows me to ensure that everyone logs with the line of the file that threw the exception.
Templates are often a better choice instead of macros, but I cannot use template functions for this example because I need to use the __LINE__ and __FILE__ functions from the place of the throw, not from the location of the template function.
Where should you not use macros? Anywhere you can use something else. Macros, like any #define are preprocessed, so the compiler does not see them at all. This means that there is never any symbols created for HELLO_MAC or THROW_EXCEPT, and so they cannot be seen in a debugger. They can also be confusing if you get compile errors, especially if they are long macros.