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

D

Dawn Minnis

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;
}
 
M

Mysidia

Dawn said:
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. */
}
 
D

Dawn Minnis

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.
 
C

CBFalconer

Dawn said:
.... 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.
 
L

Lawrence Kirby

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
 
K

kenuplus

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.
 
L

Lawrence Kirby

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
 

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,755
Messages
2,569,535
Members
45,007
Latest member
obedient dusk

Latest Threads

Top