我已经根据每个学生的成绩为他/她分配了一个字母等级。我想计算每个字母年级的学生总数。但是由于某些原因,结果完全错误。谁能告诉我我做错了哪些部分?谢谢!
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);
}
最佳答案
始终使用大括号,即使对于单个语句也是如此:
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
块的一部分,但不是。省略括号并绝对没有任何好处
一切都输了。
简洁的代码易于阅读和维护,并显示出您的关心:
始终以一致的格式格式化代码,而不要那么密集,以便您可以知道发生了什么以及括号缺失的版本出了什么问题。
查看具有大量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中进行。
Explicit is always better than Implicit!
避免
== null
检查;完全避免使用null
:始终将文字与带有
.equals()
的变量进行比较,以避免可能出现的NullPointerExceptions
。避免完全使用
null
引用,在每种情况下都有可能,即使在看起来合理的情况下也是如此。如果为Tony Hoare,则其发明人thinks it is a mistake
谁在争论。
始终使用描述性名称命名变量!
我不确定
letterA
应该代表什么,而不是a
应该代表什么。因此,没人能告诉您这些是否正确,因为没人知道它们在语义上代表什么。没有未命名的数字常数(Magic Numbers):
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 */ }
哪一个更明显并且可以自我记录,因此更多
可维护的?
干-Don't Repeat Yourself:
逻辑上
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(); }
具有描述性名称的更多小型方法始终胜于大型方法
内联代码的整体块。
这个问题表明了巨大的努力和对学习的真正渴望:
因此,我拟定了一个完整的解决方案(提供了部分/不完整的代码)的外观。
Q34081279.java
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));
}
}
关于java - 无法打印正确的金额,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34081279/