问题
I currently am stuck on a small part of an assignment I need to do. One requirement of the assignment is
"Call a function that prompts the user for each of the values of the coefficients a, b, and c for the quadratic equation and returns the value entered, with error checking for a valid input (scanf returned a value)."
and I can't figure out how to do this. I can easily prompt the user for input and I can check if it is valid input, but I don't know how to turn this into a function. My current code is:
{
if (isalpha(a))
{
printf("INPUT ERROR!\n");
printf("Enter a value for a: ");
scanf("%d", &a);
}
} //this is how I would normally check the input
int main(void) //start of main() function definition
{
int a, b, c, n, D; //declares integer variables a, b, c, n, and D
float root1, root2; //declares float variables root1 and root2
do //do while loop starts here
{
printf("Enter a value for a: "); //prompts user to input integer for variable 'a'
scanf("%d", &a); //reads an integer from the keyboard and stores in the variable 'a'
printf("%d\n", a); //returns value of integer that was input for variable 'a'
printf("Enter a value for b: "); //prompts user to input integer for variable 'b'
scanf("%d", &b); //reads an integer from the keyboard and stores in the variable 'b'
printf("%d\n", b); //returns value of integer that was input for variable 'b'
printf("Enter a value for c: "); //prompts user to input integer for variable 'c'
scanf("%d", &c); //reads an integer from the keyboard and stores in the variable 'c'
printf("%d\n", c); //returns value of integer that was input for variable 'c'
...}
Sorry for any formatting mistakes, but that is basically the part of the program I am stuck with.
My question is, how can I combine the first function with everything in the do/while loop to make one big function that I can call three times?
I don't know how I'd be able to switch out all the instances of a for b and c using a function, as I've never really had to use a function like this before.
回答1:
scanf()
already processes the input for you according to the format specifier (%d
) so you just need to understand how scanf
works and use it to check and build your function :)
When you write scanf("%d", &a);
the program expects you write an integer because of the %d
specifier, and if an integer is read, the program writes it into variable a
.
But the function scanf
also has a return value, ie, you can do check = scanf("%d", &a);
and check
will have a value of 0 or 1 in this case. This is because the return value records how many values have been successfuly read. If you entered dsfugnodg
there's no number so it would return 0. If you entered 659 32
it would read the 1st value successfully and return 1.
Your function would look something like:
#include <stdio.h>
int getAndPrint(char label)
{
int n = 0, val = 0;
do {
printf("Enter a value for %c: ", label);
n = scanf("%d", &val);
if (n == 0) {
printf("Error, invalid value entered.\n");
/* Consume whatever character leads the wrong input
* to prevent an infinite loop. See:
* https://stackoverflow.com/questions/1669821/scanf-skips-every-other-while-loop-in-c */
getchar();
}
} while (n == 0);
printf("%c = %d\n", label, val);
return val;
}
int main()
{
int a, b, c;
a = getAndPrint('a');
b = getAndPrint('b');
c = getAndPrint('c');
printf("a=%d, b=%d, c=%d\n", a, b, c);
}
See also: Scanf skips every other while loop in C
回答2:
Function that prompts user for integer value and checks for valid input
If users only entered valid integer text on a line-by-line basis, then code is easy:
// Overly idealized case
fputs(prompt, stdout);
char buf[50];
fgets(buf, sizeof buf, stdin);
int i = atoi(buf);
But users are good, bad and ugly and **it happens. If code wants to read a line, parse it for an in-range int
, and detect a host of problems, below is code that vets many of the typical issues of bogus and hostile input.
I especially interested in detecting overly long input as hostile and so invalid as a prudent design against hackers. As below, little reason to allow valid input for a 32-bit int
with more than 20 characters. This rational deserve a deeper explanation.
- End-of-file
- Input stream error
- Overflow
- No leading numeric test
- Trailing non-numeric text
- Excessive long line
First a line of input is read with fgets()
and then various int
validation tests applied. If fgets()
did not read the whole line, the rest is then read.
#include <limits.h>
#include <ctype.h>
// Max number of `char` to print an `int` is about log10(int_bit_width)
// https://stackoverflow.com/a/44028031/2410359
#define LOG10_2_N 28
#define LOG10_2_D 93
#define INT_DEC_TEXT (1 /*sign*/ + (CHAR_BIT*sizeof(int)-1)*LOG10_2_N/LOG10_2_D + 1)
// Read a line and parse an integer
// Return:
// 1: Success
// 0: Failure
// EOF: End-of-file or stream input error
int my_get_int(int *i) {
// Make room for twice the expected need. This allows for some
// leading/trailing spaces, leading zeros, etc.
// int \n \0
char buf[(INT_DEC_TEXT + 1 + 1) * 2];
if (fgets(buf, sizeof buf, stdin) == NULL) {
*i = 0;
return EOF; // Input is either at end-of-file or a rare input error.
}
int success = 1;
char *endptr;
errno = 0;
long value = strtol(buf, &endptr, 10);
// When `int` is narrower than `long`, add these tests
#if LONG_MIN < INT_MIN || LONG_MAX > INT_MAX
if (value < INT_MIN) {
value = INT_MIN;
errno = ERANGE;
} else if (value > INT_MAX) {
value = INT_MAX;
errno = ERANGE;
}
#endif
*i = (int) value;
if (errno == ERANGE) {
success = 0; // Overflow
}
if (buf == endptr) {
success = 0; // No conversion
}
// Tolerate trailing white-space
// Proper use of `is...()` obliges a `char` get converted to `unsigned char`.
while (isspace((unsigned char ) *endptr)) {
endptr++;
}
// Check for trailing non-white-space
if (*endptr) {
success = 0; // Extra junk
while (*endptr) { // quietly get rest of buffer
endptr++;
}
}
// Was the entire line read?
// Was the null character at the buffer end and the prior wasn't \n?
const size_t last_index = sizeof buf / sizeof buf[0] - 1;
if (endptr == &buf[last_index] && buf[last_index - 1] != '\n') {
// Input is hostile as it is excessively long.
success = 0; // Line too long
// Consume text up to end-of-line
int ch;
while ((ch = fgetc(stdin)) != '\n' && ch != EOF) {
;
}
}
return success;
}
Sample usage
puts("Enter a value for a: ", stdout);
fflush(stdout); // Insure output is seen before input.
int a;
if (my_get_int(&a) == 1) {
printf("a:%d\n", a);
}
回答3:
My question is, how can I combine the first function with everything in the do/while loop to make one big function that I can call three times?
Well, the function need not be big. The things to factor out are the prompt string and the variable to read - the latter can be left in the calling main()
and assigned from a return value. Regarding how you would normally check the input, I recommend leaving this checking to scanf()
and just test its return value.
#include <stdio.h>
#include <stdlib.h>
int input(char *prompt)
{ // prompts user to input integer
// reads an integer from standard input and returns it
int a, s; // leave it to scanf to check the input:
while (printf("%s", prompt), fflush(stdout), s = scanf("%d", &a), !s)
{
printf("INPUT ERROR!\n");
do s = getchar(); while (s != '\n' && s != EOF); // consume bad input
}
if (s == EOF) puts(""), exit(0); // no more input
return a;
}
In main()
you can then just do
a = input("Enter a value for a: ");
b = input("Enter a value for b: ");
c = input("Enter a value for c: ");
(without a loop).
回答4:
I think the following code is you wanted:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h> // for isalpha
void InputAndCheck(int * pValue, const char * pName)
{
do
{
printf("Enter a value for %s: ", pName);
scanf("%d", pValue);
if (isalpha(*pValue))
{
printf("INPUT ERROR!\n");
continue;
}
else
{
break;
}
} while (1);
// clear the input buffer
fflush(stdin);
return;
}
int main()
{
int a, b, c;
InputAndCheck(&a, "a");
InputAndCheck(&b, "b");
InputAndCheck(&c, "c");
printf("a=%d;b=%d;c=%d;\r\n",a,b,c);
return 0;
}
回答5:
What you are looking for is an introduction to functions. Here is one : https://www.tutorialspoint.com/cprogramming/c_functions.htm
This is a very important building block in programming and you should definitely learn to master that concept.
functions will allow you to execute some code in different contexts over and over, just changing the context (the parameters).
It is declared like this
int add(int first, int second){
//here we can use first and second
printf("first: %d\n", first);
printf("second: %d\n", second);
//and eventually return a value
return first+second;
}
Now when using we are reusing our previous code to excute a task which result will vary depending of the arguments we pass.
printf("1+2 = %d\n", add(1, 2));
-->3
printf("2+2 = %d\n", add(2, 2));
-->4
Example solution for your task:
//this will handle validation
int validateInput(int input){
if(isalpha(input)){
printf("INPUT ERROR!\n");
return 0;
}
return 1;
}
//this will prompt the user and return input only if the input is valid
int askForCoefficient(unsigned char coefficientName){
int valid = 0;
int value = 0;
while(!valid){
printf("Enter a value for %c: ", coefficientName);
value = scanf("%d", &value);
valid = validateInput(value);
}
printf("%d\n", value);
return value;
}
来源:https://stackoverflow.com/questions/52830100/function-that-prompts-user-for-integer-value-and-checks-for-valid-input