CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 1 of 2 12 LastLast
Results 1 to 15 of 30
  1. #1
    Join Date
    Mar 2008
    Posts
    55

    Student Quiz Scores

    I am being asked to code a program that is described as follows:

    Code:
    Write a program to keep records and perform statistical analysis for a class of students. The class may have up to 40 students. There are five quizzes during the term. Each student is identified by a four-digit student ID number.
    The program is to print the student scores and calculate and print the statistics for each quiz. The output is in the same order as the input; no sorting is needed. The input is to be read from a text file. The output from the program should be similar to the following -
    
    Stud Q1 Q2 Q3 Q4 Q5
    1234 78 83 87 91 86
    2134 67 77 84 82 79
    1852 77 89 93 87 71
    High Score 78 89 93 91 86
    Low Score 67 77 84 82 71
    Average 73.4 83.0 88.2 86.6 78.6
    
    Try and implement ideas learned in class.
    Use one and two-dimensional arrays only. Test your program with the following data -
    
    Stud Qu1 Qu2 Qu3 Qu4 Qu5
    1234 052 007 100 078 034
    2134 090 036 090 077 030
    3124 100 045 020 090 070
    4532 011 017 081 032 077
    5678 020 012 045 078 034
    6134 034 080 055 078 045
    7874 060 100 056 078 078
    8026 070 010 066 078 056
    9893 034 009 077 078 020
    1947 045 040 088 078 055
    2877 055 050 099 078 080
    3189 022 070 100 078 077
    4602 089 050 091 078 060
    5405 011 011 000 078 010
    6999 000 098 089 078 020
    
    Some help with Lab 6
    ---------------------
    You must apply the following concepts in Lab 6.
    1. Object Theory
    2. File IO
    3. Wrapper Classes.
    
    To read data from a text file you may want to read a line and then tokenize the line (breaking it into smaller strings) using StringTokenizer and storing the results in an array of Objects.
    Main should not be more than 20-30 lines of code.
    My instructor has not taught us the StringTokenizer method and I've had problems using it, so I have been using the .split method instead. What I have done so far is put all of the data into a text file (Data.txt) and I've created a class IO with a method read() to read the data from the text file. I have printed the results of the read in my main as well as a test of the .split method.

    Code:
    import corejava.*;
    import java.io.*;
    
    public class IO {
    	void read() {
    		try {
    			FileReader file = new FileReader("Data.txt");
    			BufferedReader buff = new BufferedReader(file);
    			boolean eof = false;
    			while (!eof) {
    				String line = buff.readLine();
    				if(line == null) {
    					eof = true;
    				}
    				else {
    					System.out.println(line);
    				}
    			}
    		buff.close();
    		} catch (IOException e) {
    			System.out.println("Error --" + e.toString());
    		}
    	}
    	public static void main (String [] args) {
    		IO a = new IO();
    		a.read();
    		String[] result = "this is a test".split("\\s");
    		for (int x = 0; x < result.length; x++) {
    			System.out.println(result[x]);
    		}
    	}
    }
    Can anyone help me brainstorm on what to do from here? I'm confused as to how I'll be able to utilize the .split method to read and split the lines from Data.txt. I figure if I am able to do this, I will then be able to convert the quiz scores into an int and create methods for calculating high, low, and average.

  2. #2
    Join Date
    Jun 1999
    Location
    Eastern Florida
    Posts
    3,877

    Re: Student Quiz Scores

    Start with a Search for .split() and get some coding examples.
    Then write a small, simple program that takes a short string and uses the split method to break the string up into parts and use a loop and println to show what the parts look like. Play around with it until you see how to use it then move it into your program.

    Also you look at the Scanner class in the same way.
    Norm

  3. #3
    Join Date
    Mar 2008
    Posts
    55

    Re: Student Quiz Scores

    Thanks Norm. I have coded this into the else statement:

    So now my data read from Data.txt prints out one word per line. I am now trying to brainstorm as to how to take that data and sort it into arrays. What I have done next is created a Student class to be able to initiate a new array of Students that will hold student numbers and quiz scores data.

    Since the data is being outputted one word per line, I have initiated a Student array in else and have also set variables equal to results.

    This now has all of the results filled into my Student arrays and variables num, quiz1, quiz 2, etc. filled in as well. I have set these variables as a String datatype because the first line (Stud, Qu1, Qu2, etc.) would result in an error if I set it to int and tried to cast s[i].num = (result[0]).

    Now I'm trying to figure out how I would be able to print my results...

    Here is my entire program thus far:

    Code:
    import corejava.*;
    import java.io.*;
    
    class Student {
    	String num, quiz1, quiz2, quiz3, quiz4, quiz5;
    	void print() {
    		System.out.print("Student Number: " + num);
    	}
    }
    
    public class IO extends Student {
    	void read() {
    		try {
    			FileReader file = new FileReader("Data.txt");
    			BufferedReader buff = new BufferedReader(file);
    			boolean eof = false;
    			while (!eof) {
    				String line = buff.readLine();
    				if(line == null) {
    					eof = true;
    				}
    				else {
    					String[] result = line.split("\\s");
    					Student[] s = new Student[40];
    					for(int i = 0; i < s.length; i++) {
    						for(int x = 0; x < 6; x++) {
    							s[i].num = (result[0]);
    							s[i].quiz1 = (result[1]);
    							s[i].quiz2 = (result[2]);
    							s[i].quiz3 = (result[3]);
    							s[i].quiz4 = (result[4]);
    							s[i].quiz5 = (result[5]);
    							s[i].print();
    						}
    					}
    				}
    			}
    		buff.close();
    		} catch (IOException e) {
    			System.out.println("Error --" + e.toString());
    		} //end of try
    	} //end of read()
    	public static void main (String [] args) {
    		IO a = new IO();
    		a.read();
    	}
    }
    And the error I receive when I try to run this is:

    Code:
    Exception in thread "main" java.lang.NullPointerException
            at IO.read(IO.java:27)
            at IO.main(IO.java:45)
    I initiated the Student objects there because that was the only way I could think of to read the results. I'd just like to get my Student objects to print something properly so that I'll know I'm headed in the right direction.

  4. #4
    Join Date
    Jun 1999
    Location
    Eastern Florida
    Posts
    3,877

    Re: Student Quiz Scores

    Student[] s = new Student[40];
    This is a big problem for new java programmers. The above statement creates an array to hold 40 Student objects. It does NOT create any Student objects. What you have to do is create a new Student object at each index before you try to put data into it. You'd do that after the for(int i= statement.
    Instead of the bunch of assignment statements in the for(int x loop, use the constructor for Student to assign the values.
    The for(int x ... statement doesn't appear to be needed. Where do you use x in the loop?

    Your program assumes that there are exactly 6 scores in the data. That is a poor technique. Your code should handle the case where there are any number of scores. Put an array in Student to hold all the scores. split creates an array with all the tokens from the line, so you can use the size of that array to know how many scores there are.
    Norm

  5. #5
    Join Date
    Apr 2007
    Posts
    442

    Re: Student Quiz Scores

    Think small, before thinking big. One of commonest things people do when starting up coding is jump right on to coding. Consider what it is you must accomplish, break that into smaller bits, methods. Be very mindfull of the method signatures and return values. Having designed those sensibly really is half your code and nearly whole of your API.

    If you do that well, you would avoid something as insensicle as an IO read method, which returns nothing and handles only local variables.

    Code:
    					String[] result = line.split("\\s");
    					Student[] s = new Student[40];
    					for(int i = 0; i < s.length; i++) {
    						for(int x = 0; x < 6; x++) {
    							s[i].num = (result[0]);
    							s[i].quiz1 = (result[1]);
    							s[i].quiz2 = (result[2]);
    							s[i].quiz3 = (result[3]);
    							s[i].quiz4 = (result[4]);
    							s[i].quiz5 = (result[5]);
    							s[i].print();
    						}
    Each line has six values, fine. But each line produces a 40 count Student array? Probably not. And if you are sure that you have six values in each result, and you use them literally as you do, is there really reason for the inner loop?

    My humble advice would be smaller steps. Make a method that returns you the files content in a two dimensional String array. You pass that to another method, which provides you the Students out of that data. Compartmentalized issues are easier to manage.

  6. #6
    Join Date
    Mar 2008
    Posts
    55

    Re: Student Quiz Scores

    Student[] s = new Student[40];
    This is a big problem for new java programmers. The above statement creates an array to hold 40 Student objects. It does NOT create any Student objects.
    This is a very helpful tip. I have restructured my code a little bit. I have included a method to build Student objects:

    Code:
    static void buildStudent(Student s[][]) {
    	for(int i = 0; i < s.length; i++) {
    		s[i][i] = new Student();
    	}
    }
    not sure if this is the proper way to build a two-dimensional array of objects as I've only done one-dimensional. Then I have created an array of students and built them in main:

    Code:
    Student[][] s = new Student[40][5];
    Student.buildStudent(s);
    I understand what both of you are saying about the for int x loop. The statement I had originally included in that loop was

    Code:
    System.out.println(result[x]);
    but I now see that if I am sure that there are 6 scores, this is not needed.

    split creates an array with all the tokens from the line, so you can use the size of that array to know how many scores there are.
    From the size of the array, how will I determine this? The first line that split creates is the student number followed by the score of quiz 1, quiz 2, etc. When I outputted my results earlier using println, it would look like this for the first and second students:

    Code:
    1234 //first student number
    052
    007
    100
    078
    034
    2134 //second student number
    090
    036
    090
    077
    030
    There are actually only 5 scores, with the first value set to student number. I assume for the purpose of this assignment, I should code it to only handle the case of 5 scores, but I am still curious as to how this is done for any number of scores.

    Also, though I have created an array for 40 students, in actuality there is only 15 so I would have to take that into account as well.

    Think small, before thinking big.
    Great advice as well! I am trying to get this all figured out, so please continue to leave helpful bits of information until I can fully grasp what I need to do. Thanks!

  7. #7
    Join Date
    Apr 2007
    Posts
    442

    Re: Student Quiz Scores

    The thing with arrays is that they are fixed size. So working with something that you cannot tell "how many there is" poses a problem. Making your array larger than you expect to need, is one way... but what would you really base this expectation on? What if there were 41 lines in the text file? What you should grasp, is the fact that you cannot know the size of the array in beforehand. There is in fact a lot of this stuff when it comes to coding.

    No doubt for the purposes of what you are doing, "40 index array" -approach is sufficient. If you want to tackle the issue more, what you would need to do, is keep on copying values to a larger array as long as you have new stuff to put in. That way you get exactly what really is there, no clutter and no being worried with your expected array size. Try coding one, if you get mixed up, heres an aged example.

    Code:
    public static String[][] readFile(File file, String delimiter){
    	try {
    		BufferedReader r=new BufferedReader(new FileReader(file));
    		String line=null;
    		String[][] data=null;
    		while((line=r.readLine())!=null){
    			String[] values=line.split(delimiter);
    			if(data==null){
    				data=new String[1][values.length];
    				data[0]=values;
    			}else{
    				String[][] temp=new String[data.length+1][];
    				for(int i=0;i<data.length;i++){
    					temp[i]=data[i];
    				}
    				temp[temp.length-1]=values;
    				data=temp;
    			}
    		}
    		return data;
    	} catch (Exception e) {
    		e.printStackTrace();
    	}
    	return null;
    }
    From the size of the array, how will I determine this?
    As mentioned, any array is always of fixed size. Thus the String array produced by split(..) method, has its length of Strings. Now you know, that the first value is always student id, then the first quiz result, second.... Through sensible reading of the data, making the Students becomes less of a pain.

  8. #8
    Join Date
    Jun 1999
    Location
    Eastern Florida
    Posts
    3,877

    Re: Student Quiz Scores

    Several questions/comments:
    Why a 2 dim array for Students?

    When you read in a record the first value is the student number and the rest are the scores.
    So the number of scores = the number of elements - 1. Don't assume you know the number of scores.

    When you create the new Student object do it when you have all the data for that object available. Use the Student class constructor to put the data into the object. Pass the scores in as an array. You'll have to create a new array and copy elements starting at index 1 (o was the student number).
    Norm

  9. #9
    Join Date
    Mar 2008
    Posts
    55

    Re: Student Quiz Scores

    Londbrok, thanks for the explanation and the example. I can see from the example how I would code it if I didn't have a set number of arrays, but for the purpose of the assignment I will stick to a 40 index array.

    Why a 2 dim array for Students?
    Norm, from a brief mention of 2-dimensional arrays my instructor said that the first dimension would correspond to the student and the second dimension would correspond to the quizzes:

    Code:
    int Student[][] = new int[4][2];
    Total number of cells = 4 * 2 = 8 cells
    Dimension 1 = Student
    Dimension 2 = Quiz
    This is all I have from my notes on multi-dimensional arrays, so he hasn't given an example of how this would work. Should I change my previous code to:

    Code:
    Student[][] s = new Student[40][6];
    since I want the first index of the second dimension to house the student number, the second index quiz 1, etc.

    When you create the new Student object do it when you have all the data for that object available. Use the Student class constructor to put the data into the object. Pass the scores in as an array. You'll have to create a new array and copy elements starting at index 1 (o was the student number).
    This is the part that I'm having the most trouble understanding. I think I have properly built the Student objects as coded in my last post, but I'm confused as to how or where to pass the scores. Reading your statement, the scores should be passed in the Student class constructor?

    I understand that

    [code]String[] result = line.split("\\s");
    for(int x = 0; x < result.length; x++) {
    System.out.println(result[x]);}

    creates an array for result and splits the line up, but I don't understand what this array looks like or how to pass these values onto my Student arrays.

    For example result[0] would return student number 1234, but how can I pass this value onto my Student[0][0] index when at the next line result[0] would return the next student number?

    Sorry for all of the questions, but it was a really poor choice on my part to take this course online. My instructor isn't the most responsive, so in a way you're all my instructors!

  10. #10
    Join Date
    Apr 2007
    Posts
    442

    Re: Student Quiz Scores

    Should I change my previous code to:
    Student[][] s = new Student[40][6];
    Absolutely not. You are clearly making a bigger monster out of two dimensional arrays than you should. Think of it as a "box of data", whereas a one dimensional array is a "line of data". Two dimensional array, simply holds an amouth of other arrays. This is your initial data:

    Stud Qu1 Qu2 Qu3 Qu4 Qu5
    1234 052 007 100 078 034
    2134 090 036 090 077 030
    3124 100 045 020 090 070
    4532 011 017 081 032 077
    5678 020 012 045 078 034
    6134 034 080 055 078 045
    7874 060 100 056 078 078
    8026 070 010 066 078 056
    9893 034 009 077 078 020
    1947 045 040 088 078 055
    2877 055 050 099 078 080
    3189 022 070 100 078 077
    4602 089 050 091 078 060
    5405 011 011 000 078 010
    6999 000 098 089 078 020
    It is as a "box of data" -sense 6 items wide, and 15 items tall. So it resolves to an array holding 15 arrays. Could be declared as follows:

    Code:
    15 rows, 6 columns...
    String[][] data=new String[15][6];
    Now, each row (one of the 6 lenght array) contains what you need to construct a Student instance. You can do it by looping through each of the "rows" and calling the constructor with the values of each array found at that index. Of course, you need to code the constructor first.

    for example:

    Code:
    public Student(String id, String quiz1, String quiz2, Syring quiz3, String quiz4, String quiz5){
    //asssign variables.
    }
    the values that fill the constructor upon call, are naturally values found in the indexes of each 6 lenght array.
    hope this made any sense

  11. #11
    Join Date
    Mar 2008
    Posts
    55

    Re: Student Quiz Scores

    You can do it by looping through each of the "rows" and calling the constructor with the values of each array found at that index.
    Every time I think I understand, I wind up getting more confused. Am I supposed to set s[0][0] = id, s[1][0] = id, etc.?

    Code:
    public Student(String id, String quiz1, String quiz2, String quiz3, String quiz4, String quiz5){
    for(int i = 0; i < s.length; i++) {
    s[i][0] = id;}
    }
    So confoozled...

  12. #12
    Join Date
    Apr 2007
    Posts
    442

    Re: Student Quiz Scores

    Heres an example.

    Code:
    String[][] data=(the arrays you red from the file);
    Student[] students=new Student[data.length];
    
    //loop the "rows"
    for(int i=0;i<data.length;i++){
    //get the "columns" for that row. It is a six index array.
    
    String[] st=data[i];
    
    //you know what values at each indes mean, first is id etc.
    //check that all data is there, not a tinhat check, but better than nothing.
    
    if(st!=null && st.lenght==6){
    //create a new Student at a student arrays index.
    student[i]=new Student(st[0], st[1], st[2], st[3],st[4], st[5]);
    
    }
    
    }
    Loop the Strings out of the arrays, pass them to a Student instance through a constructor, make sure you store the Students somewhere non-local variable.... and thats that.

  13. #13
    Join Date
    Mar 2008
    Posts
    55

    Re: Student Quiz Scores

    So in your example, you have the Students as a one-dimensional array?

    //loop the "rows"
    does this mean the rows from

    Code:
    String[][] data=(the arrays you red from the file);
    You have a two-dimensional array for data, but in this step

    Code:
    String[] st=data[i];
    you only have one array dimension specified for data. Is this how you

    //get the "columns" for that row. It is a six index array.
    If I am understanding correctly, putting this

    Code:
    if(st!=null && st.lenght==6){
    //create a new Student at a student arrays index.
    student[i]=new Student(st[0], st[1], st[2], st[3],st[4], st[5]);
    in the constructor will create a new Student with values for id, quiz1, quiz2, etc. so long as there are values stored in st[0], st[1], st[2], etc.?

    student[0].id = st[0]
    student[1].quiz1 = st[1]

    Is this basically what is happening here?

    Really not sure where

    Code:
    String[][] data=(the arrays you red from the file);
    this goes, but since you stated that these are the arrays being read from the file, would it be somewhere in here?

    Code:
    String[] result = line.split("\\s"); //should this be changed?
    	for(int i = 0; i < data.length; i++) {
    ??? how should i pass the result values into arrays in this for loop?
    } //end of for result[x]

  14. #14
    Join Date
    Apr 2007
    Posts
    442

    Re: Student Quiz Scores

    in the constructor will create a new Student with values for id, quiz1, quiz2, etc. so long as there are values stored in st[0], st[1], st[2], etc.?

    student[0].id = st[0]
    student[1].quiz1 = st[1]

    Is this basically what is happening here?

    Really not sure where
    Yes basically, yet direct dot notation accessing that you are doing has nothing at all to do with a contsructor. And you are accessing them all bogus anyway. st was a one dimensional array, that would hold data for a single student. Ask yourself what you are actually doing there?

    Firstly.. as Norm noted... arrays of Objects (such as Student) DO NOT get instatiated when the array is created. So calling student[0].id would cause a
    nullpointer.

    Also... Suppose st[] depicts student "Harry", at the students array he would be at index 0. "John the Baptist" is at index 1. Now you are setting Harry with the correct id, but then populating John with Harrys first quiz result.

    It is highly recommended that you use a constructor, and hide instance variables by declaring them private.

    But if you have no idea what any of that means, for the time being, use direct acessing. Just understand, that you need to instatiate the Students first, and know to which student you assign which values.

    String[] st=data[i];
    that is asking for the one dimensional array st from two dimensional array's (data) index i.


    this goes, but since you stated that these are the arrays being read from the file, would it be somewhere in here?
    It would be a call to a method that returns a two dimensional String array. Presumably in this case it would read the student data from the file and return the array.

    The advise, the coding snipplets and such tat you have been provided here do not need to be taken literally. Inpect them, get the idea of "why would I use constuctors", "why would I read the two dimensional array first", or as Norm noted "why would you read any array at all". Put them into context of what your approach was, how you were aiming to tackle the issue. If you dont have any approach, stop coding, start researching untill you do.

  15. #15
    Join Date
    Mar 2008
    Posts
    55

    Re: Student Quiz Scores

    Hi thought I'd take a break from this project before returning to it and see if I could tackle it again. I've revised my code to the following:

    Code:
    import corejava.*;
    import java.io.*;
    
    class Student {
    	String id, quiz1, quiz2, quiz3, quiz4, quiz5;
    	void print() {
    	}
    	static void buildStudent(Student s[][]) {
    		for(int i = 0; i < 40; i++) {
    			for(int j = 0; j < 6; j++) {
    				s[i][j] = new Student();
    			}
    		}
    	}
    	static void read(Student s[][]) {
    		try {
    					FileReader file = new FileReader("Data.txt");
    					BufferedReader buff = new BufferedReader(file);
    					boolean eof = false;
    					while (!eof) {
    						String line = buff.readLine();
    						if(line == null) {
    							eof = true;
    						}
    						else {
    							String[] result = line.split("\\s");
    							for(int i = 0; i < 25; i++) {
    								for(int j = 0; j < 6; j++) {
    									s[i][j] = new Student(result[0], result[1], result[2], result[3], result[4], result[5]);
    								}
    							}
    						}
    					}
    					buff.close();
    				} catch(IOException e) {
    					System.out.println("Error --" + e.toString());
    		}
    	}
    	Student() { }
    	Student(String id, String quiz1, String quiz2, String quiz3, String quiz4, String quiz5) {
    		this.id = id; this.quiz1 = quiz1; this.quiz2 = quiz2; this.quiz4 = quiz4; this.quiz5 = quiz5;
    	}
    
    	public static void main (String [] args) {
    		Student[][] s = new Student[40][6];
    		Student.buildStudent(s);
    		Student.read(s);
    		System.out.println(s[0][0].id);
    	}
    }
    This is working out relatively well as Student objects are initiated and their variables are being defined. The only problem now is that since the results are split like so:

    Code:
    Data from Data.txt
    5405 011 011 000 078 010
    6999 000 098 089 078 020
    
    line split from result
    5405 (result[0])
    011 (result[1])
    011 (result[2])
    000 (result[3])
    078 (result[4])
    010 (result[5])
    6999 (result[0])
    000 (result[1])
    098 (result[2])
    089 (result[3])
    078 (result[4])
    020 (result[5])
    the corresponding result[x] cycles from 0-5, and when I assign it using:

    Code:
    String[] result = line.split("\\s");
    for(int i = 0; i < 25; i++) {
    	for(int j = 0; j < 6; j++) {
    		s[i][j] = new Student(result[0], result[1], result[2], result[3], result[4], result[5]);
    	}
    }
    this makes every Student id = 6999, quiz 1 = 000, quiz 2 = 098, etc. It basically only assigns the very last line read from the file splitter. Not sure how to go about fixing this.

Page 1 of 2 12 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured