Why does my simple while loop printf 2x?

G

Geoff

So the specification could be simplified to

Return true if 'Y' typed or if ' ' typed and default is 'Y'.
Return false otherwise.
Yes.

Anyway, if you replaced the second condition with "return false;", under
what conditions would there be a change in the value returned or a
side-effect of the function?
At this time I see none. The behavior meets the requirements.
 
S

Stefan Ram

Geoff said:
On 25 May 2014 22:58:41 GMT, (e-mail address removed)-berlin.de (Stefan Ram)
It's not required to distinguish any other responses. Erroneous input
is erroneous input and the function returns false in that case.

The documentation comment was:

|//============================================================================
|// Get user's yes/no answer from console input.
|// Argument: "y" or "n" indicating the default answer expected.
|// Blank reply means accept default answer.
|//============================================================================

It says: »Get user's yes/no answer«.
Erroneous input is no »yes/no answer«.

Also, it seems that the meaning of the bool result
(true/false) is not given in the documentation comment at
all. This would mean that the user of the library cannot not
learn what a result of »true« or »false«, respectively,
means.

Outside of the documentation comment you then wrote:

|This function receives an argument string, either "y" or "n"
|depending on what you expect to be default and returns
|accordingly.

We could decide to take that as a part of the documentation,
but »returns accordingly« is a little bit vague.
 
G

Geoff

The documentation comment was:

|//============================================================================
|// Get user's yes/no answer from console input.
|// Argument: "y" or "n" indicating the default answer expected.
|// Blank reply means accept default answer.
|//============================================================================

It says: »Get user's yes/no answer«.
Erroneous input is no »yes/no answer«.

Also, it seems that the meaning of the bool result
(true/false) is not given in the documentation comment at
all. This would mean that the user of the library cannot not
learn what a result of »true« or »false«, respectively,
means.

Outside of the documentation comment you then wrote:

|This function receives an argument string, either "y" or "n"
|depending on what you expect to be default and returns
|accordingly.

We could decide to take that as a part of the documentation,
but »returns accordingly« is a little bit vague.

//
//============================================================================
// Get user's yes/no answer from console input.
// Argument: "y" or "n" indicating the default answer expected.
// Blank reply means accept default answer.
// Return: true only if "Y" or "y" or if '\n' received and
// argument is "y" else return false.
//============================================================================
//

Better?
 
J

James Kuyper

On 26 May 2014 04:40:25 GMT, (e-mail address removed)-berlin.de (Stefan Ram) ....
//============================================================================
// Get user's yes/no answer from console input.
// Argument: "y" or "n" indicating the default answer expected.
// Blank reply means accept default answer.
// Return: true only if "Y" or "y" or if '\n' received and
// argument is "y" else return false.
//============================================================================
//

Better?

Your function treats an invalid answer the same as a valid answer of "N"
or "n", which is also the same way it treats a default answer of "n"
that is confirmed. Your documentation should reflect that fact:

// Check for a yes answer from console input.
// Argument: "y" or "n" indicating default answer expected.
// Blank reply means accept default answer.
// Return: true only if "Y" or "y" is received or if a default
// answer of "y" is accepted. Otherwise, return false.
 
B

Ben Bacarisse

I think you really need to consider this question.
No, this doesn't cover the case where the default response is supposed
to be N or space. The point of the function is to set a bit according
to query at the user prompt with the expectation that user will hit
return to indicate the default answer. The program it's derived from
asks a series of yes/no questions, some default to yes, some default
to no. A response other than empty string or Y or N returns false.
Only a Y answer can set it true in the case of a default no
expectation and any other input results in the default case.

Yes, I understood your intent. Unfortunately I've run out of
explanations so I simply offer you a test program that provides fake
input to both functions and shows the results:

#include <iostream>
#include <iomanip>
#include <algorithm>

const char *answer;

void getline(std::istream &is, std::string &line)
{
line = answer;
}

bool GetYesNo (std::string yn)
{
std::string str;

getline(std::cin, str);
std::transform(str.begin(), str.end(), str.begin(), ::tolower);
std::transform( yn.begin(), yn.end(), yn.begin(), ::tolower);

// if expecting y and get blank or y, return true
if ((yn.compare(0, 1, "y") == 0 && str.compare(0, 1, "") == 0) ||
str.compare(0, 1, "y") == 0)
return true;

// if expecting n and get n or blank, return false
if ((yn.compare(0, 1, "n") == 0 && str.compare(0, 1, "") == 0) ||
str.compare(0, 1, "n") == 0)
return false;
else
return false;
}

bool BensYesNo (std::string yn)
{
std::string str;

getline(std::cin, str);
std::transform(str.begin(), str.end(), str.begin(), ::tolower);
std::transform( yn.begin(), yn.end(), yn.begin(), ::tolower);

return str.compare(0, 1, "") == 0 && yn.compare(0, 1, "y") == 0 ||
str.compare(0, 1, "y") == 0;
}

int main()
{
const char *alist[] = { "yes", "no", "other", "" };
std::cout << " default answer results\n";
for (auto deflt : alist)
for (auto a : alist) {
answer = a;
std::cout << std::setw(9) << deflt << std::setw(9) << answer
<< " " << GetYesNo(deflt)
<< " " << BensYesNo(deflt) << "\n";
}
return 0;
}

The output is:

default answer results
yes yes 1 1
yes no 0 0
yes other 0 0
yes 1 1
no yes 1 1
no no 0 0
no other 0 0
no 0 0
other yes 1 1
other no 0 0
other other 0 0
other 0 0
yes 1 1
no 0 0
other 0 0
0 0

In every case, the two functions agree. (I've included some unusual
default strings, but that's because the test code is simpler that way.)
I take your point and I like your solution even though it doesn't
completely satisfy the requirements.

That may be, but I can't yet see what's missing. Can you give an example?
 
T

Tim Rentsch

Ben Bacarisse said:
[snip]

Another method I've taken to using when extra output is needed on the
second and subsequent executions of a loop is to add it as an explicit
string, initialised to the empty string. (A good example is printing a
list with separating commas). Here, it would look like this:

int confirm(void) {
int reply;
const char *extra_prompt = "";
do {
int c;
printf("%sEnter Y or N (not case-sensitive): ", extra_prompt);
reply = c = toupper(getchar());
while (c != EOF && c != '\n') c = getchar();
extra_prompt = "The first character must be Y or N.\n";
} while (reply != 'Y' && reply != 'N');
return reply;
}

This idea can be turned to advantage by adding a parameter to the
function to allow a caller to give a prefix string before the
first iteration, thusly -

static int skip_to_EOL( int c );

int
confirmation( const char *start_text ){
printf( "%sEnter Y or N (not case-sensitive): ", start_text );
fflush( stdout );

int first = toupper( getchar() ), last = skip_to_EOL( first );

return first == 'N' || first == 'Y' ? first
: last == EOF ? last
: confirmation( "The first character must be Y or N.\n" );
}

int
skip_to_EOL( int c ){
return c == EOF || c == '\n' ? c : skip_to_EOL( getchar() );
}

This version also returns EOF if/when EOF is reached in the input
stream (rather than looping infinitely).
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,228
Members
46,817
Latest member
AdalbertoT

Latest Threads

Top