I write a lot of code like this
int x = 0;
//in some loop
x++;
if (x > 10) {
x = 0;
//call some function
}
How could I extract this into a function, or a macro, where I can combine the decrementing (or incrementing), the value to exceed (or go under), the reset value (0 in this case) and the function call?
EDIT:
I'd love to do something like (pseudocode)
cycle_counter(x, ++, <10, 0, myfunc);
#define SATURATE_ADD(x, max, inc, reset) ((x) = (x) > (max) ? (reset) : (x) + (inc))
and in your example:
int x = 0;
SATURATE_ADD(x, 10, 1, 0);
And if you want to call some function, just add a function parameter that you will call in your macro.
I tried to create a function to solve the problem similar to the function in pseudocode
void cycle_counter(int *px, char operatorr, int max, int init, void (*p)())
{
*px=init;
//in some loop
operatorr?(*px)++:(*px)--; //if the operator is 0 we usee -- otherwise ++
((*px)>max)?((*px)=0,p()):0; // This line replaces the if statement in your
// code and the callback
}
so here we have used the pointer named px which is pointing to x so it can keep the changes
The operator operatorr is a boolean which takes the value 0 for -- and ++ otherwise
max is an integer that will be provided for comparison. In your example it will be 10
init is for the initialisation of the integer pointed by the pointer px
Finally p refers to a pointer to function
Now if you want to call this function in the main function you will proceed like that
cycle_counter(px, 1, 10, 0, myfunc);
with px is
int x;
int *px=&x;
There are some exceptions not treated but I've jsut tried to make the difficult part which treats the pointers to functions. The other part (not done > and >=) is easy you can make the ternary operator even more complicated to handle all the cases but you will probably get a lovely line which can be considered as an obfuscated line ;)
Related
How could I achieve something like this ...
int main(void)
{
if (f(x) == (a || b))
{
puts("Success");
}
return (0);
}
This would print Success if the return of f(x) is equal to a or b.
I know it is possible to store it in a variable but my question is:
"Could something like this be done by calling the f(x) function only once without using a variable?"
Edit 1: I'm not allowed to use the switch statement for this assignment
Edit 2: Could I set a range with only one expression like this?
if ( 2 < f(x) < 5)
Would this be valid (return type is int)?
how to test for multiple return values from a function called once without storing into a variable (?)
Not really, but with some restrictions let us abuse C and assume a, b and f() return a character.
1Form a character array made up of a and b and search it using memchr(). Inspired by #David C. Rankin (It does not store the result of f() in a variable, but does call a function)
int main(void) {
// v-------------v compound literal
if (memchr((char [2]){a,b}, f(x), 2)) {
puts("Success");
}
return 0;
}
I see OP added "return type is int" - Oh well.
if ( 2 < f(x) < 5) is valid code, but is does not do what OP wants.
It is like if ( (2 < f(x)) < 5) which compares f(x) with 2 and results in 0 or 1, which is always less than 5.
Tough crowd tonight, so how about the below. Needs a bit of extension math for int overflow`, but is close.
abs(2*f(x) - (a+b)) == abs(a-b)
1 Not serious code suggestions for production code - use a temporary.
This can obviously be done using a switch statement. Another way would be calling a function returning true or false with the first function value as input, another way could be a jump table or even > or bit checking using binary operators depending on a and b values (very common for testing multiple bit flags at once).
But really you shouldn't care about using or not using a variable in such cases. Current compilers are quite good putting temporary variables like that in registers.
EDIT: given the constraints, the most likely solution is using some bit fu, but it fully depends of values of a and b and c, etc. The common way is using powers of two as values to check. Then you can check a set of values in only one operation.
exemple: a = 1, b = 2, c = 4
if (f(x) & (1+2+4)) {...}
checks if we have a or b or c or a superposition of these values.
C language does not such constructs. You need do save the result of the function or/and both a & b.
Of course you can:
int compare(int a, int b, int f)
{
if(a == f || b == f) { puts("Success"); return 0;}
return -1;
}
int f(int x)
{
return x * x;;
}
int main()
{
compare(5,8,f(3));
}
but of course it saves all the values as the functions parameters.
I just started programming in C, and while practicing with for loops, I came up with the following piece of code:
#include <stdio.h>
int main()
{
int x;
for (x=0;x=10;x=x+1)
printf("%d\n",x);
return 0;
}
When I run the code, I fall into an infinite loop. In my C manual it says that the condition x =10 is always true, but I can't get my head around it. If I give the variable x a value of 0 at the beginning, should the for loop not even start, or when the value of x reaches 10, shouldn't the loop stop?
Thanks in advance!
The condition part of your for loop is wrong. What you are doing is :
for (x = 0; x = 10; x = x +1) {
// Operations
}
The condition you have got here is x = 10 which is an affectation. So x = 10 will return 10, which also means true. Your for loop is equivalent to :
for (x = 0; true; x = x + 1) {
// Operations
}
This is why you have got an infinite loop, you should replace the affectation operator = by the comparason one with two equals sign ==. This means the for will loop while x is equals to 10.
EDIT : As Virgile mentioned in comments, for the second for loop, x will go from 0 to INT_MAX, then the behavior is undefined. So, your code is more likely to look like :
for (x = 0; true; x = 10) {
// Operations
}
When entering a for loop, the initialization part is performed first. So after the loop initialization x is 0.
Before entering the body of the loop, even the first time, the condition is checked. The "condition" in this case does not compare x to 10 but sets it to 10 since you are using = instead of ==.
Since an assignment as an expression has the value of the variable after assignment, the conditional expression has a value of 10 since that is what was assigned to x. Because this value is non-zero, it evaluates to true, and always will.
The problem here is, Take a close look on the condition part(2), in this what x=10, means is it is just assigning the value 10 to x, and it returns "True" always, so no problem what you have incrementing, it comes to 10 always, Thus infinite loop.
What you are trying to do is, you are implicitly converting int to bool in this line:
for (x=0;x=10;x=x+1)
^^^^
here, x=10; results true
So, it prints 10 everytime as you are using the = assignment operator.
for(int x=0;true;x=x+1)
What you could do to maintain the loop?
Use relational operators:
for (x=0;x!=10;x=x+1)
for (x=0;x==10;x=x+1)
for (x=0;x<10;x=x+1)
int reverse(int);
void main()
{
int no =5;
reverse(no);
}
int reverse(int no)
{
if(no == 0)
return 0;
else
printf("%d",no);
reverse(no--);
}
This program goes in infinite loop.Why is that so? I am not able to get the desired ouput.
Desired output should be 5 4 3 2 1.Thank you in advance
In this recursive call:
reverse(no--);
You are passing the value of no--. Since this uses the postfix -- operator, this means "decrement no, then pass the original value of no into the recursive call to reverse." This causes infinite recursion, since you are constantly making a recursive call with reverse set to the same value.
To fix this, change this to read
reverse(no - 1);
Notice that there's no reason to decrement no here, since within the current recursive call you will never read no again. You can just pass the value of no - 1 into the function. In fact, you might want to in general avoid using -- in recursive calls, since it almost always indicates an error in the code.
Hope this helps!
You're using the post-decrement operator on no. That first gets the value of no and uses that as the value of the expression and then decrements no (still using the undecremented value as the value of the expression). You probably want to use --no or even just no - 1. (The former will modify no, whereas the latter will not, but it does not matter because no is not referenced after that point.)
Change:
reverse(no--);
to:
reverse(no-1);
no-- returns the original value before the decrement occurred. So this line will always call reverse(5). Hence, infinite loop.
n-- is post increment which first use n as argument of the function and then decrement n.
So n-- essentially does is
reverse(n);
n = n - 1;
What you want is --n
You are using post-decrement. First evaluates, then reduces value.
Change this:
reverse(no--);
to this:
return reverse(--no);
--no is pre-decrement. First decrease "no", then pass the value to reverse.
Note that I'm RETURNING the result value, you function always have to return an int, due to its declaration.
You want to do
int reverse(int);
int main()
{
int no =5;
reverse(no);
}
int reverse(int no)
{
if(no == 0)
return 0;
else
printf("%d",no);
return reverse(--no);
}
So that you're returning a number every time you call reverse and you decrement no before you use it.
I am really new to programming (I'm an electronics and comm. engineer) and I am not able to figure out why one program works and the other one doesn't.
I'd like to get a good understanding of recursive functions before going any further with my learning. I would appreciate any help regarding this.
I know the difference between the x++ and --x. But in this context of this program, I thought both of these programs should run the same way. But they don't.
void rec(int x)
{
if(x>0)
rec(x--);
printf("%d",x);
}
int main()
{
rec(4);
_getch();
} /*This doesn't work. And shows a stackoverflow */
void rec(int x)
{
if(x>0)
rec(--x);
printf("%d",x);
}
int main()
{
rec(4);
_getch();
} /*This gives a proper output as expected*/
/*The output is 00123*/
Thanks!
P.S: Forgive me if this is a trivial or stupid question, but I am stuck on this and I thought this is the best place I can look for help.
void rec(int x) {
if (x>0)
rec(x--);
printf("%d",x);
}
This will recurse forever (or at least until you exhaust your stack space). x-- means use the current value of xand then decrement it.
In other words, let's call rec with the parameter 20. That's greater than zero, so it will in turn call rec again with the current value of 20 then decrement x (but effectively after the call returns.
Hence you're forever calling rec with the value of 20, which is why you're blowing out your stack.
If you change x-- to --x, it decrements x before passing it to the function, hence it will go 20, 19, 18, ... 1, 0, at which point it will run back up the stack printing all those values.
If you had put a printf ("before: %d\n", x) before the if statement, you would have seen a lot of 20 lines output to the screen.
x-- calls the function with the old value of x (before decrement). So you will get an infinite recursion of it calling itself with the same value. --x calls the function with the new (decremented)) value of x, so it eventually hits the x > 0 condition.
Another way to investigate this is to do the following:
int a, b;
a = b = 1;
printf("--a: %d b--: %d\n", --a, b--); // Output is --a: 0 b--: 1
Why does the following code report an Lvalue required error?? And how can we write a macro that receives an array and the number of elements in the array as arguments and then print out the elements of the array??
#define arr(b) printf("%d",b++);\
printf("%d",b);
int main()
{
arr(5);
}
If you expand the macro, you get the following:
int main()
{
printf("%d",5++);
printf("%d",5);
}
You cannot postincrement the constant 5, so you get an error.
Remember, macros aren't functions. If you want it to act like a function, simply make a function:
void arr(int b) {
printf("%d",b++);
printf("%d",b);
}
Because part of that macro expands to 5++, which is not valid C. Consider using b+1 instead of b++.
The first l in lvalue stands for left.
Only left values can be assigned.
when you write x ++ you mean x = x + 1 (also you get a value from it).
So the problem is it does not make sense to write 5 = 5 + 1
maybe you would like to do this:
int x = 5;
arr(x);