Witam, powoli uczę się javy i napotkałem kilka problemów przy rozwiązywaniu zadania o treści “Napisz program, który policzy średnią z kilku przedmiotów. Możemy założyć, że uczeń w szkole ma 3 przedmioty i z każdego z nich dostał po 4 oceny”. Otóż:
jak policzyć średnią dla każdego przedmiotu osobno?
gdy wpisuję nazwę przedmiotu dłuższą niż 4 znaki pętla kończy wyjątkiem po otrzymaniu 5 oceny (choć po 4 już powinien być kolejny przedmiot).
Błąd: Exception in thread “main” java.lang.ArrayIndexOutOfBoundsException: 4
at Lesson6.Ex1.PobierzPrzedmiotyIocene(Ex1.java:27)
at Lesson6.Ex1.main(Ex1.java:40)
Prośba o wskazówki niż gotowca. Z góry dziękuję za pomoc, kod poniżej
import java.util.Scanner;
class Ex1 {
private String name;
private String[] subjects = new String[3];
private float[][] notes = new float[3][4];
float result;
Scanner sc = new Scanner(System.in);
private void PobierzImieOdUsera() {
System.out.print("Podaj imię ucznia: ");
name = sc.next();
}
private void PobierzPrzedmiotyIocene() {
for (int i = 0; i < subjects.length; i++) {
System.out.print("Podaj nazwy przedmiotów, których uczy się " + name + " ");
subjects[i] = sc.next();
for (int j = 0; j < subjects[i].length(); j++) {
System.out.print("Podaj ocenę dla przedmiotu: " + subjects[i] + " ");
notes[i][j] = sc.nextFloat();
}
}
}
private void SrednieOcen() {
}
public static void main(String[] args) {
Ex1 n = new Ex1();
n.PobierzImieOdUsera();
n.PobierzPrzedmiotyIocene();
n.SrednieOcen();
}
}
Nie mam Javy na kompie ani na żadnej virtualnej maszynie, a nie chce mi się instalować dla jednego przykładu. Pokaż zrzut ekranu przed wystąpieniem błędu.
Exception in thread "main" java.util.NoSuchElementException
at java.util.Scanner.throwFor(Scanner.java:862)
at java.util.Scanner.next(Scanner.java:1371)
at Ex1.PobierzImieOdUsera(Main.java:12)
at Ex1.main(Main.java:33)
Nie jestem pewny bo w Javie pisałem tylko na studiach, ale ja bym zrobił reader.nextLine() zamiast reader.next() być może w metodzie wczytywania jest problem.
Możesz zapisać 3 przedmioty i 4 oceny do każdego przedmiotu. Autor chyba się przejęzyczył w jednym miejscu bo takie wartości są też podane w treści zadania. Też się nad tym chwilę zastanawiałem, ale tak wynika z kodu i treści zadania, więc założyłem, że to literówka.
Tyle, że 4 ocenę przerabia mi na przedmiot np. “2” i się momentalnie program w kompilatorze online przerywa.
Przerobiłem peltę i rozmiar tablicy to nagle źle zaczęło liczyć średnią 4 ocen. Pewnie źle myślę jak to przerobić stąd problem - chyba przeskakuje po 2 ocenie na inną liczbę jak sobie wyświetliłem (pierwsze dwie oceny OK, a kolejne dwie z drugiego przedmiotu).
Teraz dopatrzyłem się błędu który jest w kodzie autora
for (int j = 0; j < subjects[i].length; j++) {
Nie możemy brać długości subjects[i] bo subjects to tablica stringów z nazwami przedmiotów, a to oznacza, że w tym miejscu mamy zwracaną długość danego stringa - czyli 3 bo zawsze podajesz 3 znakową nazwę.
Dlatego musi być
for (int j = 0; j < notes[i].length; j++) {
Rozwiązuje to też drugi problem którego nie mogłem ogarnąć bez kompilacji kodu, ale teraz już to widzę. Wcześniej mieliśmy błąd index out of bounds gdy podawaliśmy dłuższą nazwę przedmiotu niż 3 znaki bo mogliśmy wstawić tylko 4 oceny, a 3 znaki w stringu to tak naprawdę 4 ponieważ jest jeszcze znak końca linii. Ten błąd powodował, że zamiast wczytać 4 oceny wczytywaliśmy do tablicy 4-ro elementowej tyle ocen z ilu znaków składa się nazwa przedmiotu.
Zmiana w tej linijce co napisałem naprawi wszystkie błędy.
Dodatkowo proponuję użyć stałych do określenia liczby przedmiotów i maksymalnej liczby ocen. W tedy można takie stałe również użyć w pętlach zamiast dynamicznie pobierać długości tablic, kod w tedy będzie czytelniejszy no i jeśli będziemy chcieli zmienić liczbę przedmiotów to tylko w jednym miejscu, a nie w całym kodzie. W ten sposób unikniemy wielu błędów w przyszłości.
Faktycznie, już poprawiam. Po prostu w różnych środowiskach różnie jest z length, czasami jest wystawiona jako api, a czasem jako public properties. Zależy od konwencji danej biblioteki.
Panowie, no prawie działa tylko teraz błąd, o którym pisałem przeniósł się w inne miejsce. A kod wygląda tak:
/*
Napisz program, który policzy średnią z kilku przedmiotów.
Możemy założyć, że uczeń w szkole ma 3 przedmioty i z każdego z nich dostał po 4 oceny
*/
package Lesson6;
import java.util.Scanner;
class Ex1 {
private String name;
private String[] subjects = new String[3];
private float[][] notes = new float[3][4];
Scanner sc = new Scanner(System.in);
private void PobierzImieOdUsera() {
System.out.print("Podaj imię ucznia: ");
name = sc.next();
}
private void PobierzPrzedmiotyIocene() {
for (int i = 0; i < subjects.length; i++) {
System.out.print("Podaj nazwy przedmiotów, których uczy się " + name + " ");
subjects[i] = sc.next();
for (int j = 0; j < notes[i].length; j++) {
System.out.print("Podaj ocenę dla przedmiotu: " + subjects[i] + " ");
notes[i][j] = sc.nextFloat();
}
}
}
private void SrednieOcen() {
float subjectAverage[] = new float[4];
for(int i = 0; i < subjectAverage.length; i++)
{
float average = 0;
for(int j = 0; j < notes[i].length; j++)
average += notes[i][j];
subjectAverage[i] = average / notes[i].length;
}
}
public static void main(String[] args) {
Ex1 n = new Ex1();
n.PobierzImieOdUsera();
n.PobierzPrzedmiotyIocene();
n.SrednieOcen();
}
}
przy average 0.0 kompilator krzyczał błąd.
Błąd jest w linii for(int j = 0; j < notes[i].length; j++)
Exception in thread “main” java.lang.ArrayIndexOutOfBoundsException: 3
at Lesson6.Ex1.SrednieOcen(Ex1.java:38)
at Lesson6.Ex1.main(Ex1.java:51)