1
votes

Recherche linéaire de nombre via le nom de la personne à l'aide d'un tableau - la méthode ne fonctionne pas si le nom n'existe pas

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();  
}
} 


4 commentaires

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)) {


3 Réponses :


1
votes

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;


5 commentaires

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



1
votes

É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;
}


0 commentaires

0
votes

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:

  • Si le nom correspond, nous renvoyons ce numéro
  • S'il n'y a pas de correspondance, nous renvoyons un -1

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 .


3 commentaires

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!