Why isn't my for loop triggering?

  • Thread starter Of Mike and Men
  • Start date
  • Tags
    Loop
In summary: They are not the same. In the initial version, the for loop is inside the while loop. In the new version, the for loop is outside the while loop.
  • #1
Of Mike and Men
54
3

Homework Statement


First of all, this ISN'T homework. This is independent study. I am in a CS program, but I am going through PPP by Bjarne Stroustrup to keep the language fresh. I'm working on one of the last assignment in chapter 4 which is this:

Write a program where you first enter a set of name·and·value pairs,
such as Joe 17 and Barbara 22. For each pair, add the name to a vector
called names and the number to a vector called scores (in corresponding
positions, so that if names[7]=="Joe" then scores[7]==17). Terminate
input by the line No more ("more" will make the attempt to read another
integer fail ). Check that each name is unique and terminate with an error
message if a name is entered twice. Write out all the (name,score) pairs,
one per line

I know my code isn't complete but I cannot get my for loop to run. I've ran various test cases, the while-loop is working, and it completes the full iteration of the while-loop. However, my for-loop never executes. It simply skips it (that is, code within the while-loop that appears before the for-loop and after the for-loop execute during each iteration). I.E. where hello1 and hello2 appear in the code, these execute fine.

Homework Equations

The Attempt at a Solution


[/B]
I'm pretty sure it has to do with my < sign in the for loop since <= will execute the for-loop but crash the program.

C:
#include <iostream>
#include <string>
#include <vector>
using namespace std;

int main() {
    vector<string> all_names;
    vector<int> all_scores;
 
    string names;
    int scores;
 
    while(cin>>names>>scores){
        cout << "hello1";
        for(int i = 0; i < all_names.size(); i++ ){
            if( all_names[i] == names ){
                cout << "duplicate name.";
            }
            else{
                all_names.push_back(names);
                all_scores.push_back(scores);
            }
        cout << "hello2";
        }
    }
    return 0;
}
However, if I keep the < sign and re-write the for-loop like this, it works. But I'm not seeing why... Since to me this code is essentially the same, just using an unnecessary flag.
C:
while(cin>>names>>scores){
       bool valid = true;
       for( int i = 0; i < all_names.size(); i++ ){
           if( all_names[i] == names ){
               valid = false;
           }
       }
       if(valid){
           all_names.push_back(names);
           all_scores.push_back(scores);
       }
       else{
           cout << "duplicate name";
       }
   }
 
Last edited:
Physics news on Phys.org
  • #2
C:
for(int i = 0; i < all_names.size(); i++ )
In the first iteration of your loop here, all_names is empty, so all_names.size() is zero. Since 0 is not less than 0, the test expression is false and the for loop exits. If you change the comparison to <=, 0 is less than or equal to itself, the body of the for loop is executed.

BTW, it's not considered good practice for a program to ask for input without prompting the user as to what to enter (e.g. cin >> names >> scores in your while loop. It's also better to input just a single variable at a time unless you're pulling data from a file.
 
  • #3
Mark44 said:
C:
for(int i = 0; i < all_names.size(); i++ )
In the first iteration of your loop here, all_names is empty, so all_names.size() is zero. Since 0 is not less than 0, the test expression is false and the for loop exits. If you change the comparison to <=, 0 is less than or equal to itself, the body of the for loop is executed.

BTW, it's not considered good practice for a program to ask for input without prompting the user as to what to enter (e.g. cin >> names >> scores in your while loop. It's also better to input just a single variable at a time unless you're pulling data from a file.

Thanks. I normally don't use input as the conditions of my loops, but it's what Stroustrup was doing, along with the double input.

When I change it to <= the program crashes. I forgot to mention that. :/
 
  • #4
Here's your new version (which you added after I replied earlier)
C:
while(cin>>names>>scores){
       bool valid = true;
       for( int i = 0; i < all_names.size(); i++ ){
           if( all_names[i] == names ){
               valid = false;
           }
       }
       if(valid){
           all_names.push_back(names);
           all_scores.push_back(scores);
       }
       else{
           cout << "duplicate name";
       }
   }
I don't think the valid variable is an unnecessary flag variable. The code above reads in a name and a score, and assumes that the name is valid (isn't a duplicate). The code then compares the entered name with each name in all_names. If it finds a match, the name is a duplicate, so the code sets the valid flag to false. The code adds the new name and score only if the name wasn't a duplicate.

In your earlier code, you were comparing all_names and names when the all_names vector was undefined at the index i.
 
  • #5
Mark44 said:
In your earlier code, you were comparing all_names and names when the all_names vector was undefined at the index i.

I guess I'm confused how these two portions of the code vary. Why does the for loop only get executed in code B, when the code in principle looks the same as code A?

Of course, the method of flagging it with a bool value varies, but nothing differs other than initializing 'valid' before the for-loop. That is, in my first example, it checks to see if it's a valid name by comparin. If it isn't a valid name, it skips it. If it is a valid name it inputs it. Then it should run the while-loop again.

It seems to me that if the for-loop in code 'A' doesn't run, then neither should it in code 'B'. If you remove the bool value, and the statements within the for-loop, the code is EXACTLY the same. In both examples it appears that the vector has nothing in it at the time of the for-loop.

Code A:
C:
    while(cin>>names>>scores){
        for(int i = 0; i < all_names.size(); i++ ){
            if( all_names[i] == names ){
                cout << "duplicate name.";
            }
Code B:
C:
while(cin>>names>>scores){
       bool valid = true;
       for( int i = 0; i < all_names.size(); i++ ){
           if( all_names[i] == names ){
               valid = false;
           }
 
  • #6
Of Mike and Men said:
I guess I'm confused how these two portions of the code vary. Why does the for loop only get executed in code B, when the code in principle looks the same as code A?

Of course, the method of flagging it with a bool value varies, but nothing differs other than initializing 'valid' before the for-loop. That is, in my first example, it checks to see if it's a valid name by comparin. If it isn't a valid name, it skips it. If it is a valid name it inputs it. Then it should run the while-loop again.

It seems to me that if the for-loop in code 'A' doesn't run, then neither should it in code 'B'. If you remove the bool value, and the statements within the for-loop, the code is EXACTLY the same. In both examples it appears that the vector has nothing in it at the time of the for-loop.

Code A:
C:
    while(cin>>names>>scores){
        for(int i = 0; i < all_names.size(); i++ ){
            if( all_names[i] == names ){
                cout << "duplicate name.";
            }
Code B:
C:
while(cin>>names>>scores){
       bool valid = true;
       for( int i = 0; i < all_names.size(); i++ ){
           if( all_names[i] == names ){
               valid = false;
           }
It's the rest of the while loop where the difference shows up.
 
  • #7
Those push_back statements shouldn't be inside the for loop. Only after the for loop is done and you have checked all the names in the list for a duplicate, you must add the name+score to the vectors exactly once.

Your first program adds the name+score more than once to the list if there's more than one name not equal to the new name in the list, and doesn't add any names if the list is empty. This is a design error.

You should have a high level description like this:

repeat while there are still names to read
read in a name + score
check if the name is already in the list
yes?
output error
no?
add the name+score to the list

If you implement this line by line the part for "check if the name is already in the list" and "add the name+score to the list" shouldn't be mixed.
You can either use a boolean variable, or implement "check if the name is already in the list" as a function with a boolean result.
 
  • #8
willem2 said:
Your first program adds the name+score more than once to the list if there's more than one name not equal to the new name in the list, and doesn't add any names if the list is empty. This is a design error.
Mark44 said:
It's the rest of the while loop where the difference shows up.

The first program doesn't even enter the for-loop once, so nothing is even entering the vector at all. It skips the for-loop entirely. That's why I'm confused. I know the implementation is different. But, I don't see why one should enter the for-loop and the other doesn't when there's no difference prior to the loop. I don't see why the contents of the loop makes any difference what-so-ever if it's not even entering it. For example:

C:
#include <iostream>
#include <string>
#include <vector>
using namespace std;

int main() {
    vector<string> all_names;
    vector<int> all_scores;

    string names;
    int scores;

    while(cin>>names>>scores){
        cout << "You're in the while-loop\n";
        if(all_names.size() == 0) {
            cout <<"all_names has 0 elements.\n";[
        }
        if(all_names.size() != 0) {
            for(string e : all_names) {
                cout << e << endl;
            }[/B]
        }
        for(int i = 0; i < all_names.size(); i++ ){
            cout << "You're now in the for-loop";
            if( all_names[i] == names){
                cout << "duplicate name.";
            }
            else{
                all_names.push_back(names);
                all_scores.push_back(scores);
                ;
            }
        cout << "You're out of the for-loop\n";
        }
    }
    return 0;

}

This is my I/O from the code above:
>>Name1 2
<<You're in the while-loop
<<all_names has 0 elements.
>>Name1 3
<<You're in the while-loop
<<all_names has 0 elements.
>>Name1 4
<<You're in the while-loop
<<all_names has 0 elements.

This is running the code ONCE. Note: The edits I made were on Lines 14-17, 24, and 33.

So based on my output, it's entering the while-loop, and runs all the lines right before the for-loop, but once it hits the for-loop it skips EVERYTHING else. Even the stuff that comes AFTER the for-loop. I don't see why it's not even ENTERING it to check the conditionals. If it's not being added to the vector, or being added to much to the vector, fine, it's something I can fix. But, it's not even reaching that part of the code. If I use the <= sign on my for-loop, it still doesn't enter the loop and the program crashes.

Maybe you guys are explaining it plain as day, but I'm not seeing it... at all. I can see the implementation is much different, but it still doesn't make sense why it's only repeating the first part of the while-loop and skipping the rest.
 
  • #9
Are you using a debugger? If you're not, you really should be.

Here's the relevant part of your code from post #8. I've edited it slightly, removing an extra left bracket and a closing bold tag.
C:
while(cin>>names>>scores){
        cout << "You're in the while-loop\n";
        if(all_names.size() == 0) {
            cout <<"all_names has 0 elements.\n";
         }
        if(all_names.size() != 0) {
            for(string e : all_names) {
                cout << e << endl;
            }
         }
        for(int i = 0; i < all_names.size(); i++ ){
            cout << "You're now in the for-loop";
            if( all_names[i] == names){
                cout << "duplicate name.";
            }
            else{
                all_names.push_back(names);
                all_scores.push_back(scores);
                ;
            }
        cout << "You're out of the for-loop\n";
        }
    }
First while loop iteration, with input of Name1 and 2
"You're in the while-loop\n" is printed.
First if block prints "all_names has 0 elements.\n"
Second if block does not execute.
For loop does not execute since all_names.size() is still 0, and 0 is not less than 0.

Second while loop iteration, with input of Name1 and 3
"You're in the while-loop\n" is printed.
First if block prints "all_names has 0 elements.\n"
Second if block does not execute.
For loop does not execute since all_names.size() is still 0, and 0 is not less than 0.

Third while loop iteration, with input of Name1 and 4
"You're in the while-loop\n" is printed.
First if block prints "all_names has 0 elements.\n"
Second if block does not execute.
For loop does not execute since all_names.size() is still 0, and 0 is not less than 0.

Etc.

At no time does the name get added to the all_names vector.
Of Mike and Men said:
So based on my output, it's entering the while-loop, and runs all the lines right before the for-loop, but once it hits the for-loop it skips EVERYTHING else.
The only statement after the for loop is the return statement.

Your indentation fooled you, but it didn't fool the compiler. The last output statement is actually the last statement in the for loop, but the way you have it indented, you apparently meant it to be just after the for loop. This is one reason I prefer to have my left and right braces aligned, rather than having the left brace on the same line is the for, if, while, etc. headers. That way it is abundantly clear exactly which code is part of a loop body or if/else body.

One other comment:
C:
 if(all_names.size() != 0) {
            for(string e : all_names) {
                cout << e << endl;
            }
         }
This really should be
C:
 else {
            for(string e : all_names) {
                cout << e << endl;
            }
         }
all_names.size() either is or isn't equal to 0. Your if statement already checks to see if the size is 0, so you don't need to check to see if it isn't 0. Just use else, as above.
 
  • #10
Mark44 said:
Are you using a debugger? If you're not, you really should be.

I am not. Do you have one that you recommend? I use DevC++ and CLion for C++ programming.

Mark44 said:
...
For loop does not execute since all_names.size() is still 0, and 0 is not less than 0.
...
etc.

At no time does the name get added to the all_names vector.

Oh. My. God. I think I see what you're saying now. *rolls eyes* smh. Haha.

In code 'b', it added the name to the vector after the for-loop since it didn't trigger a flag. Similarly I could just do a conditional statement before the for-loop saying (in pseudo) if 'i' is 0, then add it to the vector, else proceed to for-loop. In terms of efficiency it seems the same since a conditional gets checked through every loop in both codes.

This also explains why the <= is crashing since nothing will be in my vector at this time.

Mark44 said:
The only statement after the for loop is the return statement.

Your indentation fooled you, but it didn't fool the compiler. The last output statement is actually the last statement in the for loop, but the way you have it indented, you apparently meant it to be just after the for loop. This is one reason I prefer to have my left and right braces aligned, rather than having the left brace on the same line is the for, if, while, etc. headers. That way it is abundantly clear exactly which code is part of a loop body or if/else body.

Thanks for this comment. I've always included it on the first line because I felt like it made reading it flow smoother (and looked more aesthetic to me). However, I never come across blocks of code that have tripped be up like this. Initially I learned Python so indentation has always felt natural. But I can see why moving the curly brackets down would actually make it easier to read (and all this time I thought it looked ugly).

Thanks for your patience...
 
  • #11
Of Mike and Men said:
I am not. Do you have one that you recommend? I use DevC++ and CLion for C++ programming.
I've been using MSFT Visual Studio for a long time, and the Borland C++ compiler before that, so I'm not familiar with the two compilers you listed. Here's a link to something that might be helpful: https://studylib.net/doc/15537786/tutorial---debugging-in-dev-c---introduction.

If you do a web search for "dev-c++ debugger" you'll get a lot of hits.

I strongly recommend that you start using a debugger.
 

1. Why is my for loop not running at all?

There could be several reasons why your for loop is not running. Some possible causes include syntax errors in your code, incorrect variable initialization, or incorrect conditions in your for loop. Make sure to check your code for any mistakes and ensure that your loop conditions are properly set.

2. Why is my for loop running infinitely?

This issue is commonly caused by incorrect loop conditions. Check to make sure that your loop conditions will eventually evaluate to false, otherwise the loop will continue to run indefinitely. Additionally, make sure that your loop is properly incrementing or decrementing, otherwise it may never reach the end condition.

3. Why is my for loop only running once?

If your for loop is only running once, it is likely due to your loop conditions being set incorrectly. Make sure that your loop conditions are properly set to iterate through the desired number of times. Additionally, check that your loop is properly incrementing or decrementing to ensure that it will reach the end condition.

4. Why is my for loop not iterating through all the elements in my array?

If your for loop is not iterating through all the elements in your array, it is possible that your loop conditions are set incorrectly. Make sure that your loop is set to iterate through the entire length of the array. Additionally, check that your loop is properly incrementing or decrementing to ensure that it will reach the end condition.

5. Why is my for loop not working on my specific data?

In some cases, the issue may not be with your for loop, but rather with the data you are trying to loop through. Make sure that the data is in the correct format and that it is compatible with your loop logic. If needed, try debugging your loop to see where the issue is occurring with the specific data.

Similar threads

  • Engineering and Comp Sci Homework Help
Replies
3
Views
516
  • Engineering and Comp Sci Homework Help
Replies
8
Views
1K
  • Engineering and Comp Sci Homework Help
Replies
10
Views
1K
  • Engineering and Comp Sci Homework Help
Replies
24
Views
2K
  • Engineering and Comp Sci Homework Help
Replies
3
Views
2K
  • Programming and Computer Science
2
Replies
66
Views
4K
  • Engineering and Comp Sci Homework Help
Replies
3
Views
1K
  • Engineering and Comp Sci Homework Help
Replies
6
Views
2K
  • Engineering and Comp Sci Homework Help
Replies
2
Views
2K
  • Programming and Computer Science
Replies
2
Views
1K
Back
Top