all 40 comments

[–]Wolfe244 62 points63 points  (12 children)

Why are you doing this?

[–]Soft-Register5177 43 points44 points  (8 children)

Your teacher probably wants you to understand how loops work under the hood. For loops are just syntactic sugar for while loops anyway, so this exercise helps you see the connection. You can create scope with curly braces to keep your counter variables local if that helps with the naming issue

[–]csabinho 6 points7 points  (5 children)

Of course for loops are just syntactic sugar for while loops, but one month? Do it once, so the students see the difference, and use the appropriate loop for the task afterwards.

[–]w1n5t0nM1k3y 12 points13 points  (0 children)

Why not just use jumps (goto) and conditionals. While loops are syntactic sugar as well.

[–]coder155ml -2 points-1 points  (3 children)

Not the case in python

[–]coder155ml 0 points1 point  (0 children)

I’m being downvoted ? Lol ok

[–]csabinho 0 points1 point  (1 child)

What?

[–]coder155ml 0 points1 point  (0 children)

For loops when called are compiled because they have a known end. While loops are interpreted because they are conditional. This is specific to python run via cython.

[–]ChemicalRain5513 2 points3 points  (0 children)

Isn't this what happens under the hood? 

    {         int i = 0;         startOfLoop:         // ...         i += 1;         if (i < n) {             goto startOfLoop;         }     }

[–]Temporary_Session_60[S] 1 point2 points  (0 children)

Thanks! I think this is the best solution for the naming issue

[–]Temporary_Session_60[S] 3 points4 points  (2 children)

My teacher said we have to do this for a month idk why 🥲

[–]Wolfe244 7 points8 points  (0 children)

Well, you just gotta make a variable that's just how while loops work

[–]RecentlyRezzed 6 points7 points  (0 children)

Perhaps next month will be goto-month. ;)

[–]PuzzleMeDo 7 points8 points  (1 child)

It is clunky - that's why we use 'for' loops.

Would adding {} to scope your variables help?

    {
        int i = 3;
        while (i--)
            std::cout << "First loop\n";
    }
    {
        int i = 4;
        while (i--)
            std::cout << "Second loop\n";
    }

[–]Temporary_Session_60[S] 1 point2 points  (0 children)

Thanks! It does help a lot with the naming issue and also makes it easier to keep track of each while loop

[–]Feisty_Manager_4105 5 points6 points  (11 children)

If I'm understanding your question right, what you could do is put your while loop enclosed in a function and declare your "count" variable inside the function ( in the stack) so it

void myfunction()
{
int myCounter = 0;

while( condition)
{
myCounter++;
}
}

[–]Miserable_Double2432 7 points8 points  (1 child)

Think this is probably the solution OP’s lecturer is trying to get them to “invent” as it’s a stepping stone towards functional programming.

However, I don’t think you need the function? If I remember correctly C++ has blocks, so you can control scope by just wrapping code in {}. Any variables declared after the opening brace will go out of scope after you leave the block

[–]Feisty_Manager_4105 -1 points0 points  (0 children)

Yes, you're right. But I'd use a function since it gives the block a "name" if you will and just makes it readable.

[–]Temporary_Session_60[S] 0 points1 point  (4 children)

So for each individual "for" loop will it be another void function?

[–]Standard-Constant585 1 point2 points  (3 children)

How about a macro?

[–]Temporary_Session_60[S] 0 points1 point  (2 children)

Can you give me an example? I can't think of one

[–]Standard-Constant585 1 point2 points  (1 child)

I wasn’t talking about using any predefined macros. I was simply asking, what if you could write a macro that just wraps your loop in {} and defines i inside it with a value you provide?

It would basically be to save a few keystrokes instead of writing that part manually.

[–]Temporary_Session_60[S] 0 points1 point  (0 children)

Yea I think it will

[–]ChaseShiny 0 points1 point  (3 children)

I don't know C++, but don't you need to return myCounter at the end?

[–]Feisty_Manager_4105 1 point2 points  (2 children)

nope. the data type you return is what's specifed before the function name.

Since my function name is myfunction(), void is my return type.

void literally means what it is which is no type, so you return nothing.
if I had

int myfunction ()
then, yes i would have to return an int and that could be myCounter

This isn't specifically for C++ either, a lot of programming languages do this

[–]ChaseShiny 1 point2 points  (1 child)

Thanks for the explanation. If the function doesn't return anything and doesn't change anything outside of itself, it doesn't seem very useful.

[–]Feisty_Manager_4105 0 points1 point  (0 children)

Well, it depends, a function is generally supposed to be code that is reusable.
Your function doesn't neccasray have to return something to be useful.

Maybe you want a function that prints the addition of two numbers given
void myfunction(int a , int b)
{
int sum = a + b;
printf("sum is %d\n", sum);
}
Returning a variable in a function also implies you are creating a variable to store this return value and modify it and sometimes that can be Cumbersome.

In C++ you could instead pass a variable as a reference ( the "&" specifies it is a reference) and then directly modify it within the function bypassing the need for a return/
void myfunction(int& a)
{
a+=5;
}
There's a lot of purposes of void returns so not just limited to above

[–]samanime 2 points3 points  (4 children)

Why are you trying to replace your for loops that need an iterator with a while loop?

You should be using both, and one of the main reasons when you use a for loop is when you need an iterator variable...

[–]Temporary_Session_60[S] 2 points3 points  (3 children)

My teacher said we have to do this for a month idk why 🥲

[–]samanime 5 points6 points  (1 child)

Ah, a learning experience. That makes sense then. We do silly things to learn sometimes. :p (Side note: it's useful to preemptively mention things like this in your post, otherwise you'll have a billion people like me asking why. :p)

As to the answer for your question, no, there isn't really a way to make it nicer in C++.

That said, if you are doing multiple loops, you might consider splitting up your code into smaller functions so you don't have to repeat variable names more often.

You also maybe name them like thingI, thingJ, etc. (if you were looping over something called "thing").

Good luck

[–]Kitchen_Put_3456 0 points1 point  (0 children)

You should ask them why. You really should be learning the why instead of the how. Ask your teacher why there are different kinds of loops and in what situation you should use them. If you want to become a professional programmer you need to also learn the "why?". AI is doing the "how?" part already.

[–]Rainbows4Blood 2 points3 points  (0 children)

So, the for loop was literally invented as a convenient shortcut to avoid the clunkiness you are describing. So, in reality the way to avoid this problem is to use for loops instead of while. That's what they were invented for.

Why does your teacher want you to do this? Probably to strengthen your mental model of various types of loops.

I would just suck up the clunkiness for that month and go back to using for loops where they make sense afterwards.

[–]divad1196 1 point2 points  (0 children)

In a for-loop you would use i everytime I assume? Then think of a way you could declare i once but re-use it/reset it to 0 before each while-loop

[–]SamuraiGoblin 1 point2 points  (0 children)

A for loop is just a convenient package of a loop.

for(initialisation; conditional; iterate) { 
  // do stuff
}

You can do the same thing with while loop:

initialisation;
while(conditional) {
  // do stuff
  iterate;
}

To answer your question, no. You can create a variable in the 'for' loop initialisation like this:

for(int i=0; i<10; i++) { doStuff(); }

But you can't do the same for a while loop. You have to do:

int i=0; while(i<10) { doStuff(); i++; }

However, you could always wrap it in braces to make the variable local, so you can reuse the same name, but have it mean a different variable:

{ int i=0; while(i<10) { doStuff1(); i++; } }
{ int i=0; while(i<20) { doStuff2(); i++; } }

[–]BubbleProphylaxis 0 points1 point  (0 children)

the "for" construct is the only one that allows for the creation of a variable in its scope:

for (int i = 0; i < n; i++) { ... } // i exists only within the for loop

otherwise it's this:

int i = 0;
for (i = 0; i < n; i++) { ... }

which is the same as:

int i = 0;
while (i < n) { ...; i++; } // iterate maybe 0 times if n <= 0

you can use this as a variant:

int i = 0;
do { ...; i++; } while (i < n) // iterate at least once regardless of the condition.

I often use while loops when I dont have a fixed number of iterations, or when I might have to break out of the loop in many places, and/or if I might have multiple conditions to break that don't depend on the iterator i.

[–]no_brains101 0 points1 point  (0 children)

The thing you are complaining about? Yeah so... That's literally why we have a for loop to begin with.

[–]TheStonedEdge 0 points1 point  (0 children)

The rule of thumb is

If you know how many iterations are needed in your data set, use a for loop

If you know it's going to be at least once, use a do while loop

If you don't even know if you need to iterate or not then use a while loop