Printf command after an if statement does not work - c

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.

Related

while loop not breaking even with break C programming

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;
}

Scanf() not working correctly in C when inputting value

I'm trying to work on a program to input a phone number and test if it is the right amount of digits in C, also checking if the first value is not 0 or 1. Scanf is not taking a value when I enter it and I do not understand why. If someone could please point out to me what the issue is it'd be much appreciated.
#include <stdio.h>
int main (void){
int number = 0;
int loop = 0;
while(loop == 0){
printf("Enter a phone number: ");
scanf(" %d ", &number);
printf("%d", number);
int firstDigit;
while(number >= 10){
firstDigit = number/10;
}
if((number/1000000) >= 1 && (number/1000000) < 10){
if(firstDigit == 1){
printf("Invalid central office code: 1");
}
else if(firstDigit == 0){
printf("Invalid central office code: 0");
}
else{
int firstThree = (number/10000);
int lastFour = (number%10000);
printf("%d - %d", firstThree, lastFour);
}
}
else if(number == 0){
printf("Exiting.");
loop = 1;
}
else{
if((number/1000000)>=10){
printf("Invalid phone number: too many digits");
}
else if((number/1000000)<1){
printf("Invalid phone number: too few digits");
}
}
}
return 0;
}
This:
while(number >= 10) {
firstDigit = number/10;
}
is an infinite loop, because you are not modifying number.
What you probably want to do is:
while(number >= 10) {
firstDigit = number/10;
number /= 10;
}
You should avoid scanf() to read input. Better use fgets(), and then sscanf() for parsing.
char input[1024]; // This should be large enough
if (!fgets(input, sizeof input, stdin)) {
printf("Input error\n");
return 1;
}
input[strcsnp(input, "\n")] = '\0'; // Because fgets reads \n so remove it
if (sscanf(input, "%d", &number) != 1) {
printf("Parsing error\n");
return 1;
}
// Use number...
Also, scanf() and sscanf() "ignore" the first 0s you type as part of the phone number, so your solution might not be correct. The best way to represent a phone number is either by storing it as a string (as mentioned in a comment), or by defining a phone number structure.
Int size in c is 4 bytes, which can hold values only -2,147,483,648 to 2,147,483,647.
It can't store all 10 digit values.
you can use long
long number = 0;
scanf("%ld", &number);
printf("%ld", number);

Running into a segfault when referencing pointer

I'm taking an intro to C programming course, and I'm trying to understand pointers, and how exactly they work. I tried to pass just the variable counter through gameRuntime();, but counter wasn't being returned towards after the while loop. So, I opted to use a pointer. And now I'm in a bigger mess than I started.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int *gameRuntime(int *counter)
{
srand(time(NULL));
int random = rand() % 100 + 1;
printf("> %d <\n", random);
int guess;
*counter = 1;
int local_counter = (*counter);
while ((guess != random) && (local_counter <= 10))
{
printf("\n-----------------------\n");
printf("What is your guess?\n-----------------------\n> ");
scanf("%d", &guess);
if ((guess > 100) || (guess < 1))
{
printf("Please choose a number between 1 and 100\n");
}
else if (guess < random)
{
printf("My number is larger than %d!\n", guess);
local_counter++;
printf("%d guesses left!\n", (11 - local_counter));
}
else if (guess > random)
{
printf("My number is less than %d!\n", guess);
local_counter++;
printf("%d guesses left!\n", (11 - local_counter));
}
else if (guess == random)
{
printf("You guessed it! My number was %d!\n", random);
printf("You found it with just %d guess(es)!\n", local_counter);
}
}
(*counter) = local_counter;
return counter;
}
int main()
{
char quit;
int counter;
int random;
printf("Welcome to the Number Guess Game!\n");
printf("I chose a number between 1 and 100 and you have only 10 chances to guess it!\n\n");
printf("Continue? [Y\\N]\n\n> ");
scanf("%c", &quit);
if ((quit == 'n') || (quit == 'N'))
{
printf("Exiting....");
return 0;
}
else
{
printf("\n=*=+=*=+=*=+=*==*=+=*=+=*=+=*==*=+=*=+=*=+=*==*=+=*=+=+*\n");
printf(" ~ ~ ~ Ready? ~ ~ ~ \n");
printf("=*=+=*=+=*=+=*=+=*=+=*=+=*=+=*=+=*=+=*=+=*=+=*=+=*=+=*=+=*\n");
printf("\n");
printf("\n-----------------------");
printf("\nOk, I've made up my mind!\n");
printf("-----------------------\n");
}
gameRuntime(counter);
printf("\n---%d---\n", counter);
char continueGame;
while ((continueGame != 'N') || (continueGame != 'n'))
{
printf("\n---%d---\n", counter);
if (counter >= 10)
{
printf("SORRY! You could not find my number with 10 guesses!\n");
printf("My number was %d\n", random);
printf("Maybe next time!\n");
printf("\nTry again? [Y\\N]\n");
scanf(" %c", &continueGame);
if ((continueGame == 'Y') || (continueGame == 'y'))
{
gameRuntime(counter);
}
else
{
printf("Thanks for playing! See you later!");
return 0;
}
}
else
{
printf("Play again? [Y\\N]\n> ");
scanf(" %c", &continueGame);
if ((continueGame == 'Y') || (continueGame == 'y'))
{
gameRuntime(counter);
}
else
{
printf("\nThanks for playing! See you later!");
return 0;
}
}
}
}
Any help would be much appreciated, TIA
Change
gameRuntime(counter);
to
gameRuntime(&counter);
You are passing the value of counter, and then you used it like if it was the address of something (you dereferenced the pointer). It does compile because pointers and ints are interchangeable in c, but that doesn't mean that the behavior is defined. It should however, generate a warning about pointer to int conversion. You can also, convert all warnings to errors to prevent compilation in case of a warning.
Warnings can be ignored in very rare cases, so as a rule of thumb make your compiler warn about everything it can and if possible, let it treat warnings as errors.
By applying the suggested fix, you pass the address of counter, which is a pointer holding the location of counter in memory, thus you can then affect the value at that location by dereferencing the pointer.

Microsoft Visual Studio 2013 C Program Exception

I am using Microsoft Visual Stusio 2013 Community Edition Update 4 to write a program in the C programming language (not C++). Whenever I try to build and run my program, partway through execution it tells me "Unhandled exception at 0x52873FD4 (msvcr120d.dll) in program.exe: 0xC0000005: Access violation writing location 0x00C40000." When I copy and paste the contents of the .c file into another IDE (code blocks) it compiles and runs without a problem. (Although I do have to change all the scanf_s statements in the code to scanf)
The source code from within the .c file of my program
#include <math.h>
#include <stdio.h>
#include <string.h>
#define PI 3.14159265358979323846;
double add();
double cos_d_r();
double div();
double mult();
void list();
int main()
{
//Declaration of variables
char oper[20];
double ans;
int loop = NULL;
//While loop allows for multiple executions without restarting program
while (!loop)
{
printf("\n\nEnter a mathematical operation.\n\nFor a list of options, enter 'list'\n\n");
scanf_s(" %s", oper);
//If statement to determine which operation to do
//Addition
if (strcmp(oper, "add") == 0 || strcmp(oper, "addition") == 0 || oper[0] == '+')
{
ans = add();
printf("The sum is %.2f\n", ans);
}
//Cosine
else if (strcmp(oper, "cos") == 0 || strcmp(oper, "cosine") == 0)
{
ans = cos_d_r();
printf("The cosine of the angle is %lf\n", ans);
}
//Division
else if (strcmp(oper, "divide") == 0 || strcmp(oper, "division") == 0 || oper[0] == '/')
{
ans = div();
printf("The quotient is %.2f\n", ans);
}
//List of possible operations
else if (strcmp(oper, "list") == 0)
{
list();
}
//Multiplication
else if (strcmp(oper, "multiply") == 0 || strcmp(oper, "multiplication" == 0) || oper[0] == '*')
{
ans = mult();
printf("The product is %.2f", ans);
}
}
return 0;
}
//Declaration of functions
//Addition
double add()
{
double ans;
double num_1;
double num_2;
puts("Enter the first number");
scanf_s(" %lf", &num_1);
puts("Enter the second number");
scanf_s(" %lf", &num_2);
ans = num_1 + num_2;
return ans;
}
//Cosine
/*Uses cos() function from math.h
this function adds option for degrees or radians*/
double cos_d_r()
{
char deg_rad;
double angle;
double ans;
int loop = NULL;
while (!loop)
{
puts("Degrees or radians? Enter 'd' or 'r'");
scanf_s(" %c", &deg_rad);
//Degrees
if (deg_rad == 'd')
{
puts("Enter an angle in degrees");
scanf_s(" %lf", &angle);
angle = angle / 180 * PI;
ans = cos(angle);
loop = 1;
return ans;
}
//Radians
else if (deg_rad == 'r')
{
puts("Enter an angle in radians");
scanf_s(" %lf", &angle);
ans = cos(angle);
loop = 1;
return ans;
}
//Else statement repeats loop if user enters text other than 'd' or 'r'
else
{
puts("ERROR. Enter either 'd' or 'r'");
}
}
}
//Division
double div()
{
double ans;
double num_1;
double num_2;
puts("Enter the dividend");
scanf_s(" %lf", &num_1);
puts("Enter the divisor");
scanf_s(" %lf", &num_2);
ans = num_1 / num_2;
return ans;
}
//Multiplication
double mult()
{
double ans;
double num_1;
double num_2;
puts("Enter the first number");
scanf_s(" %lf", &num_1);
puts("Enter the second number");
scanf_s(" %lf", &num_2);
ans = num_1 * num_2;
return ans;
}
//List of possible operations
void list()
{
printf("The possible operations are:\n\n");
printf("Operation\tDescription\tCommand");
printf("Addition\tAdds two numbers together\tAdd, Addition, +\n");
printf("Cosine\tFinds the cosine of the angle entered\tCos, Cosine");
printf("Division\tDivides the first number by the second\tDivide, Division, /");
printf("Multiplication\tMultiplies the two numbers\tMultiply, Multiplication, *");
}
You should read description of functions you use first! Take a look at scanf_s function description at MSDN. You programm crashes at first call of this function
scanf_s(" %s", oper);
The correct way to use it:
scanf_s("%s", oper, _countof(oper)); // or sizeof(oper), but only with char array
Also you should correct other calls of scanf_s in your code. (Or disable errors for scanf call with #define _CRT_SECURE_NO_WARNINGS before #include <stdio.h>)

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