while loop not breaking even with break C programming - c

Trying to make a GPA calculator.
Here is my code:
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
int main()
{
float fgpa, grade, n;
char reply;
n = 1;
grade = 1;
printf("--- GPA Calculator ---");
while(fgpa < 1 || fgpa > 4)
{
printf("\n\nEnter your current GPA: ");
scanf("%f", &fgpa);
if(fgpa < 1 || fgpa > 4)
printf("Invalid Input! Please re-enter value.");
}
printf("\nUsing the following table to convert grade to points\n\nA+ = 4.0\nA = 4.0\nB+ = 3.5\nB = 3\nC+ = 2.5\nC = 2.0\nD+ = 1.5\nD = 1\nF = 0\n");
while(grade > 0, n++)
{
printf("\nEnter points for module %.0f, enter \"0\" if there are no more additional modules: ", n);
scanf("%f", &grade);
printf("%f", grade);
fgpa = (fgpa + grade) / n;
}
fgpa = fgpa* n / (n-1);
n--;
printf("\n\nNumber of modules taken: %.0f\nFinal GPA: %.1f", n, fgpa);
return 0;
}
I've tried using if(grade = 0) break; but its still not breaking the loop even when the grade is correctly read 0.
picture of 0 being read correctly but loop still continuing

There are multiple problems in the code:
fgpa is uninitialized so the first test in the loop has undefined behavior.
you should also test the return value of scanf() to detect invalid or missing input.
while (grade > 0, n++) is incorrect too: you should instead always read the next grade and test its value and break from the loop before incrementing n.
Your averaging method seems incorrect too: you do not give the same weight to every module.
It seems more appropriate for your purpose to use for ever loops (for (;;)), unconditionally read input, check for scanf() success and test the input values explicitly before proceeding with the computations.
Here is a modified version:
#include <stdio.h>
// flush the rest of the input line, return EOF at end of file
int flush(void) {
int c;
while ((c = getchar()) != EOF && c != \n')
continue;
return c;
}
int main() {
float fgpa;
float grade;
int n = 1;
char reply;
printf("--- GPA Calculator ---");
for (;;) {
printf("\n\nEnter your current GPA: ");
if (scanf("%f", &fgpa) == 1) {
if (fgpa >= 1 && fgpa <= 4)
break;
}
} else {
if (flush() == EOF) {
fprintf(stderr, "unexpected end of file\n");
return 1;
}
}
printf("Invalid Input! Please re-enter value.\n");
}
printf("\nUsing the following table to convert grade to points\n\n"
"A+ = 4.0\nA = 4.0\nB+ = 3.5\nB = 3\nC+ = 2.5\n"
"C = 2.0\nD+ = 1.5\nD = 1\nF = 0\n");
for (;;) {
printf("\nEnter points for module %d, enter \"0\" if there are no more additional modules: ", n);
if (scanf("%f", &grade) == 1) {
if (grade <= 0)
break;
printf("%f\n", grade);
fgpa = fgpa + grade;
n = n + 1;
} else {
if (flush() == EOF)
break;
printf("Invalid Input! Please re-enter value.\n");
}
}
fgpa = fgpa / n;
printf("\n\nNumber of modules taken: %d\nFinal GPA: %.3f\n", n, fgpa);
return 0;
}

Related

How do I make the program give the "Invalid Grade" message and ask for the grade to be entered again infinitely as long as the grade is >100 or <100

So in this C code the program will give an error message that says "Invalid grade" and it asks the user to enter the grade again if the entered grade is >100 or <0, but this only happens once. If the user enters an invalid grade again the program returns black rather than giving the error message again and asking user to reenter the grade. How can I fix this?
#include <stdio.h>
#include <math.h>
int main()
{
double grade;
printf("Enter the student's grade: ");
scanf("%lf",&grade);
if (grade<0 || grade>100)
{
printf("Invalid grade\n");
printf("Enter the student's grade: ");
scanf("%lf", &grade);
}
if (grade>=90 && grade<=100)
printf("A");
if (grade>=80 && grade<=89)
printf("B");
if (grade>=70 && grade<=79)
printf("C");
if (grade>=60 && grade<=69)
printf("D");
if (grade<60 && grade>=0)
printf("F");
return 0;
}
This type of user-input validation code is where a do-while loop is idiomatic:
int scanned;
do
{
printf("Enter a grade between 0 and 100 (inclusive): ");
scanned = scanf(" %lf", &grade);
}
while(scanned != 1 && (grade < 0.0 || grade > 100.0));
Also note:
I check the return value of scanf to ensure that it's the same value as the number of format specifiers in the string. This tells me that scanf succeeded.
I put a space before the format specifier in the scanf format string. This consumes all whitespace left in the buffer prior to the new input.
You don't need to combine conditions with && operator.
if (grade >= 90)
{
printf("A");
}
else if (grade >= 80)
{
printf("B");
}
else if (grade >= 70)
{
printf("C");
}
else if (grade >= 60)
{
printf("D");
}
else if (grade >= 0)
{
printf("F");
}
Try this one:
#include <stdio.h>
#include <math.h>
int main()
{
double grade;
printf("Enter the student's grade: ");
scanf("%lf",&grade);
while (grade<0 || grade>100)
{
printf("Invalid grade\n");
printf("Enter the student's grade: ");
scanf("%lf", &grade);
}
if (grade>=90 && grade<=100)
printf("A");
if (grade>=80 && grade<=89)
printf("B");
if (grade>=70 && grade<=79)
printf("C");
if (grade>=60 && grade<=69)
printf("D");
if (grade<60 && grade>=0)
printf("F");
return 0;
}
This is hard to do with generality. scanf was not really meant for interactive programmes; see why not use scanf. The accepted answer of using a loop is good, and checking the return value is important. However, it fails for many edge cases; I've expended and covered some of them here as an addendum.
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <ctype.h>
#include <math.h>
int main(void) {
int scanned, garbage, is_infected;
double grade;
const double max_grade = 100;
input:
printf("Enter a grade between 0 and %.0f (inclusive): ", max_grade);
/* Ignore leading whitespace. */
scanned = scanf(" %lf", &grade);
/* Ignore up to EOL for future input. */
is_infected = 0;
while((garbage = getchar()) != '\n' && garbage != EOF)
if(!isspace(garbage)) is_infected = 1;
if(is_infected) { fprintf(stderr, "Non-numerical input.\n"); goto input; }
/* `scanned` can be EOF, 0, or 1. */
switch(scanned) {
case EOF: /* EOF could mean different things. */
if(ferror(stdin)) { /* It could mean an error. */
/* ISO C doesn't strictly define whether bumped to `errno`. */
if(!errno) errno = EILSEQ;
perror("input");
} else { /* Or it could mean EOF. */
fprintf(stderr, "Premature EOF.\n");
}
return EXIT_FAILURE;
case 1: /* Successfully matched a double. */
/* `isnan` is C99; C90, `grade != grade` is true by IEEE754, which some
compilers relax. */
if(isnan(grade) || grade < 0.0 || grade > max_grade) {
fprintf(stderr, "Out of range [0, %.0f].\n", max_grade);
goto input;
}
grade = fabs(grade); /* For -0.0. */
break;
default: /* 0, unlikely (impossible?) because of clear of `stdin`. */
fprintf(stderr, "No number.\n");
goto input;
}
printf("number: %f\n", grade);
return 0;
}

Printf command after an if statement does not work

I just started programming a couple of days ago. I tried to program something that calculates my CGPA. I haven't completed it yet; for example, I have to improve the menu etc. It works properly for the 1st and 3rd choice. I will do something else for the second choice. The problem is, after calculation, it doesn't print the text "qwerty" on the bottom.
#include <stdio.h>
#include <stdlib.h>
int main()
{
char h[2];
double numGrade;
double credit, percent, overallCredit, sumCredit;
double contribution=0, GPA=0, semGPA=0, CGPA=0;
int courseNum, i, semesters, k, menu;
printf("Input\n\"1\" for computing your CGPA\n\"2\" if you know each semester's GPA\n\"3\" if you know your CGPA\n");
scanf("%d", &menu);
if(menu == 1)
{
printf("Enter the number of semesters you have studied: ");
scanf("%d", &semesters);
for(k=1; k<=semesters; k++)
{
printf("Enter the number of courses you took in semester %d: ", k);
scanf("%d", &courseNum);
overallCredit = 0;
sumCredit = 0;
for(i=1; i<=courseNum; i++)
{
printf("Enter the credit of the course %d: ", i);
scanf("%lf", &credit);
overallCredit += credit;
printf("Enter your letter grade: ");
scanf("%s", h);
if(strcmp(h, "AA") == 0)
{
numGrade = 4.0;
}else if(strcmp(h, "BA") == 0)
{
numGrade = 3.5;
}else if(strcmp(h, "BB") == 0)
{
numGrade = 3.0;
}else if(strcmp(h, "CB") == 0)
{
numGrade = 2.5;
}else if(strcmp(h, "CC") == 0)
{
numGrade = 2.0;
}else if(strcmp(h, "DC") == 0)
{
numGrade = 1.5;
}else if(strcmp(h, "DD") == 0)
{
numGrade = 1.0;
}else if(strcmp(h, "FD") == 0)
{
numGrade = 0.5;
}else if(strcmp(h, "DD") == 0)
{
numGrade = 0.0;
}else
{
printf("Invalid Grade\n");
}
percent = numGrade/4.0;
contribution = percent*credit;
sumCredit += contribution;
}GPA = (sumCredit/overallCredit)*4.0;
printf("Your GPA for semester %d is: %f\n", k, GPA);
semGPA += GPA;
}CGPA = semGPA/semesters;
printf("CGPA is: %.2f", CGPA+0.005);
}else
{
printf("Enter your CGPA: ");
scanf("%lf", &CGPA);
printf("Your CGPA is: %.2f", CGPA+0.005);
}
printf("qwerty"); //This does not print.
return 0;
}
The problem here is that you're running into undefined behaviour! (This means anything can happen - code will work, sometimes, not work, sometimes, and maybe even wipe your hard disk, sometimes.)
This happens because you are trying to read too many characters into your h variable: you have declared it: char h[2], which can hold only one letter plus the terminating nul. But you try to read two letters into it. Declare it a bit longer: char h[3] and your code should work. But it's maybe better to be safer, and declare it longer, say char h[20];, in case the user types too much data in; alternatively, specify in the input format a maximum string length: scanf("%2s", h);, which will truncate (ignore) any letters after the second.
In your code, the scanf operation writes beyond the memory allocated to h and, thus, maybe changes other 'control' variables in the compiled code.
EDIT: PS, it may not actually be the scanf call that triggers the undefined behaviour! It could be the subsequent strcmp call - the h argument to this will not have a nul terminator and the function will then overflow the string buffer, looking for a zero.

Program that does not return anything

I am working on a program in C that can return loan payment.
yearInt is year interest
loanAmt is total amount of loan
monthlyPay is monthly payment
numberPay is number of monthly payment
For some reasons, when I run the program, there is nothing shows up, even I type in a negative number.
Is there anyway to fix it?
#include <stdio.h>
int main(void)
{
float yearInt = -1;
int loanAmt = -1;
float monthlyPay = -1;
int numberPay = -1;
int count = 0;
while (loanAmt<0)
{
printf("Please enter valid loan value: \n");
scanf("%f", &loanAmt);
}
while (yearInt<0)
{
printf("Please enter valid yearly interest value: \n");
scanf("%f", &yearInt)
}
while (monthlyPay<0)
{
printf("Please enter valid monthly payment value: \n");
scanf("%f", &monthlyPay);
}
while (numberPay<0)
{
printf("Please enter valid number of monthly payments: \n");
scanf("%f", &numberPay);
}
if(loanAmt>monthlyPay)
{
while(count<numberPay)
{
loanAmt = loanAmt*(1 + (yearInt/12)) - monthlyPay;
count += count+1;
}
printf("The amount of last payment is: %.2f\n", loanAmt);
else
printf("The amount of last payment is: %.2f\n", loanAmt);
}
return 0;
}
You are using the wrong format specifier to read loanAmount and numberPay. Instead of "%f", use "%d".
scanf("%d", &loanAmt);
and
scanf("%d", &numberPay);
Also, always check the return value of scanf to make sure that it was able to assign data to all the variables.
Change the loop:
while (loanAmt<0)
{
printf("Please enter valid loan value: \n");
scanf("%d", &loanAmt);
}
to
while (loanAmt<0)
{
printf("Please enter valid loan value: \n");
if ( scanf("%d", &loanAmt) != 1 )
{
// Discard the rest of the line.
int c;
while ( (c = fgetc(stdin)) = '\n' && c != EOF );
}
}
It will be still better to put all the checks in a function and call the function from main.
int readInt(char const* prompt)
{
int val = -1;
printf("%s\n", prompt);
while ( scanf("%f", &val) != 1 || val < 0)
{
// Discard rest of the line.
int c;
while ( (c = fgetc(stdin)) = '\n' && c != EOF );
// If EOF is reached, we have a problem.
if ( c == EOF )
{
exit(0);
}
printf("%s\n", prompt);
}
return val;
}
and then, use:
loanAmount = readInt("Please enter valid loan value: ");
Add a similar function to read floats and call it for reading the variables that are of type float.
scanf("%f", &loanAmt); // loanAmt is int
...
scanf("%f", &numberPay); //numberPay is int
In both wrong argument is passed to %f , therefore , causes UB . Use %d specifier .
And in this one } is missing -
if(loanAmt>monthlyPay)
{
while(count<numberPay)
{
loanAmt = loanAmt*(1 + (yearInt/12)) - monthlyPay;
count += count+1;
}
printf("The amount of last payment is: %.2f\n", loanAmt); //use %d
// ADD '}' here
else // ADD '{' here
printf("The amount of last payment is: %.2f\n", loanAmt); //use %d
}
Put a } before else {.

Problems in C code

I am trying to make a simple calculator in Turbo C(I have my own reasons to why I use Turbo C now)
#include <stdio.h>
#define P printf
int loop[] = {1, 1, 1, 1};
int num;
char input[64];
void main()
{
int num1, num2;
char x, y;
while(loop[0] == 1)
{
clrscr();
P("Hello!, This simple calculator will help you compute 2 numbers.");
P("\nPress the corresponding key to choose the operation you will use.");
P("\n\nA - (A)ddition");
P("\nS - (S)ubtraction");
P("\nM - (M)ultiplication");
P("\nD - (D)ivision");
P("\n\nAnswer: ");
while(loop[1] == 1)
{
x = getchar();
if(tolower(x) == 'a')
{
P("\nYou have chosen addition.");
num1 = askForNumber("\n\nEnter 1st number: ");
num2 = askForNumber("\nEnter 2nd number: ");
P("\n\n%d + %d = %d", num1, num2, num1+num2);
}
else if(tolower(x) == 's')
{
P("\nYou have chosen subtraction.");
num1 = askForNumber("\n\nEnter 1st number: ");
num2 = askForNumber("\nEnter 2nd number: ");
P("\n\n%d - %d = %d", num1, num2, num1-num2);
}
else if(tolower(x) == 'm')
{
P("\nYou have chosen multiplication.");
num1 = askForNumber("\n\nEnter 1st number: ");
num2 = askForNumber("\nEnter 2nd number: ");
P("\n\n%d * %d = %d", num1, num2, num1*num2);
}
else if(tolower(x) == 'd')
{
P("\nYou have chosen division.");
num1 = askForNumber("\n\nEnter 1st number: ");
num2 = askForNumber("\nEnter 2nd number: ");
P("\n\n%g* %g = %.2f", (float)num1, (float)num2, (float)(num1/num2));
}
else
{
P("\nYou have entered an invalid character!");
P("\n\nAnswer: ");
continue;
}
while(loop[2] == 1)
{
P("\n\nDo you want to do another calculation? Y/N: ");
y = getchar();
if(tolower(y) == 'y' || tolower(y) == 'n')
{
loop[2] = 0;
}
else
{
P("\nYou have entered an invalid character.");
continue;
}
}
loop[1] = 0;
}
if(tolower(y) == 'y')
{
continue;
}
if(tolower(y) == 'n')
{
loop[0] = 0;
}
}
}
int askForNumber(const char *string)
{
P("%s", string);
while(loop[3] == 1)
{
fgets(input, (sizeof(input)/sizeof(input[0]))-1, stdin);
if(sscanf(input, "%d", &num) != 1)
{
num = 0;
P("Invalid number!");
continue;
}
return num;
}
}
I have these bugs:
After I finish a calculation, and press 'Y', it clears the screen non-stop.
After "Enter 1st number: ", the "Invalid number" shows up once even though I haven't typed anything yet(but i can still input a number and it will be saved to 'num1', "Invalid number just bugs me".
At the top where I am to input 'a' or 's' or 'm' or 'd' to choose an operation, if I put some letter except for that above, i get this
OUTPUT:
Answer: o
You have entered an invalid character!
Answer:
You have entered an invalid character!
Answer:
the error shows up twice, but i only typed once.
When there are no characters in the input buffer, the getchar function blocks until the return key is pressed. All keys, including return, are stored in the input buffer, then getchar returns the first character in the buffer. The next call to getchar will immediately return the next character in the buffer.
So if you press 'y' then return, the first call to getchar returns the 'y' character, and the next returns a newline character, i.e. the return key.
You need to flush the input buffer each time you use getchar to skip over the newline:
do {
c = getchar();
} while (c == '\n');
You nedd #include ctype.h to lower is part of that library tolower uses this library and its nowhere in your code

C Program that counts how many pass or fail grades and exits when a negative number is inputted

I'm a newbie to C Programming and we're still starting on the loops. For our exercise today, we were tasked to create a do-while program that counts how many pass and fail grades there are but the loop breaks when a negative number is inputted. Also, numbers above 100 is skipped. This is my program:
#include<stdio.h>
#include<conio.h>
int main()
{
int grade, pass, fail;
pass = 0;
fail = 0;
do {
printf("Enter grade:\n");
scanf("%d", &grade);
printf("Enter -1 to end loop");
}
while(grade == -1){
if(grade < 100){
if(grade >= 50){
pass = pass + 1;
}
else if {
fail = fail + 1;
}
}
break;
}
printf("Pass: %d", pass);
printf("Fail: %d", fail);
getch ();
return 0;
}
Can someone please tell me how to improve or where I went wrong?
You need to put all of the code that you loop between the do and the while statements.
do {
printf("Enter -1 to end loop");
printf("Enter grade:\n");
scanf("%d", &grade);
if(grade <= 100 && grade >= 0) {
if(grade >= 50){
pass = pass + 1;
}
else {
fail = fail + 1;
}
}
} while(grade >= 0);
The general structure of a do-while loop is:
do {
// all of the code in the loop goes here
} while (condition);
// <-- everything from here onwards is outside the loop
#include <stdio.h>
#include <conio.h>
int main()
{
int grade, pass, fail;
pass = 0;
fail = 0;
do {
printf("\nEnter grade:\n");
scanf("%d", &grade);
printf("Enter -1 to end loop");
if (grade < 100 && grade >= 50)
pass = pass + 1;
else
fail = fail + 1;
printf("\nPass: %d", pass);
printf("\nFail: %d", fail);
}
while (grade >= 0);
getch();
}
do {
// stuff
}
while {
// more stuff
}
Is mixing 2 concepts together: the while loop and the do while loop - I'd start by refactoring that piece.
The logic for your problem is:
Keep running while the input is not -1. If input is -1, break/exit execution and display output.
Enter grade.
If the grade is less than or equal to 100 or greater than or equal to 0 perform pass/fail checks:
If the grade is greater than or equal to 50, that person has passed. Increment the number of passes.
If the grade is less than 50, that person has failed. Increment the number of failed exams.
jh314's layout logic is correct, but doesn't fix the execution logic:
int grade, pass, fail;
pass = 0;
fail = 0;
do {
printf("Enter -1 to end loop");
printf("Enter grade:\n");
scanf("%d", &grade);
//you want grades that are both less than or equal to 100
//and greater than or equal to 0
if(grade <= 100 && grade >= 0){
if(grade >= 50){
pass = pass + 1;
}
//if the grades are less than 50, that person has failed.
else {
fail = fail + 1;
}
}
} while(grade != -1);
printf("Pass: %d", pass);
printf("Fail: %d", fail);

Resources