我正在为那些不知情的人设计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"));
}
}
}
}
答案 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));
}
另请注意,上述某些方法会在遇到包含错误信息的意外情况时抛出异常,例如帮助确定问题原因的意外得分/等级。正如我所说,这远非一个理想的程序,但它确实提出了一个方向,以帮助您诊断自己的问题。