我根据他/她的成绩为每个学生分配了一个字母等级。我想计算每个字母等级的学生总数。但由于某些原因,结果完全错了。谁能告诉我哪些部分我做错了?谢谢!
String letter ="A";
int letterA=0;
int letterB=0;
int letterC=0;
int letterD=0;
int letterF=0;
int a=0;
int b=0;
int c=0;
int d=0;
int f=0;
for (int row=0;row<100;row++){ //the outer loop, have 100 rows to go through
for ( int column=0;column<words.length;column++) {
if(words[column].equals(table[row][column])){ // compare two arrays
count++; }// add the score for each student if he/she is right
}
if (count >=18)
letter=("A");
if(count>=16 && count<18)
letter=("B");
if(count>=14 && count<16)
letter=("C");
if(count>=12 && count<14)
letter=("D");
if(count<12)
letter=("F");
System.out.println("Student Grade: "+letter+"\t");
count=0; // make sure the count will go back to 0, and run the loop again
if (letter.equals("A"))
letterA++;
a+=letterA;}
if (letter.equals("B"))
letterB++;
b+=letterB;
if (letter.equals("C"))
letterC++;
c+=letterC;
if (letter.equals("D"))
letterD++;
d+=letterD;
if (letter.equals("F"))
letterF++;
f+=letterF;
System.out.print("Question A "+a);
System.out.print("Question B "+b);
System.out.print("Question C "+c);
System.out.print("Question D "+d);
System.out.print("Question F "+f);
}
答案 0 :(得分:3)
if (letter.equals("A"))
letterA++;
a+=letterA;}
if (letter.equals("B"))
letterB++;
b+=letterB;
if (letter.equals("C"))
letterC++;
c+=letterC;
if (letter.equals("D"))
letterD++;
d+=letterD;
if (letter.equals("F"))
letterF++;
f+=letterF;
应永远是:
if ("A".equals(letter)) { letterA++; }
else if ("B".equals(letter)) { letterB++; }
else if ("C".equals(letter)) { letterC++; }
else if ("D".equals(letter)) { letterD++; }
else if ("F".equals(letter)) { letterF++; }
else { throw new RuntimeException("Invalid Letter " + letter); }
如果您希望它们在视觉上紧凑,请使用单行语句,但是 仍然使用大括号,因为他们保证了目标的意图 在给定的块中完成,它们也充当该意图的文档 为未来的人(包括你在内的人)知道将要发生的事情 上。
我认为他们从未使用过的单字母变量没有正当理由,我不明白为什么他们在那里?
在if
匹配时执行if
后,退出大括号仅表示第一个语句,下一行始终执行。
if (letter.equals("A"))
letterA++;
a+=letterA;
实际上是
if (letter.equals("A")) { letterA++; }
a+=letterA;
这意味着无论if
测试中的表达式如何评估,大括号外的行总是会被执行。第二行的缩进将该语句混淆为if
块的一部分,而不是。{/ p>
通过省略大括号来获得绝对无 一切都要失去。
始终一致地格式化您的代码,而不是那么密集,以便您可以知道正在发生什么以及缺少大括号的版本有什么问题。
看看它有很多white space的最佳广告,干净的格式化代码应该有足够的一致white space,以便我们的大脑可以快速模式匹配并扫描相关的事情,如匹配对括号。
清理格式化的代码只是所有值得使用的IDE的按键。
清洁代码表明您关心自己在做什么,并使您的问题更具吸引力,这意味着其他人也会关心他们的答案。
清洁代码可以让您了解他们所知道的内容,并让您与那些不关心或不知道他们正在看什么的人分开。
最重要的清洁代码更容易推理并且更少 错误,没有微妙的错误,并且更容易维持。
始终使用if/else if/else
进行互斥测试。
如果所有if
子句都是互斥的并且您匹配第一个子句,则所有其余子句仍然无法使用if/if/if/if
结构进行评估。 if/else if/else if/else if/else
仅在匹配或匹配之前进行评估。
如果没有else
,则不会涵盖所有可能不匹配的情况,这通常是在没有else
的情况下以静默方式发生的错误。
不要只覆盖happy path,覆盖特殊路径,而是在least defensive manner possible中进行。
== null
检查;完全避免null
:始终将文字与.equals()
的变量进行比较,以避免可能的NullPointerExceptions
。
完全避免使用null
引用,在每种情况下都可能,甚至是看起来像是合法理由的情况。
如果Tony Hoare,他们的发明者thinks it is a mistake 谁会争辩。
我不确定letterA
应该代表什么a
应该代表什么。所以没有人能告诉你这些是否正确,因为没有人确切知道它们在语义上代表什么。
final int A_GRADE = 18;
final int B_GRADE = 16;
final int C_GRADE = 14;
final int D_GRADE = 12;
考虑到它们的使用方式,名称可能会更好 像
MINIMUM_A_GRADE
,但这是基于意见的,教训是避免 神奇的数字。
在同一方向上进行范围检查,以便变量在视觉中位于比较的中间。 这使得以后破坏逻辑变得更加困难,并且自我记录它是一个范围检查。
if (count >= A_GRADE) { /* omitted */ }
else if (B_GRADE <= count && count < A_GRADE) { /* omitted */ }
else if (C_GRADE <= count && count < B_GRADE) { /* omitted */ }
else if (D_GRADE <= count && count < C_GRADE) { /* omitted */ }
else /* isF */ { /* omitted */ }
哪一个更容易推理和维护?
private static boolean isA(final int count) { return count >= A_GRADE; }
private static boolean isB(final int count) { return B_GRADE <= count && count < A_GRADE; }
private static boolean isC(final int count) { return C_GRADE <= count && count < B_GRADE; }
private static boolean isD(final int count) { return D_GRADE <= count && count < C_GRADE; }
然后您将拥有以下内容:
if (isA(count)) { /* omitted */ }
else if (isB(count)) { /* omitted */ }
else if (isC(count)) { /* omitted */ }
else if (isD(count)) { /* omitted */ }
else /* isF */ { /* omitted */ }
哪一个更明显,自我记录,因此更多 维护?
逻辑if (count >= A_GRADE) { letter = "A";}
与if ("A".equals(letter)) { /* do stuff */ }
完全相同,因此这是重复的逻辑。
而不是分配letter
而不是再次检查,只需将逻辑放在原始支票中。
if (count >= A_GRADE) { /* do stuff */ }
else if (B_GRADE <= count && count < A_GRADE) { /* do stuff */ }
else if (C_GRADE <= count && count < B_GRADE) { /* do stuff */ }
else if (D_GRADE <= count && count < C_GRADE) { /* do stuff */ }
else { /* omitted */ }
我认为他们从未使用过的单字母变量没有正当理由,我不明白为什么他们在那里?
重复逻辑意味着多个地方有错误和多个错误 编辑的地方修复错误,节省自己的时间和精力,并遵循
DRY
原则。
当do stuff
超过几行时,将其重构为方法调用。
if (count >= A_GRADE) { recordMarkA(); }
else if (B_GRADE <= count && count < A_GRADE) { recordMarkB(); }
else if (C_GRADE <= count && count < B_GRADE) { recordMarkC(); }
else if (D_GRADE <= count && count < C_GRADE) { recordMarkD(); }
else { recordMarkF(); }
使用描述性名称的更小的方法总是比大的方法更好 整体内联代码块。
所以我精心设计了我想要一个完整的解决方案(提供部分/不完整的代码)看起来像。
public class Q34081279
{
final static int A_GRADE = 18;
final static int B_GRADE = 16;
final static int C_GRADE = 14;
final static int D_GRADE = 12;
public static void main(final String[] args)
{
final String[] words = new String[]{}; /* this is just a placeholer, not provided in question */
final String[][] table = new String[][]{}; /* this is just a placehoder, not provided in question */
int markA = 0;
int markB = 0;
int markC = 0;
int markD = 0;
int markF = 0;
for (int row = 0; row < 100; row++)
{
int count = 0;
for (int column = 0; column < words.length; column++)
{
if (words[column].equals(table[row][column])) { count++; }
}
if (count >= A_GRADE) { System.out.format("%d = A", count); }
else if (B_GRADE <= count && count < A_GRADE) { System.out.format("%d = B", count); }
else if (C_GRADE <= count && count < B_GRADE) { System.out.format("%d = C", count); }
else if (D_GRADE <= count && count < C_GRADE) { System.out.format("%d = D", count); }
else { System.out.format("%d = F", count); }
System.out.println();
}
System.out.println(String.format("Question A %d", markA));
System.out.println(String.format("Question B %d", markB));
System.out.println(String.format("Question C %d", markC));
System.out.println(String.format("Question D %d", markD));
System.out.println(String.format("Question F %d", markF));
}
}
答案 1 :(得分:0)
@Buddy在合适的架子上,但不仅如此。所有带有多行的if
语句都需要括号。
否则编译器只读取第一行。根据Oracle的说法:
决定何时省略牙箍是个人品味的问题。省略它们会使代码变得更脆弱。如果稍后将第二个语句添加到&#34;那么&#34;条款,一个常见的错误是忘记添加新需要的大括号。编译器无法捕获这种错误;你会得到错误的结果。
例如:
if (letter.equals("A")) {
letterA++;
a+=letterA;
}
if (letter.equals("B")) {
letterB++;
b+=letterB;
}