How to prevent an infinite loop with scanf failure - c

The Code is supposed to make change for a dollar and works fine. but the professor says that he will be enter random numbers along with letters. It works fine with numbers but when a letter is entered an infinite loop will occur any suggestions?
#include <stdio.h>
#include <stdlib.h>
#define amtPaid 1
#define SENTINAL -1
int quarters(int numChange);
int dimes(int numChange);
int nickels(int numChange);
int pennies(int numChange);
int main(void)
{
double amtDue = 0; // how much is paid
while(1){
printf("\nPlease enter the price less than 1 dollar: ");
scanf(" %lg", &amtDue);
int changeReturn = (amtPaid - amtDue) * 100 + 0.5; // convert decimal to whole number
int updated = 0; // remaining change after amt of change
int numberQuarters = quarters(changeReturn); // number of quarters needed
if(changeReturn >= 0 && changeReturn <= 100){ // if changereturn is between 0 and 100 execute code
printf("\nNice!");
printf("\nWe owe you %i cents" , changeReturn);
if(numberQuarters >= 0){ // get and print number of quarters
printf("\nQuarters: %i", numberQuarters);
updated = changeReturn % 25;
}
if(dimes(updated) >= 0){ // get and print number of dimes
printf("\nDimes: %i", dimes(updated));
updated = updated % 10;
}
if(nickels(updated)>= 0){ // get and print number of nickels
printf("\nNickels: %i", nickels(updated));
updated = updated % 5;
}
if(pennies(updated) >= 0){ // get and print number pennies
printf("\nPennies: %i", pennies(updated));
}
}
else if(amtDue == SENTINAL){
break;
}
else {
printf("That does not make sense to me. please type a valid number");
}
printf("\n %g", amtDue);
}
return 0;
}
int quarters(int numChange){
int numQuarters = 0;
numQuarters = numChange / 25;
return numQuarters;
}
int dimes(int numChange){
int numDimes = 0;
numDimes = numChange / 10;
return numDimes;
}
int nickels(numChange){
int numNickels = 0;
numNickels = numChange / 5;
return numNickels;
}
int pennies(numChange){
return numChange;
}

In case an inappropriate value is supplied other than the expected value of the format specifier with scanf(), the scanf() will fail and the inappropriate value will remain in the input buffer, providing the feed to next scanf(), only to cause successive failures. In that case, you need to clean up the input buffer before going for next input. You can use something like
check the return value of scanf()
In case of failure, use while( getchar() != '\n' ); to clean the input buffer.
That said, int nickels(numChange) is now invalid in c (C99 onwards). You have to make it as int explicitly.

Instead of using scanf(" %lg", &amtDue);, get the user input as a string, so you can do proper checking.
char input[500];
fgets(input, 500, stdin);
// do some input checking
double val = atof(input);
// do calculations on the number
To check, there's all kinds of functions to help you in ctype.h, one that you might find interesting is isalpha.
Manual References:
fgets
atof converts string to double
atoi converts string to integer
isalpha

Related

(Visual Studio)Calculation _using for sentence

Want to elicit average of entered real value,until negative value is entered.
My problem is
My calculation don't quit when negative value is entered
It keep asks printf sentence for 3 time.
What did I do wrong?
#include <stdio.h>
int main(void)
{
double total = 0.0;
double input=0.0;
int num = 0;
for (; input >= 0.0;)
{
total += input;
printf("real number(minus to quit):");
scanf_s("%1f", &input);
num++;
}
printf("average:%f \n", total / (num - 1));
return 0;
}
you have many problems with your code :
it's not %1f in the line scanf_s("%1f", &total); as %1f will give you undefined behavior , it's %lfas you are scanning a double , there is a big difference between number one and lower case L
the function called scanf returns an integer indicating how many elements could be assigned to the input that the user entered , so , you should do if(scanf_s("%lf", &input) == 1) to check if the assignment done successfully, that will help you in detecting if - is entered instead of the number
if the user entered a lonely - then sacnf will fail to convert and you have to take another approach
when you are printing the average in this line : printf("average:%f \n", total / (num - 1)); , you actually prints a double , so it's %lf instead of %f
the condition of the for loop is incorrect , you are saying for (; input >= 0.0;) but this will prevent you from entering any negative values as when entering a negative value , the for loop will break , so you could use while(1) instead of the for loop and only break when a - is entered alone
so here is my edited version of yours , I introduced a dummy string to read the buffer and check whether the input was a lonely - or not , and if not then I try to convert it to double and here is my edited solution :
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char dummy[30];
double total = 0.0;
int num = 0;
double DecimalConverted = 0;
while(1)
{
printf("real number(minus to quit):");
fgets(dummy, 30, stdin); // gets the input into the buffer
if(dummy[0] == '-' && dummy[1] == '\n') // break from the loop on condition that '-' only entered
break;
// convert the string to decimal
DecimalConverted = strtod(dummy ,NULL);
if(DecimalConverted == 0)
printf("not a number\n");
else{
total += DecimalConverted;
num++;
}
}
printf("average:%lf \n", total / (num - 1));
return 0;
}
and here is the output :
real number(minus to quit):12
real number(minus to quit):-51
real number(minus to quit):-
average:-39.000000

C programming Luhn algorithm

I have tried to write a program in C to check Luhn algorithm for credit cards, but it doesn't work. I think I do not have quite clear how getchar() works, but this program looked sensible to me. Can you tell me what is wrong with it? Thank you in advance for any help with this.
#include <stdio.h>
int main(void) {
char x;
int n, sum, i, c;
sum = 0;
printf("Insert the number of digits: ");
scanf("%d",&n);
printf("Insert the digits: ");
for(i = n; i > 1; i = i - 1){
x = getchar();
if(i%2==0)
if(2*x < 10) sum = sum + 2*x;
else sum = sum + 2*x - 9;
else sum = sum + x;
i = i - 1;
}
c = (9*sum)%10;
x = getchar();
getchar();
if(x == c) printf("Last digit: %d,\nCheck digit: %d,\nMatching",x,c);
else printf("Last digit: %d,\nCheck digit: %d,\nNot Matching",x,c);
}
getchar() reads one character. Therefore, the x = getchar(); in the loop is not good because
It firstly read a newline character if you enter that after the first "number of digits".
It will read a character, not an integer. Character codes typically differ from the integer the character represents, and it may affect the check digit calculation.
Instead of x = getchar();, you should do this in the loop:
scanf(" %c", &x); /* ignore whitespace characters (including newline character) and read one character */
x -= '0'; /* convert the character to corresponding integer */
#include <stdio.h>
#define N 16
void luhn_algorithm();
int main(){
int a[N];
int i;
printf("type the card number:\n");
for(i=1;i<=N;i++){
scanf("%d",&a[i]);
}
luhn_algorithm(a);
}
void luhn_algorithm(int *a){
int i,multiply=1,m,sum=0,total=0;
for(i=1;i<=N;i++){
if(i%2!=0){
multiply=a[i]*2;
if(multiply>9){
while(multiply>0){
m=multiply%10;
sum+=multiply;
multiply/=10;
}
multiply=sum;
}
}
else if(i%2==0){
multiply=a[i]*1;
if(multiply>9){
while(multiply>0){
m=multiply%10;
sum+=multiply;
multiply/=10;
}
multiply=sum;
}
}
total+=multiply;
}
if(total%10==0){
printf("\nthis credit card is valid ");
}
else{
printf("\nthis credit card is not valid");
}
}
this is the program i made to check if credit card number is valid or not try this out.
I took the numbers in an array and then multiplied it according to their position and added them all if the last digit of the added total comes out to be 0 that means the card is valid otherwise its not.
check it out if theres something wrong please tell me.

Not sure why my program keeps prompting error when I try to close it?

#include <stdio.h>
#include <stdlib.h>
int add_even(int);
int add_odd(int);
int main() {
int num, result_odd, result_even, even_count, odd_count;
char name;
printf("What is your name?\n");
scanf("%s", &name);
while (num != 0) {
printf("Enter a number:\n");
scanf("%d", &num);
if (num % 2 == 1) {
printf ("odd\n");
odd_count++;
} else
if (num == 0) {
printf("%s, the numbers you have entered are broken down as follows:\n",
name);
result_even = add_even(num);
printf("You entered %d even numbers with a total value of %d\n",
even_count, result_even);
result_odd = add_odd(num);
printf("You entered %d odd numbers with a total value of %d\n",
odd_count, result_odd);
} else {
printf("even\n");
even_count++;
}
}
return 0;
}
int add_even(int num) {
static int sum = 0;
if (num % 2 != 0) {
return 0;
}
sum += add_even(num);
return sum;
}
int add_odd(int num) {
static int sum = 0;
if (num % 2 == 0) {
return 0;
}
sum += add_odd(num);
return sum;
}
Can anyone give me some insight as to what I did wrong exactly?
The point of the code is to get inputs from the user until they decide to stop by inputting 0. Separating the evens from the odd. Tell them how many even/odd they put and the total of all the even/odd numbers.
I understand how to separate the evens from the odds. I think my issue is with my function.
There are multiple problems in your code:
scanf() causes undefined behavior when trying to store a string into a single character. Pass an array and specify a maximum length.
you should check the return value of scanf(): if scanf() fails to convert the input according to the specification, the values are unmodified, thus uninitialized, and undefined behavior ensues. In your case, if 2 or more words are typed at the prompt for the name, scanf("%d",...) fails because non numeric input is pending, no further characters are read from stdin and num is not set.
num is uninitialized in the first while (num != 0), causing undefined behavior.
functions add_even() and add_odd() are only called for num == 0, never summing anything.
functions add_even() and add_odd() should always return the sum and add the value of the argument num is it has the correct parity. They currently cause undefined behavior by calling themselves recursively indefinitely.
odd_count and even_count are uninitialized, so the counts would be indeterminate and reading their invokes undefined behavior.
In spite of all the sources of undefined behavior mentioned above, the reason your program keeps prompting without expecting an answer if probably that you type more than one word for the name. Only a single word is converted for %s, leaving the rest as input for numbers, which repeatedly fails in the loop. These failures go unnoticed as you do not verify the return value of scanf().
Here is a corrected version:
#include <stdio.h>
#include <stdlib.h>
int add_even(int);
int add_odd(int);
int main(void) {
int num, result_odd, result_even, even_count = 0, odd_count = 0;
char name[100];
printf("What is your name? ");
if (scanf("%99[^\n]", name) != 1)
return 1;
for (;;) {
printf("Enter a number: ");
if (scanf("%d", &num) != 1 || num == 0)
break;
if (num % 2 == 1) {
printf("odd\n");
odd_count++;
add_odd(num);
} else {
printf("even\n");
even_count++;
add_even(num);
}
printf("%s, the numbers you have entered are broken down as follows:\n", name);
result_even = add_even(0);
printf("You entered %d even numbers with a total value of %d\n",
even_count, result_even);
result_odd = add_odd(0);
printf("You entered %d odd numbers with a total value of %d\n",
odd_count, result_odd);
}
return 0;
}
int add_even(int num) {
static int sum = 0;
if (num % 2 == 0) {
sum += num;
}
return sum;
}
int add_odd(int num) {
static int sum = 0;
if (num % 2 != 0) {
sum += num;
}
return sum;
}
You declared:
char name; // One single letter, such as 'A', or 'M'
printf("What is your name?\n"); // Please enter a whole bunch of letters!
scanf("%s", &name); // Not enough space to store the response!
What you really want is more like
char name[31]; // Up to 30 letters, and an End-of-String marker
printf("What is your name?\n"); // Please enter a whole bunch of letters!
scanf("%s", name); // name is the location to put all those letters
// (but not more than 30!)

Having Trouble Calculating The Correct Average of 10 Integer Values in C

Hello Stack Community!
I am having trouble calculating the correct average for 10 integers.
The expected output average is supposed to be 140.0 with one integer value recognized as not a positive program by the compiler.
This is what I have compiled, and it recognized the negative integer but the average still comes to 150.0
Just trying to figure out what I am missing here.
Thanks!
#include <stdio.h>
int main ()
{
/* variable definition: */
int count, value, sum;
double avg;
/* Initialize */
count = 0;
sum = 0;
avg = 0.0;
// Loop through to input values
while (count < 10)
{
printf("Enter a positive Integer\n");
scanf("%d", &value);
if (value >= 0) {
sum = sum + value;
count = count + 1;
}
else {
printf("Value must be positive\n");
}
}
// Calculate avg. Need to type cast since two integers will yield an integer
avg = (double) sum/count;
printf("average is %lf\n " , avg );
return 0;
}
Values are: 100 100 100 100 -100 100 200 200 200 200
You want to read exactly 10 positive numbers, with count from 0 to 9.
After reading 100 100 100 100 -100 100 200 200 200 200 the value of count is 9 (because -100 neither added to the sum nor counted), which is less that 10 so the loop is executed one more time.
This time scanf() fails, so value remains unchanged; effectively you are reading another 200.
This is why the sum of the numbers is 1500 and the average 150.
AlexP found the explanation: you must check the return value of scanf(), otherwise, you will silently accept input that is not a number and reuse the last converted value.
Also note that the cast in avg = (double) sum/count; applies to sum and binds stronger than /. It is considered good style to make this more explicit by writing avg = (double)sum / count;
Here is a modified version of your program:
#include <stdio.h>
int main(void) {
/* variable definitions */
int count, value, sum;
double avg;
/* Initializations */
count = 0;
sum = 0;
avg = 0.0;
// Loop through to input values
while (count < 10) {
printf("Enter a positive Integer\n");
if (scanf("%d", &value) != 1) {
break;
}
if (value >= 0) {
sum = sum + value;
count = count + 1;
} else {
printf("Value must be positive\n");
}
}
// Calculate avg.
// Need to type cast to force floating point division instead of integer division
if (count > 0) {
avg = (double)sum / count;
printf("average is %f\n", avg);
}
return 0;
}
If I understand your problem correctly, this is what you want to do :
int last_known_positive_value = 0;
// Loop through to input values
while (count < 10)
{
printf("Enter a positive Integer\n");
scanf("%d", &value);
if (value >= 0) {
sum = sum + value;
last_known_positive_value = value;
}
else {
printf("Value must be positive\n");
sum = sum + last_known_positive_value;
}
count = count + 1;
}
check-answer-here
There are a number of different ways to approach the problem. (1) you can read your values as a string with fgets and then call sscanf and gain the benefit of a NULL return from fgets indicating EOF and a test of the buffer containing only '\n' to indicate a user pressed [Enter] to signal end of input.
(2) you can read the values numerically with scanf and then check for EOF to indicate end of input, or some other predetermined sentinel.
Regardless of which you choose, the approach is basically the same. (a) make a call to the function you are using for input, (b) check the RETURN, and (c) validate the value input is within the required range, and handle the data.
You get the drift, on all input, check the return of your read function and handle any error or EOF condition, then validate the input is within the expected range.
A quick example using your code and reading numeric values with scanf could be something like:
#include <stdio.h>
int main (void) {
/* define/initialize variables */
int count = 0, value = 0, sum = 0;
double avg = 0.0;
while (1) { /* infinite loop to process input */
int rtn;
printf ("Enter a positive Integer ([ctrl+d] to quit): ");
if ((rtn = scanf ("%d", &value)) != 1) {
if (rtn == EOF) { /* always handle user cancellation of input */
putchar ('\n'); /* tidy up with POSIX line ending */
break; /* on to final calculation */
}
}
if (value < 0) /* check out of range */{
printf ("Value must be positive\n");
continue; /* try again */
}
sum = sum + value; /* compute sum */
count = count + 1; /* increment count */
}
/* Calculate avg. (typecast to avoid integer division) */
avg = count > 0 ? (double) sum/count : 0; /* protect div by zero */
printf ("\n (%d/%d) => average: %lf\n", sum, count, avg);
return 0;
}
Example Use/Output
$ ./bin/sumavg < <(echo "100 100 100 100 -100 100 200 200 200 200")
Enter a positive Integer ([ctrl+d] to quit):
<snip>
(1300/9) => average: 144.444444
One common thread running between all complete examples is to always handle a manual EOF generated by the user allowing them to cancel an individual input, or input as a whole (you decide based on your needs). On Linux the manual EOF is generated by [ctrl+d] on windoze [ctrl+z].
Look all answers over and let me know if you have any questions related to the above.
while (count < 10) {
printf("Enter a positive Integer\n");
scanf("%d", &value);
if (value >= 0) {
sum += value;
count++;
}
else {
printf("Value must be positive\n");
count++;
}
}
This will increment "count" even if negative integer is inputted.
Thus you will get the desired average.

Problem with scanf, C. Floating point exception

i'm learning C.
i'm using ubuntu and have Code::Blocks as IDE
i have this code:
#include <stdio.h>
int rev (int num);
int main (){
int numb = 0;
printf("%d\n\n", numb);
printf("Please enter a number. Enter 9999 to stop\n");
scanf("%d", &numb);
printf("there?");
printf("%d\n", numb);
while (numb != 9999){
printf("The reversed number is %d\n", rev(numb));
printf("Please enter a number. Enter 9999 to stop\n");
scanf("%d", &numb);
} /* end of while */
}
int rev (int num){
printf("here?");
int total = 0;
long max = 10;
long max_const = 10;
printf("here");
for (max; max < num; max *= 10);
printf("%ld", max);
max_const = max;
for (int i = 0; i <= max_const; i *= 10, max /= 10){
total += num / max * i;
} /* end for */
return total;
}
I'm doing it in this way cause my book isn't clear...however, the problem is that it raise a Floating Point exception, in scanf...i'm typing normal numbers... the strange thing is that if i type everything but 9999, the program crash. if i type 9999, it prints 'there?' (so scanf it's ok) and stop later, obviously. why?
Thank you.
The two existing (be sure to return the result in rev, and put \n on the ends of printfs to be sure they make it through the buffer) answers are good points, but not the thing that's actually triggering your floating point exception. Try running it in a debugger, and you'll see that your algorithm is bad: eventually max becomes zero and you divide by it. I'll leave fixing that as an exercise for the reader; the problem isn't anything to do with scanf.
Your rev function needs to return the reversed number.

Resources