如何将字母转换成数字并打印出BTEC最终成绩

时间:2015-05-29 12:09:48

标签: c#

我正在为那些不知情的人设计BTEC等级计算器; BTEC是在英国完成的一种资格认证,并且有一个不同的'点评分系统主要基于课程作业。有许多单位(20),每个单位你可以获得每个单位的通行证,优点和区别。每次传球,优点和区别都会增加到很多分数,而这些分数也会影响整体成绩。

例如,120分的分数将映射到PPP分数,240分将映射到MMM,依此类推。

我已经根据以下伪代码编写了一个程序:

Prompt for student name:
Operator enters student name
Operator enters their grade units one at a time (D, M, P, D etc):
Display Message about final grade:
    Your final Grade is:
    DMM

以下是我当前的代码,但需要进行更改和修复。目前,我需要输入单位成绩作为数字(20,40)。我希望能够输入成绩单(D,M,P)。如何更改我的程序以便它可以解释字母并将它们映射到单位分数?

我也遇到了从最终成绩转换到最终成绩的问题。目前,如果我输入两个单位等级80,总得分为160,显示的等级应为MPP,但是打印120.我做错了什么?

class Program
{
    static void Main(string[] args)
    {
        int counter;
        double score;

        while (true)
        {
            counter = 1;
            score = 0.0;
            Console.WriteLine("Enter Your Name or type 'exit' to quit): ");
            // Naming for exiting 
            string name = Console.ReadLine();
            if (name == "exit")
            {
                Environment.Exit(0);
            }
            else
            {
                int numberOfUnits = 20;
                Console.WriteLine("Number of Units:  ");
                numberOfUnits = int.Parse(Console.ReadLine());

                while (counter <= numberOfUnits)
                {
                    Console.WriteLine("Final Grade Score {0}", counter);
                    score += double.Parse(Console.ReadLine());
                    counter++;
                }
                // Add up and print letter grade. 
                score = (score / (counter - 1));
                if (score < 120)
                {
                    Console.WriteLine("Letter Grade: PPP");
                }
                else if (score < 160)
                {
                    Console.WriteLine("Letter Grade: MPP");
                }
                else if (score < 200)
                {
                    Console.WriteLine("Letter Grade: MMP");
                }
                else if (score < 240)
                {
                    Console.WriteLine("Letter Grade: MMM");
                }
                else if (score < 280)
                {
                    Console.WriteLine("Letter Grade: DMM");
                }
                else if (score < 320)
                {
                    Console.WriteLine("Letter Grade: DDM");
                }
                else if (score < 360)
                {
                    Console.WriteLine("Letter Grade: DDD");
                }
                    // After DDD it goes up by 20's ..... D* = 20 not 40...
                else if (score < 380)
                {
                    Console.WriteLine("Letter Grade: D*DD");
                }
                else if (score < 400)
                {
                    Console.WriteLine("Letter Grade: D*D*D");
                }
                else if (score < 420)
                {
                    Console.WriteLine("Letter Grade: D*D*D*");
                }
                Console.WriteLine("Grade: {0}", (score).ToString("P"));
            }
        }
    }
}

2 个答案:

答案 0 :(得分:0)

以下是包含一些小编辑的代码,以及用于将字母转换为数字的switch语句。

public class Program
{
    static void Main(string[] args)
    {
        int counter;
        double score;

        while (true)
        {
            counter = 1;
            score = 0.0;
            Console.WriteLine("Enter Your Name or type 'exit' to quit): ");
            // Naming for exiting 
            string name = Console.ReadLine();
            if (name == "exit")
            {
                return;
            }
            else
            {
                int numberOfUnits = 20;
                Console.WriteLine("Number of Units:  ");
                numberOfUnits = int.Parse(Console.ReadLine());

                while (counter <= numberOfUnits)
                {
                    Console.WriteLine("Final Grade Score {0}", counter);
                    string s = Console.ReadLine().ToUpper();
                    double d;
                    if (double.TryParse(s, out d)) //parsing as a number was successfull, and the result is in d.
                        score += d;
                    else //parsing failed.
                    {
                        switch (s)
                        {
                            case "D":
                                score += 20;
                                break;
                            case "M":
                                score += 50;
                                break;
                            case "P":
                                score += 70;
                                break;
                            default:
                                counter--; //parsing of a letter failed. reducing counter that will be later incremented, to offset the effect.
                                Console.WriteLine("Could not parse your grade. Enter a number or a letter");
                                break;
                        }
                    }
                    counter++;
                }
                // Add up and print letter grade. 
                score = (score / (counter - 1));

                if (score < 120) Console.WriteLine("Letter Grade: PPP");
                else if (score < 160) Console.WriteLine("Letter Grade: MPP");
                else if (score < 200) Console.WriteLine("Letter Grade: MMP");
                else if (score < 240) Console.WriteLine("Letter Grade: MMM");
                else if (score < 280) Console.WriteLine("Letter Grade: DMM");
                else if (score < 320) Console.WriteLine("Letter Grade: DDM");
                else if (score < 360) Console.WriteLine("Letter Grade: DDD");
                // After DDD it goes up by 20's ..... D* = 20 not 40...
                else if (score < 380) Console.WriteLine("Letter Grade: D*DD");
                else if (score < 400) Console.WriteLine("Letter Grade: D*D*D");
                else if (score < 420) Console.WriteLine("Letter Grade: D*D*D*");
                Console.WriteLine("Grade: {0}", (score).ToString("P"));
            }
        }
    }
}

答案 1 :(得分:0)

您的代码存在很多问题,对于SO问题来说真的太多了。正如我在评论中所说,如果您需要从任意字符串转换为数字,您可以使用一系列if语句或开关,或者您可以使用某种映射。至于你的问题从分数转换回成绩,我的印象仍然是问题就在这一行:

score = (score / (counter - 1));

将得分除以单位数是没有意义的。如果每个单位得到20分,除以单位数就会给你最终得分20 ......这看起来非常错误。

你遇到的部分问题是你已经在一个函数中编写了整个代码。您真的需要将代码分解为逻辑单元。单位将更小,更容易理解,更容易测试。我强烈建议你不要在主要方法中写很多东西。启动另一个相关课程并将工作留给它。以下是一些关于破坏程序的替代方法的建议。它远非抛光,但比较两者,看哪哪个更容易理解。

// Main class.  This doesn't do anything but spin up a new class
// and tell it to get all student grades.
class Program
{
    static void Main(string[] args)
    {
        var calculator = new BTECGradeCalculator();
        calculator.GetAllStudentGrades();
    }
}

新的BTECGradeCalculator包含多个功能。我做的第一件事就是键入上面伪代码的解释和一个新函数:

public void GetAllStudentGrades() {
    while (true) {
        string studentName = PromptStudentAndGetName();
        if (studentName.ToUpper() == "EXIT") {
            return;
        }
        List<string> studentGrades = GetStudentGrades();
        int score = CalculateScoreFromGrades(studentGrades);
        string finalGrade = CalculateGradeFromScore(score);

        PrintFinalStatement(studentName, finalGrade);
    }
}

你可以看到函数本身几乎完全由函数调用组成。每个人都有一个合理的描述性名称(非常主观),这样该方法几乎就像是伪代码。

然后我实现了这些方法。每个人都有一个与其名称相匹配的特定任务。这使您更有可能尝试识别错误。您还可以将方法公开/将其中一些方法移动到其他类,并使用像nunit这样的测试框架单独测试它们。

private string PromptStudentAndGetName() {
    Console.WriteLine("Enter Your Name or type 'exit' to quit): ");
    return Console.ReadLine();
}


private List<string> GetStudentGrades() {
    List<string> grades = new List<string>();
    Console.WriteLine("Number of Units:  ");

    int numberOfUnits = GetNumberOfUnits();

    for (int counter = 1; counter <= numberOfUnits; ) {
        Console.WriteLine("What was your grade for unit {0}", counter);
        var grade = Console.ReadLine();
        if (IsValidGrade(grade)) {
            grades.Add(grade);
            counter++;
        }
        else {
            Console.WriteLine("That's not a valid grade!");
        }
    }

    return grades;
}

private int CalculateScoreFromGrades(List<string> studentGrades) {
    int score = 0;
    foreach (var grade in studentGrades) {
        score += GetScoreFromGrade(grade);
    }
    return score;
}

private string CalculateGradeFromScore(int score) {
    if (score < 120) return "PPP";
    if (score < 160) return "MPP";
    if (score < 200) return "MMP";
    if (score < 240) return "MMM";
    if (score < 280) return "DMM";
    if (score < 320) return "DDM";
    if (score < 360) return "DDD";
    if (score < 380) return "D*DD";
    if (score < 400) return "D*D*D";
    if (score < 420) return "D*D*D*";
    throw new InvalidOperationException(string.Format("Unexpected score {0}", score));
}

private void PrintFinalStatement(string studentName, string finalGrade) {
    // Add up and print letter grade. 
    Console.WriteLine("Student: {0}", studentName);
    Console.WriteLine("Grade: {0}", finalGrade);
}

请注意,有些方法再次被细分,调用其他较小的方法以保持代码大小可管理。这些方法如下:

private int GetNumberOfUnits() {
    int numberOfUnits;

    if (!int.TryParse(Console.ReadLine(), out numberOfUnits)) {
        Console.WriteLine("Sorry... I didn't understand that.  I'm going to assume you have the expected 20 units.");
        numberOfUnits = 20;
    }
    return numberOfUnits;
}

bool IsValidGrade(string grade) {
    string [] validGrades = {"D","M","P"};
    return validGrades.Contains(grade.ToUpper());
}

private int GetScoreFromGrade(string grade) {
    switch (grade.ToUpper()) {
        case "P":
            return 20;
        case "M":
            return 40;
        case "D":
            return 80;
    }
    throw new InvalidOperationException(string.Format("Tried to get a score from an invalid grade {0}", grade));
}

另请注意,上述某些方法会在遇到包含错误信息的意外情况时抛出异常,例如帮助确定问题原因的意外得分/等级。正如我所说,这远非一个理想的程序,但它确实提出了一个方向,以帮助您诊断自己的问题。