tags:

views:

263

answers:

4

Hi there. This question is not for the faint of heart and will be time consuming..

I am learning Java, and I was wondering if anyone could walk me through my program to tell me what I did wrong and how I can fix it so that I can learn.

My whole program (in case this is needed): http://pastie.org/private/xpbgpypetvfmivcs88gbcq

Assignment:

Not allowed to use global variables! You have been asked to write a program to grade the results of a true-false quiz and display the results in tabular form. The quiz consists of 10 questions. The data file for this problem consists of 1 set of correct responses (answerkey) on line one and succeeding lines containing a four digit student identification number followed by that student's 10 responses. (The number of students taking the quiz in currently unknown.)

The data file is in the form :

TFFTFTTFTT

0461 TTFTTFTFTT

3218 TFFTTTTTFT

.....................

....................

Your program should read the key and store it in a one dimensional array. It should then read and process each succeeding line, storing the student identification numbers in a one dimensional array and the grades in two separate one dimensional arrays- one for numeric grades and the for letter grades.

Numeric grades are converted to letter according to the following system : A(10), B(9), C(8-7), D (6-5), F(4-0).

Program output should include the following :

  1. Each Student's four digit identification number, their numeric grade and their letter grade.

  2. A printed count of how many students took the quiz.

  3. The numeric quiz average for the entire class.

  4. A frequency count of the number of A's, B's, C's,D's and F's for the entire class.

EDIT:

Oh, hey. Sorry, I am still getting the hang of how to do all of this :( Alright, here goes.

The program is not compiling, and I am pretty sure it's down to my logic. (As well as some syntactical stuff).

What I'm having trouble with: 1) How to pass all of the parameters to each of the different methods, as seen here. What I would LIKE to do is have all of my values that I return such as answerKey, studentAnswers, numericGrade, average etc be up here so that I can use them and print them. But I do not know how to do that.

int[] numericGrade = computeNumericGrade(answerKey, studentAnswers);
      int[] letterGrade = computeLetterGrade(numericGrade);
      double average = average(numericGrade);
      int gradeTally = gradeTally(letterGrade);
      int studentCount = studentCount(numericGrade);

2) I cannot figure out how to individually check through each of the T or F values and check if it corresponds with the T or F in the answer key, as seen below.

What I am trying to do is to check through each letter at a specific element, and if the value is "correct" or == to answerKey, then add to the total in numericGrade for that element.

public static int[] computeNumericGrade(int[] answerKey, int[] studentAnswers) {
      int[] numericGrade = new int[50];
      int total = 0;
      for(int i = 0; i < 50;i++) {
        for(int a = 0;a == 10;a++) {
          total = studentAnswers[i].charAt(a);
          if(total == answerKey[i]) numericGrade[i]++;
        }
      }
    return numericGrade;
    }

3) I do not know how to return all of these different values, as I need them all above! I want this set of code to check the letter grade of each element and if this element is found, ++ the variable that corresponds to it, so I know how many of this letter grade was called.

public static int gradeTally(String[] letterGrade) {
      int a, b, c, d, f = 0;
      for(int i = 0;i < letterGrade.length;i++) {
        if(letterGrade[i] == 'A') a++;
        else if (letterGrade[i] == 'B') b++;
        else if (letterGrade[i] == 'C') c++;
        else if (letterGrade[i] == 'D') d++;
        else if (letterGrade[i] == 'F') f++;
      }
      return a + b + c + d + f;
    }

4) I can't figure this out... I think I am close. Here, I am trying to read the file, tokenize it, and then for each token, add it to the array 1 by 1. However, I don't think that's it's doing that properly, but I can't check since I can't get it to compile...

public static String[] getData() throws IOException {
      int[] studentID = new int[50];
      String[] studentAnswers = new String[50];
      int total = 0;

      String line = reader.readLine();
      strTkn = new StringTokenizer(line);
      String answerKey = strTkn.nextToken();

      while(line != null) {
        studentID[total] = Integer.parseInt(strTkn.nextToken());
        studentAnswers[total] = strTkn.nextToken();
        total++;
      }
    return studentAnswers;
    }

I am now done editing my post. I hope this is sufficient :)

+3  A: 

I guess you realize from the comments that this is kind of difficult to help with.

I'm not sure how much it will help, but I'd like to give some general tips about how you might approach this.

First of all, I'd probably throw away what you have and start over. I've NEVER regretted throwing away code--it always helps your code in the long run and you learn a lot more the second time through.

Secondly, start small. Make something that works--even if it just reads in the values and proves they were read in properly, then expand it. Test CONSTANTLY. Whenever you add to your code, add a line to your test to ensure the new code works as well as everything that has come before it

This way if anything breaks, you'll know exactly what broke it--the last thing you edited.

To do this kind of quick test, you should either learn to use JUnit for unit testing or have a main made just for testing so that you can hit a single button and get an immediate answer. (JUnit really isn't hard and it's built into Eclipse. Oh yeah, next hint). .

USE ECLIPSE or NetBeans!

These are all things that experienced programmers just know and do automatically. A little investment of time and effort in the beginning can save a LOT of pain in the long run.

Bill K
Or IntelliJ - better than both of them.
duffymo
Judging by the experience level of the askers, I'd say using industry strength tools and practices is not advisable at such an early stage. There are better, more focussed **teaching** tools available, such as BlueJ which I'd recommend before Eclipse/NB/IDEA.
Grundlefleck
BlueJ is nice I used it quite a bit, but it doesn't have the instant error detection. It's not like it makes you "Lazy" or anything, it just stops you from having to compile before you see your errors which can save a lot of time. Also used IntelliJ for about 5 years. I still haven't decided if it's better than the others, maybe a little but no where near to compensate for it's lack of FOSS.
Bill K
A: 

I've had a quick look through points 2) and 3):

2) I presume the aim here is to determine the number of correct answers by checking which elements in the studentAnswers array equal the elements in answerKey. Assuming this is the goal then my tips would be:

  • Why are you returning an array? Surely it would make more sense to return a single integer equal to the total number of matches?
  • You should be able to structure the code as a single loop, whereby you iterate using an index (e.g. i), comparing the elements of the two arrays.
  • The reference to charAt is wrong; this is a method on the java.lang.String class, but you aren't using Strings at all.

3) You should consider returning a different object capable of storing the grade tally. For example, you could consider a Map<Character, Integer> where the map's keys are the grades and the values are the grade frequencies.

Adamski
A: 

Java's an object-oriented language. Think in terms of objects. This is little more than C or Fortran written in Java. There's no encapsulation or information hiding that I can see.

It's probably due to the fact that it's a first programming class, and your professor might not understand objects. But that's where you ought to be headed with Java.

I'd expect to see classes like Student, Class, Grade (maybe as an enumeration), ReportCard. Instead, all I see are primitives. Someday you'll think of this as an example of how to write Java poorly.

duffymo
+2  A: 

Since you are still stuck on compiling, I will try to help you get over that stumbling block before addressing the logic in the code.

There are rules which will cause the code not to compile, including syntactic rules, but these are not generally referred to as "logic". I would describe logic errors as the program running but not doing what you want it to. Anyhoo...

Many of the compiler errors are of the form:

someField cannot be resolved

This happens when you are trying to reference a variable that can't be "seen" at that point by the compiler. In your case this is because you have declared the variables in places where they can't be seen, when you want to reference them.

This is the case with several of the fields in your main() method. This is down to an issue of scope. To be able to refer to variables, such as answerKey or studentAnswers, they must be in scope. Global scope is when you can reference a variable from anywhere, this is what you're trying to avoid. You have declared the variables answerKey, studentAnswers within a method, like so:

public static String[] getData() throws IOException {
  // other code

  String[] studentAnswers = new String[50];

  // other code 

  String answerKey = strTkn.nextToken();

  // other code
}

What you have done with these declarations, is say that studentAnswers and answerKey are "within the scope of the getData() method". This means that they cannot be referenced elsewhere, and is the cause of the compiler error within main().

One way to do this is to declare the variables globally - such as public static String answerKey; just under public class GradeResults {, but you have been asked specifically not to do this (and for good reason, which I won't get into).

A different way I would recommend is to "encapsulate" the variables. This is a fancy programming word which roughly means wrap up the data and behaviour into an object, and let the object decide how to behave, and change itself. I'll give you one way you could get started with this (there are many, many ways you could do it). That is to encapsulate all the information about a student within an object, which we can create, using a new class, called Student.

 // this is a new class, and will have to be saved in a file called Student.java
public class Student {

    // these are field declarations
    private int id;
    private String answers;

    // this is the constructor, it creates a new instance of Student
    public Student(int newStudentsId, String newStudentsAnswers) {
        // these lines take the parameters (in brackets on the line above)
        // and assign them to the fields of this instance
        this.id = newStudentsId;
        this.answers = newStudentsAnswers;
    }

    // after this you could have getters for the fields,
    // these are often referred to as "accessors" in introductory texts
    // this is all I'll give you of this example, to get you started

} // End of class Student.java

The remaining compiler errors you see are slightly easier:

Incompatible operand types String and char

In the code:

public static int gradeTally(String[] letterGrade) {
  // other code
    if(letterGrade[i] == 'A') a++;  // error on this line

The type of the variable referenced by letterGrade[i] is a String, and the constant 'A' is a char. There are two choices for fixing this

  • change the 'A' to "A", notice double quotations instead of single, single is for char types, double is for String types. Other choice is:
  • change the type of the letterGrade array to char[] letterGrade where it's declared (in the parameter list of the method signature).

This is roughly the same problem which is causing the compiler error:

Cannot invoke charAt(int) on the primitive type int

With the code:

total = studentAnswers[i].charAt(a);

charAt is a method of the String class, therefore studentAnswers[i] must refer to a variable of type String. But it is declared as int[] studentAnswers, so there's a "type mismatch" there.

There's a lot to think about here, and I've left plenty of gaps which you'll have to fill in yourself. A good introductory text on object oriented programming with Java (for example Objects First With Java) should cover everything you need.

Grundlefleck