Validate input to integer within a given range c - c

I am trying to get my input validated between a range and to type integer. Currently I have the following code.The range needed is 0-100 for X and 0-50 for Y.
for(loop=0;loop<3;loop++){
printf("\n\nEnter MAGENTA X coordinate from 0 to 100:\n");
scanf("%d",&mg[loop].x);
printf("\nEnter MAGENTA Y coordinate from %d to 50:\n");
scanf("%d",&mg[loop].y);
}
I need the option of the user ending the input prematurely with perhaps by entering "end" or something like that. This should then move onto the next color which is Yellow.
Does anyone know how I could implement this using scanf?
------EDIT-----
I've implemented the following and it defaults to "failure". I increased the handle to 2 and got the error end is being use without being initialized.
for(loop=0;loop<3;loop++){
printf("\n\nEnter MAGENTA X coordinate from 0 to 100:\n");
if(scanf("%d%c",&mg[loop].x) != 1 || end !='\n')
printf("failure");
else
printf("\nEnter MAGENTA Y coordinate from 0 to 50:\n");
scanf("%d",&mg[loop].y); /*Use the same validation here as above*/
}

You can use scanf, that's fine. Why not? scanf returns the number of items successfully read, so that 0 indicates a format error. After such you want to discard the remaining input before asking for another one.
Then you test the read variables against the boundaries.
You can specify a special value for the user's wish to exit, perhaps some string like "exit" which makes scanf fail whereupon you check whether it's "exit". The break command comes handy when you want to exit from a loop.

You can use scanf() but error reporting tends to be trickier. Minimally adapting your code:
for (loop = 0; loop < 3; loop++)
{
int rc;
printf("\n\nEnter YELLOW X coordinate from 0 to 100:\n");
while ((rc = scanf("%d", &ylw[loop].x)) == 1 &&
(ylw[loop].x < 0 || ylw[loop].y > 100)
printf("Enter a value between 0 and 100\n");
if (rc != 1)
{
fprintf(stderr, "Error reading x-value.\n");
break;
}
printf("\nEnter YELLOW Y coordinate from 0 to 50:\n");
while ((rc = scanf("%d", &ylw[loop].y)) == 1 &&
(ylw[loop].x < 0 || ylw[loop].y > 50)
printf("Enter a value between 0 and 50\n");
if (rc != 1)
{
fprintf(stderr, "Error reading y-value.\n");
break;
}
}
However, that repetition cries out for a function — albeit one with a modestly complex interface:
int prompt_for(const char *what, int min, int max, int err)
{
int value;
int rc;
printf("\nEnter %s from %d to %d:", what, min, max);
while ((rc = scanf("%d", &value)) == 1 && (value < min || value > max))
printf("Enter a value between %d and %d\n", min, max);
if (rc != 1)
{
fprintf(stderr, "Error reading %s.\n", what);
return err;
}
return value;
}
Sample use:
for (loop = 0; loop < 3; loop++)
{
ylw[loop].x = prompt_for("YELLOW X coordinate", 0, 100, -1);
if (ylw[loop].x == -1)
break;
ylw[loop].y = prompt_for("YELLOW Y coordinate", 0, 50, -1);
if (ylw[loop].y == -1)
break;
}
If you were using fgets() and sscanf(), you'd use:
int prompt_for(const char *what, int min, int max, int err)
{
int value;
int rc;
char line[4096];
printf("\nEnter %s from %d to %d:", what, min, max);
while (fgets(line, sizeof(line), stdin) != 0 &&
(rc = sscanf(line, "%d", &value)) == 1 &&
(value < min || value > max))
printf("Enter a value between %d and %d\n", min, max);
if (rc != 1)
{
fprintf(stderr, "Error reading %s.\n", what);
return err;
}
return value;
}
This isn't making much use of fgets(), though; it scores when you want multiple data items on a single line, because then you can report the whole line that was entered.
Warning: none of this code has been compiled

If you want to enforce that every input is on its own line of input (which is advisable when alternating prompt and reading from stdin), I recommend first reading a line into a temporary line buffer and then scanning that buffer with sscanf. Then check whether your input is valid in a last step.
Because this can clutter up your code, you might wright your own function for this:
/*
* Read an integer from stdin. Repeat until a valid number between
* lo and hi has been given. Returns 0 when a number was read and
* -1 when the input has run out.
*/
int read_int(int *x, int lo, int hi)
{
char buf[80];
char c;
for (;;) {
if (fgets(buf, sizeof(buf), stdin) == NULL) return -1;
if (sscanf(buf, "%d %c", x, &c) != 1 || *x < lo || *x > hi) {
printf("Please enter a single value between %d and %d.\n",
lo, hi);
} else {
break;
}
}
return 0;
}
You can then read your coordinates like so:
struct Coord ylw[3] = {{0, 0}};
int i;
for(i = 0; i < MAX; i++) {
printf("\n\nEnter YELLOW X coordinate #%d from 0 to 100:\n", i);
if (read_int(&ylw[i].x, 0, 100) < 0) break;
printf("\nEnter YELLOW Y coordinate #%d from 0 to 50:\n", i);
if (read_int(&ylw[i].y, 0, 50) < 0) break;
}
If the user types an eod-of-file character (Ctrl-D un Unix, Ctrl-Z on Windows), the number of coordinates can be cut short. If you want to end the input with a certain keyword, say "end", you can add this to your function by reading a string and checking first:
int read_int(int *x, int lo, int hi)
{
char buf[80];
char key[5];
char c;
for (;;) {
if (fgets(buf, sizeof(buf), stdin) == NULL) return -1;
if (sscanf(buf, "%4s ", key) == 1) {
if (strcmp(key, "end") == 0) return -1;
if (strcmp(key, "END") == 0) return -1;
}
if (sscanf(buf, "%d %c", x, &c) != 1 || *x < lo || *x > hi) {
printf("Please enter a single value between %d and %d.\n",
lo, hi);
} else {
break;
}
}
return 0;
}
(Scahhing a string from a string may seem redundant, but this way the user can type "end" after some spaces. You can also use a case-insensitive string comparison function.)

Related

Check for correct input via scanf

I have an integer 'n' that is responsible for amount of numbers to enter later on.
I need to check for any incorrect inputs here.
The first scanf for 'n' works fine, but the second has some flaws.
The case is following:
n = 3 (e.g.) - doesn't matter
Then I want to scanf: 1 2 3 4
It will be scanned first 3 values but I need to throw out an error.
Same goes with: 1 2 3.5 - (last number is float but it still reads 3)
and with a char: 1 2 3g
if (scanf("%d", n) == 1 && getchar() == '\n') {
if (n > NMAX || n < 0) {
error = 1;
return;
}
for (int i = 0; i < n; i++) {
if (scanf("%d", p) == 1) {
The ONLY correct input is the exact same amount of integer numbers (equals to 'n') to scan in a for loop.
UPD: I can use only <stdio.h> library as well as only scanf.
Create a helper function to read an int and validate it.
The key is that to validate input, form a helper function that you can improve as needed, like using fgets() rather than scanf() once the poor "only scanf" requirement is removed.
// Sample
// Return 1 on success
// Return EOF on end-of-file
// Else return 0
int read_int(int *i, int min, int max, int line) {
long long num;
int result = scan("%18lld", &num); // Accept many out of int range input
if (result == EOF) return result; // or if (result < 0)
if (line) {
// consume the rest of the line
int ch;
while ((ch = getchar()) != '\n' && ch != EOF) {
if (!isspace(ch)) { // or `ch != ' ' && `ch != '\t' && ...
result == 0;
}
}
}
if (result == 1) {
if (num < min || num > max) {
return 0;
}
*i = (int) num;
}
return result;
}
Sample usage
if (read_int(&n, 0, NMAX, 1) != 1) {
error = 1;
return;
}
for (int i = 0; i < n; i++) {
if (read_int(&p, INT_MIN, INT_MAX, i + 1 == n) != 1) {
error = 1;
return;
}
...
Note: read_int() does not catch all errors, just many of them. Easy enough to improve, once all OP's limitations and goals are known.
Try using scansets with scanf. %1[\n] will scan up to one character that is a newline. %99[ \t] will scan up to 99 characters that are space or tab. If the character is not a newline, space or tab, it is replaced in the input stream.
If scanf with %d can't scan an int, it will return 0. scanf could also return EOF.
fgets and parse with strtol or others is the better solution.
#include <stdio.h>
int main ( void) {
char space[100] = "";
char newline[2] = "";
int number = 0;
int count = 0;
int quantity = 3;
printf ( "enter %d integers\n", quantity);
while ( 1) {
if ( 1 == scanf ( "%d", &number)) {
++count;
}
else {
printf ( "could not parse an integer\n");
break;
}
scanf ( "%99[ \t]", space);
if ( 1 == scanf ( "%1[\n]", newline)) {
if ( count == quantity) {
printf ( "scanned %d integers\n", quantity);
break;
}
else if ( count > quantity) {
printf ( "too many integers\n");
break;
}
else printf ( "enter another integer\n");
}
}
return 0;
}
Check if this works
while(n-1)
{
scanf("%d ",p);
n-=1;
}
scanf("%d",p);
//After this you can scan again to check if there is anything extra in input
//and throw error accordingly

how to get program to accept only positive integer values in c

writing a program that will be finding min, max, avg of values entered by user. Having trouble writing something that will check to make sure there are only postive integers entered and produce an error message. heres my for statement that is reading the input so far:
for (int value = 0; value <= numofvals; ++value) {
printf("Value %d: %f\n", value, val_input);
scanf("%f", &val_input);
}
mind you I've been learning code for about 3 weeks and was just introduced to loops this week so my understanding is rudimentary at best!
First, don't use scanf. If stdin doesn't match what it expects it will leave it in the buffer and just keep rereading the same wrong input. It's very frustrating to debug.
const int max_values = 10;
for (int i = 0; i <= max_values; i++) {
int value;
if( scanf("%d", &value) == 1 ) {
printf("Got %d\n", value);
}
else {
fprintf(stderr, "I don't recognize that as a number.\n");
}
}
Watch what happens when you feed it something that isn't a number. It just keeps trying to read the bad line over and over again.
$ ./test
1
Got 1
2
Got 2
3
Got 3
foo
I don't recognize that as a number.
I don't recognize that as a number.
I don't recognize that as a number.
I don't recognize that as a number.
I don't recognize that as a number.
I don't recognize that as a number.
I don't recognize that as a number.
I don't recognize that as a number.
Instead, use fgets to reliably read the whole line and sscanf to parse it. %f is for floats, decimal numbers. Use %d to recognize only integers. Then check if it's positive.
#include <stdio.h>
int main() {
const size_t max_values = 10;
int values[max_values];
char buf[1024];
size_t i = 0;
while(
// Keep reading until we have enough values.
(i < max_values) &&
// Read the line, but stop if there's no more input.
(fgets(buf, sizeof(buf), stdin) != NULL)
) {
int value;
// Parse the line as an integer.
// If it doesn't parse, tell the user and skip to the next line.
if( sscanf(buf, "%d", &value) != 1 ) {
fprintf(stderr, "I don't recognize that as a number.\n");
continue;
}
// Check if it's a positive integer.
// If it isn't, tell the user and skip to the next line.
if( value < 0 ) {
fprintf(stderr, "Only positive integers, please.\n");
continue;
}
// We got this far, it must be a positive integer!
// Assign it and increment our position in the array.
values[i] = value;
i++;
}
// Print the array.
for( i = 0; i < max_values; i++ ) {
printf("%d\n", values[i]);
}
}
Note that because the user might input bad values we can't use a simple for loop. Instead we loop until either we've read enough valid values, or there's no more input.
Something easy like this may work for you:
int n;
int ret;
for (;;) {
ret = scanf("%d", &n);
if (ret == EOF)
break;
if (ret != 1) {
puts("Not an integer");
for (;;)
if (getchar() == '\n')
break;
continue;
}
if (n < 0) {
puts("Not a positive integer");
continue;
}
printf("Correct value %d\n", n);
/* Do your min/max/avg calculation */
}
/* Print your results here */
This is just an example and assumes you do not need to read floating point numbers and then check if they are integers, as well as a few other things. But for starters, it is simple and you can work on top of it.
To break out of the loop, you need to pass EOF (typically Ctrl+D in Linux/macOS terminals, Ctrl+Z in Windows ones).
An easy and portable solution
#include <limits.h>
#include <stdio.h>
int get_positive_number() {
char buff[1024];
int value, ch;
while (1) {
printf("Enter positive number: ");
if (fgets(buff, 1023, stdin) == NULL) {
printf("Incorrect Input\n");
// Portable way to empty input buffer
while ((ch = getchar()) != '\n' && ch != EOF)
;
continue;
}
if (sscanf(buff, "%d", &value) != 1 || value < 0) {
printf("Please enter a valid input\n");
} else {
break;
}
}
return value;
}
void solution() {
// Handling malformed input
// Memory Efficient (without using array to store values)
int n;
int min = INT_MAX;
int max = INT_MIN;
double avg = 0;
printf("Enter number of elements: ");
scanf("%d", &n);
getc(stdin);
int value;
for (int i = 0; i < n; i++) {
value = get_positive_number();
if (value > 0) {
if (min > value) {
min = value;
}
if (max < value) {
max = value;
}
avg += value;
}
}
avg = avg / n;
printf("Min = %d\nMax = %d\nAverage = %lf\n", min, max, avg);
}
int main() {
solution();
return 0;
}
Output:
Enter number of elements: 3
Enter positive number: 1
Enter positive number: 2
Enter positive number: a
Please enter a valid input
Enter positive number: -1
Please enter a valid input
Enter positive number: 1
Min = 1
Max = 2
Average = 1.333333

Characters as numbers, comparing them

I've recently started programming and currently i'm working on a game.
In this game i need to compare current input with the last input from an array.
It's really easy in number systems up to decimal.
Here is the code that i've written and works with numbers from systems up to decimal.
#include <stdio.h>
#define Max_size 256
#define N 36
void Game(int NumberSystem,int MaxRepetitions,char *Player1,char *Player2);
int main (void)
{
int temp,status,NumberSystem,MaxRepetitions ;
char Player1 [Max_size] ;
char Player2 [Max_size] ;
printf("Please enter the first player's name\n");
scanf("%s",&Player1);
printf("Please enter the second player's name\n");
scanf("%s",&Player2);
printf("Please enter a Number System between %d and %d\n",4,35);
status = scanf("%d",&NumberSystem );
while( NumberSystem > 35 || NumberSystem < 4 || status != 1 )
{
while((temp=getchar()) != EOF && temp != '\n');
printf("Please enter a valid Number System \n");
status = scanf("%d", &NumberSystem );
}
printf("Please enter a Number of maximum repetitions\n");
status = scanf("%d",&MaxRepetitions);
while( (MaxRepetitions<= 0) || (status != 1) )
{
while((temp=getchar()) != EOF && temp != '\n');
printf("Please enter a valid number of maximum repetitions\n");
status = scanf("%d",&MaxRepetitions);
}
Game(NumberSystem,MaxRepetitions,Player1,Player2);
}
void Game(int NumberSystem,int MaxRepetitions,char *Player1,char *Player2)
{
int status,counter,k,i,temp;
char fnumber,number;
counter = k = 1;
int *array1 = malloc(MaxRepetitions*NumberSystem*sizeof(int));
int *array2 = malloc(NumberSystem*sizeof(int));
char CharArray[N] = {'0','1','2','3', '4','5','6','7','8','9','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};
for(i=0; i<NumberSystem*sizeof(int),i++;)
array2[i] = 0;
printf("Let's start the game! %s begins.\n",Player1);
status = scanf("%d",&fnumber);
while(status != 1 || fnumber <= 0 || fnumber>NumberSystem-1)
{
while((temp=getchar()) != EOF && temp != '\n');
printf("First number must be a positive decimal number between %d and %d\n",1,NumberSystem-1);
status = scanf("%d", &fnumber);
}
array1[0] = fnumber;
array2[fnumber]++;
while( array2[number] < MaxRepetitions)
{
status = scanf("%d",&number);
while(status != 1 || number < 0 || number>NumberSystem-1 || ( (array1[k-1]!= NumberSystem-1) && (array1[k-1] >= number) ) )
{
while((temp=getchar()) != EOF && temp != '\n');
printf("You must enter a number greater than %d and smaller or equal to %d\n",array1[k-1],NumberSystem-1);
status = scanf("%d", &number);
}
array2[number]++;
array1[k] = number;
k++;
counter++;
}
if(counter%2 == 0)
{
printf("%s entered %d for the %dth time and exceeded the possible limit. %s won!",Player2,array1[k-1],MaxRepetitions,Player1);
}
else
{
printf("%s entered %d for the %dth time and exceeded the possible limit. %s won!",Player1,array1[k-1],MaxRepetitions,Player2);
}
free (array1);
free (array2);
}
Problem is i'd like it to be possible to play with greater numeric systems for example hexadecimal. I'm stuck at comparing value of the currently entered letter with letter that was entered before.
I'm seeking for any advice or suggestions.
Also if i did something really dumb in the first code (which probably i did) i would be glad to hear constructive criticism from you guys.
Thank you!
Here is the code to the "2nd" version where i tried to make this work with greater numeric systems. It's buggy and i don't know what have i done wrong.
#include <stdio.h>
#define Max_size 256
#define N 36
void Game(int NumberSystem,int MaxRepetitions,char *Player1,char *Player2);
int main (void)
{
int temp,status,NumberSystem,MaxRepetitions ;
char Player1 [Max_size] ;
char Player2 [Max_size] ;
printf("Please enter the first player's name\n");
scanf("%s",&Player1);
printf("Please enter the second player's name\n");
scanf("%s",&Player2);
printf("Please enter a Number System between %d and %d\n",4,35);
status = scanf("%d",&NumberSystem );
while( NumberSystem > 35 || NumberSystem < 4 || status != 1 )
{
while((temp=getchar()) != EOF && temp != '\n');
printf("Please enter a valid Number System \n");
status = scanf("%d", &NumberSystem );
}
printf("Please enter a Number of maximum repetitions\n");
status = scanf("%d",&MaxRepetitions);
while( (MaxRepetitions<= 0) || (status != 1) )
{
while((temp=getchar()) != EOF && temp != '\n');
printf("Please enter a valid number of maximum repetitions\n");
status = scanf("%d",&MaxRepetitions);
}
Game(NumberSystem,MaxRepetitions,Player1,Player2);
}
void Game(int NumberSystem,int MaxRepetitions,char *Player1,char *Player2)
{
int status,counter,k,i,temp;
char fnumber,number;
counter = k = 1;
char *array1 = malloc(MaxRepetitions*NumberSystem*sizeof(char));
int *array2 = malloc(NumberSystem*sizeof(int));
char CharArray[N] = {'0','1','2','3', '4','5','6','7','8','9','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};
for(i=0; i<NumberSystem*sizeof(int),i++;)
array2[i] = 0;
printf("Let's start the game! %s begins.\n",Player1);
//scanf("%c",&fnumber); // This part is ignored completely i don't know why
status = 0;
// for(i=0; i<NumberSystem-1; i++)
//{if(fnumber == CharArray[i]) status = 1;}
printf("Current status : %d\n",status);
while(status == 0)
{
while((temp=getchar()) != EOF && temp != '\n');
scanf("%c", &fnumber);
for(i=0; i<NumberSystem-1; i++)
if(fnumber == CharArray[i]) status = 1;break;
printf("First number must be a positive decimal number between %d and %d (in %d number system)\n",1,NumberSystem-1,NumberSystem);
}
array1[0] = fnumber;
array2[fnumber]++;
printf("Przed druga petla array1[0] : %c,array2[fnumber] : %d\n",array1[0],array2[fnumber]);
while( array2[k] < MaxRepetitions)
{
scanf("%c",&number);
status = 0;
for(i=0; i<NumberSystem-1; i++)
if(number == CharArray[i]) status = 1;
while(status == 0 || ( (array1[k-1] != CharArray[NumberSystem-1]) && (array1[k-1] >= number) ) )
{
while((temp=getchar()) != EOF && temp != '\n');
printf("You must enter a number greater than %c and smaller or equal to %d\n",array1[k-1],NumberSystem-1);
scanf("%c", &number);
status = 0;
for(i=0; i<NumberSystem-1; i++)
if(number == CharArray[i]) status = 1;break;
}
array2[number]++;
array1[k] = number;
k++;
counter++;
}
if(counter%2 == 0)
{
printf("%s entered %d for the %dth time and exceeded the possible limit. %s won!",Player2,array1[k-1],MaxRepetitions,Player1);
}
else
{
printf("%s entered %d for the %dth time and exceeded the possible limit. %s won!",Player1,array1[k-1],MaxRepetitions,Player2);
}
free (array1);
free (array2);
}
As far as I can understand what you want to do, you are not far from the solution. But I would recommend to use %1s instead of %c to read your characters. %c accept any characters including blank and newline. In the opposite, %1s will skip all eventual blanks and newline.
Simply, as %1s gives a null terminated string, you have to use an array (char anumber[2];), read one character into the array (the second will be\0`) and affect it to the char you use. For example, you have just to replace
scanf("%c", &fnumber);
with
scanf("%1s", anumber);
fnumber = anumber[0];

Taking Input from user and storing it in an array

I'm really new to C so it would be great if someone could tell me how I can do this:
I am trying to get user input using fgets. So if the user enters the following integers:
1 2 3 4 5
How do i scan them and put them in an array of ints= [1,2,3,4,5]
Here is what I am trying to do right now: I am continuously looping and asking the user to input a number until the user does not put anything. In each iteration, I am saving the input of the user to the array
int myArray[200];
char input_str[1024];
fprintf(stdout, "Enter numbers: ");
if (fgets(input_str, sizeof(input_str), stdin) == 0){
fprintf(stderr, "Error returned from fgets()...\n");
exit(1);
}
sscanf(input_str, "%d", &n);
myArray[i]=n;
//The while loop will continue as long as the string is not null
while( input_str[0]!='\0'){
if (fgets(input_str, sizeof(input_str), stdin) == 0){
break;
}
for (i=1;i<201;i++){
sscanf(input_str, "%d", &n);
myArray[i]=n;
}
}
#include <stdio.h>
int main(void){
int myArray[200];
char input_str[1024];
int i, n = 0;
size_t full = sizeof(myArray)/sizeof(*myArray);
fprintf(stdout, "Enter numbers: ");
while(fgets(input_str, sizeof(input_str), stdin) != NULL){
char *p = input_str;
int v, len;
if(*input_str == '\n' || n == full)
break;//input end if blank line
while(1==sscanf(p, "%d%n", &v, &len)){
myArray[n++] = v;
p += len;
if(n == full)
break;
}
}
//check print
for (i=0;i<n;i++)
printf("%d ", myArray[i]);
return 0;
}

A basic/ manual way to check that a value entered by the user is numeric

I've searched in and out of these forums but am still having trouble. My understanding of C is still very basic. I'm creating a small program that takes 3 numerical values entered by the user and then calculates the highest. I nailed that.
I now want to ensure that the user enters only integer values. I managed to get the prog to keep prompting the user to re-enter the value until it is within the specified numerical range (for example, any number between 1 and 1000 inclusive, piece of cake) but that's not good enough. I used 3 while loops to test each value, but this only works as long as the input is of type integer.
The trick is I cant use built in functions. It needs to be manual (sorry, poor choice of words) I tried to use char variables and x = getchar(); to get the ASCII value and test it in a condition but I can't get it working in a loop. (while/ do-while)
I also tried using a "for loop" and array variables but once again am struggling to get it to keep prompting the user.
I've also tried to test the value returned by scanf to see if its integer but my knowledge level of correct C syntax is level: noob. Either my loops don't loop or they loop infinitely.
Here is some sample code:
int x, y, z =0;
printf("Enter the first number:\n");
scanf("d", &x);
while (condition) /* Here is where I need to determine that the entered val is false */
{
printf("Wrong input. Re-enter a valid value.\n");
x =0;
scanf("%d", &x); /*user re-prompted */
}
I'm getting the idea that I'll have to use ASCII and a loop, but I just can't get to it. Also, the values entered get sent to a function for comparing and are then returned.
Could someone give me some advice and a few tips please?
Much thanks
You would have to use something like fgets, and strtol:
long someValue;
char *bufEnd = NULL;
char buf[128]; // max line size
do {
printf("enter a value: ");
fgets(buf, 128, stdin);
someValue = strtol(buf, &bufEnd, 10); // base 10
} while (bufEnd == buf || *bufEnd != '\n');
printf("got value: %li", someValue);
What we are doing here is we are tapping into strtol's capability to tell us where it stopped parsing, by passing in bufEnd.
Then, we are making sure that bufEnd doesn't point to the beginning of buf (in which case, it didn't start with a number), and also checking to make sure that bufEnd points to \n, or the end of the line (making sure that the user didn't enter something like 123abc, which strtol would interpret as 123). You may wish to trim buf of whitespace characters first, however.
You're absolutely on the right track with "scanf()". Just check the return value. If you don't get the expected #/values, then you got invalid input:
char found = FALSE;
int ival;
double x;
while (!found)
{
printf("Please enter a valid integer: ");
if (scanf("%d", &ival) !=1) {
printf ("Invalid! Please re-enter!\n");
continue;
}
printf("Please enter a valid floating point number: ");
if (scanf("%lf", &x) !=1) {
printf ("Invalid! Please re-enter!\n");
continue;
}
found = TRUE;
}
Here's my solution. It safe against buffer overflow and straightforward .
#include <stdio.h>
#define LEN 10
int main() {
int a;
char str[LEN];
fgets( str, LEN, stdin );
while ( !sscanf( str, "%d", &a ) )
fgets( str, 10, stdin );
printf("Num is : %d\n", a);
return 0;
}
#include <stdio.h>
#include <limits.h>
#include <ctype.h>
int getInteger(int* err){
int ch;
int n;//int32
int takeNum, sign;
long long int wk;//long long int as int64
wk=0LL;
*err = 0;
takeNum = 0;//flag
sign = 1;//minus:-1, other:1
/* //skip space character
while(EOF!=(ch=getchar()) && (ch == ' ' || ch == '\t' || ch == '\n'));
ungetc(ch, stdin);
*/
while(EOF!=(ch=getchar())){
if(ch == '-'){
if(takeNum != 0){//in input number
*err = 1;
break;
}
if(sign == -1){//already sign
*err = 2;
break;
}
sign = -1;
continue;
}
if(ch >= '0' && ch <= '9'){//isdigit(ch) in ctype.h
if(takeNum == 0)
takeNum = 1;
wk = wk * 10 + (ch - '0')*sign;
if(INT_MAX < wk || INT_MIN > wk){//overflow
*err = 3;
break;
}
continue;
}
if(ch != '\n'){//input other [-0-9]
*err = 4;
}
break;
}
if(takeNum == 0){//not input number
*err = 5;
} else {
n=wk;
}
while(ch != '\n' && EOF!=(ch=getchar()));//skip to newline
return n;
}
int getValue(const char* redoprompt, int low, int high){
int num, err=0;
while(1){
num = getInteger(&err);
if(err || low > num || high < num)
printf("%s", redoprompt);
else
break;
}
return num;
}
#define max(x,y) ((x)>(y))? (x) : (y)
int main(){
const char *error_message = "Wrong input. Re-enter a valid value.\n";
int x, y, z, max;
x = getValue(error_message, 1, 1000);
y = getValue(error_message, 1, 1000);
z = getValue(error_message, 1, 1000);
max = max(max(x,y), z);
printf("max:%d\n", max);
return 0;
}

Resources