Ошибка сегментации ядра сбрасывается ...? - PullRequest
0 голосов
/ 06 ноября 2011

Я пытаюсь сделать это:

Напишите программу, которая принимает три пользовательских ввода: отметка о назначении, промежуточная отметка и итоговый экзамен mark.

Эти входы имеют тип float и должны иметь значения от 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)

Что я делаю неправильно?

Ответы [ 4 ]

3 голосов
/ 06 ноября 2011

Это ваша проблема:

scanf("%d",mark);

Вам нужно передать адрес переменной, а спецификатор должен быть %f.Попробуйте:

scanf("%f", &mark);

Кстати, есть C FAQ по этому поводу.

2 голосов
/ 06 ноября 2011

Еще несколько замечаний по вашему коду:

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

Обратите внимание, что я:

  • удалены бесполезные комментарии

  • удалены магические числа (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);

^ Как уже упоминалось, вы должны использовать %f и &mark в этом scanf.

    checkMark(mark);

^ Здесь должно быть mark = checkMark(mark);, если вы хотите, чтобы переменная 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';
}

Возможно, вам придется исправить некоторые вещи, которые я не упомянул, но по крайней мере вы должны быть ближе к своим целям с некоторыми из этих исправлений.

2 голосов
/ 06 ноября 2011

Если вы используете Linux, посмотрите на мой ответ здесь . Это о valgrind, инструменте, помогающем отлаживать ошибки, утечки памяти и т. Д.

1 голос
/ 06 ноября 2011

Ошибки сегментации возникают, когда ваша программа пытается получить доступ к области памяти вне той, которая назначена вашей программе. scanf() ожидает адрес переменной. В своем коде вы передали значение переменной scanf() вместо ее адреса, как указано cnicutar.

scanf("%d",mark);

Переменная mark не инициализирована и содержит некоторые случайные данные, которые сканирует как местоположение памяти при сканировании, и когда он пытается записать по этому адресу ... Ошибка сегментации возникает из-за обращения к ограниченной памяти. Кроме того, mark является переменной с плавающей точкой, поэтому вы должны использовать спецификатор %f.

scanf("%f", &mark);
...