473,382 Members | 1,480 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,382 software developers and data experts.

Discarding unread data after scanf()

Is this a good way to discard unread data after scanf()?

while (getchar() != '\n')
;

According to the FAQ scanf always leaves the trailing newline on the input
stream, so there's no risk of discarding any more than needed. (In the best
case, when scanf() correctly works and the user hasn't input spurious data
beside those required in the control string, the loop will only iterate
once.)

(The only problem is if for some reason stdin is a file and it ends. But I
could well use drastic solutions such as
assert(!feof(stdin) && !ferror(stdin));
as the loop body, since if a program designed to be interactive reads from a
file which ends we can't do anything better than abort execution.)

--
#include <stdio.h>
#include <stdlib.h>
int main(void) /* Don't try this at home */ {
const size_t dim = 256; int i;
for (i=0; malloc(dim); i++) /*nothing*/ ;
printf("You're done! %zu\n", i*dim);
puts("\n\n--Army1987"); return 0;
}
Mar 25 '07 #1
8 5110
Army1987 wrote:
>
Is this a good way to discard unread data after scanf()?
A call to fscanf with stdin as the first argument,
is just like a call to scanf.

/* BEGIN fscanf_input.c */
/*
** There are only three different values
** that can be assigned to rc
** from the fscanf calls in this program.
** They are:
** EOF
** 0
** 1
** If rc equals EOF, then the end of file was reached,
** or there is some input problem;
** ferror and feof can be used to distinguish which.
** If rc equals 0, then an empty line was entered
** and the array contains garbage values.
** If rc equals 1, then there is a string in the array.
** Up to LENGTH number of characters are read
** from a line of a text stream
** and written to a string in an array.
** The newline character in the text line is replaced
** by a null character in the array.
** If the line is longer than LENGTH,
** then the extra characters are discarded.
*/
#include <stdio.h>

#define LENGTH 40
#define str(x) # x
#define xstr(x) str(x)

int main(void)
{
int rc;
char array[LENGTH + 1];

puts("The LENGTH macro is " xstr(LENGTH) ".");
do {
fputs("Enter any line of text to continue,\n"
"or just hit the Enter key to quit:", stdout);
fflush(stdout);
rc = fscanf(stdin, "%" xstr(LENGTH) "[^\n]%*[^\n]", array);
if (!feof(stdin)) {
getc(stdin);
}
if (rc == 0) {
array[0] = '\0';
}
if (rc == EOF) {
puts("rc equals EOF");
} else {
printf("rc is %d. Your string is:%s\n\n", rc, array);
}
} while (rc == 1);
return 0;
}

/* END fscanf_input.c */
--
pete
Mar 25 '07 #2

"pete" <pf*****@mindspring.comha scritto nel messaggio
news:46***********@mindspring.com...
Army1987 wrote:
>>
Is this a good way to discard unread data after scanf()?

A call to fscanf with stdin as the first argument,
is just like a call to scanf.
I know that. But that isn't what I was asking.

#include <stdio.h>
int input(const char *prompt)
{
int flag, result;
puts(prompt);
flag = scanf("%d", &result);
while (getchar() != '\n')
;
while (flag < 1) {
puts("Please enter an integer value");
flag = scanf("%d", &result);
while (getchar() != '\n')
;
}
return result;
}

Is this ok (supposing stdin is interactive)?
Mar 25 '07 #3

"Army1987" <pl********@for.itha scritto nel messaggio
news:eu**********@tdi.cu.mi.it...
#include <stdio.h>
int input(const char *prompt)
{
int flag, result;
puts(prompt);
fflush(stdout); /* forgot that... */
flag = scanf("%d", &result);
while (getchar() != '\n')
;
while (flag < 1) {
puts("Please enter an integer value");
fflush(stdout);
flag = scanf("%d", &result);
while (getchar() != '\n')
;
}
return result;
}

Is this ok (supposing stdin is interactive)?

Mar 25 '07 #4
Army1987 wrote:
puts(prompt);
fflush(stdout); /* forgot that... */
I don't think that fflush(stdout) is required
after a newline character is output.
puts always outputs a complete
line of text with newline character at the end.
I think of puts as creating a line of text from a string.

In case you don't know, a "line in a text stream"
is somewhat analagous to a "string in memory",
with a "line" being terminated by a newline character
while a "string" is terminated by a null character.

I misread your intial post as "Is there..."
when you has actually written "Is this..."

I will take another look at your code.

--
pete
Mar 25 '07 #5
Army1987 wrote:
>
Is this a good way to discard unread data after scanf()?

while (getchar() != '\n')
;
Your while loop will prevent endless looping from alpha input
while scanfing for int input.

/* BEGIN new_1.c output */

Please enter an integer value
ksdhfgkdashfkfrhwe
Please enter an integer value
wekjwerhiweuq
Please enter an integer value
wejuf
Please enter an integer value
wekjh
Please enter an integer value
ds
Please enter an integer value
42

The result is 42

/* END new_1.c output */

/* BEGIN new_2.c output */

Please enter an integer value
a
Please enter an integer value
Please enter an integer value
Please enter an integer value
Please enter an integer value
Please enter an integer value
Please enter an integer value ... and so on and so forth.

/* BEGIN new_1.c */

#include <stdio.h>

int input(const char *prompt);

int main(void)
{
puts("/* BEGIN new_1.c output */\n");
printf("\nThe result is %d\n",
input("Please enter an integer value"));
puts("\n/* END new_1.c output */");
return 0;
}

int input(const char *prompt)
{
int flag, result;

puts(prompt);
flag = scanf("%d", &result);
while (getchar() != '\n') {
;
}
while (flag < 1) {
puts("Please enter an integer value");
flag = scanf("%d", &result);
while (getchar() != '\n') {
;
}
}
return result;
}

/* END new_1.c */

/* BEGIN new_2.c */

#include <stdio.h>

int input(const char *prompt);

int main(void)
{
puts("/* BEGIN new_2.c output */\n");
printf("\nThe result is %d\n",
input("Please enter an integer value"));
puts("\n/* END new_2.c output */");
return 0;
}

int input(const char *prompt)
{
int flag, result;

puts(prompt);
flag = scanf("%d", &result);
while (flag < 1) {
puts("Please enter an integer value");
flag = scanf("%d", &result);
}
return result;
}

/* END new_2.c */

--
pete
Mar 25 '07 #6
On Sun, 25 Mar 2007 12:54:19 +0200, "Army1987" <pl********@for.it>
wrote:
>Is this a good way to discard unread data after scanf()?

while (getchar() != '\n')
;

According to the FAQ scanf always leaves the trailing newline on the input
stream, so there's no risk of discarding any more than needed. (In the best
case, when scanf() correctly works and the user hasn't input spurious data
beside those required in the control string, the loop will only iterate
once.)

(The only problem is if for some reason stdin is a file and it ends. But I
could well use drastic solutions such as
assert(!feof(stdin) && !ferror(stdin));
as the loop body, since if a program designed to be interactive reads from a
file which ends we can't do anything better than abort execution.)
If you are worried about end of file as well as end of line you can
use something like
{int x; while (((x = getchar()) != '\n' ) && x != EOF) /* */;}
Remove del for email
Mar 25 '07 #7
"Army1987" <pl********@for.itwrites:
Is this a good way to discard unread data after scanf()?

while (getchar() != '\n')
;
No.
According to the FAQ scanf always leaves the trailing newline on the input
stream, so there's no risk of discarding any more than needed. (In the best
case, when scanf() correctly works and the user hasn't input spurious data
beside those required in the control string, the loop will only iterate
once.)
What scanf leaves on the input stream depends on the format string.
With the right format string, it can consume the trailing newline.

In a later followup, you said you're using a "%d" format. In that
case, *if* you're going to use scanf() for input, then the above loop
with the addition of a check for EOF (see below) is reasonable,
assuming you want to accept just one integer value per input line.

But scanf() is usually not the best way to handle interactive input.
A better approach is to use fgets() to read an entire line at a time,
then use sscanf() to parse the line.

But even that has problems. If either scanf() or sscanf() with a "%d"
format attempts to read a number that won't fit in type int, the
behavior is undefined; there's no way to detect the error once it's
happened. If that's a concern, you might consider using strtol(),
which does detect and report overflow and underflow.

fgets() can also have problems with very long lines. I *think* this
is covered in the FAQ.
(The only problem is if for some reason stdin is a file and it ends. But I
could well use drastic solutions such as
assert(!feof(stdin) && !ferror(stdin));
as the loop body, since if a program designed to be interactive reads from a
file which ends we can't do anything better than abort execution.)
By "stdin is a file", I assume you mean that the program is reading
from a disk file rather than from, say, a keyboard. But you can
easily reach an end-of-file condition when reading from a keyboard.
<OT>On Unix-like systems, this is usually caused by the user typing
control-D; on DOS or Windows systems, it's usually control-Z.</OT You
should handle that case cleanly.

You can do much better than just aborting execution with a message
like:

assertion "!feof(stdin) && !ferror(stdin)" failed: file "c.c", line 6

You can test for end-of-file (preferably by comparing the result of
getchar() to EOF, not by calling feof() or ferror()), and you can
*gracefully* terminate the program. Quite often, reaching end-of-file
is the normal way for a program to terminate, simply because it has no
more work to do. In an interactive program that's expecting more
input, you can at least terminate with an error message that's going
to be meaningful to the user.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Mar 25 '07 #8
Groovy hepcat Army1987 was jivin' on Sun, 25 Mar 2007 12:54:19 +0200
in comp.lang.c.
Discarding unread data after scanf()'s a cool scene! Dig it!
>Is this a good way to discard unread data after scanf()?

while (getchar() != '\n')
;
No, not really. You need to test for EOF.
>According to the FAQ scanf always leaves the trailing newline on the input
stream, so there's no risk of discarding any more than needed. (In the best
case, when scanf() correctly works and the user hasn't input spurious data
beside those required in the control string, the loop will only iterate
once.)

(The only problem is if for some reason stdin is a file and it ends.
Or it's an interactive device, and the user presses whatever key
combination (or takes whatever course of action) indicates an end of
file condition on the device. Or it's a punched tape reader, and the
tape breaks. Or it's an electroencephalograph, and the person whose
noggin it's wired up to has fallen asleep. Or it's any kind of device
ever invented by the mind and made by the hand of mankind, and
something goes wrong with it.
But I
could well use drastic solutions such as
assert(!feof(stdin) && !ferror(stdin));
Indeed that is a drastic solution. Don't do that. That's no way to
use assert(). It's for catching programming errors, not input errors.
When NDEBUG is defined, every use of assert() becomes a no-op. In this
situation you lose all your input error checking. And you don't want
to lose that.
Besides, there are better ways of determining whether there's a file
stream problem. Use the return value of the input function you're
using. All the file input functions return some indication of whether
or not they failed or tryed to read beyond the end of the file. For
example, getchar() returns EOF on failure or end of file. You can then
use ferror() or feof() to determine which of those two conditions
occurred.
>as the loop body, since if a program designed to be interactive reads from a
file which ends we can't do anything better than abort execution.)
I recently posted a simple function that could do what you want. But
since you lurked here for some time before posting, as all good Usenet
denizens do, as they should, you must know that. I'm sure it just
slipped your mind. So I will refresh your memory. Here is the
function, slightly modified to return EOF on error or end of file:

#include <stdio.h>

int skip2nl(FILE *fp)
{
int c;

while(EOF != (c = fgetc(fp)) && '\n' != c)
;

return c;
}

You could use this function something like this:

int main(void)
{
int status;

puts("Enter some stuff on stdin, "
"and I will attempt to skip it...\n");

status = skip2nl(stdin);
if(EOF == status)
{
if(ferror(stdin))
{
puts("File error on stdin.");
}
else
{
puts("End of file on stdin.");
}
}
else
{
puts("Newline read from stdin.");
}

return 0;
}

--

Dig the even newer still, yet more improved, sig!

http://alphalink.com.au/~phaywood/
"Ain't I'm a dog?" - Ronny Self, Ain't I'm a Dog, written by G. Sherry & W. Walker.
I know it's not "technically correct" English; but since when was rock & roll "technically correct"?
Mar 28 '07 #9

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

8
by: CAFxX | last post by:
i'm writing a program that executes some calculations on a bitmap loaded in memory. these calculation ends up with pixel wth values far over 255, but i need them to be between 0 and 255 since i...
2
by: Cincin | last post by:
We were building this forum application and we stumble on how to identify unread post. One thing would be to keep in the database what an user have seen but it doesn't seem doable because of the...
1
by: Kondapanaidu | last post by:
Hi, I am using C#.NET2.0, My Outlook Inbox is having some mails. My system Configured with Outlook, I need to capture the Unread mail subject line. How to capture the subject line from...
2
by: a | last post by:
keep a list of read and unread items hi guys i m building an rss reader and i want you suggestions for datastructure for keeping read and unread list for each use i m assuming it will be very...
1
by: PhilD | last post by:
My C#.NET console app checks a public folder every 24 hours for incoming emails. For each unread email in the folder, it copies any attachments to the network, then loads the contents of these files...
14
by: main() | last post by:
I know this is the problem that most newbies get into. #include<stdio.h> int main(void) { char a; scanf("%c",&a); /*1st scanf */ printf("%c\n",a); scanf("%c",&a); /*2nd scanf*/...
2
by: subramanian100in | last post by:
Consider the following program named as x.c #include <stdlib.h> #include <stdio.h> int main(void) { unsigned int u; char str;
30
by: George | last post by:
1 0001000000000000001 2 0001000000000000001 3 10000011001000000000000001 4 10000011001000000000000001 5 10000011001000000000000001 6 10000011001000000000000001 7 ...
17
by: vishal1082 | last post by:
i wanna get number of unread mails from mail servers, like gmail, yahoo, msn, aim and any other email server which user gives but the problem is - i dont know HOW (lol) i tried this DLL:...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.