Avatar billede mjense173 Nybegynder
28. september 2004 - 15:50 Der er 23 kommentarer og
1 løsning

Opdel konsol input i array

Jeg har en BufferedReader, som tager input fra brugeren i en konsol, eks:

> kommando parm1 "parm2" parm3 "parm4" "parm5"

Der kan altsaa baade komme parametre med og uden anfoerselstegn.
Antallet af parametre er ikke fast.

Jeg skal bruge en funktion der kan kalde en anden funktion ved det navn der straar forst i linjen, og med de parametre der staar efter.
Avatar billede arne_v Ekspert
28. september 2004 - 15:59 #1
String[] parts = line.Split(" ");

opdeler ved mellemrum (kræver dog Java 1.4 eller nyere).

Hvus du skal kunne håndtere mellemrunde inde i de double quotede strenge, så
skal du nok have skrevet en lille parser.
Avatar billede mjense173 Nybegynder
28. september 2004 - 16:02 #2
Ja, det er jo der skoen klemmer..
ved de double quotede strenge med mellemrum i.

Hvordan laver man saadan en parser?
Avatar billede arne_v Ekspert
28. september 2004 - 16:04 #3
Jeg laver lige et eksempel
Avatar billede mjense173 Nybegynder
28. september 2004 - 16:10 #4
Kanon!
Avatar billede arne_v Ekspert
28. september 2004 - 16:11 #5
import java.util.*;

public class CmdParse {
    public static void foo(int a, int b) {
        System.out.println("foo " + a + " " + b);
    }
    public static void bar(String c) {
        System.out.println("bar " + c);
    }
   
    public static void process(String cmdlin) {
        StringBuffer sb = new StringBuffer("");
        List parts = new ArrayList();
        boolean inquote = false;
        for(int i = 0; i < cmdlin.length(); i++) {
            char c = cmdlin.charAt(i);
            switch(c) {
                case ' ':
                    if(!inquote) {
                        parts.add(sb.toString());
                        sb = new StringBuffer("");
                    } else {
                        sb.append(c);
                    }
                    break;
                case '"':
                    inquote = !inquote;
                    break;
                default:
                    sb.append(c);
                    break;
            }
        }
        parts.add(sb.toString());
        String cmd = (String)parts.get(0);
        if(cmd.equals("foo")) {
            foo(Integer.parseInt((String)parts.get(1)), Integer.parseInt((String)parts.get(1)));
        } else if(cmd.equals("bar")) {
            bar((String)parts.get(1));
        } else {
            System.out.println("unknown command");
        }
    }
    public static void main(String[] args) {
        process("foo 123 456");
        process("bar \"Dette er en test\"");
        process("xxxx");
    }
}
Avatar billede arne_v Ekspert
28. september 2004 - 16:11 #6
Det er meget muligt at din kode skal se noget anderledes ud,  men det viser ihvertfald teknikken.
Avatar billede mjense173 Nybegynder
28. september 2004 - 16:14 #7
Kigger lige paa det..
Avatar billede arne_v Ekspert
28. september 2004 - 16:20 #8
En forbedret version (flere mellemrum og mulighed for "" som " inden i "..."):

import java.util.*;

public class CmdParse {
    public static void foo(int a, int b) {
        System.out.println("foo " + a + " " + b);
    }
    public static void bar(String c) {
        System.out.println("bar " + c);
    }
   
    public static void process(String cmdlin) {
        StringBuffer sb = new StringBuffer("");
        List parts = new ArrayList();
        boolean inquote = false;
        boolean dquote = false;
        for(int i = 0; i < cmdlin.length(); i++) {
            char c = cmdlin.charAt(i);
            switch(c) {
                case ' ':
                    if(!inquote) {
                        if(sb.length() > 0) {
                            parts.add(sb.toString());
                            sb = new StringBuffer("");
                        }
                    } else {
                        sb.append(c);
                    }
                    break;
                case '"':
                    if(dquote && (i > 0) && cmdlin.charAt(i-1)=='"') {
                        sb.append(c);
                        dquote = false;
                    } else if(inquote && (i < cmdlin.length() - 1) && cmdlin.charAt(i+1)=='"') {
                        dquote = true;
                    } else {
                        inquote = !inquote;
                    }
                    break;
                default:
                    sb.append(c);
                    break;
            }
        }
        if(sb.length() > 0) {
            parts.add(sb.toString());
        }
        String cmd = (String)parts.get(0);
        if(cmd.equals("foo")) {
            foo(Integer.parseInt((String)parts.get(1)), Integer.parseInt((String)parts.get(1)));
        } else if(cmd.equals("bar")) {
            bar((String)parts.get(1));
        } else {
            System.out.println("unknown command");
        }
    }
    public static void main(String[] args) {
        process("foo 123 456");
        process("bar \"Dette er en test\"");
        process("xxxx");
        process("foo    123    456  ");
        process("bar    \"Dette er en test\"");
        process("bar \"\"\"\"");
    }
}
Avatar billede mjense173 Nybegynder
28. september 2004 - 16:30 #9
Genialt!!
Avatar billede mjense173 Nybegynder
28. september 2004 - 17:24 #10
Ved du om det evt. er muligt at skrive

Runtime.getRuntime().exec(parts);

i slutningen af din process funktion?

saadan at den returnerer det som funktionen der ligger som element 0 i parts retunerer
Avatar billede arne_v Ekspert
28. september 2004 - 18:36 #11
Ikke lige umiddelbart. Men det kan nemt rettes til så det kan.
Avatar billede arne_v Ekspert
28. september 2004 - 18:37 #12
Prøv:

Runtime.getRuntime().exec(parts.toArray(new String[parts.size()]));
Avatar billede arne_v Ekspert
28. september 2004 - 19:16 #13
Den var lige en tand for smart.

Den duer ikke.

        String[] sa = new String[parts.size()];
        parts.toArray(sa);
        Runtime.getRuntime().exec(sa);

virker !
Avatar billede keet Nybegynder
28. september 2004 - 20:02 #14
Hvordan ser den endelige kode ud. Har indsat "Runtime..." ind i en try, hvorefter jeg får flere fejl der siger:
.
.
java.io.IOException: java.io.IOException: bar: not found
java.io.IOException: java.io.IOException: xxxx: not found
.
Avatar billede arne_v Ekspert
28. september 2004 - 20:36 #15
Ja dit operativ system har vel ikke kommandoer bar og xxxx ....
Avatar billede mjense173 Nybegynder
28. september 2004 - 20:42 #16
Ahh, jeg har hele tiden troet at den kaldte metoder i klassen.. altså at:
Runtime.getRuntime().exec("foo");

ville kalde metoden foo som står øverst i klassen.
Avatar billede keet Nybegynder
28. september 2004 - 20:43 #17
ahh... jeg har ikke lige tænkt mig om :) Hvilken kode kan jeg bruge for at kalde en af de andre java-metoder? Hvis jeg nu har en metode foo med parametrene 1 og "myParm".
Avatar billede arne_v Ekspert
28. september 2004 - 20:44 #18
Jeg tror at du leder efter det som hedder reflection !

Lookup af metoder via navn på runtime.
Avatar billede keet Nybegynder
28. september 2004 - 20:56 #19
Ja det er det jeg skal bruge.
Avatar billede arne_v Ekspert
28. september 2004 - 20:57 #20
Med statiske metoder:

import java.lang.reflect.*;

public class Refl1 {
    public static void m1(String a, String b) {
        System.out.println("m1: " + a + " " + b);
    }
    public static void m2(String a, String b) {
        System.out.println("m2: " + a + " " + b);
    }
    public static void c(String className, String methodName, String a, String b) {
        try {
            Class declarg[] = new Class[2];
            declarg[0] = String.class;
            declarg[1] = String.class;
            Method m = Class.forName(className).getMethod(methodName, declarg);
            Object callarg[] = new Object[2];
            callarg[0] = a;
            callarg[1] = b;
            m.invoke(null, callarg);
        } catch (Exception e) {
        }
    }
    public static void main(String[] args) {
        m1("a", "b");
        m2("a", "b");
        c("Refl1", "m1","a", "b");
        c("Refl1", "m2","a", "b");
    }
}
Avatar billede arne_v Ekspert
28. september 2004 - 20:57 #21
Med ikke statiske metoder:

import java.lang.reflect.*;

public class Refl2 {
    public void m1(String a, String b) {
        System.out.println("m1: " + a + " " + b);
    }
    public void m2(String a, String b) {
        System.out.println("m2: " + a + " " + b);
    }
    public static void c(Object o, String methodName, String a, String b) {
        try {
            Class declarg[] = new Class[2];
            declarg[0] = String.class;
            declarg[1] = String.class;
            Method m = o.getClass().getMethod(methodName, declarg);
            Object callarg[] = new Object[2];
            callarg[0] = a;
            callarg[1] = b;
            m.invoke(o, callarg);
        } catch (Exception e) {
        }
    }
    public static void main(String[] args) {
        Refl2 r = new Refl2();
        r.m1("a", "b");
        r.m2("a", "b");
        c(r, "m1","a", "b");
        c(r, "m2","a", "b");
    }
}
Avatar billede keet Nybegynder
28. september 2004 - 21:00 #22
Er der ikke noget indbygget i java, der kan håndtere det nemmere?
Avatar billede arne_v Ekspert
28. september 2004 - 21:02 #23
Nej - ikke hvis jeg har forstået problemet korrekt.
Avatar billede keet Nybegynder
28. september 2004 - 21:10 #24
okay :) jeg laver det på den måde du foreslog. Mange tak for hjælpen.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester