如何将字母转换成数字并打印出BTEC最终成绩
本文关键字:打印 BTEC 数字 转换 | 更新日期: 2023-09-27 17:51:09
我正在设计一个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"));
}
}
}
}
下面是经过一些小编辑的代码,以及将字母转换为数字的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"));
}
}
}
}
你的代码有相当多的问题,太多的问题真的。正如我在评论中所说的,如果你需要将任意字符串转换为数字,你可以使用一系列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));
}
还要注意,上面的一些方法在遇到包含有关错误信息的意外情况时抛出异常,例如意外的分数/等级,以帮助确定问题的原因。正如我所说的,这不是一个理想的程序,但它确实有希望为您提供一个方向,以帮助您诊断自己的问题。