2
\$\begingroup\$

Is there a better way to implement my code in Java? I used to code this in C++ and pretty much worked right off the bat. But in Java, it is different, as it won't let me input data on the string array name. It seems to skip and move on to ask the user for the age rather than starting on name.

package student;
import java.util.*;

public class Student {


public static void main(String[] args) {
   int i, q, z, c, b;
   int x=0;
   String[] name = new String[30];
   int[] age = new int[30];
   String[] course = new String[30];
   String[] year = new String[30];
   String[] section = new String[30];
   int menuChoice;

   Scanner input = new Scanner (System.in);

   start:
   do{

       System.out.println("\t\t\tStudent Record Menu");
       System.out.println("\t\t1. Add Student\t2. View Students\t3. Search Student\t4. Exit");
       System.out.println("Enter a choice: ");
       menuChoice = input.nextInt();

       if (menuChoice==1)
       {
           for (z=x; z<=29; z++)
           {
               System.out.println("Full name:");
               name [z] = input.nextLine();
               System.out.println("Age:");
               age [z] = input.nextInt();
               System.out.println("Course:");
               course [z] = input.next();
               System.out.println("Year:");
               year [z] = input.next();
               System.out.println("Section:");
               section [z] = input.next();
               x++;
               continue start;
           }
       }
               else if (menuChoice==2)
               {
                   for (i=0; i<x; i++)
                   {
                       System.out.println(name[i] + age [i] + course [i] + year [i] + section [i]);
                   }
               }

   } while (menuChoice<4);

}
}
\$\endgroup\$
2
  • 3
    \$\begingroup\$ You need to forget the main method for a bit and concentrate on creating first your Student class, a class with private instance fields, with at least one maybe two constructors, with getters and setters. Do this first, then create a main method where you create a Student[] array, and try to fill it. \$\endgroup\$ Aug 28 '14 at 3:24
  • \$\begingroup\$ You'd better add what logic you want to do in your questions so that we can pick every up easily. \$\endgroup\$
    – Jaskey
    Aug 28 '14 at 3:51
0
\$\begingroup\$

Here is how I would code this. This was implemented independently from Msnik's answer (which is great by the way).

The interesting part is in main() and the use of Scanner. This solution also uses an ArrayList to store the results, and a for-each loop to iterate through them.

import java.util.*;

public class Student
{
    private String m_name;
    private int m_age;
    private String m_course;
    private String m_year;
    private String m_section;

    public Student( String name, int age, String course, String year, String section )
    {
        m_name = name;
        m_age = age;
        m_course = course;
        m_year = year;
        m_section = section;
    }

    public String getName()
    {
        return m_name;
    }

    public int getAge()
    {
        return m_age;
    }

    public String getCourse()
    {
        return m_course;
    }

    public String getYear()
    {
        return m_year;
    }

    public String getSection()
    {
        return m_section;
    }

    public String toString()
    {
        return "name: " + m_name + ", age: " + m_age + 
               ", course: " + m_course + ", year: " + m_year +
               ", section: " + m_section;
    }

    public static void main(String[] args) 
    {
       ArrayList<Student> students = new ArrayList<Student>();
       Scanner input = new Scanner(System.in);

       int menuChoice = 4;
       do {
           System.out.println("\t\t\tStudent Record Menu");
           System.out.println("\t\t1. Add Student\t2. View Students\t3. Search Student\t4. Exit");
           try {
               System.out.println("Enter a choice: ");
               menuChoice = Integer.parseInt(input.nextLine());
           } catch (NumberFormatException e) {
               continue;
           }

           if (menuChoice==1)
           {
               System.out.println("Full name:");
               String name = input.nextLine();

               int age = -1;
               do {
                   try {
                       System.out.println("Age:");
                       age = Integer.parseInt(input.nextLine());
                   } catch (NumberFormatException e) {
                       System.out.println("Enter a number!");
                       continue;
                   }
               } while (age <= 0);

               System.out.println("Course:");
               String course = input.nextLine();

               System.out.println("Year:");
               String year = input.nextLine();

               System.out.println("Section:");
               String section = input.nextLine();

               Student student = new Student(name, age, course, year, section);
               students.add(student);

           } else if (menuChoice==2) {
               System.out.println("Students:");
               for (Student student : students)
               {
                   System.out.println(student);
               }
           }
       } while (menuChoice<4);
    }
}

We want to call nextLine() to collect an entire line of input at a time. Calling next() will return the next token, and supposing the user enters a series of \$n\$ words (a space delimited list of tokens) it will consume the next \$n\$ calls to next().

You saw it skip over name and go straight to age for a similar reason - the call to nextInt() captured your menu choice after the user hits enter but it did not capture the line return itself - the subsequent call to nextLine() did that (consuming both calls on the menuchoice and denying the user the chance to enter a name).

Instead we'll call nextLine every time. For our string values we can assign this directly. For our ints we'll use parseInt() to convert first. We must catch a NumberFormatException in the event the user fails to enter an int, and in this case we'll just prompt them again.

\$\endgroup\$
1
  • \$\begingroup\$ Thank you! I really apologize you and Mshnik have to do the code. This explains a lot for me. \$\endgroup\$
    – CinnamonRii
    Aug 28 '14 at 8:58
0
\$\begingroup\$

To start with OOP, you should think of the Student class as an Object, a tangible thing like a ball. Say you were given a student. What properties might it have? For example, it may have a name, a gender, a major, a list of courses, etc etc. What could you ask it to do? You could ask it to tell you its name, to tell you whether it is enrolled in a given course or not, whether it shares a course with a given other student or not, etc etc.

In your example, Students appear to have a name, an age, a course, a year, and a section. These are the values that define a student. We can begin a more OOP approach by defining a Student class that adequately stores this information about a student, and allows construction and access to these fields:

public class Student{
    public String name;
    public int age;
    public String course;
    public String year;
    public String section;

    /** Constructs a Student object with the given values */
    public Student(String name, int age, String course, String year, String section){
        this.name = name;
        this.age = age;
        this.course = course;
        this.year = year;
        this.section = section;
    }

}

Now, you may notice that everything in the above example is public. This is (almost certainly) wrong. For example, making the age field public allows anyone to walk up to a student and say "you are now -12 years old". Certainly a bug. Let's revise and only allow get access to be public.

public class Student{
    private String name;
    private int age;
    private String course;
    private String year;
    private String section;

    /** Constructs a Student object with the given values */
    public Student(String name, int age, String course, String year, String section){
        this.name = name;
        this.age = age;
        this.course = course;
        this.year = year;
        this.section = section;
    }

    /** Returns the name of this Student */
    public String getName(){
        return name;
    }

    /** Returns the age of this Student */
    public int getAge(){
        return age;
    }

    /** Returns the course of this Student */
    public String getCourse(){
        return course;
    }

    /** Returns the year of this Student */
    public String getYear(){
        return year;
    }

    /** Returns the section of this Student */
    public String getSection(){
        return section;
    }
}

Now, while a student does have an intrinsic value for their age, you can't access it directly. You can, however, ask the student how old they are with getAge(), which will tell you what you wanted to know.

Finally, let's tackle the main method you were doing in the first place. Now that we have the Student class, we can represent a (name, age, course, year, section) as a single Student object. Instead of having 5 separate arrays, one for each field, we have a single array of Students. Just add this main method to the above Student class:

public static void main(String[] args) {
   int x = 0;
   int menuChoice = -1;
   Student[] students = new Student[30]; //As a note, hard-coding this '30' is a bad idea.
                                         //Probably should be static, final const in class.
   Scanner input = new Scanner (System.in);
   do{
       System.out.println("\t\t\tStudent Record Menu");
       System.out.println("\t\t1. Add Student\t2. View Students\t3. Search Student\t4. Exit");
       System.out.println("Enter a choice: ");
       menuChoice = input.nextInt();

       if (menuChoice==1){
           if(x < 30) { //Able to add new student.
               System.out.println("Full name:");
               String name = input.next();     //This was your error - should be next like the others,
                                               //Not nextLine()
               System.out.println("Age:");
               int age = input.nextInt();
               System.out.println("Course:");
               String course = input.next();
               System.out.println("Year:");
               String year = input.next();
               System.out.println("Section:");
               String section = input.next();

               //Create the new student using the given inputs
               Student s = new Student(name, age, course, year, section);

               //Place in array
               students[x] = s;

               //Increment x for next student placement
               x++;
           } else {  //Not able to add new student
               System.out.println("Can't add new student, students full");
           }
       }
       else if (menuChoice==2) {
           for (int i=0; i<x; i++) {
               Student s = students[i];
               System.out.println(s.getName() + s.getAge() + s.getCourse() 
                                      + s.getYear() + s.getSection());
           }
       }
       else if(menuChoice < 1 || menuChoice > 4){
           System.out.println("Unrecognized menu choice; please re-enter");
       }
   } while (menuChoice != 4);

   //Do close your scanners when you're done with them to avoid a resource leak.
   //This is closing System.in (which is bad), but you're code is terminating anyway
   //so its ok
   input.close();
}

Some places you could go from here are using a List (ArrayList will do) instead of an array for student storage in the main method, because arbitrarily limiting the number of students to 30 seems silly. You could also give students more complex behavior (a list of friends, for example) to do some really cool stuff.

Welcome to Java and OOP! If there's any way I can clarify my answer let me know.

\$\endgroup\$
4
  • \$\begingroup\$ Thank you for the answers and a brief run through of Java and OOP concepts. I have another question, is it possible to put the following codes on seperate class (.java) file, compile and run it? If I'm not mistaken, it's something called a 'package' right? I'm using NetBeans as my IDE. \$\endgroup\$
    – CinnamonRii
    Aug 28 '14 at 4:11
  • \$\begingroup\$ packages are the organization of .java files (and slightly affect who can access what, but that's a different question entirely). The important part is that you can only have one public class per .java file, with the file name the same as the class name. For the moment you can probably stick to the default package - just create your .java files in the src directory. Netbeans should be able to pick up the main method to call when you run the project. \$\endgroup\$
    – Mshnik
    Aug 28 '14 at 4:14
  • \$\begingroup\$ I see. Thank you for the answers so far. Is there a limit to how many values you can put in this particular line: public Student(String name, int age, String course, String year, String section) For example I'm gonna add a double midtermgrade, a double finalgrade, and double gpa and also a student number search system (to search and view the records of a specific student), which I am currently formulating. \$\endgroup\$
    – CinnamonRii
    Aug 28 '14 at 4:28
  • \$\begingroup\$ Shouldn't be, no. We've gone pretty far into the comments though, so if you have further questions you should ask them as full questions. \$\endgroup\$
    – Mshnik
    Aug 28 '14 at 4:31