-1

Given the head of linked list, when walking through a linked list to calculate the size of the list, the common way to do it may be

ListNode* curr = head;
int count = 0;
while(curr) {
    curr = curr->next;
    count++;
}

But I also saw people do this:

ListNode* curr = head;
int count = 0;
while(curr = curr->next) {
    count++;
}

I recall that in parsing string, we often do

stringstream content(intputStr);
string outputStr;
while(content >> outputStr) {
    ...
}

I am wondering can I always condition my while() on the execution of a line of code (e.x. in this topic, condition on curr = curr->next)? If not, what are the edge cases? And is this a good practice?

Thanks

John Tan
  • 147
  • 1
  • 9

3 Answers3

2

In C++, operators can have return values just like functions. Whether you can use an expression as a conditional entirely depends on what they return. For that, you'll have to consult the documentation.

In an assignment: a = b, the default behavior is to return whatever the value of b is; this is so that chain assignments like a = b = c = 5 would work.

That expression would be equivalent to a = (b = (c = 5)). c = 5 will return 5, the expression becomes a = (b = 5), and b = 5 returns 5, and so once again, the expression becomes a = 5, thus assigning 5 to a, b, and c.

A stream object can be directly evaluated as a bool because it was designed to do so via the overridden bool operator.

In the case of a >> operator on a stream object, that operator is overridden to return the stream object, so in something like: while (cin >> userInput), cin >> userInput returns cin, which will yield either true or false.

Is this good practice?

I'm still a university student, so grains of salt needs to be taken with this. In the case of a stream, I'd say it's good practice as this is a well known pattern to do things. Most people can tell what you intend to do straightaway whereas alternatives aren't as clear.

As for the assignment, I'm leaning towards no, but it depends on who's reading your code and what you're doing. If you use it too much, it may become hard to differentiate between things like if (userInput = 5) and if (userInput == 5), making bugs hard to find.

Alex
  • 3,111
  • 6
  • 27
  • 43
1

The basic concept is that the expression inside the while loop must be convertible to a bool.

The curr = curr->next expression returns the left hand side of the expression by reference (see chained assignments). And the left hand side of the expression is a pointer, which is convertible to a boolean. If the pointer is equal to nullptr then the converted boolean value will be a false, otherwise it will be a true.

The expression content >> outputStr returns a reference to the content stream. That is the reason why you can chain the >> operator like so

cin >> a >> b;

cin >> a returns a reference to the cin object, therefore the evaluation of the expression works like this

cin >> a;
cin >> b;

And the cin object has a member function defined that allows it to be convertible to a boolean expression (http://en.cppreference.com/w/cpp/io/basic_ios/operator_bool), so you can do something like this

cin >> a;
cout << "cin has failed (true/false) : " << std::boolalpha << static_cast<bool>(cin) << endl;
// static_cast<bool>(cin) is the same as cin.(operator bool()) 
// if that syntax exists

That converts the cin object to a boolean expression with the operator bool() method. Something in a boolean expression like in an if() statement or a while() gets converted to a boolean.

I am wondering can I always condition my while() on the execution of a line of code (e.x. in this topic, condition on curr = curr->next)? If not, what are the edge cases? And is this a good practice?

You can do so if the expression is convertible to a bool, and in many cases embedding the expression in a loop is an idiomatic use of the "conversion to bool" feature. The edge cases depend on the implementation details of the expression.

Community
  • 1
  • 1
Curious
  • 20,870
  • 8
  • 61
  • 146
0

Your example is a little twisted, but as for your question:

can I always condition my while() on the execution of a line of code (e.x. in this topic, condition on curr = curr->next)? If not, what are the edge cases?

The condition in a while can be any expression that's implicitly convertible to bool. In your example, "curr = curr->next" evaluates to a pointer, which fits this requirement.

And is this a good practice?

Code that doesn't confuse you is good practice.

Drew Dormann
  • 59,987
  • 13
  • 123
  • 180