Hitta minst en brist i koden
Uppgift:
Nedanstående kod har minst en allvarlig brist, vilken? Bortse från utelämnad kod (…).
public static int f(int[] keys,HashMap<Integer,String> table) {
int totalLength = 0;
for ( int k : keys )
totalLength += table.get(k).length();
return totalLength;
}
public static void main(String[] arg) {
HashMap<Integer,String> m = new HashMap<Integer,String>();
...
int[] arr = new int[100];
...
System.out.println(f(arr,m));
}a. kompilatorn rapporterar ett syntaxfel
b. kompilatorn rapporterar ett typfel
c. ett exekveringsfel kan inträffa
d. inget onormalt inträffar, koden är felfri
Fråga:
Problemet är väl att arr aldrig ges några värden så när den skall användas i anropet av metoden f så kommer vi inte kunna använda den i for-each-loopen eftersom att den är tom? Om så är fallet så funderar jag på vilken typ av fel detta räknas som. Påstående c tycker jag låter mest rimlig, men att det står kan inträffa gör mig osäker. Räknas inte ett NullPointerException som ett exekveringsfel?
Antag att den utelämnade koden gör rätt saker. Felet, om det finns ett fel, finns i den skrivna koden. Är nycklarna i HashMap deklarerade som den primitiva typen int? Om inte vad händer då när variabeln arr deklareras som int[]?
Ser en mängd problem eller oväntade resultat som kan inträffa. Om koden testas så tror jag att de blir uppenbara.
- Om arr inte tilldelas några värden, vad händer då vid programkörning?
- Om m inte tilldelas några nycklar eller värden, vad händer då vid programkörning?
- Om arr inte tilldelas några värden och m tilldelas nyckel 0 samt värdet "Hej", vad händer då vid programkörning?
- Om arr inte tilldelas några värden och m tilldelas nyckel 1 och värdet "Hej", vad händer då vid programkörning?
- Om arr[0] tilldelas värdet 1 och m tilldelas nyckel 0 samt värdet "Hej", vad händer då vid programkörning?
- Om arr[0] tilldelas värdet 1 och m tilldelas nyckel 1 samt värdet "Hej", vad händer då vid programkörning?
- ...
Det är korrekt att du får ett NullPointerException i exekveringen av f(...). Att de skriver "kan inträffa" verkar märkligt ...
Ja, och när denna NullPointerException rättats så blir det fler oväntade resultat...
Lindehaven skrev:Ser en mängd problem eller oväntade resultat som kan inträffa. Om koden testas så tror jag att de blir uppenbara.
- Om arr inte tilldelas några värden, vad händer då vid programkörning?
- Om m inte tilldelas några nycklar eller värden, vad händer då vid programkörning?
- Om arr inte tilldelas några värden och m tilldelas nyckel 0 samt värdet "Hej", vad händer då vid programkörning?
- Om arr inte tilldelas några värden och m tilldelas nyckel 1 och värdet "Hej", vad händer då vid programkörning?
- Om arr[0] tilldelas värdet 1 och m tilldelas nyckel 0 samt värdet "Hej", vad händer då vid programkörning?
- Om arr[0] tilldelas värdet 1 och m tilldelas nyckel 1 samt värdet "Hej", vad händer då vid programkörning?
- ...
Räknas en tom array som medför ett NullPointerException vid körning, som ett syntaxfel? När jag tänker på syntaxfel så tänkter jag på exempelvis uteblivna semikolon, tilldelning med '==' istället för '=' etc. Dvs något som är fel. Ett NullPointerException kastas väl när något saknas
Aerius skrev:
Antag att den utelämnade koden gör rätt saker. Felet, om det finns ett fel, finns i den skrivna koden. Är nycklarna i HashMap deklarerade som den primitiva typen int? Om inte vad händer då när variabeln arr deklareras som int[]?
Nej, måste jag inte konvertera till int för att få göra den tilldelningen? Dvs
...
for ( int k : (int) keys )
totalLength += (int) table.get(k).length();
...
En tom array som deklarerats korrekt ger inte syntaxfel. Men beroende på hur den används så kan den ge upphov till fel - t ex NullPointerException - vid exekvering.
Det jag tänkte på var att nycklarna i HashMap är deklarerade som typen Integer medan int är en primitiv typ. Det hade kunnat ge typfel men det gör det inte. Jag skrev ett litet program och testade. Ett tips vid programmeringsuppgifter är att skriva små program och se vad varje del av koden gör.
Det jag tror dom menar är ett allvarligt fel är raden int[] arr = new int[100]; . Att skriva 100 gör att för att funktionen f(arr, m) ska fungera måste det vara 100 nycklar i HashMap m, annars blir det exekeveringsfel. Det skulle vara bättre att skriva koden så man inte behöver ändra raden int[] arr = new int[100]; varje gång en ny nyckel läggs till HashMap m. Annars vet jag inte vad som söks. Hoppas det klarnar. Men fråga läraren som gav ut uppgiften. Om uppgiften kommer från en gammal uppgiftssamling kanske den inte gäller. Det är svårt att göra programmeringsuppgifter för att träna på ett visst problem. Om uppgiften är gammal då kan språket förändrats så pass mycket att problemet försvunnit.
Aerius skrev:Det jag tänkte på var att nycklarna i HashMap är deklarerade som typen Integer medan int är en primitiv typ. Det hade kunnat ge typfel men det gör det inte. Jag skrev ett litet program och testade. Ett tips vid programmeringsuppgifter är att skriva små program och se vad varje del av koden gör.
Det jag tror dom menar är ett allvarligt fel är raden int[] arr = new int[100]; . Att skriva 100 gör att för att funktionen f(arr, m) ska fungera måste det vara 100 nycklar i HashMap m, annars blir det exekeveringsfel. Det skulle vara bättre att skriva koden så man inte behöver ändra raden int[] arr = new int[100]; varje gång en ny nyckel läggs till HashMap m. Annars vet jag inte vad som söks. Hoppas det klarnar. Men fråga läraren som gav ut uppgiften. Om uppgiften kommer från en gammal uppgiftssamling kanske den inte gäller. Det är svårt att göra programmeringsuppgifter för att träna på ett visst problem. Om uppgiften är gammal då kan språket förändrats så pass mycket att problemet försvunnit.
Okej, så en möjlig förbättring skulle kanske kunna vara att byta ut arrayen mot en ArrayList? Den expanderas väl i takt med att fler element läggs till?
Aerius skrev:Det jag tänkte på var att nycklarna i HashMap är deklarerade som typen Integer medan int är en primitiv typ. Det hade kunnat ge typfel men det gör det inte. Jag skrev ett litet program och testade. Ett tips vid programmeringsuppgifter är att skriva små program och se vad varje del av koden gör.
När man använder generisk deklaration (alltså typer med <>-tecken) accepteras inte primitiva typer (int, byte, char, o.s.v.) utan man måste använda sig av wrapper-typerna Integer, Byte, Character, o.s.v. Det är alltså så att man måste skriva Integer istället för int för att det ska fungera. Kompilatorn kan även konvertera mellan Integer och int automatiskt, så det är inget man behöver bry sig om.
Det jag tror dom menar är ett allvarligt fel är raden int[] arr = new int[100]; . Att skriva 100 gör att för att funktionen f(arr, m) ska fungera måste det vara 100 nycklar i HashMap m, annars blir det exekeveringsfel. Det skulle vara bättre att skriva koden så man inte behöver ändra raden int[] arr = new int[100]; varje gång en ny nyckel läggs till HashMap m. Annars vet jag inte vad som söks. Hoppas det klarnar. Men fråga läraren som gav ut uppgiften. Om uppgiften kommer från en gammal uppgiftssamling kanske den inte gäller. Det är svårt att göra programmeringsuppgifter för att träna på ett visst problem. Om uppgiften är gammal då kan språket förändrats så pass mycket att problemet försvunnit.
Det måste inte vara hundra nycklar i m, egentligen behöver man bara sätta in ett värde för nyckeln noll (eftersom alla värden i arr som inte specificerats som något annat kommer att vara lika med noll).
Den utelämnade koden (...) i den här uppgiften gör att allting bara blir flummigt eftersom det inte går att säga vad syftet med koden är. Om det är tänkt att antalet element i arr alltid ska vara 100 är koden fullt rimlig (så länge m fylls med värden på rätt sätt).
Ett annat alternativ är att det är tänkt så att det ska maximalt vara 100 element i arr och att vissa element i arrayen ska vara fyllda. Eftersom elementen i arr som inte fyllts med något kommer att vara noll kan man länka nyckeln noll i m till "" vilket gör så att alla tomma element i arr inte ger något bidrag till den totala längden. Om man fyller ut ... i koden enligt denna tolkning får man koden
public static void main(String[] args) {
HashMap<Integer, String> m = new HashMap<>();
m.put(0, "");
m.put(5, "Lorem");
m.put(55, "Ipsum");
int[] arr = new int[100];
arr[0] = 5;
arr[1] = 55;
System.out.println(f(arr,m));
}public static int f(int[] keys, HashMap<Integer, String> table) {
int totalLength = 0;
for (int k : keys) {
totalLength += table.get(k).length();
}
return totalLength;
}
Denna kod är fullt fungerande och mäter den sammanlagda längden av elementen som specificeras i arr.
Visst, den är både ineffektiv och svår att förstå sig på, men om man tolkar det hela på det här sättet är koden i alla fall fungerande.