Reputation: 605
I'm trying to accomplish this:
Write a program that accepts three user inputs: assignment mark, midterm mark, and final exam mark.
These inputs are of type float and should have values between 0 and 100.
The program should compute the final grade as a percentage and a letter grade.
• Final grades are computed as: Assignments 20%, Midterm 30%, Final exam 50%. Letter grades are computed as: A (final grade ≥ 80%), B (80 > final grade ≥ 70%), C (70 > final grade ≥ 60%), D (60 > final grade ≥ 50%), and F (50 > final grade).
The final grade and letter grade are displayed.
with the following code:
#include <stdio.h>
int checkMark(int);
float getMark();
float computeFinalGrade(float assign, float midterm, float finalExam, float finalGrade);
int computeLetterGrade(float);
int checkMark(int x)
{
while(x<0 || x>100) //While x is a negative number:
{
printf("Invalid entry.Try again:");
scanf("%d",&x);
}
if(x>0 && x<=100)//If x is a positive number:
x=x;
return x;
}
float getMark(void)
{
float mark=0,assignMark=0,midMark=0,examMark=0,finalMark=0;
char letterGrade;
printf("Enter assignment grade:");
scanf("%d",mark);
checkMark(mark);
assignMark=mark;
printf("\nEnter midterm mark:");
scanf("%f",&mark);
checkMark(mark);
midMark=mark;
printf("\nEnter exam mark:");
scanf("%f",&mark);
checkMark(mark);
examMark=mark;
finalMark=computeFinalGrade(assignMark,midMark,examMark,finalMark);
letterGrade=computeLetterGrade(finalMark);
printf("The final grade for the course is %.1f, and the letter grade is %c.\n",finalMark,letterGrade);
return 0;
}
float computeFinalGrade(float assign, float midterm, float finalExam, float finalGrade)
{
assign=(float)0.2*assign;
midterm=(float)0.3*midterm;
finalExam=(float)0.4*finalExam;
finalGrade=(float)assign+midterm+finalExam;
return finalGrade;
}
int computeLetterGrade(float finalGrade)
{
int grade;
if(finalGrade>=80)
grade=65;
if(finalGrade<80)
if(finalGrade>=70)
grade=66;
if(finalGrade<70)
if(finalGrade>=60)
grade=67;
if(finalGrade<60)
if(finalGrade>=50)
grade=68;
if(finalGrade<50)
grade=70;
return grade;
}
int main()
{
getMark();
return 0;
}
When I debug the program above and enter a negative number it gives me this:
Enter assignment grade:123
Segmentation fault (core dumped)
What am I doing wrong exactly?
Upvotes: 1
Views: 14295
Reputation: 2935
If you are on linux, take a look at my answer here. It's about valgrind, a tool that helps debugging segfaults, memory leaks etc.
Upvotes: 2
Reputation: 9437
Some more remarks on your code:
int checkMark(int x)
{
while(x<0 || x>100) //While x is a negative number:
{
printf("Invalid entry.Try again:");
scanf("%d",&x);
}
if(x>0 && x<=100)//If x is a positive number:
x=x;
return x;
}
should rather be:
#define MIN_GRADE 0
#define MAX_GRADE 100
int checkMark(int x)
{
while(x<MIN_GRADE || x>MAX_GRADE)
{
printf("Invalid entry.Try again:");
scanf("%d",&x);
}
return x;
}
Notice that I:
removed useless comments
removed magic numbers (0 and 100)
removed a useless test (if you exit the while loop, then x is in {0, ..., 100}
allowed x
to be equal to 0
removed an idempotent assignment (x=x
doesn't do anything useful...)
Then:
float getMark(void)
{
float mark=0,assignMark=0,midMark=0,examMark=0,finalMark=0;
char letterGrade;
printf("Enter assignment grade:");
scanf("%d",mark);
^ As mentioned by others, you should use %f
and &mark
in this scanf
.
checkMark(mark);
^ Here, it should be mark = checkMark(mark);
if you want the mark
variable in this code to be updated. This is because the value of mark
is passed to the function, not a reference to the variable mark
. Another solution is to pass such a reference, but I don't think you're ready for this yet :)
assignMark=mark;
printf("\nEnter midterm mark:");
scanf("%f",&mark);
checkMark(mark);
midMark=mark;
printf("\nEnter exam mark:");
scanf("%f",&mark);
checkMark(mark);
examMark=mark;
^ Same remarks for all these lines
finalMark=computeFinalGrade(assignMark,midMark,examMark,finalMark);
^ Passing finalMark
as a parameter here is completely useless. It should just be finalMark = computeFinalGrade(assignMark, midMark, examMark);
, don't you think?
letterGrade=computeLetterGrade(finalMark);
printf("The final grade for the course is %.1f, and the letter grade is %c.\n",finalMark,letterGrade);
return 0;
}
As mentioned just earlier, you don't need to pass some finalGrade
value to computeFinalGrade
, you should be okay with just:
float computeFinalGrade(float assign, float midterm, float finalExam)
{
return 0.2*assign + 0.3*midterm + 0.4*finalExam; // this could even be a macro
}
Finally, in computeLetterGrade
, you are doing a lot of redundant tests, and your control flow is messed up by this variable assignment, plus you should use a char
rather than an int
. Try this instead:
char computeLetterGrade(float finalGrade)
{
if(finalGrade>=80) return 'A';
// Since we did not return, necessarily finalGrade < 80
if(finalGrade>=70) return 'B';
if(finalGrade>=60) return 'C';
if(finalGrade>=50) return 'D';
// All other ifs failed, therefore finalGrade < 50
return 'E';
}
You will probably need to fix some things I didn't mention, but at least you should be closer to your goals with some of these corrections.
Upvotes: 2
Reputation: 6451
Segmentation faults occur when your program tries to access a memory region outside the one assigned to your program. scanf()
expects an address of the variable. In your code, you passed variable's value to scanf()
instead of its address as pointed out by cnicutar.
scanf("%d",mark);
The mark variable is not initialized and has some random data, which is treated as a memory location by scanf and when it tries to write to that address... Segmentation fault occurs because you accessed a restricted memory. Also, mark is float variable and so you should use %f
specifier..
scanf("%f", &mark);
Upvotes: 1