int getIndex(){
int index = 0;
do{
printf("Enter your Index(0..80),-1 to STOP,-2 to RESTART,-3 to START NEW BOARD: ");
scanf("%d", &index);
} while (!(index >= -3 && index <=80));
return index;
}
Hello, given that i have written the above method in C for a sudoku game board . what can i do to prevent the user from entering a alphabet? and keep prompting until the valid input is gotten. i have just started C .what is limiting me is the scanf flag specifier, i specified a int flag which means if a user enters a string, im screwed.
All you need is to check the return value of scanf and then clear the character from the input buffer(stdin) if any invalid input was entered. So change your code to the following:
int getIndex()
{
int index = 0;
while(1) //infinite loop
{ printf("Enter your Index(0..80),-1 to STOP,-2 to RESTART,-3 to START NEW BOARD: ");
if(scanf("%d", &index)==1) //scanf is successful scanning a number(input is a number)
{
if(index >= -3 && index <= 80) // if input is in range
break; //break out of while loop
printf("Number must be in range of -3 to 80\n"); //input is a number,but not in range
}
else //input is not a number
{
scanf("%*s"); //Clear invalid input
//printf("Invalid input\n");
fprintf(stderr, "Invalid input\n"); //printf also works but errors are meant to be in the stderr
}
}
return index;
}
Related
My program only allows positive integers up to 200 to be entered. -1 and the rest of negative numbers are not allowed to be read, and for safety, the 10th digit is not allowed to be read, program should stop reading.
That is my code.
#include <stdio.h>
int main(void) {
int age[10] = {0}; // initalized an array
printf("Please enter ages: "); // allow user to enter numbers
for (int i = 0; i < 10; i++) {
if (age[i] == -1 || i > 9) { // if the element of is euqal to zero and 10th element
printf("invalid number");
break; // program stop
}
else if (age[i] < 0 || age[i] > 150 ){
printf("It is invalid number, the valid number is bigger than 0 and smaller than 150");
scanf("%d",&age[i]); // allow user enter again
}
else {
scanf("%d",&age[i]);
}
}
return 0;
}
The major question is that my code not stop reading when i enter the negative number.
Your program doesn't work, because you check if the numbers are negative, before you actually read them. Also, you check if i is greater than 9, which is redundant, since the for-loop already checks that. Finally, when the user enters an invalid number, you shouldn't just scanf a new one, because they might enter an invalid one again: you should instead run another iteration of the loop with the same i (decrease i by one and continue).
#include <stdio.h>
int main(void) {
int age[10] = {0}; // initalized an array
printf("Please enter ages: "); // allow user to enter numbers
for (int i = 0; i < 10; i++) {
printf("#%d: ",i);
scanf("%d",&age[i]); // allow user enter again
if (age[i] < 0 || age[i] > 150 ){
printf("It is invalid number, the valid number is bigger than 0 and smaller than 151...\n");
i--;
continue;
}
}
return 0;
}
I'm writing a program in C where I want a user to be able to change their existing PIN, the only requirement to allow pin to be able to be changed is that user must enter a new PIN that must be a 4 digit number of any combination including those that start with 0 (eg: 0000, 0297, 0005, 0050...) and the PIN must not contain any alphabetical characters
they must then re-enter their new PIN to confirm it
if re-entered pin matches the first newly entered pin then users will be assigned new pin.
if (temppin1 == temppin2)
I have initialised the temp pins to be an int, for comparison arguments like above.
here is a snippet of my code
case '2':
//program asks user to enter their new PIN.
printf("Enter your new PIN:\n");
scanf("%04d", &temp_pin1);
//program asks user to re-enter their new PIN.
printf("Please re-enter to confirm your new PIN:\n");
scanf("%04d", &temp_pin2);
//if the re-entered pin matches the temp_pin1 then then the program will assign the new PIN to the users actual_pin.
if (temp_pin1 == temp_pin2 && (isalpha(temp_pin1) == 0) && (temp_pin1 >= 1000 && temp_pin1 < 9999)) {
printf("\n\n New PIN has been confirmed\n\n");
actual_pin = temp_pin1;
}
//if the user input as letter, some other character or a number outside of the four digit including number starting with 0 range the program will give an appropriate error message.
else if ((temp_pin1 != temp_pin2) && ((temp_pin1 > 1000) && (temp_pin1 < 9999))) {
printf("error: your new PIN didn't match\n");
printf("We couldn't confirm your new PIN\n\n");
}
//all possible 4 digit are between this range and if a number is entered outside this range the user will be given an appropriate error message.
else if ((temp_pin1 < 1000) || (temp_pin1 > 9999)) {
printf("error: Your new pin didn't meet our 4 digit PIN criteria\n\n");
}
break;
I figured out you can use isalpha() == 0 to make sure the user input doesn't accept alphabetical numbers, I also figured out the range of of all possible 4 digit numbers that begin with (1,2,3,4,5,6,7,8,9). the last part I just need to figure out is how to let user 4 digit number that can begin with 0 (eg: 0000, 0297, 0005, 0050...) and store it with the initial 0, I know C will take inputed int numbers beginning with 0 as a null value so but I also need to compare the two variable and see if they are the same, maybe a different datatype needs to be used... but I'm not sure.
Any help, or insight into what I can do to solve this tricky validation problem would be very much appreciated.
scanf can be done using %n to capture the number of characters processed. This will reject inputs of 12, 005 or 12345. %d will only accept digits so abc will be rejected. No need for isalpha.
Clean the input with getchar. If any characters other than a newline are in the input stream. the input is rejected to prevent an input of 1234abc.
fgets can also be used to read a line. strspn will count the consecutive matching characters. The matching digits must be followed by a newline or the input is rejected.
Normally DO NOT MIX FGETS and SCANF. This uses both and will work only because after scanf, getchar cleans the input stream of pending characters.
#include <stdio.h>
#include <string.h>
int main ( void) {
char line[100] = "";
int temp_pin1 = 0;
int temp_pin2 = 0;
int result = 0;
int start = 0;
int end = 0;
int index = 0;
int clean = 0;
do {
if ( temp_pin1 != temp_pin2) {
printf ( "PIN does not match. re-enter PIN\n");
}
do {
if ( clean) {
printf ( "try again\n");
}
end = 0;
start = 0;
printf("Enter your new PIN:\n");
fflush ( stdout);
if ( ( result = scanf ( " %n%d%n", &start, &temp_pin1, &end))) {
if ( 4 != end - start) {
result = 0;
}
}
while ( ( clean = getchar ( ))) {
if ( '\n' == clean) {
break;
}
else {
result = 0;//found trailing characters
}
if ( EOF == clean) {
fprintf ( stderr, "End Of File\n");
return 1;
}
}
} while ( 1 != result);
clean = 0;
do {
if ( clean) {
printf ( "try again\n");
}
index = 0;
clean = 0;
printf("Please re-enter to confirm your new PIN:\n");
fflush ( stdout);
if ( fgets ( line, sizeof line, stdin)) {
index = strspn ( line, "0123456789");
clean = 1;
}
else {
fprintf ( stderr, "End Of File\n");
return 1;
}
} while ( 4 != index || '\n' != line[index]);
sscanf ( line, "%d", &temp_pin2);
} while ( temp_pin1 != temp_pin2);
printf ( "new PIN: %04d\n", temp_pin1);
return 0;
}
Testing isalpha(temp_pin1) makes no sense: you are testing if the PIN number is the ASCII code for a letter, which is irrelevant: 0065 is a valid PIN, but also happens to be the ASCII code for 'A'.
You should just read the PIN as an int an verify that it is in the range 0 to 9999 inclusive:
case '2':
//program asks user to enter their new PIN.
printf("Enter your new PIN:\n");
if (scanf("%d", &temp_pin1) != 1 || temp_pin1 < 0 || temp_pin1 > 9999) {
printf("invalid PIN: must be 4 digits\n");
break;
}
//program asks user to re-enter their new PIN.
printf("Please re-enter to confirm your new PIN:\n");
if (scanf("%d", &temp_pin2) != 1 || temp_pin1 != temp_pin2) {
printf("error: your new PIN didn't match\n");
printf("We couldn't confirm your new PIN\n\n");
break;
}
printf("\n\n New PIN has been confirmed\n\n");
actual_pin = temp_pin1;
break;
Your program is fully functional; there is no need for any change. 0008 is same as 8, as it is stored internally as an integer. There will not be any problem during comparison. If needed, you can change int to char[4] (or char[5] for the terminating null byte if you want to process it like a string) if necessary. Read the pin using
char temp_pin1[5];
scanf("%4s", temp_pin1);
or
char temp_pin1[4];
scanf("%c%c%c%c", &temp_pin1[0], &temp_pin1[1], &temp_pin1[2], &temp_pin1[3]);
And then check if the characters are numbers.
When I enter a letter the loop runs infinitely. Does a letter store as a zero when it is input as an int? How can I reject a non digit answer, just I have rejected an answer outside the range?
int main(int argc, const char * argv[]) {
// insert code here...
int categoryToScore;
int categoryScores = 6;
printf("Enter category to save score: ");
scanf("%d", &categoryToScore);
while (categoryToScore >= categoryScores || categoryToScore <= 0) {
printf("Error: invalid command. Enter 1-5 to save to an unused category\n");
printf("Enter category to save score: ");
scanf("%d", &categoryToScore);
}
return 0;
}
Just for background
I want to:
print a request an input that is between 1 and an upper bound
scanf for the input
check if the input is of a correct type and within the correct range
if it isn't then print an error message and go back to 1.
if it is then proceed
You are asking scanf to read a number from standard input. Scanf finds a non-digit character in the standard input and does not remove it from the standard input. Scanf fails and returns 0 (the number of fields successfully processed).
The next time you call scanf, it finds the same character at the start of standard input. So the process repeats indefinitely.
One solution is to read stdin one character at a time.
Another solution is to read (and discard) the one character from stdin before calling scanf again.
int main(int argc, const char * argv[]) {
// insert code here...
int categoryToScore;
int categoryScores = 6;
int scantRetVal;
printf("Enter category to save score: ");
scantRetVal = scanf("%d", &categoryToScore);
if (scantRetVal != 1) {
getchar(); // read and discard one character from stdin
categoryToScore = 0;
}
while (categoryToScore >= categoryScores || categoryToScore <= 0) {
printf("Error: invalid command. Enter 1-5 to save to an unused category\n");
printf("Enter category to save score: ");
scantRetVal = scanf("%d", &categoryToScore);
if (scantRetVal != 1) {
getchar(); // read and discard one character from stdin
categoryToScore = 0;
}
}
return 0;
}
Rather than fix this particular program I will show how to solve ANY similar problem using a concept called an "exit condition".
The idea of an exit condition is that you have an infinite loop and it has various exit conditions. Often there are two exit conditions: one for success and one for an error.
while( true ){ /* infinite loop */
char c = ... /* get the character you want */
if( c < '0' || c > '9' ){
printf( "invalid character, not a digit\n" );
continue; // get another character
}
... /* do whatever you with valid data */
if( c == '3' ) break; /* your exit condition, whatever it is */
if( c == '7' ) exit(0); /* exit the whole program */
}
Note: If you are accepting free form input (numbers and strings), scanf is probably not a good idea. scanf accepts very specific, well-formatted input. So if you ask for a %d, then there better be a %d (decimal number) in the input or you will have problems.
For example, if you accept numbers and strings, you should take everything as strings using fgets or something like that.
Here is a complete program that does what you want:
#include <stdio.h>
#include <stdbool.h>
int main(int argc, const char * argv[]) {
int iMaxScore = 6;
int charInput = 0;
int iInputValue = 0;
while( true ){
printf("Enter category to save score: ");
GetInput:
charInput = getchar();
if( charInput == 10 || charInput == 13 ) goto GetInput; /* ignore enter key */
if( charInput == 'q' ) break;
if( charInput < '0' || charInput > '9' ){
printf( "invalid entry, not a digit %d\n", charInput );
break;
}
iInputValue = charInput - '0';
if( iInputValue > iMaxScore ){
printf( "Error, input value exceeds maximum category %d\n", iMaxScore );
continue; /* try again */
}
printf( "you entered category %d\n", iInputValue );
/* continue ... */
}
return 0;
}
I am trying to make this run in a loop until a non-numeric input is given. The problem is that when I input a letter to exit the while loop, it goes into an infinite loop. It also goes into the first if statement and continues to loop through that. If someone has any ideas on how to fix this, it would be great.
int counter;
int input[100]
int num = 1
while (input[num] == 0)
{
printf("score #%d:", counter);
scanf("%d",&input[num]);
if (input[num] <= 0){
printf("you cannot use negative numbers\n");
continue;
}
if (input[num] >= 100){
printf("you cannot use numbers greater than 100\n");
continue;
}
num++;
counter++;
}
The problem is that when scanf is provided with a non-numeric input when you try reading with %d format, the non-numeric data does not get removed from the buffer. When your loop reaches scanf again, it gets the same data, and continues failing in an infinite loop.
To fix this, remove non-numeric input when scanf does not read a proper number of items:
int readCount = scanf("%d",&input[num]);
if (readCount != 1) {
scanf("%*s");
printf("Please enter a valid number.\n");
continue;
}
Note that your loop's ending condition is incorrect, because num is always past the last element that has been read. You can fix it like this:
while (num < 100)
{
... // Read and error checks go here
if (input[num] == 0) {
break;
}
num++;
counter++;
}
First of all,num is supposed to be 0 as array index starts from 0 not 1.
Then,you have input[num]==0 in the condition in the while . You test using an uninitialized variable as input has not been initialized. This is the same for counter.
Your code won't compile as you have missed the ; at the end of line 2 and 3.
Lastly,replace your scanf with the following code:
if(scanf("%d",&input[num])==0)
{printf("non-numeric character entered .Exiting loop...\n");
scanf("%*s");// asterick tells scanf to discard scanned string(clear the entered char)
break;
}
So finally,the modified code:
int counter=1; // initialize variable
int input[100]; //semicolon here
int num = 0; //num must be 0
while (1) //infinite loop
{
printf("score #%d:", counter);
if(scanf("%d",&input[num])==0) //if no value is scanned
{printf("non-numeric character entered .Exiting loop...\n");
scanf("%*s");// asterick tells scanf to discard scanned string(clear the entered char)
break;
}
if (input[num] <= 0 )
printf("you cannot use negative numbers\n");
else if (input[num] >= 100)
printf("you cannot use numbers greater than 100\n");
else{
num++;
counter++;}
}
Homework Assignment #2 for Program Design Class
Part 1:
Prompt user for 8 digit account number (0-9), repeat until valid.
Part 2:
Prompt user to set 4 digit pin number (0-9), repeat until valid.
Prompt user to verify pin number, return to Part 2 if invalid.
The program works, however, I'd like to validate for some extra things:
Accept leading zeros ex., '00123456'
Reject additional letters ex., '12345678a'
Reject additional 'words' ex., '12345678 123abc'
I'm thinking, prompt for a string input, check the length of it (4 or 8) and if it passes that test, convert it to an integer and proceed with the tests in place.
Any thoughts?
[ A lot of you dislike the use of scanf, I know. I'm more interested in how I can make minimal changes to my program instead of reinventing [my] wheel! :) ]
#include <stdio.h>
int main()
{
int return_val = 0;
int account_number = 0;
int pin_number = 0;
int pin_number_verify = 0;
int valid_pin = 0;
// Account # Validation
while(1)
{
printf ("Please enter your 8 digit account number:\n");
return_val = scanf("%d", &account_number);
if((account_number > 9999999) && (account_number < 99999999))
{
if (return_val == 1)
{
break;
}
}
printf("Invalid account number. Account number must be 8 digits.\n\n");
while (getchar() != '\n'); /* Clear keyboard input buffer */
}
return_val = 0;
// Pin # Validation
while(1)
{
printf ("\nPlease choose a 4 digit pin number:\n");
return_val = scanf("%d", &pin_number);
while (getchar() != '\n'); /* Clear keyboard input buffer */
if((pin_number > 999) && (pin_number < 9999))
{
if (return_val == 1)
{
while(1)
{
printf("Re-enter pin number:\n");
return_val = scanf("%d", &pin_number_verify);
while (getchar() != '\n'); /* Clear keyboard input buffer */
if(pin_number != pin_number_verify)
{
printf("Pin setup unsuccessful\n\n");
break;
}
else
{
valid_pin = 1;
break;
}
}
}
}
if (valid_pin == 1) {
break;
}
printf("Invalid pin number. Pin number must be 4 digits.\n");
while (getchar() != '\n'); /* Clear keyboard input buffer */
}
// Successful account setup prompt
printf("\nPin setup successful!\n");
printf("Account #: %d\n", account_number);
printf("Pin #: %d\n", pin_number);
printf("Have a nice day.\n");
return 0;
}
I have done a similar approach by having a char array, then used a function that accept the right amount of digit, which can include alphabets or special signs, and used a validating function to validate the input all a series of digits to pass validation. all depending on the requirements!
you also can use a function that read all digits of the right amount and save each digit into the char array and increment a pointer, if you receive any invalid input while typing, you can ignore it and keep taking input for up to a number of ignoring time till breaking out, or return an error.
after all I think you should use a char array because 0001 is still a valid pass key.
If you want to check if they've entered the right number of characters, read a line of input and check the length. Then you can check the contents for validity (all numeric).
you can use isalpha() to check there is any character or not.