do {...} while () ;

A

Aleramo

I don't understand the reason cos this cycle:

do {
printf ("\nCome devono essere posizionati gli elementi?\n") ;
printf ("* premere E, nel caso di posizionamento sul piano
E\n") ;
printf ("(ricezione onde orizzontali);\n") ;
printf ("* premere H, nel caso di posizionamento sul piano
H\n") ;
printf ("(ricezione onde verticali).\n") ;
scanf ("%c", &scelta_piano) ;
} while ((scelta_piano != 'H') && (scelta_piano != 'h') &&
(scelta_piano != 'E') && (scelta_piano != 'e')) ;

write its content two time. So the output is:

Come devono essere posizionati gli elementi?
* premere E, nel caso di posizionamento sul piano E
(ricezione onde orizzontali);
* premere H, nel caso di posizionamento sul piano H
(ricezione onde verticali).

Come devono essere posizionati gli elementi?
* premere E, nel caso di posizionamento sul piano E
(ricezione onde orizzontali);
* premere H, nel caso di posizionamento sul piano H
(ricezione onde verticali).

I hope someone can help me.
Bye bye Aleramo.
 
F

Flash Gordon

Aleramo said:
I don't understand the reason cos this cycle:

do {
printf ("\nCome devono essere posizionati gli elementi?\n") ;
printf ("* premere E, nel caso di posizionamento sul piano
E\n") ;
printf ("(ricezione onde orizzontali);\n") ;
printf ("* premere H, nel caso di posizionamento sul piano
H\n") ;
printf ("(ricezione onde verticali).\n") ;
scanf ("%c", &scelta_piano) ;
} while ((scelta_piano != 'H') && (scelta_piano != 'h') &&
(scelta_piano != 'E') && (scelta_piano != 'e')) ;

write its content two time. So the output is:

<snip>

In future, please provide a *complete* compilable example that
demonstrates your problem and also tell us what input you are using. The
bug could be anywhere in the 250000 lines of code you have not posted.
However, I'm in a good mood and I'll guess that you have this problem
somewhere in the code you did not post
http://c-faq.com/stdio/scanfinterlace.html

In general I would recommend against using scanf. Use fgets (not, *ever*
the more appealing looking gets) and then pass the line you have read
using the tool of choice, be that sscanf, strtol, a hand written passer
or whatever.
 
E

Eric Sosman

Aleramo said:
I don't understand the reason cos this cycle:

do {
printf ("\nCome devono essere posizionati gli elementi?\n") ;
printf ("* premere E, nel caso di posizionamento sul piano
E\n") ;
printf ("(ricezione onde orizzontali);\n") ;
printf ("* premere H, nel caso di posizionamento sul piano
H\n") ;
printf ("(ricezione onde verticali).\n") ;
scanf ("%c", &scelta_piano) ;
} while ((scelta_piano != 'H') && (scelta_piano != 'h') &&
(scelta_piano != 'E') && (scelta_piano != 'e')) ;

write its content two time. [...]

Probably because the first character read by scanf()
was not H, h, E, or e. You could check this by adding
an extra printf() right after the scanf(), for debugging
purposes:

printf ("Input is '%c' (code %d or 0x%X)\n",
scelta_piano, scelta_piano, scelta_piano);

Where did that phantom character come from? It was
probably from some earlier input that a previous scanf()
did not consume. For example, if your program executed

int numero;
...
printf ("Enter an integer\n");
scanf ("%d", &numero);

.... and you responded by pressing 4 and 2 and ENTER, the
first scanf() would convert the 4 and 2 and store the value
42 in numero. However, the line also contained a newline
character '\n', which the first scanf() would not swallow.
When the second scanf() executes, it finds the newline and
stores it in scelta_piano. Your program sees that '\n' is
not one of H,h,E,e, so it repeats. The second time through
the loop, scanf() finds the character you intended, stores
it in scelta_piano, and your program accepts it.

scanf() is not a very good function for interactive input,
because it treats the input as one long stream of characters.
Usually, interactive input should be "synchronized" by some
mechanism like pressing ENTER, and this means that it is more
natural to think of interactive input as a sequence of complete
lines. One way to deal with this problem is to use fgets()
to read a complete line into a character array, and then use
sscanf() -- two s'es -- to "read" from the character array.
 
C

CBFalconer

Aleramo said:
I don't understand the reason cos this cycle:

do {
printf ("\nCome devono essere posizionati gli elementi?\n") ;
printf ("* premere E, nel caso di posizionamento sul piano
E\n") ;
printf ("(ricezione onde orizzontali);\n") ;
printf ("* premere H, nel caso di posizionamento sul piano
H\n") ;
printf ("(ricezione onde verticali).\n") ;
scanf ("%c", &scelta_piano) ;
} while ((scelta_piano != 'H') && (scelta_piano != 'h') &&
(scelta_piano != 'E') && (scelta_piano != 'e')) ;

write its content two time. So the output is:

I suggest you think about it differently. I believe you want to
present a prompt, and get one of a subset of possible response
characters. So isolate this operation in a function.

int promptandgetresponse(const char *prompt,
const char *acceptable);

Note the return of an int, so that an EOF can be detected. The
assumption is being made that stdout is used for prompting, and
stdin for input. You could add parameters to control this, if
desired. So the first step is to present the prompt:

do {
if (prompt) {
printf("%s", prompt); fflush(stdout);
}
/* Now get a reply */
} while ( /* reply is not satisfactory */ );

Note the fflush, which allows the prompt to not end with a \n. The
test on prompt allows you to avoid prompting entirely, by supplying
NULL.

Looking at this you may see a possible problem. How is the user to
know why his response is not acceptable? So you may want to modify
the system to give feedback on this later. This is left as an
exercise.

Now, how do we get a reply? There is no need to complicate things
with the highly unruly scanf if we keep a couple of useful
auxiliary routines around:

int skipblanks(void) {
int ch;
while (' ' == (ch = getchar())) continue;
return ch;
}

which will gobble up leading blanks. We can also gobble up all
unused line portions with:
+
int flushln(void) {
int ch;
while (('\n' != (ch = getchar())) && (EOF != ch)) continue;
return ch;
}

Notice that both routines will exit, and return EOF, if an EOF is
encountered. These routines are so useful that you should always
have them available for interactive use. They are better
generalized to access arbitrary files, supplied as a parameter.

Now lets embellish the promptandgetresponse routine to use these.

int promptandgetresponse(const char *prompt,
const char *acceptable)
{
int ch;

do {
if (prompt) {
printf("%s", prompt); fflush(stdout);
}
/* Now get a reply */
ch = skipblanks(); /* get first non-blank char */
if ('\n' != ch) flushln(); /* set up to try again */
} while ( /* reply is not satisfactory */ );
return ch;
}

This hasn't resolved "reply is not satisfactory" yet, and has some
other minor difficulties. You should try the condition:

strchr(acceptable, ch)

to replace that comment. This will require #include <strings.h>.

Things to think about: What if the user enters only an empty
line? You could make this select a default, such as the first
character in acceptable. What if an EOF is encountered while
skipping blanks? while executing flushln? You can resolve most of
these by insisting that responses be properly terminated with '\n',
i.e. an <enter> on most machines. Otherwise you will return an EOF
and not try to preserve data from an invalid entry. After all,
once EOF has been signalled you can't do anything more.

Once you get this running cleanly, you will have solved many of
your interactive problems for the future. Note that the routine(s)
need not be long and complex, rather they should be short and you
should be able to see flaws easily on inspection.

BTW, notice that the code I am proposing is not confused by
language difficulties. What the prompt is, and its language, have
no effect whatsoever. Similarly the translation of single char.
responses.

The above code is untested. So beware.

--
Some informative links:
http://www.geocities.com/nnqweb/
http://www.catb.org/~esr/faqs/smart-questions.html
http://www.caliburn.nl/topposting.html
http://www.netmeister.org/news/learn2quote.html
 
A

Aleramo

Thank u to everyone!!!
i use gets () for the input before and now the "eco effect" has ended.
The input before was a string. With gets () i have a message of worning
with scanf () no.
The trouth shown me i have problems with the opposite.
I use gcc 3.4, i hope the 4 hasn't this problems.

Bye bye!!!
Aleramo.
 
C

CBFalconer

Aleramo said:
Thank u to everyone!!!
i use gets () for the input before and now the "eco effect" has ended.
The input before was a string. With gets () i have a message of worning
with scanf () no.
The trouth shown me i have problems with the opposite.
I use gcc 3.4, i hope the 4 hasn't this problems.

Never ever use gets. Do include adequate context with your
messages, and don't assume that the distorted google view of usenet
is accurate. Read the following sig, and read the references
therein, before replying again.

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
More details at: <http://cfaj.freeshell.org/google/>
Also see <http://www.safalra.com/special/googlegroupsreply/>
 
K

Keith Thompson

Aleramo said:
Thank u to everyone!!!
i use gets () for the input before and now the "eco effect" has ended.
The input before was a string. With gets () i have a message of worning
with scanf () no.
The trouth shown me i have problems with the opposite.
I use gcc 3.4, i hope the 4 hasn't this problems.

Never use gets. It cannot be used safely.

Never use silly abbreviations like "u" for "you"; they just make your
text more difficult to read.

Never post a followup via Google without first reading
<http://cfaj.freeshell.org/google/>.
 
C

CBFalconer

Keith said:
Never use gets. It cannot be used safely.

Never use silly abbreviations like "u" for "you"; they just make
your text more difficult to read.

Never post a followup via Google without first reading
<http://cfaj.freeshell.org/google/>.

I wonder if he got the idea from this chorus of replies :)

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
More details at: <http://cfaj.freeshell.org/google/>
Also see <http://www.safalra.com/special/googlegroupsreply/>
 
A

Aleramo

Maybe i made a few of confusion. I addict some rows before:

char scelta_array [10], scelta_piano ;

puts ("Scrivere:\n* lineare, per studiare un array lineare;") ;
puts ("* piano, per studiare un array piano;") ;
puts ("* qualunque altra parola per uscire.") ;
gets (scelta_array) ; /* Con scanf () non funziona!!! con gets
dà il messaggio di worning ma non ga eco. */

do {
printf ("\nCome devono essere posizionati gli elementi?\n") ;
printf ("* premere E, nel caso di posizionamento sul piano
E\n") ;
printf ("(ricezione onde orizzontali);\n") ;
printf ("* premere H, nel caso di posizionamento sul piano
H\n") ;
printf ("(ricezione onde verticali).\n") ;
scanf ("%c", &scelta_piano) ;
} while ((scelta_piano != 'H') && (scelta_piano != 'h') &&
(scelta_piano != 'E') && (scelta_piano != 'e')) ;

Before i used:

scanf ("%s", scelta_array) ;

and i substituted it with:

gets (scelta_array) ;

I receive the message of Worning for gets (), but i can execute the
program withouth any problems. My question is: have you thought i
changet the scanf () in the cycle with the gets () ? it's the gets ()
there ok? or you advise me to change the solution?

Thank you to everyone!!!
Aleramo.
 
M

Marc Thrun

Aleramo said:
Maybe i made a few of confusion. I addict some rows before:

char scelta_array [10], scelta_piano ;

puts ("Scrivere:\n* lineare, per studiare un array lineare;") ;
puts ("* piano, per studiare un array piano;") ;
puts ("* qualunque altra parola per uscire.") ;
gets (scelta_array) ; /* Con scanf () non funziona!!! con gets
dà il messaggio di worning ma non ga eco. */

do {
printf ("\nCome devono essere posizionati gli elementi?\n") ;
printf ("* premere E, nel caso di posizionamento sul piano
E\n") ;
printf ("(ricezione onde orizzontali);\n") ;
printf ("* premere H, nel caso di posizionamento sul piano
H\n") ;
printf ("(ricezione onde verticali).\n") ;
scanf ("%c", &scelta_piano) ;
} while ((scelta_piano != 'H') && (scelta_piano != 'h') &&
(scelta_piano != 'E') && (scelta_piano != 'e')) ;

Before i used:

scanf ("%s", scelta_array) ;

and i substituted it with:

gets (scelta_array) ;

I receive the message of Worning for gets (), but i can execute the
program withouth any problems. My question is: have you thought i
changet the scanf () in the cycle with the gets () ? it's the gets ()
there ok? or you advise me to change the solution?

Thank you to everyone!!!
Aleramo.
Don't use gets() as it does not allow you to control the number of
characters to be read into the buffer. This leads to buffer overrun when
gets() tries to write beyond the supplied buffer. With fgets() you can
control the number of characters to be read and thus prevent buffer
overruns.

Also, have a look at http://c-faq.com/stdio/getsvsfgets.html as Eric
Sosman already stated.
 
C

CBFalconer

Aleramo said:
.... snip ...

I receive the message of Worning for gets (), but i can execute the
program withouth any problems. My question is: have you thought i
changet the scanf () in the cycle with the gets () ? it's the gets ()
there ok? or you advise me to change the solution?

Then why are you using it? Never use gets. You seem to have paid
zero attention to a fairly complete solution I offered you
yesterday, involving a generalized prompt and get response
mechanism.
 
R

Robin Haigh

Maybe i made a few of confusion. I addict some rows before:

char scelta_array [10], scelta_piano ;

puts ("Scrivere:\n* lineare, per studiare un array lineare;") ;
puts ("* piano, per studiare un array piano;") ;
puts ("* qualunque altra parola per uscire.") ;
gets (scelta_array) ; /* Con scanf () non funziona!!! con gets
dà il messaggio di worning ma non ga eco. */

do {
printf ("\nCome devono essere posizionati gli elementi?\n") ;
printf ("* premere E, nel caso di posizionamento sul piano
E\n") ;
printf ("(ricezione onde orizzontali);\n") ;
printf ("* premere H, nel caso di posizionamento sul piano
H\n") ;
printf ("(ricezione onde verticali).\n") ;
scanf ("%c", &scelta_piano) ;
} while ((scelta_piano != 'H') && (scelta_piano != 'h') &&
(scelta_piano != 'E') && (scelta_piano != 'e')) ;

Before i used:

scanf ("%s", scelta_array) ;

and i substituted it with:

gets (scelta_array) ;

I receive the message of Worning for gets (), but i can execute the
program withouth any problems. My question is: have you thought i
changet the scanf () in the cycle with the gets () ? it's the gets ()
there ok? or you advise me to change the solution?


Your original line

scanf ("%s", scelta_array) ;

had two problems. One is that it doesn't discard the '\n' at end-of-line.
The other is the buffer overrun.

Using gets() is a fix for the '\n' problem. But it doesn't do anything
about the buffer overrun. It doesn't make it any worse than it was before,
it just gets the compiler and everybody else pointing it out.

Sadly, fgets() doesn't help much. Unlike gets(), it doesn't always read a
line. It avoids a buffer overrun at the risk of leaving surplus input in
the input stream, which is the problem you had to start with.

Incidentally, if you type an X instead of an H or an E, don't you get the
echo thing again?
 
E

Eric Sosman

Robin said:
Your original line

scanf ("%s", scelta_array) ;

had two problems. One is that it doesn't discard the '\n' at end-of-line.
The other is the buffer overrun.

His original line was

scanf ("%c", &scelta_piano);

.... so it had only one of the two problems you mention.
 

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

No members online now.

Forum statistics

Threads
474,175
Messages
2,570,946
Members
47,497
Latest member
PilarLumpk

Latest Threads

Top