468,458 Members | 1,855 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 468,458 developers. It's quick & easy.

problems writing a printf/scanf function that handles both int and char input from the console

Hi (running Win xp and developing using Miracle C. Running applications in
windows command prompt)

I'm new to the group so be gentle with me. I am currently writing a C
program to perform matrix by matrix (mxm) and matrix by vector (mxv)
multiplication, so obviously one of my first considerations is to ask the
user if they want an mxm or mxv multiplication performed. I have written the
code below (this is a working snippet of the current, substantially larger
program I am working on. My problem at the moment, is that when I run this
code and enter any integer from 0-9 it handles the error accordingly and
iterates around the loop until the values 1 or 2 are entered. Upon which it
prints "successful response" and finishes (again cut down and missing all
the other queries and algorithms).

Now, here comes the problem. When I enter in characters or symbols OTHER
than integers it spirals into a never ending loop, that I can only exit by
closing the command prompt window.

So, can anyone take a quick look at this program and spot for me what I
assume would be a glaringly obvious reason for this to happen? Such as the
use of int for the function declaration, or %d when reading in the value.
But I don't know how to correct the program so that it "accepts" all
possibilities and then handles them.

Thanks, kind regards
Dawn
-*-*-*-program
below-*-*-*-
-----------------------------------------------------------------------------------------------------------

#include <stdio.h>
#include <stdlib.h>

int main()
{
int doMMorMV;
printf("Do you wish to perform MxM or MxV? \nPlease enter 1 for MxM or 2 for
MxV: ");
scanf("%d", &doMMorMV);

while(doMMorMV != 1 && doMMorMV != 2)
{
//call reiterative error message 1
doMMorMV = error1();
}

printf("successful response");

return 0;
}

//reiterative error message 1
int error1()
{
int doMMorMV;
printf("\n Error, not a valid response, \n\t please enter 1 for MxM or 2 for
MxV: \n");
scanf("%d", &doMMorMV);
return doMMorMV;
}
Nov 14 '05 #1
6 2571

Dawn Minnis wrote:
int main()
{
int doMMorMV;
printf("Do you wish to perform MxM or MxV? \nPlease enter 1 for MxM or 2 for MxV: ");
scanf("%d", &doMMorMV);
Suppose the user enters 'blah'

Scanf will fail to read an integer, so it
will return 0, indicating zero items were scanned
successfully.

The value in 'doMMorMV' is not changed, since nothing was
scanned into it, its value is now undefined (could be anything)

'b' will remain at the start of the input, not consumed
by this scanf.

Meaning that the next scanf("%d", &doMMorMV); will also fail,
hence the endless loop.

try

if (scanf("%d", &doMMorMV) < 1) {
/* Error occured.. */

/* Note this does not mean the waiting input item has
been assumed. */
}
while(doMMorMV != 1 && doMMorMV != 2)
{
//call reiterative error message 1
doMMorMV = error1();
}


Nov 14 '05 #2
Thanks for your quick response

I have spent the last while trying different variations using that but it
doesn't seem to like it. I have moved on.

My next challenge is to read in a string and parse it as an integer. I am
attempting to use the atoi() function but it throws back a weird response.
eg if I pass it 234 it read in 2my. Any idea why this is?

also is there a C equivalent to declaring a string?

I only started programming in C about 3-4 weeks so the function calls are
very different. what I want to do is like this:

String userInput;
int intVal;
...
userInput = System.in.readln();
intVal = Integer.parseInt(userInput);
...

But thats java. And I need it in C.

"Mysidia" <my*****@gmail.com> wrote in message
news:11*********************@f14g2000cwb.googlegro ups.com...

Dawn Minnis wrote:
int main()
{
int doMMorMV;
printf("Do you wish to perform MxM or MxV? \nPlease enter 1 for MxM

or 2 for
MxV: ");
scanf("%d", &doMMorMV);


Suppose the user enters 'blah'

Scanf will fail to read an integer, so it
will return 0, indicating zero items were scanned
successfully.

The value in 'doMMorMV' is not changed, since nothing was
scanned into it, its value is now undefined (could be anything)

'b' will remain at the start of the input, not consumed
by this scanf.

Meaning that the next scanf("%d", &doMMorMV); will also fail,
hence the endless loop.

try

if (scanf("%d", &doMMorMV) < 1) {
/* Error occured.. */

/* Note this does not mean the waiting input item has
been assumed. */
}
while(doMMorMV != 1 && doMMorMV != 2)
{
//call reiterative error message 1
doMMorMV = error1();
}

Nov 14 '05 #3
Dawn Minnis wrote:
.... snip ...
Now, here comes the problem. When I enter in characters or symbols
OTHER than integers it spirals into a never ending loop, that I can
only exit by closing the command prompt window.

So, can anyone take a quick look at this program and spot for me
what I assume would be a glaringly obvious reason for this to
happen? Such as the use of int for the function declaration, or
%d when reading in the value. But I don't know how to correct the
program so that it "accepts" all possibilities and then handles
them.

.... snip unindented code with over long lines ...
(because it is too ugly to read)

In general, if you input values with scanf the char that terminates
the input or signals that the input cannot be done at all, remains
in the input stream. You have to get rid of it. Now lets change
your mechanism to something general (untested code, I am just
writing things down on the fly). Lets say you want to get one of
the chars in a specified string and reject everything else.
Meanwhile you want to prompt with something:

/* flush stdin until a '\n' or EOF occurs */
int flushln(void)
{
int ch;

while (('\n' != (ch = getchar())) && (EOF != ch)) continue;
return ch;
} /* flushln */

int getone(const char *prompt, const char* allowed)
{
int entered;

while (1) {
printf("%s", prompt); fflush(stdout);
entered = getchar();
flushln(); /* we only want the first line char */
if (strchr(allowed, entered)) { /* acceptable */
return entered; /* so return it */
}
else {
printf("Invalid entry '%c', retry:\n", entered);
}
}
} /* untested */

Which encapsulates prompting, getting a char, testing validity, and
retrying until the entry is valid. All assuming I have made no
silly goofs above.

So, to get your 1 or 2, you would call:

doMMorMV = getone("Enter 1 or 2 for M or V", "12");

which means you have the friendlier method of:

doMMorMV = getone("Enter M for MM, or V for MV:", "MV");
or
doMMorMV = getone("Enter M for MM, or V for MV:", "MmVv");

with confidence that you are getting something you expect and that
you have gobbled a complete input line. This simplifies life
greatly.

--
"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
Nov 14 '05 #4
On Mon, 07 Feb 2005 00:00:31 +0000, Dawn Minnis wrote:
Thanks for your quick response

I have spent the last while trying different variations using that but it
doesn't seem to like it. I have moved on.

My next challenge is to read in a string and parse it as an integer. I am
attempting to use the atoi() function but it throws back a weird response.
eg if I pass it 234 it read in 2my. Any idea why this is?

also is there a C equivalent to declaring a string?

I only started programming in C about 3-4 weeks so the function calls are
very different. what I want to do is like this:

String userInput;
int intVal;
...
userInput = System.in.readln();
intVal = Integer.parseInt(userInput);
...

But thats java. And I need it in C.


A good way to read line based input in C is the fgets() function, e.g.

char buffer[100];

if ((fgets(buffer, sizeof buffer, stdin) != NULL) {
int intVal;

if (sscanf(buffer, "%d", &intVal) != 1) {
/* Converison failed */
}
}

You could also use atoi() but that doesn't test for invalid input. A
better function is strtol() which handled bad input including values too
large, but is a bit more complex to use correctly.

Lawrence
Nov 14 '05 #5
Hi.when getchar works,it firstly look at buffer ,If there is somethink
in buffer
it use what there is .On the contrary,if there is nothing in buffer,it
will wait input from user.After, user enter input and
enter('\n'),getchar only will take input not '\n'.'\n' will stay in
buffer.when again getchar() works,it will take '\n' at buffer,In other
words,getchar() won't wait user's input.so if you cope with your
problem,use flush(stdin) to clear buffer.
CBFalconer <cb********@yahoo.com> wrote in message news:<42***************@yahoo.com>...
Dawn Minnis wrote:

... snip ...

Now, here comes the problem. When I enter in characters or symbols
OTHER than integers it spirals into a never ending loop, that I can
only exit by closing the command prompt window.

So, can anyone take a quick look at this program and spot for me
what I assume would be a glaringly obvious reason for this to
happen? Such as the use of int for the function declaration, or
%d when reading in the value. But I don't know how to correct the
program so that it "accepts" all possibilities and then handles
them.

... snip unindented code with over long lines ...
(because it is too ugly to read)

In general, if you input values with scanf the char that terminates
the input or signals that the input cannot be done at all, remains
in the input stream. You have to get rid of it. Now lets change
your mechanism to something general (untested code, I am just
writing things down on the fly). Lets say you want to get one of
the chars in a specified string and reject everything else.
Meanwhile you want to prompt with something:

/* flush stdin until a '\n' or EOF occurs */
int flushln(void)
{
int ch;

while (('\n' != (ch = getchar())) && (EOF != ch)) continue;
return ch;
} /* flushln */

int getone(const char *prompt, const char* allowed)
{
int entered;

while (1) {
printf("%s", prompt); fflush(stdout);
entered = getchar();
flushln(); /* we only want the first line char */
if (strchr(allowed, entered)) { /* acceptable */
return entered; /* so return it */
}
else {
printf("Invalid entry '%c', retry:\n", entered);
}
}
} /* untested */

Which encapsulates prompting, getting a char, testing validity, and
retrying until the entry is valid. All assuming I have made no
silly goofs above.

So, to get your 1 or 2, you would call:

doMMorMV = getone("Enter 1 or 2 for M or V", "12");

which means you have the friendlier method of:

doMMorMV = getone("Enter M for MM, or V for MV:", "MV");
or
doMMorMV = getone("Enter M for MM, or V for MV:", "MmVv");

with confidence that you are getting something you expect and that
you have gobbled a complete input line. This simplifies life
greatly.

Nov 14 '05 #6
On Tue, 08 Feb 2005 04:15:21 -0800, kenuplus wrote:
Hi.when getchar works,it firstly look at buffer ,If there is somethink
in buffer
it use what there is .On the contrary,if there is nothing in buffer,it
will wait input from user.After, user enter input and
enter('\n'),getchar only will take input not '\n'.'\n' will stay in
buffer.when again getchar() works,it will take '\n' at buffer,In other
words,getchar() won't wait user's input.so if you cope with your
problem,use flush(stdin) to clear buffer.


C has no function called flush() and fflush(stdin) is a serious error in
C, invoking fflush() on input streams invokes undefined behaviour. The
implication here is that you want to read input by line. A good way of
doing that is to use fgets() and then parse the input using C's string
handling facilities.

Lawrence

Nov 14 '05 #7

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

8 posts views Thread by CAFxX | last post: by
7 posts views Thread by jmac | last post: by
7 posts views Thread by happy | last post: by
3 posts views Thread by happy | last post: by
reply views Thread by kmladenovski | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.