Требуется помощь по L oop для усреднения оценок с использованием awk. Выходные данные выводит одинаковую оценку для каждого студента - PullRequest
0 голосов
/ 13 апреля 2020
BEGIN {
    FS=","
    OFS = "\t" 
    OFMT = "%.2f"
    }

$4~/[0-9]/ {

    EARN[$1$2]+=$4
    POS[$1$2]+=$5
    CLASS[$1]++
    TYPE[$2]++
}
END{ 
    TOTAL=0
    for (STUDENT in CLASS){ 

        HW=(EARN[$1"Homework"]/POS[$1"Homework"])*0.30
        LAB=(EARN[$1"Lab"]/POS[$1"Lab"])*0.50
        QUIZ=(EARN[$1"Quiz"]/POS[$1"Quiz"])*0.10
        FINAL=(EARN[$1"Final"]/POS[$1"Final"])*0.10
        WS=(EARN[$1"Survey"]/POS[$1"Survey"])*0.10
        TOTAL=(HW+LAB+QUIZ+FINAL+WS)*100
        GRADE= "A"

        if (TOTAL < 90) {
            GRADE="B"
        }
        if ( TOTAL < 80){
            GRADE="C"
        }
        if (TOTAL < 70){
            GRADE="D"
        }
        if( TOTAL < 60) {
            GRADE="E"
        }

    }
    print "Student\t Total \t Letter Grade"
        print STUDENT, TOTAL, "\t" GRADE    
}

Код / должен / давать уникальную оценку для каждого учащегося, но с моим файлом примера каждый ученик получает одинаковую оценку (которая, как я полагаю, является оценкой первого учащегося), код проходит через колонку 4 ЗАРАБОТАТЬ ( заработанные баллы) и сравнивая его с колонкой $ 5 POS (возможные баллы)

1 Ответ

0 голосов
/ 13 апреля 2020

У вас есть 2 основные проблемы с вашим сценарием (но хорошая работа и хорошие усилия - вы были близки). Во-первых, вам нужно переместить ваши печатные заявления. Первый в начале END, например,

END{ 
    print "Student\t Total \t Letter Grade"

, а следующий в пределах for (STUDENT in CLASS){ l oop, например,

        if( TOTAL < 60) {
            GRADE="E"
        }

        print STUDENT, TOTAL, "\t" GRADE    
    }
}

Второй и наиболее проблемный c error - использование $1 in, e, g, HW=(EARN[$1"Homework"]/... вместо использования STUDENT (который является вашей переменной l oop), например, HW=(EARN[STUDENT"Homework"]/...

Наряду со вторым, в ваших расчетах, если учащийся не имеет определенной c оценки (например, "Survey" или "Final", как в данных, которые вы указали в комментарии), вы получите деление на ноль, поскольку не будет соответствующей Например, POS[STUDENT"Survey"], и он будет принят за ноль.

Вы можете избежать этого с помощью троичной переменной, чтобы убедиться, что элементы отличны от нуля, или использовать 1 для значения, например, вместо:

    FINAL=(EARN[STUDENT"Final"]/POS[STUDENT"Final"])*0.10

вы можете использовать:

    FINAL=(EARN[STUDENT"Final"]/(POS[STUDENT"Final"] ? POS[STUDENT"Final"] : 1))*0.10

(это просто гарантирует, что знаменатель равен 1, если индекс не находится в массиве POS)

с этим изменением Вы можете использовать:

#!/bin/awk -f

BEGIN {
    FS=","
    OFS = "\t" 
    OFMT = "%.2f"
}

$4~/[0-9]/ {

    EARN[$1$2]+=$4
    POS[$1$2]+=$5
    CLASS[$1]++
    TYPE[$2]++
}
END{ 
    print "Student\t Total \t Letter Grade"
    TOTAL=0
    for (STUDENT in CLASS){ 

        HW=(EARN[STUDENT"Homework"]/(POS[STUDENT"Homework"] ? POS[STUDENT"Homework"] : 1))*0.30
        LAB=(EARN[STUDENT"Lab"]/(POS[STUDENT"Lab"] ? POS[STUDENT"Lab"] : 1))*0.50
        QUIZ=(EARN[STUDENT"Quiz"]/(POS[STUDENT"Quiz"] ? POS[STUDENT"Quiz"] : 1))*0.10
        FINAL=(EARN[STUDENT"Final"]/(POS[STUDENT"Final"] ? POS[STUDENT"Final"] : 1))*0.10
        WS=(EARN[STUDENT"Survey"]/(POS[STUDENT"Survey"] ? POS[STUDENT"Survey"] : 1))*0.10
        TOTAL=(HW+LAB+QUIZ+FINAL+WS)*100
        GRADE= "A"

        if (TOTAL < 90) {
            GRADE="B"
        }
        if ( TOTAL < 80){
            GRADE="C"
        }
        if (TOTAL < 70){
            GRADE="D"
        }
        if( TOTAL < 60) {
            GRADE="E"
        }

        print STUDENT, TOTAL, "\t" GRADE    
    }
}

( примечание: Я бы использовал "F" в качестве окончательной оценки вместо "E" - никогда не слышал об этом ..., а также использование строчные имена для ваших пользовательских переменных)

Пример Использование / Вывод

На основе предоставленных вами данных вы получите:

$ ./calcgrades.awk grades.txt
Student  Total   Letter Grade
Chelsey 86.89           B
Sam     40.77           E

Дайте мне знать, если у вас есть вопросы.

...