How do I print Invalid for letters - c

How do I print invalid when someone enter big or small letters, because supposedly they only enter floats between 0 to 10.
I tried coding like this
It went so wrong.
#include<stdio.h>
int main()
{
int trial=0;
float judge1=0,judge2,judge3,judge4,judge5;
char a;
printf("\n%90s","Welcome to the constentant score calculator program :)");
printf("\n\n\n\n\n\rKindly enter the constentant score by 5 respected
judges:");
do
{
printf("\n\nScore by JUDGE 1 (0-10):\t");
scanf("%f",&judge1);
if ((judge1>-1)&& (judge1<11) )
printf("The constentant got %.2f from the judge",judge1);
else
printf("\aPlease input a valid score between 0 and 10:");
} while ((judge1<0) || (judge1>10)||(judge1=a>96) && (judge1=a<123)||
(judge1=a<91) && (judge1=a>64));
}
okay this is my second code
#include<stdio.h>
int main()
{
float judge1;
printf("\n%90s","Welcome to the constentant score calculator program :)");
printf("\n\n\n\n\n\rKindly enter the constentant score by 5 respected
judges:");
printf("\n\nScore by JUDGE 1 (0-10):\t");
scanf("%f",&judge1);
if ((judge1>-1) && (judge1<11))
printf("The constentant got %.2f from the judge",judge1);
else
printf("\aPlease input a valid score between 0 and 10:");
}
}

When you use the "%f" as the format string for scanf, it will read only characters that are valid for a floating point type and will stop reading if it detects any other characters. So if someone types "abc", nothing is written to judge1 and those characters are left in the input buffer to be read again. You'll then get stuck in an infinite loop reading those same characters.
Also, this expression doesn't make sense:
judge1=a>96
> has higher precedence than ==, so it is equivalent to:
judge1=(a>96)
Assuming a is assigned a value, a>96 compares that value with 96 and evaluates to either 0 or 1. Then you assign this value to judge1, overwriting what was read from the user. Assuming you meant to use == this doesn't make sense either. That being the case, either judge1==0 or judge1==1 is evaluated depending on the result of a>96. So the above expression will only be true if judge1 is 1 and a is greater than 96 or judge1 is 0 and a is less than or equal to 96.
Another problem is that a is never assigned a value. You seem to be under the impression that when you call scanf("%f",&judge1); that the first character read is written to a. There is no link that causes that to happen, so a is left uninitialized.
What you want to do instead is read in a line of text using fgets, then using strtof to read a float. The strtof function accepts the address of a pointer as the second parameter to let you know where in the string the parsing stopped. So if this pointer does not point to the null terminator at the end of the string (or to a newline character, since fgets reads and stores the newline), then you know you read a non-float character.
float judge1;
char line[100];
char *p;
int invalid_input;
do {
invalid_input = 0;
fgets(line, sizeof(line), stdin);
errno = 0;
judge1 = strtof(line, &p);
if (errno || ((*p != 0) && (*p != '\n')) || (judge1 < 0) || (judge1 > 10)) {
printf("Please input a valid score between 0 and 10:");
invalid_input = 1;
} else {
printf("The constentant got %.2f from the judge\n ",judge1);
}
} while (invalid_input);

First, check the return value of scanf. If it fails to match the item it will return 0. Then you can check whether the number entered is within bounds:
int r, judge1;
...
r = scanf("%d", &judge1);
if(r != 1)
{
printf("invalid input\n");
while((r = fgetc(stdin)) != EOF && r != '\n');
}
else if((judge1 < 0) || (judge1 > 10))
printf("input out of range\n");
else
printf("valid input\n");

The problem is you have the bad charachter stuck in the stream. The solution is here:
scanf fails why?.
The suggested thing to do from John Bode is to use a getchar to get it out. Also apply the check mnistic suggested and it should work.
it doesn't offer anything and it only messes with the greater picture.

Related

Analyze a variable in C and then decide what to do

Hi I'm still a C beginner and a beginner coder,
I've been trying to develop some sort of a rudimental interface via command line and would like to implement that when the user inserts something that isn't a number the loop breaks and moves on
(my dream would be that it checks when the input is equal to the word new) Anyhow here's my code snippet:
do {
printf("\nInsert the score you obtained: ");
scanf("%d", &avg);
} while ( isdigit(avg) == 0 );
Basically until the input is a number it will keep going and when something that isn't an integer is inserted it should exit the loop.
To receive something that isn't an integer, you have to scanf something that isn't an integer.
char* input;
do {
printf("\nInsert the score you obtained, or exit to quit: ");
scanf("%[^/n]", input);
...
Now that you have a variable that can hold both "quit" and some number (represented as characters), you need to make a decision based on what kind of input you received.
char input[80];
do {
printf("\nInsert the score you obtained, or exit to quit: ");
scanf("%[^/n]", &input);
while ( strncmp(input, "exit", 4) == 0 );
this means also that you'll have to possibly convert the "string" of the number into a number value.
char input[80];
do {
printf("\nInsert the score you obtained, or exit to quit: ");
scanf("%[^/n]", &input);
int number = convert_to_number(input);
while ( strncmp(input, "exit", 4) == 0 );
but the conversion should only happen if it looks like a number
do {
printf("\nInsert the score you obtained, or exit to quit: ");
scanf("%[^/n]", &input);
if ( looks_like_number(input) ) {
int number = convert_to_number(input);
}
} while ( strncmp(input, "exit", 4) == 0 );
and finally you might need to collect multiple inputs, as the loop will accept them now
do {
printf("\nInsert the score you obtained, or exit to quit: ");
scanf("%[^/n]", &input);
if ( looks_like_number(input) ) {
sum = add(sum, convert_to_number(input));
}
} while ( strncmp(input, "exit", 4) == 0 );
This is only one solution of a very large number of possible ways to do this.
This solution also could be improved (like trimming white space around the "exit" flag, so a user could type " exit" or "exit " to leave. One could also make the loop not a loop, as the question seems to imply entering one number or "exit" once, while a loop will permit many numbers until exit was typed. And one could remove the silly add function which was only used to demonstrate with a word a very clear idea, when + might do.
Even if the above loop / approach isn't a perfect fit for your need, please look at it carefully because the ideas within it can be used to make your program a success.
Also, don't use isdigit for checking for an entire number. Look into sscanf which is like printf but for reading stuff out of strings. sscanf your number off the string, and check the return value to see if you found a number within the string.
isdigit (prototyped as int isdigit (int Test_Character);) is not the right function to use with testing whether an int is a digit or a number. isdigit() is used rather to test if a single character is a decimal digit (0-9). The input to this function must be a character with integer value between 0 and 255. ( refer to ASCII table to view what these value are.)
The right thing to do here is to determine if scanf converted an input value correctly.
The function scanf() is prototyped with a return value, indicating success or failure, but your code does not currently check it.
So, in summary, your while loop can be written using the return of scanf():
int main(void)
{
int count = 0;
int avg= 0;
do
{
printf("\nInsert the score you obtained: ");
count = scanf("%d", &avg);
}while(count > 0); //stays in loop for any numeric value
// } while ( isdigit(avg) == 0 );//Note; input containing decimal points will be truncated
//to contain only integer portion
return 0;
}
As long as the input is an integer numeric value, scanf will return count as a positive value (the number of values scanned correctly.)
For example:
123, -123, 8, 0 will all allow the loop to continue.
a, dfg will all result in a failed attempt to convert the input to a numeric, and return EOF (-1)
Process as string representation of numeric: (similar behavior with alternative coding approach.)
I promised to show how to use strtol():
By changing the input format specifier from "%d" to "%s", scanf() will read the input value of 123 as a string: "123". When input is brought into your program as a string representation of a numeric, it must be converted to a number a numeric type before it can be used. strtol() can be used to do this conversion.
Here is a modification of your original program illustrating how it can be done:
int main(void)
{
int count = 0;
char avg[20] = {0};//changed to string variable
long val = 0;
bool success = FALSE;
do
{
printf("\nInsert the score you obtained: ");
count = scanf("%s", avg);//changed format specifier to read strings
if(count)
{
success = parseLong(avg, &val);//see correct usage of strtol in function
}
}while(success); //Stays in loop for any numeric input.
//Note: input containing decimal values
//will be truncated to contain integer portion only.
return 0;
}
bool parseLong(const char *str, long *val)
{
char *temp;
BOOL rc = TRUE;
errno = 0;
*val = strtol(str, &temp, 0);
if (temp == str || ((*val == LONG_MIN || *val == LONG_MAX) && errno == ERANGE))
rc = FALSE;
return rc;
}

scanf test failing inside a function in C

I'm trying to do a program with a simple game for a user to guess the number. My code is below:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAX 30
#define TRYING 5
void guessnumber(int, int, int *);
int main(void) {
int mytry = 1;
guessnumber(MAX, TRYING, &mytry);
if (mytry <= TRYING)
printf("Congratulations! You got it right in %d tries\n", mytry);
else
printf("Unfortunately you could not guess the number in the number of tries predefined\n");
printf("End\n");
return EXIT_SUCCESS;
}
void guessnumber(int _n, int _m, int *_mytry) {
srandom(time(NULL));
int generated = 0, mynum = 0, test = 0;
generated = rand() % (_n + 1);
printf("Welcome to \"Guess the number\" \n");
printf("A number between 0 and %d was generated\n", _n);
printf("Guess the number:\n");
while (*_mytry <= TRYING) {
test = scanf(" %d", &mynum);
if (test != 1 || mynum < 0 || mynum > MAX)
printf("ERROR: please enter a valid number \n");
else
if (mynum > generated)
printf("Wrong! The number your trying to guess is smaller\n");
else
if (mynum < generated)
printf("Wrong ! The number your trying to guess is bigger\n");
else
break;
*_mytry = *_mytry + 1;
}
}
Okay, now the program is working pretty ok except for one thing: the scanf test.
It works if I try to enter a number out of my range (negative or above my upper limit) but it fails if I for example try to enter a letter. What it does is that it prints the message of error _m times and then it prints "Unfortunately you could not guess the number in the number of tries predefined" and "End".
What am I doing wrong and how can I fix this?
In case, a character is entered, you're trying to detect it correctly
if(test!=1 ......
but you took no action to correct it.
To elaborate, once a character is inputted, it causes a matching failure. So the input is not consumed and the loop falls back to the genesis position, only the loop counter is increased. Now, the previous input being unconsumed, is fed again to the scanf() causing failure once again.
This way, the loop continues, until the loop condition is false. Also, for every hit to scanf(), as unconsumed data is already present in the input buffer, no new prompt is given.
Solution: You need to clean the input buffer of existing contents when you face a failure. You can do something like
while ((c = getchar()) != '\n' && c != EOF);
to clean the buffer off existing contents.
When you enter a letter, scanf() leaves the letter in the input stream since it does not match the %d conversion specifier. The simplest thing to do is use getchar() to remove the unwanted character:
if (test != 1) {
getchar();
}
A better solution would be to use fgets() to get a line of input, and sscanf() to parse the input:
char buffer[100];
while (*_mytry<=TRYING)
{
if (fgets(buffer, sizeof buffer, stdin) == NULL) {
fprintf(stderr, "Error in fgets()");
exit(EXIT_FAILURE);
}
test=sscanf(buffer, "%d", &mynum);
if(test!=1 || mynum<0 || mynum>MAX)
printf ("ERROR: please enter a valid number \n");
else if(mynum>generated)
printf("Wrong! The number your trying to guess is smaller\n");
else if(mynum<generated)
printf("Wrong ! The number your trying to guess is bigger\n");
else
break;
*_mytry=*_mytry+1;
}
In the above code, note that the leading space has been removed from the format string. A leading space in a format string causes scanf() to skip leading whitespaces, including newlines. This is useful when the first conversion specifier is %c, for example, because any previous input may have left a newline behind. But, the %d conversion specifier (and most other conversion specifiers) already skips leading whitespace, so it is not needed here.
Additionally, your code has srandom() instead of srand(); and the call to srand() should be made only once, and probably should be at the beginning of main(). And, identifiers with leading underscores are reserved in C, so you should change the names _m, _n, and _mytry.

how to control input data format (C)?

anyone knows an efficient way to check out the format of an scanf'ed data?
e.g. if I try to read an integer and I type a character, how would you do to tell the program that is not correct?
You can check if scanf() succeeds, it returns the number of successful conversions it performed.
You should always check this, before relying on the result since if it failed the variable(s) might contain undefined data leading to undefined results if referenced.
You can use if to check, and re-try with a different conversion specifier on failure:
if(scanf("%d", &x) == 1)
printf("got integer %d\n", x);
else if(scanf("%c", &y) == 1)
printf("got character '%c'\n", y);
else /* more attempts */
Of course it can become troublesome if there are "sub-matches", so the order can matter. It's also way better to split the input processing into two steps for the above:
Read a full line of input using fgets()
Use sscanf() to parse the line
That way you avoid problems due to the input being streamed in:
char line[128];
if(fgets(line, sizeof line, stdin) != NULL)
{
int x;
char y;
if(sscanf(line, "%d", &x) == 1)
printf("got integer %d\n", x);
else if(sscanf(line, "%c", &y) == 1)
printf("got character '%c'\n", y);
}
Note that if you wanted to scan for both an integer and a float, it can still become troublesome since a typical float (such as "3.1416") begins with what is a legal integer. For those cases you can use the strtoXXX() family of functions, which let you check the remainder after doing the conversion.
As you have mentioned in the question that you are playing with numbers and chars only there is a very simple solution as follows
//while reading a char
scanf("%c",&temp);
if(!((temp >= 65 && temp <= 90) || (temp >= 97 && temp <= 122)))
printf("Only characters are allowed!\n");
hope this helps!
scanf("%s", &c);
if(!atoi(c)) puts("You have entered a character");
if(atoi(c) != 0) puts("You have entered an integer");
Scanner sc = new Scanner (System.in);
try {
// assume that the input from the user is not an integer,
// in that case the program cannot convert the input (which is a String) into
// an integer. Because of this situation it'll jump to the 'catch' part of the
// program and execute the code.
int input = Integer.valueOf(sc.nextInt);
// if the input is an integer lines below the above code will be executed.
// Ex. "int x = ( input + 10 ) "
}
catch (Exception ex) {
System.out.println("Invalid input, please retry!");
// if you want to get more information about
// the error use the 'ex' object as follows.
System.out.println(ex);
}

How to check for end of input? C, find 42

This is the problem:Your program is to use the brute-force approach in order to find the Answer to Life, the Universe, and Everything. More precisely... rewrite small numbers from input to output. Stop processing input after reading in the number 42. All numbers at input are integers of one or two digits.
Input:
1
2
88
42
99
My first code doesn't work:
while( scanf("%d\n", &n) != 42 ){
printf("%d\n",n);
}
second code, with for loop, works but there is a test case where there is no number 42 so it returns TLE, how do I check for end of input?
for(i=1;i>0;i++){
scanf("%d\n",&n);
if(n!=42 ){ /* end of input??? */
printf("%d\n",n);
}
else {
break;
}
}
And why doesn't while loop work like it should?
scanf returns the number of characters scanned, not the result.
So, write while loop as follows:
scanf("%d", &n);
while( n != 42 ){
printf("%d\n",n);
scanf("%d", &n);
}
Always good to avoid magic numbers. Define a constant.
Check the result of scanf() (#Joachim Pileborg)
To check if the input is valid , test if scanf() result is 1 (1 format specifier correctly scanned).
To check for end of input, test if scanf() result is EOF.
while loop failure is well explained by #dbasic. Roughly, scanf() reports the number of fields scanned, not the value scanned.
There is a lot to scanf(). If up to it, read the scanf() section of the C spec. Where do I find the current C or C++ standard documents?
const int Answer_to_Life_the_Universe_and_Everything = 42;
int n;
int cnt;
// Use 2d to limit to 2 digits
while ((cnt = scanf("%2d\n",&n)) == 1) {
if(n != Answer_to_Life_the_Universe_and_Everything) { /* end of input? */
printf("%d\n",n);
}
else {
break;
}
}
if (cnt != EOF) Handle_UnexpectedInput(); // example someone type in "junk"

How to terminate a loop when a letter entered in C?

In my task I need to use a loop and get an input between 1-5, if i get any other input i need to keep iterating until i get 1-5.
Could you please tell me what am i doing wrong?
Part of my code:
int rateSelected, weeklyHours;
printf("Enter the number corresponding to the desired pay rate or action:\n");
printf("1) %.2lf$/hr 2) %.2lf$/hr\n", RATE1, RATE2);
printf("3) %.2lf$/hr 4) %.2lf$/hr\n", RATE3, RATE4);
printf("5) Quit\n");
while ((scanf("%d", &rateSelected)) != EOF && rateSelected != 5)
{
if (rateSelected > 5 || isalpha(rateSelected) ==1){
printf("please enter a number between 1-5:\n");
continue;
}
printf("Now enter your weekly hours:\n");
scanf("%d", &weeklyHours);
ChoosePayRate(rateSelected, weeklyHours);
}
tnx
The problem is your use of %d format specifier. When letters are entered instead of digits, scanf returns zero to indicate that nothing is read. If you would like to allow entering letters along with digits, you should either add a read of a string when scanf returns zero, or always read into a string buffer, and then use sscanf or atoi to convert the string to integer.
You better use fgets() and strtol() for this. Scanf and the line-buffering of stdio is not very helpful together...
char line[LINE_MAX];
do {
fgets(line, sizeof(line), stdin);
} while(!isdigit(line[0]));
int choice = strtol(line, NULL, 10);
isalpha(rateselected) will never be true because you are storing an int in rateselected.
scanf("%d",rateselected) allready takes care of catching character input, and returns 0 if that is the case. So you should change the isalpha test to a rateselected == 0 test.
Also, scanf will never return EOF. It will return 0, and then you need to test feof(stdin) to see if you really hit the end of input. (which would correspond to a ctrl-Z for keyboard input).
Remove the isalpha(rateSelected).
isalpha() checks if the value passed as parameter is an alphanumeric character - but you are passing the int value which you have just read.
However, this is still not sufficient - you would need to catch the return value from scanf() to check if scanf() has actually read an int. But if no int was entered, the characters are not discarded so that the next scanf() will again try to convert them, which leads to an endless loop.
Better use the solution provided by #dasblinkenlight.
Use this:
int e;
while ((e = scanf("%d", &rateSelected)) != EOF)
{
scanf("%*[^\n]"); // this clean your input buffer
if (e==0 || rateSelected>5 || rateSelected<1) {
printf("please enter a number between 1-5:\n");
continue;
}
instead of
while ((scanf("%d", &rateSelected)) != EOF && rateSelected != 5)
{
if (rateSelected > 5 || isalpha(rateSelected) ==1){
printf("please enter a number between 1-5:\n");
continue;
}

Resources