无法打印出正确的金额

时间:2015-12-04 05:08:57

标签: 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);
 }

2 个答案:

答案 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中进行。

  

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 */ }
  

哪一个更明显,自我记录,因此更多   维护?

DRY - 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));
    }
}

答案 1 :(得分:0)

@Buddy在合适的架子上,但不仅如此。所有带有多行的if语句都需要括号。

否则编译器只读取第一行。根据Oracle的说法:

  

决定何时省略牙箍是个人品味的问题。省略它们会使代码变得更脆弱。如果稍后将第二个语句添加到&#34;那么&#34;条款,一个常见的错误是忘记添加新需要的大括号。编译器无法捕获这种错误;你会得到错误的结果。

例如:

if (letter.equals("A")) {
  letterA++;
  a+=letterA;
}  
if (letter.equals("B")) {
  letterB++;
  b+=letterB;
}