How can I implement an error check that will loop until a code within a file is entered? This is what I have so far: I have already store each code from the file in an array called array[j].code1.
Here:
printf("Enter item code: "); //Prompts user
scanf ("%14s", codenew1); //Read user input
len = strlen(codenew1); //Read each character into variable len
while (len != strspn(codenew1, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"))
{
printf ("Name contains non-alphabet characters. Try again!: "); //Prompts user to try again
scanf ("%14s", codenew1); //Reads user input
len = strlen(codenew1); //Read each character into variable len
} //Endwhile
strncpy(codenew, codenew1,2); //Copy the first two characters from the variable codenew1
codenew[2] = 0; //Store first two characters into variavle codenew
for ( j = 0; j < num_items; j++) //Loop for num_items times
{ //Beginning of for loop
if (strcmp(array[j].code1, codenew) == 0) //If codenew is found in file
{ //Beginning of if statement
price[i] = item_qty[i] * array[j].price1; //Calculating the price of an item
printf("Price : %d", price[i]); //Prints price
printf("\nEnter '%s' to confirm: ", array[j].itemname1); //Confirming the item
scanf("%19s", item_name1[i]);
while (strcmp(item_name1[i], array[j].itemname1 )!=0) //Looping until both item names are the same
{ //Begin while loop
printf("Item name is not %s ,Try Again!: ", array[j].itemname1); //Prompt user to try again
scanf ("%19s", item_name1[i]); //Reads item name into an array
len = strlen(item_name1[i]); //Reads each character into variable len
} //End while loop
len = strlen(item_name1[i]); //Read each character into variable len
while (len != strspn(item_name1[i], "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")) //While len contains non alphabetic characters
{ //Beginning while
printf ("Name contains non-alphabet characters. Try again!: "); //Prompts user to try again
scanf ("%19s", item_name1[i]); //Read user input
len = strlen(item_name1[i]); //Read each character into variable len
} //End while
strncpy(item_name[i], item_name1[i], 20); //Copy the first two characters from the variable codenew1
item_name[i][20] = 0; //Store first 20 characters in variable item_name[i]
total_price+= price[i]; //Calculate total price
break; //Terminates loop
} //End of if statement
else
if (strcmp(array[j].code1, codenew) != 0) //If codenew is found in file
{
printf("Invalid input! Try again.");
goto Here;
}
} //End of for loop
The current structure of the code is
Here:
// get "codenew" from user
for ( j = 0; j < num_items; j++ )
{
if ( strcmp(array[j].code1, codenew) == 0) )
{
// do a whole bunch of stuff
break;
}
else if ( strcmp(array[j].code1, codenew != 0) )
{
printf( "Invalid input! Try again.\n" );
goto Here;
}
}
The behavior of the code is to check the first entry in a list of codes. If the first entry matches the user input, then "whole bunch of stuff" gets executed and the loop breaks. Otherwise, an error message gets printed and the code jumps back to the label Here:. Thus, the user is forced to enter the first code in the list. Any other code just jumps back to the beginning.
I assume that what the code should do is scan the whole list to see if it can find a matching entry. To accomplish that, I would put the code into a subroutine that searches the list and returns 1 if it finds a match, or 0 if no match is found. The function would be called repeatedly until the user enters a valid code. Here's the structure of the proposed function.
int findCode( void )
{
// get "codenew" from user
for ( j = 0; j < num_items; j++ )
{
if ( strcmp(array[j].code1, codenew) == 0) )
{
// do a whole bunch of stuff
return 1; // SUCCESS, the user entered a valid code
}
}
return 0; // FAILED, no matching code in the list
}
Here's how the function would be called. The while loop will keep calling the function until it returns "success".
while ( !findCode() )
printf( "Invalid input! Try again.\n" );
Related
I am trying to count the occurrence of character for a string.
The user has two options:
first, display the result of screen
second, to store the result in a file but the file name will be a string enter also by user
My real problem is that when in comes to scan the name of the file, it does not work.
The part of my code where count[] has integer number represents the occurrence of each character. When I tryed to debug the code it seems like scan step of out[] string array was skipped, and it got uncommon characters like ÿÿtþa.
printf("Enter 1 if you want to output data on screen\nEnter 2 to output data to file : ");
int input;
scanf("%d", &input);
if(input == 1)
{
fprintf(stdout,"%s:\n\"%s\"\n", "characters count in this string", s);
fprintf( stdout, "%-20s%-4s\n", "character", "count");
for(int j = 0; j < 26; j++)
fprintf( stdout, "%-20c%-4d\n", j+65, count[j]);
}//end of if
else if(input == 2)
{
FILE *Ptr;
printf("enter file name : ");
char out[30]= {'\0'};
scanf("%29[^\n]", out);
if( (Ptr = fopen(out,"w")) == NULL)
printf("CAN NOT OPEN FILE\n");
else
{
fprintf(Ptr,"%s:\n\"%s\"\n", "characters count in this string", s);
fprintf( Ptr, "%-20s%-4s\n", "character", "count");
for(int j = 0; j < 26; j++)
fprintf( Ptr, "%-20c%-4d\n", j+65, count[j]);
}//end of else
fclose(Ptr);
}//end of else
}//end of main
I am stuck with a problem here in C. I am posting the question and the code I have written below. Here I have to enter 10 numbers in an array and then I need to check how many times a number appeared. But to verify that I have entered a number and not anything else, I have used "isdigit()" function. But this is of no use. Can anyone help me to solve it.
/*
(a) Ten numbers are entered from the keyboard into an array. The number to be searched is entered through the
keyboard by the user. Write a program to find if the number to be searched is present in the array and if it is present, display
the number of times it appears in the array.
*/
#include<stdio.h>
#include<ctype.h>
main()
{
int num[10];
int i, j, cnt=0;
char rept;
printf("Enter 10 numbers: \n\n");
for(i=0; i<=9; i++)
{
printf("Number %d = ", i+1);
scanf("%d", &num[i]);
fflush(stdin);
if ( !isdigit(num[i]) )
{
printf("OK\n");
}
else
{
printf("Invalid number. Enter again.\n");
i=i-1;
}
}
do
{
printf("\nEnter the number to be searched in array: ");
scanf(" %d", &j);
for (i=0 ; i<=24; i++)
{
if(num[i]==j)
cnt++;
}
if(cnt>0)
printf("\nNumber %d is present at %d places", j, cnt);
else
printf("\nNumber not present.");
printf("\n\nDo you want to search another number. Press Y to repeat. Any other key to exit");
fflush(stdin);
scanf("%c", &rept);
}while (rept=='y'||rept=='Y');
getch();
}
No you can't do that. isdigit() is supposed to work with characters and you passed a multigit integer variable.
What you can do is simply like this
if( scanf("%d",&a[i])== 1){
// you can be sure number is entered
}
And fflush(stdin) is undefined behavior.
So the use of scanf will be more prominent if you would do this
int clearstdin(){
int c;
while ((c = getchar()) != '\n' && c != EOF);
return (c == EOF);
}
In main()
int earlyend = 0;
for(size_t i=0; i<SIZE; i++){
...
...
int ret = scanf("%d",&a[i]);
while( ret == 0){
if( clearstdin() ){ /* EOF found */earlyend = 1; break; }
fprintf(stderr,"%s\n","Entered something wrong");
ret = scanf("%d",&a[i]);
}
if( earlyend ){ /*EOF found*/ }
if( ret == EOF) { /* Error occured */}
...
}
The %d conversion specifier will cause scanf to skip over any leading whitespace, then read a sequence of decimal digits, stopping at the first non-digit character. If there are no digit characters in the input (for example, you enter something like ”abc”), then nothing is read from the input stream, a[i] is not updated, and scanf will return 0 to indicate a matching failure.
So, you can do a test like
if ( scanf( “%d”, &a[i] ) == 1 )
{
// user entered valid input
}
But...
This doesn’t fully protect you from bad input. Suppose you enter something like ”123abc” - scanf will read, convert, and assign 123 and return a 1 indicating success, leaving ”abc” in the input stream to potentially foul up the next read.
Ideally, you’d like to reject the whole thing outright. Personally, I do this as follows:
char inbuf[SOME_SIZE]; // buffer to store input
if ( fgets( inbuf, sizeof inbuf, stdin ) ) // read input as text
{
char *chk; // use strtol to convert text to integer
int temp = (int) strtol( inbuf, &chk, 10 ); // first non-digit character written to chk
if ( isspace( *chk ) || *chk == 0 ) // if chk is whitespace or 0, input is valid
{
a[i] = temp;
}
else
{
// bad input
}
}
This still isn’t a 100% solution - it doesn’t make sure the user didn’t enter more characters than the buffer can hold, but it’s a step in the right direction.
Input validation in C is, frankly, a pain in the ass.
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;
}
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;
}
I am trying to get both parts of this program to work as you can see I have split it with first part (question 1) and second part (question 2). The problem is first part runs fine just when the second part starts I can not input any string and it just seems to skip through the code without letting me input the string.
If I delete the first part (question 1) of the program then everything works fine and I can input the string. What interrance is causing this issue.
int main()
{
first();
second();
}
//Question 1
int first()
{
/* dataarray.c */
float data[20] = {
50.972438, 93.765053, 9.252207, 1.851414, 16.717533,
71.583113, 97.377304, 20.352015, 56.309875, 0.072826,
23.986237, 36.685959, 80.911919, 86.621851, 53.453706,
96.443735, 29.845786, 18.119300, 31.079443, 52.197715 };
/* The number of elements in the data array */
int data_size = 20;
int pos;
int j;
int i;
int k;
printf("Question 1\n");
for(i=0;i<data_size;i++)
{
printf("\nArray %i is %f ",i,data[i]); //Initial arrays print statement
}
printf("\n\nArray number to delete:"); //User Choose one to delete
scanf("%i",&pos);
k =0;
for(j = 0; j< pos;j++)
{
printf("\n Array %i is now %f ",k,data[j]);
k++;
}
k=pos;
for(j=pos+1;j<data_size;j++)
{
printf("\n Array %i is now to %f ",k,data[j]); //Shows array changed to
k++;
}
data_size = data_size - 1; //Decreases data size
}
//Question 2
int second()
{
printf("\n\nQuestion 2\n");
int a,b,check=0;
char str[20];
printf("\nEnter a String:\n"); //User inputs word to check if its palindrome
gets(str);
for(b=0;str[b]!=0;b++); //Starts at 0 increment till the last length
b=b-1;
a=0;
while(a<=b)
{
if(str[a]==str[b]) //String a is forwards b is backwards
{
a=a+1;
b=b-1;
check=1; //If check = 1 then a palindrome
}
else
{
check=0; //If check = 0 then it not a plaindrome
break; //Loop break
}
}
if(check==1)
printf("It is a Palindrome:"); //Statement printed if check = 1
else
printf("It is not a Palindrome\n"); // Else if 0 this statement is printed
}
When you call scanf in part one, I presume you enter a number followed by a newline. scanf consumes the number, but the newline is left in the buffer. The gets() in part 2 then sees the newline and returns a blank line. An easy solution is to do
scanf( "%i\n", &pos );
BTW, never use gets. Use fgets instead.