J'essaye d'implémenter la recherche linéaire en utilisant des tableaux. Il est censé rechercher le nom d'une personne, renvoyer le numéro respectif si le nom existe et renvoyer -1 si ce n'est pas le cas.
J'ai des tests junit écrits pour 2 cas - où le nom existe (testLinearSearchOK) et où il n'existe pas 't (testLinearSearchFail).
Jusqu'à présent, je n'ai réussi à faire passer testLinearSearchOK qu'en utilisant le code suivant:
java.lang.NullPointerException at ASearch.linearSearch(ASearch.java:29) at ASearchTest.testLinearSearchFail(ASearchTest.java:30) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.junit.runners.ParentRunner.run(ParentRunner.java:363) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:89) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:41) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:541) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:763) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:463) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:209)
Les méthodes getName et getNumber renvoient simplement le nom et le numéro respectivement .
Voici les tests que j'ai écrits:
@Before public void setup(){ as = new ASearch(); as.addEntry(new Entry("Pete",111)); as.addEntry(new Entry("Ken",123)); as.addEntry(new Entry("Tim",222)); } @Test public void testLinearSearchOK() { assertEquals(123, as.linearSearch("Ken")); } @Test public void testLinearSearchFail() { assertEquals(-1, as.linearSearch("Leo")); }
Des conseils sur la façon de faire fonctionner cela pour testLinearSearchFail également?
Stack Trace d'Eclipse (réponse de Nicolas):
public class ASearch { private Entry[] catalogue; private int current; /* * Assume 10 entries */ public ASearch(){ catalogue = new Entry[10]; current = 0; } /* * Ignores adding if full (should really be handled by exception...) */ public void addEntry(Entry e){ if(current < 10){ catalogue[current++] = e; } } public int linearSearch(String name){ int current = 0; while (!catalogue[current].getName().equals(name)) current++; return catalogue[current].getNumber(); } }
3 Réponses :
Gardez une trace du numéro plutôt que de l'index:
int number = -1; for(int i = 0; i < catalogue.length; i++) { if(catalogue[i].getName().equals(name)) { number = catalogue[i].getNumber(); break; } } return number;
Merci d'avoir répondu, mais cela ne fait toujours pas passer testLinearSearchFail. L'erreur est une NullPointerException en ce qui concerne le test
Pouvez-vous ajouter la trace de pile à la question?
Je suis désolé mais je suis relativement nouveau dans ce domaine, puis-je savoir où trouver cela sur Eclipse s'il vous plaît?
La trace de la pile est le message d'erreur qu'Eclipse imprime sur la console, où vous voyez l'exception NullPointerException
J'ai ajouté ce que j'ai obtenu
Évitez les retours multiples, c'est un cauchemar lorsque vous essayez d'analyser ce que fait la méthode.
int linearSearch(String name) { int result = -1; for (CatalogueEntry entry : catalogue) { if (name.equals(catalogue.name()) { result = catalogue.getNumber(); break; } } return result; }
Changez votre code en:
public static int linearSearch(String name) { for (int i = 0; catalogue[i] != null; i++) { if (name.equals(catalogue[i].getName())) { return catalogue[i].getNumber(); // <--- return early if match found } } return -1; // <--- return -1 for no match }
Logique:
La raison pour laquelle votre code a échoué est que même si vous ne trouvez pas de correspondance, vous essayez de renvoyer un numéro du tableau catalogue
.
Je vérifiais la mauvaise trace de la pile, c'était en fait java.lang.NullPointerException, mon mauvais
C'est parce que vous avez créé le tableau de taille 10, mais que vous initialisez simplement les 3 premiers éléments. J'ai modifié ma réponse pour refléter la même chose. Dans l'édition, nous vérifions si chaque élément du tableau est nul ou non avant d'effectuer une opération.
Oh oui, c'est tout à fait logique maintenant, merci beaucoup!
Comment Ken est-il égal à 123?
J'ai ajouté le code pertinent, mon mauvais, j'ai raté ça
Veuillez ajouter la ligne 31 de votre code.
La ligne 31 est le début de la boucle if que vous avez suggérée: if (catalog [i] .getName (). Equals (name)) {