2

I have the following section of code that I need to use about 5 times throughout the whole program, but with different lines of code in place of the comment.

while (loop_day < (day+1)) {
    while (loop_size < (size+1)) {

        //new lines here

        size = size + 1;
    }
    loop_day = loop_day + 1;
}

I could copy and paste this multiple times, but I really would rather not, for aesthetic reasons. I tried searching for "functions that could take in statements as arguments", but found nothing appropriate.

Edit: I want to "embed" various statements into the code.

An example:

while (loop_day < (day+1)) {
    while (loop_size < (size+1)) {

        // code that stores various values into an array

        size = size + 1;
    }
    loop_day = loop_day + 1;
}


while (loop_day < (day+1)) {
    while (loop_size < (size+1)) {

        // code that reads values stored in that array

        size = size + 1;
    }
    loop_day = loop_day + 1;
}

But I want something like this:

custom_loop {
// code that stores various values into an array
}

custom_loop {
// code that reads values stored in that array
}
pulpbag
  • 23
  • 5
  • maybe `inline` functions can help. – Ali Yılmaz May 08 '18 at 10:08
  • 1
    Two things to google: macros and function pointers. – Antti Haapala -- Слава Україні May 08 '18 at 10:08
  • 1
    What variables does `new lines here` depend on? – Bathsheba May 08 '18 at 10:09
  • 1
    please *complete* the code to show an example. – Antti Haapala -- Слава Україні May 08 '18 at 10:10
  • @Bathsheba Not variables, statements. But the statements make use of members of a struct. – pulpbag May 08 '18 at 10:36
  • 1
    Simply write a function. – Lundin May 08 '18 at 10:49
  • @Lundin How can I make the function take in statements as arguments? – pulpbag May 08 '18 at 11:16
  • Pass parameters telling the function what to do. There's no general answer, it is different from case to case basis. – Lundin May 08 '18 at 11:18
  • @Lundin Can I pass something like "a[loop_day][loop_size].forget = 0;"? – pulpbag May 08 '18 at 11:23
  • @pulpbag Not sure what that's supposed to mean, a function with 3 parameters? – Lundin May 08 '18 at 11:26
  • an example with a macro is given in: [Is it OK to use a code block as an argument for a C macro?](https://stackoverflow.com/questions/17182877/is-it-ok-to-use-a-code-block-as-an-argument-for-a-c-macro) – Lanting May 08 '18 at 11:53
  • @Lundin I mean multiple statements, like "a = 0;", "b = c", "a = a + 1" all at once. – pulpbag May 08 '18 at 12:18
  • This is all one big [XY problem](https://en.wikipedia.org/wiki/XY_problem). "Passing multiple statements" is most likely the wrong solution to the actual problem. – Lundin May 08 '18 at 12:37
  • @Lundin I am very aware that one might not be able to "pass statements" as arguments, I was merely asking for an equivalent to "passing statements". (Incidentally, could you describe your take on the problem?) – pulpbag May 08 '18 at 12:51
  • There is no equivalent because it doesn't make sense to begin with. Either you pass various numeric variables and do something with them, or you pass a state variable like an enum and do different things based on that, or you can pass a function pointer executing specific behavior etc etc. Or you can call different functions in the first place, sorting out the differences in the caller instead of inside the function. Try to describe and solve the actual problem instead of trying to figure out how to do really weird things. – Lundin May 08 '18 at 13:20
  • @Lundin I was never "trying" to "pass statements" into a function, I know that's not how it works. All I wanted was a way to avoid code duplication by having my "custom loop" placed inside something-like-a-function, so that I could call on it whenever needed, with the caveat being -> you need to do different things in the middle of the loop every time you call the loop: which you would have understood if you had read the examples I included. (I also fail to see how I could "describe ... the actual problem" any better then how I already have.) – pulpbag May 08 '18 at 13:52

2 Answers2

4

You can think of callback functions. For example,

typedef void (*t_func)(int, int);

void doLoopOverDaysAndSize(t_func callback)
{
    while (loop_day < (day+1)) {
        while (loop_size < (size+1)) {
            callback(loop_day, loop_size)
            size = size + 1;
        }
        loop_day = loop_day + 1;
    }
 }

Then you can pass some function like this

void myDaySizeHandler(int day, int size)
{
    // do something
}
rhaport
  • 540
  • 3
  • 11
  • Could you elaborate on how I may apply this to my situation? – pulpbag May 08 '18 at 13:07
  • basically, you implement once the function doLoopOverDaysAndSize() as stated above. Of course, the variables loop_day and loop_size should be correctly defined local variables. Also, you should care on how day and size are provided to the function. This should be clear from the context of your application. Then you implement various functions like myDaySizeHandler which should contain the body of the loop. It corresponds to your comment // code that reads values stored in that array. Then you can call doLoopOverDaysAndSize(myDaySizeHandler); – rhaport May 08 '18 at 13:32
  • @pulpbag You said you had a repeated chunk of code you want to wrap various code with. Callbacks (function pointers) are how to do that: you pass a function in and execute it in the code that wraps the "statements you want to pass in", which are in the function you pass to the loop. Just google for "callback functions", I mean, the code in the answer is pretty much a verbatim implementation: your statements go in `myDaySizeHandler`. – Dave Newton May 08 '18 at 15:11
-1

People tend to forget that includes can be used anywhere in your code and are not just useful for headers ( Including one C source file in another?). They are frowned upon by some, however.

Example:

common.inc:

x = x + 1;

main.c

int main()
{
    {
        int x = 3;
#include "common.inc"
        printf("x = %d\n", x);
    }
    {
        double x = 1.234;
#include "common.inc"
        printf("x = %f\n", x);
    }
    return 0;
}

-Edit- For your code this would result in:

commonStart.inc

while (loop_day < (day+1))
{
    while (loop_size < (size+1))
    {

commonEnd.inc

        size = size + 1;
    }
    loop_day = loop_day + 1;
}

main.c

#include "commonStart.inc"
//new lines here
#include "commonEnd.inc"
Lanting
  • 3,060
  • 12
  • 28
  • I fail to see how I can embed multiple statements within my aforementioned bit of code (a custom loop, if you will) using this. – pulpbag May 08 '18 at 12:23
  • It’d work, but this seems a weird thing to do when you have function pointers. And IMO it’s quite a bit more difficult to read or reason about. – Dave Newton May 08 '18 at 12:38
  • This would be the answer to the question: "how can I write code that's even worse than inventing some obscure, function-like macro language of my own". Never abuse includes like this, it is nothing but obfuscation and genuinely bad advise. – Lundin May 08 '18 at 13:23
  • "They are frowned upon by some, however." Here, by "some", do you mean "essentially everyone"? I'm struggling to come up with a valid usecase that isn't handled better by pointers or macros. Can you give an example where this would be a good idea? – Dave Newton May 08 '18 at 15:13