我正在尝试创建一个程序,通过记录每个主题中获得的标记数来计算考试结果。它几乎完成但我遇到一个错误,即如果用户只是按Enter而不是输入值,应用程序将不会继续。还有什么方法可以缩短这段代码吗?
Console.WriteLine("Danyal's result calculator for students of class IX. Enter the marks requested, if not applicable leave blank and press enter :)");
Console.Write("Enter your Urdu marks: ");
int urdu = int.Parse(Console.ReadLine());
Console.Write("Enter your Maths marks: ");
int maths = int.Parse(Console.ReadLine());
Console.Write("Enter your English Literature marks: ");
int lit = int.Parse(Console.ReadLine());
Console.Write("Enter your Biology marks: ");
int bio = int.Parse(Console.ReadLine());
Console.Write("Enter your Chemistry marks: ");
int chem = int.Parse(Console.ReadLine());
Console.Write("Enter your Islamiat marks: ");
int isl = int.Parse(Console.ReadLine());
Console.Write("Enter your Physics marks: ");
int physics = int.Parse(Console.ReadLine());
Console.Write("Enter your Computer marks: ");
int comp = int.Parse(Console.ReadLine());
Console.Write("Enter your English Language marks: ");
int lang = int.Parse(Console.ReadLine());
Console.Write("Enter your Pakistan Studies marks: ");
int pst = int.Parse(Console.ReadLine());
int total = urdu + maths + lit + lang + bio + chem + physics + isl + comp + pst;
Console.WriteLine("Your total marks are {0} out of 1000", total);
float percentage = total * 100 / 1000;
Console.WriteLine("Your percentage is: {0}%",percentage);
Console.WriteLine("Note: the percentage has been rounded off. Please share this program with other classmates, also I am open to suggestions for creating more helpful programs.");
Console.ReadLine();
答案 0 :(得分:4)
如果用户将其留空或输入无效值,我不确定您想要做什么,但您可以这样做。
Dictionary<string,int> grades = new Dictionary<string, int>
{
{ "Urdu", 0 },
{ "Maths", 0 },
{ "English", 0 },
{ "Biology", 0 },
{ "Chemistry", 0 },
{ "Islamiat", 0 },
{ "Physics", 0 },
{ "Computer", 0 },
{ "English Language", 0 },
{ "Pakistan Studies", 0 },
};
foreach (string grade in grades.Keys.ToArray())
{
Console.WriteLine(string.Format("Enter your {0} marks: ", grade));
int mark;
if (int.TryParse(Console.ReadLine(), out mark))
grades[grade] = mark;
}
int total = grades.Sum((g) => g.Value);
在此示例中,如果使用错误输入,则成绩将默认为0.如果您愿意,可以将if try解析更改为循环并请求一个好的值,直到输入一个。
答案 1 :(得分:1)
这是一个不遵守DRY原则的明显案例。您正在重复基本相同的操作,不要这样做。重构代码,以便在一个地方解决常见的模式或行为。
你会怎么做?
创建一个提示用户输入特定信息的方法。用户需要什么?描述他必须做什么的信息。用户需要做什么?输入有效输入。好的,考虑到这一点,以下方法的原型似乎是一个很好的起点:
private static int GetUserInput(string message) { ... }
嗯...输入有效输入。这意味着我们需要某种验证,所以再次让我们想一想如何解决这个问题:
private static int ValidateUserInput(string input) { ... }
这够好吗?嗯......不太好。如果用户输入的号码不正确会怎样?没有方便的方式来传达输入对呼叫者无效。我们可以返回-1,或者我们可以抛出一个异常,但两者看起来都很糟糕。
最好的解决方案是返回两个值;一个告诉我们输入是否有效,另一个告诉我们输入是什么。在c#中,这并不是非常严格(至少在c#7出现之前)。这样做的方法是使用out
参数:
private static bool ValidateUserInput(string message, out int input) { ... }
现在这种方法完全符合我们的目的。返回值告诉我们输入是否有效,out
参数input
为我们提供了验证值(或者如果验证失败,我们就会忽略它。)
如果您基本上只想要总和和平均值,为什么要为每个标记创建一个int
变量?让我们创建一个List<int>
,我们存储所有标记。
另一个选项是,如果要跟踪哪个标记对应于哪个主题,将使用Dictionary<string, key>
,其中键是主题名称,值是其对应标记。但是现在让我们使用List<int>
。
考虑到这些,我们可以建立我们的解决方案:
public static void ComputeMarksSummary()
{
var marks = new List<int>();
marks.Add(GetUserInput("Enter your Urdu marks: "));
marks.Add(GetUserInput("Enter your Maths marks: : "));
marks.Add(GetUserInput("Enter your English Literature marks: "));
marks.Add(GetUserInput("Enter your Biology marks: "));
marks.Add(GetUserInput("Enter your Chemistry marks: "));
marks.Add(GetUserInput("Enter your Islamiat marks: "));
marks.Add(GetUserInput("Enter your Computer marks: "));
marks.Add(GetUserInput("Enter your English language marks: "));
marks.Add(GetUserInput("Enter your Pakistan studies marks: "));
var total = marks.Sum();
Console.WriteLine("Your total marks are {0} out of 1000", total);
Console.WriteLine("Your percentage is: {0}%", total/10.0); //note the 10.0 to force double division, not integer division where 44/10 would be 4 not 4.4
Console.WriteLine("Note: the percentage has been rounded off. Please share this program with other classmates, also I am open to suggestions for creating more helpful programs.");
//WRONG! Percentage is not rounded off, its truncated: 9/10 is 0 in integer division.
Console.ReadLine();
}
private static int GetUserInput(string message)
{
int mark;
while (true)
{
Console.WriteLine(message);
var input = Console.ReadLine();
if (!ValidateUserInput(input, out mark))
{
Console.WriteLine("Invalid input, please try again.");
}
else
{
return mark;
}
}
}
private static bool ValidateUserInput(string message, out int input)
{
//left as an excerice. Hint: look into int.TryParse(...);
//here you could decide if a blank input should be valid and parsed as zero.
}
哇,现在看起来好多了......但是,嘿,我们仍然可以做得更好一些。怎么了marks.Add(....)
?我们不能再重构代码吗?是的,我们基本上总是要求相同的事情,只有主题名称改变。我们做这样的事情怎么样:
public static void ComputeMarksSummary(IEnumerable<string> subjectNames)
{
var marks = new List<int>();
foreach (var subject in sujectNames)
{
marks.Add(GetUserInput(string.Format("Enter your {0} marks: ", subject)));
}
var total = marks.Sum();
Console.WriteLine("Your total marks are {0} out of 1000", total);
Console.WriteLine("Your percentage is: {0}%", total/10.0); //note the 10.0 to force double division, not integer division where 44/10 would be 4 not 4.4
Console.WriteLine("Note: the percentage has been rounded off. Please share this program with other classmates, also I am open to suggestions for creating more helpful programs.");
Console.ReadLine();
}
你可以这样称呼它:
ComputeMarksSummary(new string[] { "Urdu", "Maths", ... );
看起来那么干净吗?