java - 无法打印正确的金额

标签 java loops

我已经根据每个学生的成绩为他/她分配了一个字母等级。我想计算每个字母年级的学生总数。但是由于某些原因,结果完全错误。谁能告诉我我做错了哪些部分?谢谢!

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/

相关文章:

java - itextPdf 的问题,拒绝重新初始化先前失败的类 java.lang.Class<com.itextpdf.awt.PdfGraphics2D>

java - VM 初始化期间发生错误,无法为对象堆保留足够的空间 - Spring Tool Suite?

java - 为什么 Throwable.getMessage() 偶尔会返回 null?

java - 如何删除链表中的第一个节点?

loops - Lisp 帮助 |错误 : Duplicate binding in LOOP : (result)

javascript - 如何使用 JQuery 或 Javascript 动态检索图像 src 属性并将其添加到循环中的 html 中

java - 参数值丢失(接缝框架)

java - 在 Java 中,我可以使用迭代 8 次的 for 循环将位转换为最初为 0 的整数,以获得某个 8 位数字吗?

java - 边框布局循环。 J面板/Swing

python - 遍历 DictReader