分段故障核心转储...?
Posted
技术标签:
【中文标题】分段故障核心转储...?【英文标题】:Segmentation fault core dumped...? 【发布时间】:2011-11-06 08:09:32 【问题描述】:我正在努力做到这一点:
编写一个接受三个用户输入的程序:作业分数、期中分数和期末考试 标记。
这些输入的类型为浮点型,值应介于 0 和 100 之间。
程序 应该将最终成绩计算为百分比和字母成绩。
• 期末成绩计算为:作业 20%,期中 30%,期末考试 50%。字母等级 计算为:A(最终成绩 ≥ 80%),B(80 > 最终成绩 ≥ 70%),C(70 > 最终成绩 ≥ 60%), D(60 > 最终成绩 ≥ 50%)和 F(50 > 最终成绩)。
显示最终成绩和字母成绩。
使用以下代码:
#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;
当我调试上面的程序并输入一个负数时,它给了我这个:
Enter assignment grade:123
Segmentation fault (core dumped)
我到底做错了什么?
【问题讨论】:
学习使用调试器,如gnu.org/s/gdb 它在哪里崩溃?将核心文件加载到 gdb 并进行一些事后分析。然后,当您知道它崩溃的哪一行时,这个主题就容易一些了。 123 不是负数... @NickLH:在这种情况下,我认为它是 错误 中的“负面”。 他说“并输入一个负数”,即数字 【参考方案1】:这是你的问题:
scanf("%d",mark);
你需要传递变量的地址,说明符应该是%f
。试试:
scanf("%f", &mark);
顺便说一句,有一个C FAQ 与此有关。
【讨论】:
如果您使用gcc -Wall -g yourcode.c -o yourprogram
编译,编译器会捕捉到这一点。但你真的应该了解更多!
你应该学习如何使用gdb
,你应该学习更多关于如何使用gcc
。特别是,您应该始终将 -Wall
传递给 gcc
以获取您的代码。您可能还应该学习如何使用make
并在多个源文件中编写程序。玩得开心。
@BasileStarynkevitch 你是如何推断我不知道如何使用gdb
或者我没有在启用警告的情况下编译的?
Basile 可能在谈论 OP,@cnicutar
是的,你指的是Iakam99,那个正在做作业的人。【参考方案2】:
关于您的代码的更多评论:
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;
应该是:
#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;
注意我:
删除了无用的 cmets
移除了幻数(0 和 100)
删除了一个无用的测试(如果退出 while 循环,则 x 在 0, ..., 100
允许x
等于0
删除了幂等赋值(x=x
没有做任何有用的事情...)
然后:
float getMark(void)
float mark=0,assignMark=0,midMark=0,examMark=0,finalMark=0;
char letterGrade;
printf("Enter assignment grade:");
scanf("%d",mark);
^ 正如其他人所说,你应该在这个scanf
中使用%f
和&mark
。
checkMark(mark);
^ 此处,如果您希望更新此代码中的mark
变量,则应为mark = checkMark(mark);
。这是因为mark
的值被传递给函数,而不是对变量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);
^ 在这里传递finalMark
作为参数是完全没用的。应该只是finalMark = computeFinalGrade(assignMark, midMark, examMark);
,你不觉得吗?
letterGrade=computeLetterGrade(finalMark);
printf("The final grade for the course is %.1f, and the letter grade is %c.\n",finalMark,letterGrade);
return 0;
如前所述,您不需要将一些finalGrade
值传递给computeFinalGrade
,您应该可以:
float computeFinalGrade(float assign, float midterm, float finalExam)
return 0.2*assign + 0.3*midterm + 0.4*finalExam; // this could even be a macro
最后,在computeLetterGrade
中,您正在执行大量冗余测试,并且您的控制流被此变量分配弄乱了,另外您应该使用char
而不是int
。试试这个:
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';
您可能需要修复一些我没有提到的问题,但至少您应该通过其中一些更正更接近您的目标。
【讨论】:
【参考方案3】:如果您使用的是 linux,请查看我的回答 here。这是关于 valgrind,一个帮助调试段错误、内存泄漏等的工具。
【讨论】:
【参考方案4】:当您的程序尝试访问分配给您的程序的内存区域之外的内存区域时,会发生分段错误。 scanf()
需要变量的地址。在您的代码中,您将变量的值传递给scanf()
,而不是 cnicutar 指出的地址。
scanf("%d",mark);
mark 变量没有初始化并且有一些随机数据,被scanf 当作一个内存位置,当它试图写入那个地址时... 出现分段错误,因为你访问了一个受限的内存。另外,mark 是浮点变量,所以你应该使用%f
说明符..
scanf("%f", &mark);
【讨论】:
以上是关于分段故障核心转储...?的主要内容,如果未能解决你的问题,请参考以下文章