tags:

views:

251

answers:

6

After trying to make a while(bool) loop and it failing because I couldn't see the contents of the vectors because there was nothing in them, I made a while(true) loop with the intention of breaking out if the user inputs a 0. Here are the important portions of the code.

Edit: Working code, but what does|= mean?

#include "std_lib_facilities.h"

class Name_pairs
{
public:
       vector<string>names;
       vector<double>ages;
       bool test();
       string read_names();
       double read_ages();
       void print();
};

string Name_pairs::read_names()
{
       string name;
     cout << "Enter name: ";
     cin >> name;
     names.push_back(name);
     return name;
}

double Name_pairs::read_ages()
{
     double age;
     cout << "Enter corresponding age: ";
     cin >> age;
     ages.push_back(age);
     cout << endl;
     return age;
}

void Name_pairs::print()
{
     for(int i = 0; i < (names.size()-1) && i < (ages.size()-1); ++i)
             cout << names[i] << " , " << ages[i] << endl;
}

bool Name_pairs::test()
{
   if(ages.empty() || names.empty()) return true;
   if(ages.back() = 0 || names.back() == "0"){
                          return false;}
   return true;
}


int main()
{
    Name_pairs np;
    cout << "Enter names and ages. Use 0 to cancel.\n";
    bool finished = false;
    while(!finished){
    finished |= "0" == np.read_names();
    finished |= 0 == np.read_ages();}        
    np.print();
    keep_window_open();
}
+3  A: 

Well you could simply make each function return a bool, then in the loop check if the function returned false. If so break.

You could also throw an error from within the functions, catch it externally and handle it appropriately but I think this is a little extreme. I get the impression you are just looking for an 'exit code' type thing. If this is the case I would suggest simply returning a bool and checking whether you should break out of the loop.

Edit: So your updated code seems a little complicated, but this is what I was getting at as far as returning a bool goes:

void Name_pairs::read_names()
{
    cout << "Enter name: ";
    cin >> name;
    names.push_back(name);
}

bool Name_pairs::read_ages()
{
    cout << "Enter corresponding age: ";
    cin >> age;

    if ( age == 0 )
     return false;
    ages.push_back(age);
    cout << endl;
    return true;
}

// Now we can test if its time to break.
while ( true )
{
    np.read_names();
    if ( !np.read_ages() )
     break;
}
DeusAduro
I tried this but it's harder than it looks. I"ll post the code I used before.
trikker
If you must do something at least once, consider using a `do..while()` loop. That's what they're there for.
Greg D
A: 

You can have the functions return a value then check the value and break if necessary.

You could also just check the value that's been read in after you call the functions. In this case, it looks like doing if(names.back() == "something") or if(ages.back() == 0) would work.

EDIT:

Your general idea is fine(running test() on every iteration of the loop which returns false if your exit condition is met), but there are a couple implementation errors:

   if(ages[bool_counter] = 0 || names[bool_counter] == "0")

You need "==" instead of "=" for the first condition. I bet your compiler warned you about this, you should generally listen to his warnings :). Your current statement is assigning 0 to ages[0] not checking it for being 0.

You should also check the size before attempting to dereference the first element, or you will, as you noted, get errors if ages or names are empty.

So changing that to

 if( (ages.size() > 0 ) && (ages.back() == 0)) ||
     (names.size() > 0) && (names.back() == "0"))

Should work, though I prefer deus's response for clarity.

Falaina
It doesn't unless there are objects in the vectors before the loop occurs.
trikker
The assignment operator wasn't like that when implemented, I just had to rewrite the code real quick and copy and paste it because I deleted it. I tried deus's but I'm getting could not convert to bool. I"ll post the code.
trikker
A: 

You could explicitly check in test() if ages/names are empty, and only do the "real" check if they are not:

bool Name_pairs::test() {
    if (ages.empty() || names.empty())
      return true;
    return (ages.back() != 0) && (names.back() != "0");
}
sth
I really like this. However, the output is producing 0 for the ages. Not sure why.
trikker
The output of zero for the ages is because you have `ages[bool_counter] = 0` in your `test()` function. That's an assignment of 0 where you wanted the comparison `ages[bool_counter] == 0`.
sth
+1  A: 

If you change the problem and view it upside down it becomes quite simple.

Change your setter methods to actually return the value that was just entered. I also made age a local variable of the method to prevent side effects from creeping :

Double Name_pairs::read_ages()
{
     Double age;
     cout << "Enter corresponding age: ";
     cin >> age;
     ages.push_back(age);
     cout << endl;
     return age;
}

Then in the loop you can test directly for the returned value :

 bool finished = false;
 while(!finished)
 {
   finished = finished || "0" == np.read_names();
   finished = finished || 0 == np.read_ages();
 }

Since you are setting your exit condition in the main (type 0 to exit) it is preferable to test the exit condition there for consistency.

Is how I see it anyway... code is shorter and easier to understand


Edit I changed the code to reflects comments aem. This way the correct logical operator is used. As for the cascading evaluation it is quite true that if the first answer was 0 then the second question will not even be asked (finished evaluated to true thus the rest of the or statement will not be evaluated) and as such you must be careful of this (if for example you expect both Vectors to always have the same length). However I found that usability wise since the user already stated that he wanted to exit I saw no use in asking him the other question.

Newtopian
I want to try this, but what's this |= operator you're using? I've never seen it.
trikker
This worked! But what does |= do?
trikker
`finished |= condition` is equivalent of `finished = finished | (condition)` If the expressions are lazily evaluated (as in C#) then if finshed is already true the `condition` won't be evaluated. i.e. if np.read_names() == "0" then np.read_ages() won't be called.
David McEwing
Alright thanks.
trikker
|= is a *bitwise* operator, but what you want is *boolean* operations. Given that you know finished is false at the start of the loop body, you can simply write:finished = "0" == np.read_names() || 0 == np.read_ages();
aem
Actually you'd have to separate the two checks rather than using a logical OR, or else the last valid entry isn't output. But I get what you're saying, I actually changed the code to that since I think it's easier to understand.
trikker
True, thanks for the bitwise I will edit the answer to better reflect this
Newtopian
A: 

"Break a loop when outside of it?" - this question doesn't make sense. If you're outside the loop, there's no need to break out of it, because you're already outside of it.

I suggest reading up on the basics, specifically "sequence" which is a shared common point of these types of languages. http://javascript.about.com/library/blstruc1.htm

Then you can go on with loops - it's linked on the same page.

Now, this link describes Javascript, but the logic is essentially the same, and the coding style hardly differ at all from other C-type languages.

Jonny
....I don't think you even read the program. You're calling a function from inside the loop. And you want to break using that function.
trikker
A: 

a |= b is a shorthand for a = a | b. If either a or b is true, then a is true at the end.

Dave Gamble