What is the use of "," in while loop condition c++? [duplicate] - c++

This question already has answers here:
comma separated expression in while loop in C
(5 answers)
How does the Comma Operator work
(9 answers)
Closed 5 years ago.
string command;
string bookName;
while (cin >> command, command != "END")
{...}
Here in while loop's condition, there is a comma.
I know that multiple conditions can be added using && or ||.
But why use ,?
Is there any certain benefits? Can you please explain the usage and syntax?

It's the comma operator, also known as the "evaluate and forget" operator. The effect of a, b is:
Evaluate a, including any side effects
Discard its value (i.e. do nothing with it)
Evaluate b
Use the result of b as the result of the entire expression a, b
The author of the loop wanted to express the following:
Read command from cin, and then enter the loop body unless command is equal to "END"
However, they would have been better off using && instead of , here, because cin >> command can fail (i.e. if the end of input is reached before the word END is found). In such case, the condition with , will not do what was intended (it will likely loop forever, as command will never receive the value END), while the condition with && would do the right thing (terminate).

Related

`fin.get(ch);` reads last character twice while `ch=fin.get();` not inside `while(!fin.eof())` loop why? [duplicate]

This question already has answers here:
Why is iostream::eof inside a loop condition (i.e. `while (!stream.eof())`) considered wrong?
(5 answers)
Closed 1 year ago.
vicky.txt file
I was born in Hupari.
Code -1
#include <iostream>
#include<fstream>
int main()
{
char ch;
std::ifstream fin;
fin.open("vicky.txt", std::ios::in);
while (!fin.eof())
{
fin.get(ch);
std::cout<<ch;
}
fin.close();
return 0;
}
Output
I was born in Hupari..
Code -2
#include <iostream>
#include<fstream>
int main()
{
char ch;
std::ifstream fin;
fin.open("vicky.txt", std::ios::in);
while (!fin.eof())
{
ch=fin.get();
std::cout<<ch;
}
fin.close();
return 0;
}
Output
I was born in Hupari. 
Why while using fin.get(ch) it reads last character twice. On other hand ch=fin.get() reads correctly means reads last character one time only.
By the way also tell return type of fin.get(ch) ? and return type of fin.get() is char right ?
Both versions are wrong. See Why is iostream::eof inside a loop condition (i.e. while (!stream.eof())) considered wrong? for more details on how to correctly code reading loops.
Now, to the explanation what happens. The first version uses second overload of get(). This method leaves its argument unchanged if read fails (e.g. when end of file is reached) and sets flag. Thus, you print the last read character once again.
The second version uses first overload of get(). Because this version must return a character and cannot leave it unchanged like the other versions, it returns an int to be able to return special value EOF (which must not represent any valid character). EOF is typically equal to -1 (as int). Then, you implicitly cast it to char, which would make it equal to 255 (or keep it as -1, but 8 bits). You then print it. Depending on the code page used by the terminal, it could be ÿ char, non-breaking space or something else. Possibly, you have that non-breaking space character printed, or some other invisible or unprintable character.

Replacing '(' with '-' in C++ [duplicate]

This question already has answers here:
How to replace all occurrences of a character in string?
(17 answers)
Closed 4 years ago.
I've tried:
versionString = versionString.replace(versionString.begin(), versionString.end(), '(' , '-' );
The result is: "--------------". Basically replacing all the characters. What is that?
versionString is a basic string.
If you look at e.g. this std::string::replace reference you will see that there's no overload that takes the arguments you pass. Something the compiler really should warn you about.
The closes one is number 6:
basic_string& replace( const_iterator first, const_iterator last,
size_type count2, CharT ch );
which replaces the range with count2 copies of ch.
That is, you replace your string with '(' number of dashes. With ASCII that '(' will be converted to the integer 40 (it's this conversion the compiler should have warned you about).
One solution is to repeatedly find the character you want to replace, and replace only that single character.
A much simpler solution is to use the standard algorithm function std::replace:
std::replace(begin(versionString), end(versionString), '(', '-');

How does the while loop works in this case? [duplicate]

This question already has answers here:
What does while(*pointer) means in C?
(5 answers)
Closed 5 years ago.
This code will print a string of characters:
const char* aString = "This is a string";
const char* ptrString = aString;
while(*ptrString)
{ std::cout << *ptrString;
ptrString++;
}
I'm still a newbie. From what I had learnt so far, while loop always has a condition inside the bracket like while(x<10) or something. I just don't understand why does the while loop in this case has only *ptrString as its condition. What does it actually mean? Can somebody explain to me?
When the pointer reaches the end of the string it finds an end of string character which value is 0, which evaluates to false when casting to bool. Then the loop ends.
while(*ptrString)
It stops when the *ptrString is null character. As ptrString is incremented in ptrString++;, eventually *ptrString will point to null character.
You can simplify the loop body to
std::cout << *ptrString++; // Ideal use of post-fix operator
though..

Two strings between brackets separated by a comma in C++ [duplicate]

This question already has answers here:
How does the Comma Operator work
(9 answers)
Closed 9 months ago.
I came across unexpected (to me at least) C++ behavior today, shown by the following snippit:
#include <iostream>
int main()
{
std::cout << ("1", "2") << std::endl;
return 0;
}
Output:
2
This works with any number of strings between the parentheses. Tested on the visual studio 2010 compiler as well as on codepad.
I'm wondering why this compiles in the first place, what is the use of this 'feature'?
Ahh, this is the comma operator. When you use a comma and two (or more) expressions, what happens is that all expressions are executed, and the result as a whole is the result of the last expression. That is why you get "2" as a result of this. See here for a bigger explanation.
It's called the comma operator: in an expression x, y, the compiler
first evaluates x (including all side effects), then y; the results
of the expression are the results of y.
In the expression you cite, it has absolutely no use; the first string
is simply ignored. If the first expression has side effects, however,
it could be useful. (Mostly for obfuscation, in my opinion, and it's
best avoided.)
Note too that this only works when the comma is an operator. If it can
be anything else (e.g. punctuation separating the arguments of a
function), it is. So:
f( 1, 2 ); // Call f with two arguments, 1 and 2
f( (1, 2) ); // Call f with one argument, 2
(See. I told you it was good for obfuscation.)
Comma operator ( , )
The comma operator (,) is used to separate two or more expressions that are included where only one expression is expected. When the set of expressions has to be evaluated for a value, only the rightmost expression is considered.
For example, the following code:
a = (b=3, b+2);
Ref:http://www.cplusplus.com/doc/tutorial/operators/
The result of the comma (",") is the right subexpression.
I use it in loops over stl containers:
for( list<int>::iterator = mylist.begin(), it_end = mylist.end(); it != it_end; ++it )
...
The comma operator evaluates the expressions on both sides of the comma, but returns the result of the second.

c++ isalnum endless loop

Greetings!
Lets cut the excessive intro this time and get straight to the point.
I have a problem in C++ using the isalnum method.
the code:
int playAgainst = 0;
do
{
cout << "Who do you want to play against?(1/2)\n";
cout << "1: Human player\n";
cout << "2: Computer player\n";
cin >> playAgainst
} while(!isalnum(playAgainst) && playAgainst != 0);
As seen in the code, I'm providing the user with a choice. Play against human or play against a computer.
What I want is, as long as the user enters anything else then an integer value(cin >> playAgainst) to repeat the question. However, If i enter a char, or string value, it keeps looping endlessly. I am not 100% sure, but it would be obvious, if the problem is, that the non int value is already saved as the value for playAgainst.. How can I check in this bit of code if the input value is int before saving it?
Or is the only possibility to save as a char/string and then check?
If the latter is the case, a new problem arises. isalnum only accepts int as parameter, atleast from what I know. How will I check if that string or char is an int?
Thank you for taking the time to read. And hopefully Ill be accepting a reply as answer soon ^^
Thanks everyone for the answers.
I have gotten what I wanted, and everything has been solved.
The reason I chose for the accepted answer, is well... because initially, it made my code work the way I want it to. I want to accept multiple answers though..
Make playAgainst a char and compare against '0', not 0. Right now, the user has to enter the ASCII (or whatever your character set is) code for the character '1' or '2'.
isalnum won't work on ints outside the valid range of char, except for EOF. (The fact that it takes an int argument is a leftover from C, which has different integer promotions rules than C++. to accomodate for EOF.)
Remove the isalnum() check. cin >> playAgainst will convert anything except a number to zero, which will be caught by the second check. Note that this is only an option because zero is not a valid input.
isalnum() is useful if you're interpreting the characters yourself, but in this case the stream has already done that for you.
This is how the compiler will implement isalnum:
int isalnum (int ch)
{
return (ch >= 'a' && ch <= 'z') ||
(ch >= 'A' && ch <= 'Z') ||
(ch >= '0' && ch <= '9');
}
So you might as well write that code snippet in your own code, and it will be equivalent with an inlined version of isalnum.
It's because you don't clear the buffer. When the input is invalid, you need to clear it from the buffer, and then you can move on to the next input, else you're trying to extract the same input every time (which fails, because it's the same bad input), and thus enter an infinite loop.
The problem is that you're inputing an int, and not a char. And if the
text in the input isn't an int, then the input fails. In which case,
playAgainst isn't modified, and the failure is memorized in std::cin
until you explicitly clear the error. And inputting from a stream in an
error state is a no-op. What you probably want to do is
Input a single character: if you don't want to skip spaces, using
`std::cin.get( ch )` or `ch = std::cin.get()`. (In the latter
case, `ch` should be an `int`, since it must also handle `EOF`.
On the other hand, you can use `::isalnum` on it directly, which
you can't do if `ch` is a `char`.
Fully check for valid input: not just `::isalnum`, but rather
whether the input is a legal selector in your list. Something
along the lines of:
ch != EOF && std::find( legalChars.begin(), legalChars.end(), (char)ch ) != legalChars.end()
In case of error, clear any remaining input, say with:
std::cin.ignore(INT_MAX, '\n');
In practice, you'll probably want to treat EOF differently from
an erroneous command. (If you don't clear the input after EOF, you
won't be able to read anything else. But presumably, if you got EOF,
it's because the user gave up, and doesn't want to try any more.)
Finally, it's probably preferrable to keep all of the information in
a common location, using a table of:
struct Command
{
char op;
char const* prompt;
void (* func)();
};
You then loop over a table of these to output the prompt, search it to
see if the character was legal, and finally, call the function on the
entry you found. Or define an abstract base class, a concrete class
deriving from it for each command, and use an std::map<char,
AbstractBase*> for the mapping, etc. Very C++, but perhaps a bit
overkill for such a simple case.
Why not use isdigit().