1   package fi.jyu.mit.ohj2;
2   
3   import java.text.DecimalFormat;
4   import java.text.DecimalFormatSymbols;
5   
6   /**
7    * Joukko merkkijonoaliohjelmia Ohjelmointi 2-kurssin käyttöön
8    * @author Vesa Lappalainen
9    * @version 1.0, 07.01.2003
10   * @version 1.1, 09.03.2002
11   * @version 1.2, 30.09.2007 / vl, testi
12   * @version 1.3, 12.08.2008 / vl, StringBuilder
13   * @since 1.5
14   */
15  
16  public class Mjonot { // NOPMD
17  
18    //****************************************************************************
19      
20    /**
21     * Palauttaa jonon, jossa on monistettuna jono s n-kertaa
22     * <pre> tayta("kissa",3)  => "kissakissakissa"</pre>
23     * Tuplataan jonon pituus joka kerta => 100 monistusta vaatii 7 kierrosta
24     * @param s monistettava jono
25     * @param n kuinka monta kertaa monistetaan
26     * @return s monistettuna n kertaa
27     * 
28     * @example
29     * <pre name="testTayta">
30     * tayta($jono,$n) === $tulos
31     * 
32     *    $jono   | $n | $tulos
33     *  -------------------------------
34     *    "kissa" |  3 | "kissakissakissa"
35     *    ""      | 10 | ""
36     *    "kissa" |  0 | ""     
37     *    "kissa" |  1 | "kissa"
38     *    "a"     | 10 | "aaaaaaaaaa"     
39     * </pre>
40     */
41    public static String tayta(String s, int n) {
42      int pituus = n*s.length();
43      if ( pituus == 0 ) return "";
44      StringBuilder jono = new StringBuilder(pituus);
45      jono.append(s);
46      while ( 2*jono.length() < pituus  ) jono.append(jono);
47      jono.append(jono.substring(0,pituus-jono.length()));
48      return jono.toString();
49    }
50  
51  
52    /** Palauttaa merkkijonon jossa on n kappaletta välilyöntejä
53     * @param n montako välilyöntiä tarvitaan
54     * @return jono, jossa on n kpl välilyöntejä
55     * 
56     *  @example
57     * <pre name="test">
58     * tyhja(0) === ""
59     * tyhja(1) === " "
60     * tyhja(2) === "  "
61     * tyhja(10) === "          ";
62     * tyhja(1000).length() === 1000; 
63     * </pre>
64     */
65    public static String tyhja(int n) {
66      StringBuilder fill = new StringBuilder(40+n); // NOPMD sopivan kokoinen
67      while ( fill.length() < n ) fill.append("                                ");
68      fill.delete(n,fill.length());
69      return fill.toString();
70    }
71  
72    
73    /**
74     * Palauttaa jonon s muotoiltuna vähintään len-pituiseksi
75     * <pre>
76     * Esim:  fmt("2",3,'0')  => "002"
77     *        fmt("2",-3,' ') => "2  "
78     * </pre>
79     * @param s      muotoiltava jono
80     * @param len    pituus, negatiivisella vasempaan laitaan, pos. oikeaan
81     * @param fillch merkki jolla täytetään
82     * @return       muotoiltu jono
83     * 
84     * @example
85     * <pre name="test">
86     *   fmt("",3,' ')     === "   "  
87     *   fmt("",3,'0')     === "000"  
88     *   fmt("2",3,'0')    === "002"  
89     *   fmt("2",-3,' ')   === "2  "
90     *   fmt("1234",3,'0') === "1234" 
91     * </pre>
92     */
93    public static String fmt(String s,int len,char fillch) {
94      int needs = Math.abs(len) - s.length();
95      if ( needs <= 0 ) return s;
96      String fill = tayta(""+fillch,needs);
97      if ( len < 0 ) return s + fill;
98      return fill + s;
99    }
100 
101   
102   /**
103    * Palauttaa jonon s muotoiltuna vähintään len-pituiseksi
104    * <pre>
105    * Esim:  fmt("2",3)  => "  2"
106    *        fmt("2",-3) => "2  "
107    * </pre>
108    * @param s     muotoiltava jono
109    * @param len   pituus, negatiivisella vasempaan laitaan, pos. oikeaan
110    * @return      muotoiltu jono
111    * 
112    * @example
113    * <pre name="test">
114    *   fmt("2",3)    === "  2"  
115    *   fmt("2",-3)   === "2  "
116    *   fmt("1234",3) === "1234" 
117    * </pre>
118    */
119   public static String fmt(String s,int len) {
120     int needs = Math.abs(len) - s.length();
121     if ( needs <= 0 ) return s;
122     String fill = tyhja(needs);
123     if ( len < 0 ) return s + fill;
124     return fill + s;
125   }
126 
127   
128   /**
129    * Palauttaa jonon s muotoiltuna vähintään len-pituiseksi
130    * @param s     muotoiltava jono
131    * @param len   pituus, negatiivisella vasempaan laitaan, pos. oikeaan
132    * @return      muotoiltu jono
133    * @see #fmt(String s,int len)
134    * @example
135    * <pre name="test">
136    *   fmt(new StringBuffer("12"),3) === " 12"
137    * </pre>
138    */
139   public static String fmt(StringBuffer s,int len) {
140     return fmt(s.toString(),len);
141   }
142 
143   
144   /**
145    * Palauttaa jonon s muotoiltuna vähintään len-pituiseksi
146    * @param s     muotoiltava jono
147    * @param len   pituus, negatiivisella vasempaan laitaan, pos. oikeaan
148    * @return      muotoiltu jono
149    * @see #fmt(String s,int len)
150    * @example
151    * <pre name="test">
152    *   fmt(new StringBuilder("12"),3) === " 12"
153    * </pre>
154    */
155   public static String fmt(StringBuilder s,int len) {
156     return fmt(s.toString(),len);
157   }
158 
159   
160   /**
161    * Muotoilee kokonaisluvun len kokoiseen tilaan.
162    * <pre>fmt(12,4) => "  12";  fmt(12,-4) => "12  "</pre>
163    *
164    * @param n    muotoiltava luku
165    * @param len  tulosjonon vähimmäispituus
166    * @return     merkkijonoksi muotoiltu luku
167    * @see #fmt(String s,int len)
168    * 
169    * @example
170    * <pre name="test">
171    *   fmt(2,3)    === "  2"  
172    *   fmt(2,-3)   === "2  "
173    *   fmt(1234,3) === "1234" 
174    * </pre>
175    */
176   public static String fmt(int n,int len) {
177     return fmt(""+n,len);
178   }
179 
180   
181   /**
182    * Muotoilee kokonaisluvun len kokoiseen tilaan.
183    * <pre>fmt(12,4,'0') => "0012";  fmt(12,-4,' ') => "12  "</pre>
184    *
185    * @param n      muotoiltava luku
186    * @param len    tulosjonon vähimmäispituus
187    * @param fillch merkki jolla täytetään
188    * @return       merkkijonoksi muotoiltu luku
189    * @see #fmt(String s,int len)
190    * 
191    * @example
192    * <pre name="test">
193    *   fmt(2,3,'0')    === "002"  
194    *   fmt(2,-3,'0')   === "200"
195    *   fmt(2,-3,' ')   === "2  "
196    *   fmt(1234,3,'0') === "1234"
197    *   fmt(12,4,'0')   === "0012"  
198    *   fmt(12,-4,' ')  === "12  " 
199    * </pre>
200    */
201   public static String fmt(int n,int len, char fillch) {
202     return fmt(""+n,len,fillch);
203   }
204 
205 
206   /**
207    * Muotoilee reaaliluvun len kokoiseen tilaan.
208    * <pre>fmt(12.3,6,2) => " 12.30";  fmt(12.3,-6,2) => "12.30 "</pre>
209    * @param d     muotoiltava luku
210    * @param len   tulosjonon vähimmäispituus
211    * @param desim desimaalien lukumäärä tulosjonossa
212    * @return      merkkijonoksi muotoiltu luku
213    * @see #fmt(String s,int len)
214    * 
215    * @example
216    * <pre name="test">
217    *   fmt(12.3,6,2)  === " 12.30"  
218    *   fmt(12.3,-6,2) === "12.30 "
219    *   fmt(2.0,-6,2)  === "2.00  "
220    *   fmt(1234,6,0)  === "  1234"
221    *   fmt(12,-4,0)   === "12  " 
222    *   fmt(12.1,-4,0) === "12  " 
223    * </pre>
224    * 
225    */
226   public static String fmt(double d,int len,int desim) {
227     String des = "0";
228     if ( desim > 0 ) des = "0."+tayta("0",desim);
229     DecimalFormat df = new DecimalFormat(des);
230     DecimalFormatSymbols ds = new DecimalFormatSymbols();
231     ds.setDecimalSeparator('.');
232     df.setDecimalFormatSymbols(ds);
233     return fmt(df.format(d),len);
234   }
235 
236 
237   /**
238    * Poistetaan jonosta kaikki kaksin- tai useampikertaiset tyhjät.
239    * <pre>
240    * jono = "   kissa     istuu   "; 
241    * poista_2_tyhjat(jono)  => jono = " kissa istuu ";
242    * </pre>
243    * @param s jono josta tyhjät poistetaan
244    * @return viite jonoon josta poistettu
245    * @example
246    * <pre name="test">
247    *   StringBuffer sb = new StringBuffer("   kissa     istuu   ");
248    *   poista_2_tyhjat(sb).toString() === " kissa istuu ";
249    *   poista_2_tyhjat((StringBuffer)null).toString() === "";
250    * </pre>
251    * 
252    */
253   public static StringBuffer poista_2_tyhjat(StringBuffer s) {  // NOPMD sallitaan alleviiva historian painolastina
254     int tyhjia=0;
255     int l=0,k=0;
256     if ( s == null ) return new StringBuffer("");
257     int pit = s.length();
258 
259     while ( l < pit ) {
260       char c = s.charAt(l);
261       if ( c == ' ') tyhjia++;
262       else tyhjia = 0;
263       if ( tyhjia <= 1 ) s.setCharAt(k++,c);  // Jollei 2-tyhjä, kopioidaan!
264       l++;
265     }
266     s.delete(k,pit);
267     return s;
268   }
269 
270   
271   /**
272    * Poistetaan jonosta kaikki kaksin- tai useampikertaiset tyhjät.
273    * <pre>
274    * jono = "   kissa     istuu   "; 
275    * poista_2_tyhjat(jono)  => jono = " kissa istuu ";
276    * </pre>
277    * @param s jono josta tyhjät poistetaan
278    * @return viite jonoon josta poistettu
279    * @example
280    * <pre name="test">
281    *   StringBuilder sb = new StringBuilder("   kissa     istuu   ");
282    *   poista_2_tyhjat(sb).toString() === " kissa istuu ";
283    *   poista_2_tyhjat((StringBuilder)null).toString() === "";
284    * </pre>
285    * 
286    */
287   public static StringBuilder poista_2_tyhjat(StringBuilder s) {  // NOPMD sallitaan alleviiva historian painolastina
288     int tyhjia=0;
289     int l=0,k=0;
290     if ( s == null ) return new StringBuilder("");
291     int pit = s.length();
292 
293     while ( l < pit ) {
294       char c = s.charAt(l);
295       if ( c == ' ') tyhjia++;
296       else tyhjia = 0;
297       if ( tyhjia <= 1 ) s.setCharAt(k++,c);  // Jollei 2-tyhjä, kopioidaan!
298       l++;
299     }
300     s.delete(k,pit);
301     return s;
302   }
303 
304   
305   /**
306    * Poistetaan jonosta kaikki kaksin- tai useampikertaiset tyhjät.
307    * <pre>
308    * jono = poista_2_tyhjat("   kissa     istuu   ")  => jono = " kissa istuu ";
309    * </pre>
310    * @param s jono josta tyhjät poistetaan
311    * @return viite uusi jono josta tyhjät poistettu
312    * 
313    * @example
314    * <pre name="test">
315    * poista_2_tyhjat("   kissa     istuu   ") === " kissa istuu "  
316    * poista_2_tyhjat("") === ""  
317    * poista_2_tyhjat("   ") === " "  
318    * poista_2_tyhjat((String)null) === "";
319    * </pre>
320    */
321   public static String poista_2_tyhjat(String s) { // NOPMD sallitaan alleviiva historian painolastina
322     if ( s == null ) return "";
323     return poista_2_tyhjat(new StringBuilder(s)).toString();
324   }
325 
326 
327   //****************************************************************************
328   /**
329    * Erottaa jonosta valitun merkin kohdalta alkuosan ja loppuosan.
330    * Alkuosa palautetaan funktion nimessä ja loppuosa jätetään
331    * jonoon.  Merkin etsimissuunta voidaan valita (oletuksena alusta päin).
332    * Jos merkkiä ei löydy, palautetaan koko jono ja tyhjennetään jono.
333    * <pre>
334    * Käyttöesimerkki: olkoon aluksi string jono,s;
335    *  1)  jono = "123 456";  s = erota(jono);   => jono == "456"  s == "123"
336    *  2)  jono = "123";      s = erota(jono);   => jono == ""     s == "123"
337    *  3)  jono = "1 2 3";
338    *  while ( jono.length() > 0 ) System.out.print(erota(jono)+",");
339    *           => tulostaa 1,2,3,
340    * </pre>
341    * 
342    * @param jono           jono jota pilkotaan
343    * @param merkki         merkki jonka kohdalta katkaistaan
344    * @param etsitakaperin  etsitäänkö merkki oikealta vasemmalle
345    * @return               merkkiä edeltävä jono
346    * 
347    * @example
348    * <pre name="test">
349    *   StringBuffer jono= new StringBuffer("123 456"); String s;
350    *   s = erota(jono); jono.toString() === "456"; s === "123";
351    * 
352    *   jono = new StringBuffer($jono1); 
353    *   s = erota(jono,$merkki,$suunta);
354    *   jono.toString() === $jono2; 
355    *   s === $s;
356    *   
357    *   $jono1     | $merkki | $suunta | $jono2   | $s
358    *   ---------------------------------------------------
359    *   "123"      | ' '     | false   | ""       | "123"
360    *   ---        | ' '     | false   | ""       | ""
361    *   ---        | ' '     | false   | ""       | ""
362    *   "123 456"  | ' '     | false   | "456"    | "123"
363    *   ---        | ' '     | false   | ""       | "456"
364    *   ---        | ' '     | false   | ""       | ""
365    *   "12 34 6"  | ' '     | false   | "34 6"   | "12"   
366    *   ---        | ' '     | false   | "6"      | "34"
367    *   ---        | ' '     | false   | ""       | "6"
368    *   ---        | ' '     | false   | ""       | ""
369    *   "12 34 6"  | ' '     | true    | "6"      | "12 34"
370    *   ---        | ' '     | true    | ""       | "6"
371    *   ---        | ' '     | true    | ""       | ""
372    * 
373    *   erota((StringBuffer)null,' ',false) === "";
374    * </pre>
375    */
376   public static String erota(StringBuffer jono, char merkki, boolean etsitakaperin) {
377     if ( jono == null ) return "";
378     int p;
379     if ( etsitakaperin ) p = jono.lastIndexOf(""+merkki);
380     else p = jono.indexOf(""+merkki);
381     String alku;
382     if ( p < 0 ) {
383       alku = jono.toString();
384       jono.delete(0,jono.length());
385       return alku;
386     }
387     alku = jono.substring(0,p);
388     jono.delete(0,p+1);
389     return alku;
390   }
391 
392   
393   //****************************************************************************
394   /**
395    * Erottaa jonosta valitun merkin kohdalta alkuosan ja loppuosan.
396    * Alkuosa palautetaan funktion nimessä ja loppuosa jätetään
397    * jonoon.  Merkin etsimissuunta voidaan valita (oletuksena alusta päin).
398    * Jos merkkiä ei löydy, palautetaan koko jono ja tyhjennetään jono.
399    * <pre>
400    * Käyttöesimerkki: olkoon aluksi string jono,s;
401    *  1)  jono = "123 456";  s = erota(jono);   => jono == "456"  s == "123"
402    *  2)  jono = "123";      s = erota(jono);   => jono == ""     s == "123"
403    *  3)  jono = "1 2 3";
404    *  while ( jono.length() > 0 ) System.out.print(erota(jono)+",");
405    *           => tulostaa 1,2,3,
406    * </pre>
407    * 
408    * @param jono           jono jota pilkotaan
409    * @param merkki         merkki jonka kohdalta katkaistaan
410    * @param etsitakaperin  etsitäänkö merkki oikealta vasemmalle
411    * @return               merkkiä edeltävä jono
412    * 
413    * @example
414    * <pre name="test">
415    *   StringBuilder jono= new StringBuilder("123 456"); String s;
416    *   s = erota(jono); jono.toString() === "456"; s === "123";
417    * 
418    *   jono = new StringBuilder($jono1); 
419    *   s = erota(jono,$merkki,$suunta);
420    *   jono.toString() === $jono2; s === $s
421    *   
422    *   $jono1     | $merkki | $suunta | $jono2   | $s
423    *   ---------------------------------------------------
424    *   "123"      | ' '     | false   | ""       | "123"
425    *   ---        | ' '     | false   | ""       | ""
426    *   ---        | ' '     | false   | ""       | ""
427    *   "123 456"  | ' '     | false   | "456"    | "123"
428    *   ---        | ' '     | false   | ""       | "456"
429    *   ---        | ' '     | false   | ""       | ""
430    *   "12 34 6"  | ' '     | false   | "34 6"   | "12"   
431    *   ---        | ' '     | false   | "6"      | "34"
432    *   ---        | ' '     | false   | ""       | "6"
433    *   ---        | ' '     | false   | ""       | ""
434    *   "12 34 6"  | ' '     | true    | "6"      | "12 34"
435    *   ---        | ' '     | true    | ""       | "6"
436    *   ---        | ' '     | true    | ""       | ""
437    * 
438    *   erota((StringBuilder)null,' ',false) === "";
439    * </pre>
440    */
441   public static String erota(StringBuilder jono, char merkki, boolean etsitakaperin) {
442     if ( jono == null ) return "";
443     int p;
444     if ( etsitakaperin ) p = jono.lastIndexOf(""+merkki);
445     else p = jono.indexOf(""+merkki);
446     String alku;
447     if ( p < 0 ) {
448       alku = jono.toString();
449       jono.delete(0,jono.length());
450       return alku;
451     }
452     alku = jono.substring(0,p);
453     jono.delete(0,p+1);
454     return alku;
455   }
456 
457   
458   /**
459    * Erottaa jonosta valitun merkin kohdalta alkuosan ja loppuosan.
460    * @param jono           jono jota pilkotaan
461    * @param merkki         merkki jonka kohdalta katkaistaan
462    * @return               merkkiä edeltävä jono
463    * @example
464    * <pre name="test">
465    *   StringBuffer jono= new StringBuffer("123 456"); String s;
466    *   s = erota(jono,' '); jono.toString() === "456"; s === "123";
467    * </pre>  
468    */
469   public static String erota(StringBuffer jono, char merkki) {
470     return erota(jono,merkki,false);
471   }
472 
473   
474   /** Erottaa jonosta välilyönnin kohdalta alkuosan ja loppuosan.
475    * @param jono jono jota pilkotaan
476    * @return     merkkiä edeltävä jono
477    */
478   public static String erota(StringBuffer jono) {
479     return erota(jono,' ',false);
480   }
481 
482   
483   /**
484    * Erottaa jonosta valitun merkin kohdalta alkuosan ja loppuosan.
485    * @param jono           jono jota pilkotaan
486    * @param merkki         merkki jonka kohdalta katkaistaan
487    * @return               merkkiä edeltävä jono
488    * @example
489    * <pre name="test">
490    *   StringBuilder jono= new StringBuilder("123 456"); String s;
491    *   s = erota(jono,' '); jono.toString() === "456"; s === "123";
492    * </pre>  
493    */
494   public static String erota(StringBuilder jono, char merkki) {
495     return erota(jono,merkki,false);
496   }
497 
498   
499   /** Erottaa jonosta välilyönnin kohdalta alkuosan ja loppuosan.
500    * @param jono jono jota pilkotaan
501    * @return     merkkiä edeltävä jono
502    */
503   public static String erota(StringBuilder jono) {
504     return erota(jono,' ',false);
505   }
506 
507   
508   //****************************************************************************
509 
510   /**
511    * Tunnetut numeromerkit
512    */
513   public static final String NUMEROT = "0123456789";
514   
515   /**
516    * Käytetty desimaalisymboli
517    */
518   public static final char DESIMAALI = '.';
519   
520   /**
521    * Käytetty desimaalisymboli
522    */
523   public static final char ETUMERKKI = '-';
524   
525   /**
526    * Tunnetut reaaliluvun merkit
527    */
528   public static final String DOUBLEMERKIT = ETUMERKKI + NUMEROT + DESIMAALI;
529 
530   /**
531    * Tunnetut kokonaisluvun merkit
532    */
533   public static final String INTMERKIT = ETUMERKKI + NUMEROT;
534 
535   //****************************************************************************
536 
537   /**
538    * Erottaa merkkijonosta seuraavan reaaliluvun.  Jos lukua ei voida erottaa
539    * niin palautetaan oletus
540    * <pre>
541    * jono = " 12.34 km"; d = erotaDouble(jono,0);  => d = 12.34  jono = " km"
542    * jono = "12k34 km"; d = erotaDouble(jono,0);  => d = 12  jono = "k34 km"
543    * jono = "k12.34 km"; d = erotaDouble(jono,0); => d = 0  jono = "k12.34 km"
544    * </pre>
545    * @param jono merkkijono josta luku otetaan, jono lyhenee
546    * @param oletus arvo jota käytetään jos jonossa ei ole yhtään numeroa
547    * @param numerot aluksi sallitut numerot
548    * @return otettu reaaliluku
549    * 
550    * @example
551    * <pre name="test">
552    *   StringBuffer jono;
553    *   jono = new StringBuffer($jono1); erotaDouble(jono,0) ~~~ $d; jono.toString() === $jono2;
554    *   
555    *    $jono1    |  $d   | $jono2
556    *  ----------------------------------
557    *  " 12.34 km" | 12.34 | " km" 
558    *  "12k34 km"  | 12    | "k34 km"
559    *  "k12.34 km" | 0     | "k12.34 km"
560    *  "1.2 3.4"   | 1.2   | " 3.4"
561    *   ---        | 3.4   | ""
562    *  "-1.2 -3.4" | -1.2  | " -3.4"
563    *   ---        | -3.4  | ""
564    *  "-1-2 -3.4" | -1    | "-2 -3.4"
565    *   ---        | -2    | " -3.4"
566    *  ".2"        | 0.2   | ""
567    *  "-.2"       | -0.2  | ""
568    *  ".-2"       | 0.0   | "-2"
569    *  "- 2"       | 0.0   | " 2"
570    *  ""          | 0     | ""
571    *
572    *   jono = new StringBuffer("2112233451232"); 
573    *   erotaDouble(jono,0,"123") ~~~ 2112233.0; 
574    *   erotaDouble(jono,0,null) ~~~ 451232.0; 
575    *   erotaDouble((StringBuffer)null,0,null) ~~~ 0.0; 
576    *   
577    * </pre>
578    */
579   public static double erotaDouble(StringBuffer jono, double oletus, String numerot) { // NOPMD onhan se monimutkainen mutta...
580     if ( jono == null ) return oletus;
581     String num = numerot;
582     if ( num == null ) num = DOUBLEMERKIT;
583     int alku = 0; int i; boolean alkuws = true;
584     for (i=0; i < jono.length(); i++) {
585       char c = jono.charAt(i);
586       if ( alkuws && Character.isWhitespace(c) ) { alku++; continue; }
587       if ( num.indexOf(c) < 0 ) break;
588       if ( c == DESIMAALI ) num = NUMEROT;
589       int p = num.indexOf(ETUMERKKI);
590       if ( p >= 0 ) num = num.substring(0,p) + num.substring(p+1); // ei enää etumerkkiä
591       alkuws = false; // enää ei saa olla ws-merkkiä
592     }
593 
594     if ( i == 0 ) return oletus;
595     num = jono.substring(alku,i);
596     jono.delete(0,i);
597     try {
598       return Double.parseDouble(num);
599     } catch (NumberFormatException ex) {
600       return oletus;
601     }
602 
603   }
604 
605 
606   /**
607    * Erottaa merkkijonosta seuraavan reaaliluvun.  Jos lukua ei voida erottaa
608    * niin palautetaan oletus
609    * <pre>
610    * jono = " 12.34 km"; d = erotaDouble(jono,0);  => d = 12.34  jono = " km"
611    * jono = "12k34 km"; d = erotaDouble(jono,0);  => d = 12  jono = "k34 km"
612    * jono = "k12.34 km"; d = erotaDouble(jono,0); => d = 0  jono = "k12.34 km"
613    * </pre>
614    * @param jono merkkijono josta luku otetaan, jono lyhenee
615    * @param oletus arvo jota käytetään jos jonossa ei ole yhtään numeroa
616    * @param numerot aluksi sallitut numerot
617    * @return otettu reaaliluku
618    * 
619    * @example
620    * <pre name="test">
621    *   StringBuilder jono;
622    *   jono = new StringBuilder($jono1); erotaDouble(jono,0) ~~~ $d; jono.toString() === $jono2;
623    *   
624    *    $jono1    |  $d   | $jono2
625    *  ----------------------------------
626    *  " 12.34 km" | 12.34 | " km" 
627    *  "12k34 km"  | 12    | "k34 km"
628    *  "k12.34 km" | 0     | "k12.34 km"
629    *  "1.2 3.4"   | 1.2   | " 3.4"
630    *   ---        | 3.4   | ""
631    *  "-1.2 -3.4" | -1.2  | " -3.4"
632    *   ---        | -3.4  | ""
633    *  "-1-2 -3.4" | -1    | "-2 -3.4"
634    *   ---        | -2    | " -3.4"
635    *  ".2"        | 0.2   | ""
636    *  "-.2"       | -0.2  | ""
637    *  ".-2"       | 0.0   | "-2"
638    *  "- 2"       | 0.0   | " 2"
639    *  ""          | 0     | ""
640    *
641    *   jono = new StringBuilder("2112233451232"); 
642    *   erotaDouble(jono,0,"123") ~~~ 2112233.0; 
643    *   erotaDouble(jono,0,null) ~~~ 451232.0; 
644    *   erotaDouble((StringBuilder)null,0,"123") ~~~ 0.0; 
645    *   
646    * </pre>
647    */
648   public static double erotaDouble(StringBuilder jono, double oletus, String numerot) { // NOPMD onhan se monimutkainen mutta...
649     if ( jono == null ) return oletus;
650     String num = numerot;
651     if ( num == null ) num = DOUBLEMERKIT;
652     int alku = 0; int i; boolean alkuws = true;
653     for (i=0; i < jono.length(); i++) {
654       char c = jono.charAt(i);
655       if ( alkuws && Character.isWhitespace(c) ) { alku++; continue; }
656       if ( num.indexOf(c) < 0 ) break;
657       if ( c == DESIMAALI ) num = NUMEROT;
658       int p = num.indexOf(ETUMERKKI);
659       if ( p >= 0 ) num = num.substring(0,p) + num.substring(p+1); // ei enää etumerkkiä
660       alkuws = false; // enää ei saa olla ws-merkkiä
661     }
662 
663     if ( i == 0 ) return oletus;
664     num = jono.substring(alku,i);
665     jono.delete(0,i);
666     try {
667       return Double.parseDouble(num);
668     } catch (NumberFormatException ex) {
669       return oletus;
670     }
671 
672   }
673 
674 
675   /**
676    * Erottaa merkkijonosta seuraavan reaaliluvun.  Jos lukua ei voida erottaa
677    * niin palautetaan oletus
678    * <pre>
679    * jono = " 12.34 km"; d = erotaDouble(jono,0);  => d = 12.34  jono = " km"
680    * jono = "12k34 km"; d = erotaDouble(jono,0);  => d = 12  jono = "k34 km"
681    * jono = "k12.34 km"; d = erotaDouble(jono,0); => d = 0  jono = "k12.34 km"
682    * </pre>
683    * @param jono merkkijono josta luku otetaan, jono lyhenee
684    * @param oletus arvo jota käytetään jos jonossa ei ole yhtään numeroa
685    * @return otettu reaaliluku
686    * @see #erotaDouble(StringBuffer jono, double oletus, String numerot)
687    * @example
688    * <pre name="test">
689    *   StringBuffer jono;
690    *   jono = new StringBuffer(" 12.34 km"); erotaDouble(jono,0) ~~~ 12.34; jono.toString() === " km"; 
691    *   jono = new StringBuffer(" 12k34 km"); erotaDouble(jono,0) ~~~ 12.00; jono.toString() === "k34 km"; 
692    *   jono = new StringBuffer("k12.34 km"); erotaDouble(jono,0) ~~~  0.0;  jono.toString() === "k12.34 km"; 
693    * </pre>
694    */
695   public static double erotaDouble(StringBuffer jono, double oletus) {
696     return erotaDouble(jono,oletus,DOUBLEMERKIT);
697   }
698 
699 
700   /**
701    * Erottaa merkkijonosta seuraavan reaaliluvun.  Jos lukua ei voida erottaa
702    * niin palautetaan oletus
703    * <pre>
704    * jono = " 12.34 km"; d = erotaDouble(jono,0);  => d = 12.34  jono = " km"
705    * jono = "12k34 km"; d = erotaDouble(jono,0);  => d = 12  jono = "k34 km"
706    * jono = "k12.34 km"; d = erotaDouble(jono,0); => d = 0  jono = "k12.34 km"
707    * </pre>
708    * @param jono merkkijono josta luku otetaan, jono lyhenee
709    * @param oletus arvo jota käytetään jos jonossa ei ole yhtään numeroa
710    * @return otettu reaaliluku
711    * @see #erotaDouble(StringBuilder jono, double oletus, String numerot)
712    * @example
713    * <pre name="test">
714    *   StringBuilder jono;
715    *   jono = new StringBuilder(" 12.34 km"); erotaDouble(jono,0) ~~~ 12.34; jono.toString() === " km"; 
716    *   jono = new StringBuilder(" 12k34 km"); erotaDouble(jono,0) ~~~ 12.00; jono.toString() === "k34 km"; 
717    *   jono = new StringBuilder("k12.34 km"); erotaDouble(jono,0) ~~~  0.0;  jono.toString() === "k12.34 km"; 
718    * </pre>
719    */
720   public static double erotaDouble(StringBuilder jono, double oletus) {
721     return erotaDouble(jono,oletus,DOUBLEMERKIT);
722   }
723 
724 
725   /**
726    * Ottaa merkkijonosta seuraavan kokonaisluvun
727    * @param jono merkkijono josta luku otetaan, jono lyhenee
728    * @param oletus arvo jota käytetään jos jonossa ei ole yhtään numeroa
729    * @return otettu kokonaisluku
730    * @see #erotaDouble(StringBuffer jono, double oletus)
731    * 
732    * @example
733    * <pre name="test">
734    *   StringBuffer jono;
735    *   jono = new StringBuffer($jono1); erotaInt(jono,0) === $i; jono.toString() === $jono2;
736    *   
737    *    $jono1    |  $i   | $jono2
738    *  ----------------------------------
739    *  " 12.34 km" | 12    | ".34 km" 
740    *  "12k34 km"  | 12    | "k34 km"
741    *  "k12.34 km" | 0     | "k12.34 km"
742    *  "1.2 3.4"   | 1     | ".2 3.4"
743    *   ---        | 0     | ".2 3.4"
744    *  ""          | 0     | ""
745    *  " 1 2 3 "   | 1     | " 2 3 "
746    *  ---         | 2     | " 3 "
747    *  ---         | 3     | " "
748    *  ---         | 0     | ""
749    *  " -1 -2 3 " | -1    | " -2 3 "
750    *  ---         | -2    | " 3 "
751    *  ---         | 3     | " "
752    *
753    *   jono = new StringBuffer("2112233451232"); 
754    *   erotaInt(jono,0,"123") === 2112233; 
755    * </pre>
756    */
757   public static int erotaInt(StringBuffer jono, int oletus) {
758     return (int)Math.round(erotaDouble(jono,oletus,INTMERKIT));
759   }
760 
761   
762   /**
763    * Ottaa merkkijonosta seuraavan kokonaisluvun
764    * @param jono merkkijono josta luku otetaan, jono lyhenee
765    * @param oletus arvo jota käytetään jos jonossa ei ole yhtään numeroa
766    * @return otettu kokonaisluku
767    * @see #erotaDouble(StringBuffer jono, double oletus)
768    * 
769    * @example
770    * <pre name="test">
771    *   StringBuilder jono;
772    *   jono = new StringBuilder($jono1); erotaInt(jono,0) === $i; jono.toString() === $jono2;
773    *   
774    *    $jono1    |  $i   | $jono2
775    *  ----------------------------------
776    *  " 12.34 km" | 12    | ".34 km" 
777    *  "12k34 km"  | 12    | "k34 km"
778    *  "k12.34 km" | 0     | "k12.34 km"
779    *  "1.2 3.4"   | 1     | ".2 3.4"
780    *   ---        | 0     | ".2 3.4"
781    *  ""          | 0     | ""
782    *  " 1 2 3 "   | 1     | " 2 3 "
783    *  ---         | 2     | " 3 "
784    *  ---         | 3     | " "
785    *  ---         | 0     | ""
786    *  " -1 -2 3 " | -1    | " -2 3 "
787    *  ---         | -2    | " 3 "
788    *  ---         | 3     | " "
789    *
790    *   jono = new StringBuilder("2112233451232"); 
791    *   erotaInt(jono,0,"123") === 2112233; 
792    * </pre>
793    */
794   public static int erotaInt(StringBuilder jono, int oletus) {
795     return (int)Math.round(erotaDouble(jono,oletus,INTMERKIT));
796   }
797 
798   
799   /**
800    * Ottaa merkkijonosta seuraavan kokonaisluvun
801    * @param jono merkkijono josta luku otetaan, jono lyhenee
802    * @param oletus arvo jota käytetään jos jonossa ei ole yhtään numeroa
803    * @param numerot numero jotka sallitaan lukuun
804    * @return otettu kokonaisluku
805    * @see #erotaDouble(StringBuffer jono, double oletus, String numerot)
806    * 
807    * @example
808    * <pre name="test">
809    *   StringBuffer jono;
810    *   jono = new StringBuffer("211223345"); 
811    *   erotaInt(jono,0,"123") === 2112233; 
812    * </pre>
813    */
814   public static int erotaInt(StringBuffer jono, int oletus, String numerot) {
815       return (int)Math.round(erotaDouble(jono,oletus,numerot));
816   }
817 
818   
819   /**
820    * Ottaa merkkijonosta seuraavan kokonaisluvun
821    * @param jono merkkijono josta luku otetaan, jono lyhenee
822    * @param oletus arvo jota käytetään jos jonossa ei ole yhtään numeroa
823    * @param numerot numero jotka sallitaan lukuun
824    * @return otettu kokonaisluku
825    * @see #erotaDouble(StringBuilder jono, double oletus, String numerot)
826    * 
827    * @example
828    * <pre name="test">
829    *   StringBuilder jono;
830    *   jono = new StringBuilder("211223345"); 
831    *   erotaInt(jono,0,"123") === 2112233; 
832    * </pre>
833    */
834   public static int erotaInt(StringBuilder jono, int oletus, String numerot) {
835       return (int)Math.round(erotaDouble(jono,oletus,numerot));
836   }
837 
838   
839   /**
840    * Erottaa merkkijonosta seuraavan reaaliluvun.
841    * @param jono merkkijono josta luku otetaan, jono ei muutu
842    * @param oletus arvo jota käytetään jos jonossa ei ole yhtään numeroa
843    * @return otettu reaaliluku
844    * @see #erotaDouble(StringBuilder jono, double oletus)
845    * @example
846    * <pre name="test">
847    *   erotaDouble(" 12.34 km",0) ~~~ 12.34;  
848    *   erotaDouble(" 12k34 km",0) ~~~ 12.00;  
849    *   erotaDouble("k12.34 km",0) ~~~  0.0;   
850    *   erotaDouble((String)null,2) ~~~  2.0;   
851    * </pre>
852    */
853   public static double erotaDouble(String jono, double oletus) {
854     if ( jono == null ) return oletus;
855     return erotaDouble(new StringBuilder(jono),oletus);
856   }
857 
858   
859   /**
860    * Ottaa merkkijonosta seuraavan kokonaisluvun
861    * @param jono merkkijono josta luku otetaan, jono ei muutu
862    * @param oletus arvo jota käytetään jos jonossa ei ole yhtään numeroa
863    * @return otettu kokonaisluku
864    * @see #erotaInt(StringBuilder jono, int oletus)
865    * @example
866    * <pre name="test">
867    *   erotaInt(" 123k",12)  === 123; 
868    *   erotaInt(" k123k",12) === 12;
869    *   erotaInt((String)null,2) === 2; 
870    * </pre>
871    */
872   public static int erotaInt(String jono, int oletus) {
873     if ( jono == null ) return oletus;
874     return erotaInt(new StringBuilder(jono),oletus);
875   }
876 
877   
878   /**
879    * Ottaa merkkijonosta seuraavan merkin
880    * @param jono merkkijono josta merkki otetaan
881    * @param oletus arvo jota käytetään jos jonossa ei ole yhtään merkkiä
882    * @return otettu merkki
883    * 
884    * @example
885    * <pre name="test">
886    *   StringBuffer jono;
887    *   jono = new StringBuffer($jono1); erotaChar(jono,'!') === $c; jono.toString() === $jono2;
888    *   
889    *    $jono1    |  $c   | $jono2
890    *  ----------------------------------
891    *  " 12 "      | ' '   | "12 " 
892    *   ---        | '1'   | "2 "
893    *   ---        | '2'   | " "
894    *   ---        | ' '   | ""
895    *   ---        | '!'   | ""
896    *    
897    *  erotaChar((StringBuffer)null,'a') === 'a'  
898    * </pre>
899    */
900   public static char erotaChar(StringBuffer jono, char oletus) {
901     if ( jono == null ) return oletus;
902     if ( jono.length() == 0 ) return oletus;
903     char c = jono.charAt(0);
904     jono.delete(0,1);
905     return c;
906   }
907 
908   /**
909    * Ottaa merkkijonosta seuraavan merkin
910    * @param jono merkkijono josta merkki otetaan
911    * @param oletus arvo jota käytetään jos jonossa ei ole yhtään merkkiä
912    * @return otettu merkki
913    * 
914    * @example
915    * <pre name="test">
916    *   StringBuilder jono;
917    *   jono = new StringBuilder($jono1); erotaChar(jono,'!') === $c; jono.toString() === $jono2;
918    *   
919    *    $jono1    |  $c   | $jono2
920    *  ----------------------------------
921    *  " 12 "      | ' '   | "12 " 
922    *   ---        | '1'   | "2 "
923    *   ---        | '2'   | " "
924    *   ---        | ' '   | ""
925    *   ---        | '!'   | ""
926    *    
927    *  erotaChar((StringBuilder)null,'a') === 'a'  
928    * </pre>
929    */
930   public static char erotaChar(StringBuilder jono, char oletus) {
931     if ( jono == null ) return oletus;
932     if ( jono.length() == 0 ) return oletus;
933     char c = jono.charAt(0);
934     jono.delete(0,1);
935     return c;
936   }
937 
938   /**
939    * Erottaa jonosta valitun merkin kohdalta alkuosan ja loppuosan.
940    * Jono trimmataan ennen palautusta (kaikki tyhjät pois)
941    * Käyttää oletusta jos jono on tyhjä.
942    * Tehty lähinnä "kaveriksi" vastaaville int ja double funktiolle,
943    * jotta funktiopolymorfismin avulla saadaan symmetrisiä aliohjelmia
944    * jolloin kutsussa on helppo vaihtaa parametrin tyyppi
945    * <pre>
946    *   String s = erota(jono,'|',"");
947    *   double d = erota(jono,'|',0.0);
948    *   s = erota(jono,'|',s);
949    *   d = erota(jono,'|',d);
950    * </pre>
951    * @param jono           jono jota pilkotaan
952    * @param merkki         merkki jonka kohdalta katkaistaan
953    * @param oletus         arvo jota käytetään jos palasesta tulee tyhjä
954    * @return               merkkiä edeltävä jono
955    * @see #erota(StringBuffer jono, char merkki, boolean etsitakaperin)
956    * 
957    * @example
958    * <pre name="test">
959    * // Testataan merkkijono erota-metodia
960    *  StringBuffer jono = new StringBuffer(" Volvo    145 |  12300 e | 1 kpl");
961    *  erota(jono,'|',"!") === "Volvo 145"; 
962    *  erota(jono,'|',"!") === "12300 e";
963    *  erota(jono,'|',"!") === "1 kpl";
964    *  erota(jono,'|',"!") === "!";
965    *  erota(jono,'|',null) === "";
966    *
967    * </pre>
968    */
969   public static String erota(StringBuffer jono, char merkki, String oletus) {
970     String pala = erota(jono,merkki,false);
971     if ( pala.length() == 0 ) pala = oletus;
972     if ( pala == null ) pala = "";
973     return poista_2_tyhjat(pala.trim());
974   }
975 
976   /**
977    * Erottaa jonosta valitun merkin kohdalta alkuosan ja loppuosan.
978    * Jono trimmataan ennen palautusta (kaikki tyhjät pois)
979    * Käyttää oletusta jos jono on tyhjä.
980    * Tehty lähinnä "kaveriksi" vastaaville int ja double funktiolle,
981    * jotta funktiopolymorfismin avulla saadaan symmetrisiä aliohjelmia
982    * jolloin kutsussa on helppo vaihtaa parametrin tyyppi
983    * <pre>
984    *   String s = erota(jono,'|',"");
985    *   double d = erota(jono,'|',0.0);
986    *   s = erota(jono,'|',s);
987    *   d = erota(jono,'|',d);
988    * </pre>
989    * @param jono           jono jota pilkotaan
990    * @param merkki         merkki jonka kohdalta katkaistaan
991    * @param oletus         arvo jota käytetään jos palasesta tulee tyhjä
992    * @return               merkkiä edeltävä jono
993    * @see #erota(StringBuilder jono, char merkki, boolean etsitakaperin)
994    * 
995    * @example
996    * <pre name="test">
997    * // Testataan merkkijono erota-metodia
998    *  StringBuilder jono = new StringBuilder(" Volvo    145 |  12300 e | 1 kpl");
999    *  erota(jono,'|',"!") === "Volvo 145"; 
1000   *  erota(jono,'|',"!") === "12300 e";
1001   *  erota(jono,'|',"!") === "1 kpl";
1002   *  erota(jono,'|',"!") === "!";
1003   *  erota(jono,'|',null) === "";
1004   *
1005   * </pre>
1006   */
1007  public static String erota(StringBuilder jono, char merkki, String oletus) {
1008    String pala = erota(jono,merkki,false);
1009    if ( pala.length() == 0 ) pala = oletus;
1010    if ( pala == null ) pala = "";
1011    return poista_2_tyhjat(pala.trim());
1012  }
1013
1014  /**
1015   * Ottaa merkkijonosta ensin seuraavan palasen merkki-parametriin
1016   * saakka ja sitten ottaa tästä palasta reaaliluvun
1017   * @param jono           jono jota pilkotaan
1018   * @param merkki         merkki jonka kohdalta katkaistaan
1019   * @param oletus         arvo jota käytetään jos palasta ei saa reaalilukua
1020   * @return               merkkiä edeltävä jono
1021   * @see #erota(StringBuffer jono, char merkki, String oletus)
1022   * @example
1023   * <pre name="test">
1024   *   StringBuffer jono;
1025   *   jono = new StringBuffer("12.3,45"); erota(jono,',',9.0) ~~~ 12.3; erota(jono,',',9.0) ~~~ 45.0;
1026   *   jono = new StringBuffer("k,45");    erota(jono,',',9.0) ~~~ 9.0;  erota(jono,',',9.0) ~~~ 45.0;
1027   * </pre>
1028   */
1029  public static double erota(StringBuffer jono, char merkki, double oletus) {
1030    String pala = erota(jono,merkki,false);
1031    return erotaDouble(pala,oletus);
1032  }
1033
1034
1035  /**
1036   * Ottaa merkkijonosta ensin seuraavan palasen merkki-parametriin
1037   * saakka ja sitten ottaa tästä palasta reaaliluvun
1038   * @param jono           jono jota pilkotaan
1039   * @param merkki         merkki jonka kohdalta katkaistaan
1040   * @param oletus         arvo jota käytetään jos palasta ei saa reaalilukua
1041   * @return               merkkiä edeltävä jono
1042   * @see #erota(StringBuilder jono, char merkki, String oletus)
1043   * @example
1044   * <pre name="test">
1045   *   StringBuilder jono;
1046   *   jono = new StringBuilder("12.3,45"); erota(jono,',',9.0) ~~~ 12.3; erota(jono,',',9.0) ~~~ 45.0;
1047   *   jono = new StringBuilder("k,45");    erota(jono,',',9.0) ~~~ 9.0;  erota(jono,',',9.0) ~~~ 45.0;
1048   * </pre>
1049   */
1050  public static double erota(StringBuilder jono, char merkki, double oletus) {
1051    String pala = erota(jono,merkki,false);
1052    return erotaDouble(pala,oletus);
1053  }
1054
1055
1056  /**
1057   * Ottaa merkkijonosta ensin seuraavan palasen merkki-parametriin
1058   * saakka ja sitten ottaa tästä palasta kokonaisluvun
1059   * @param jono           jono jota pilkotaan
1060   * @param merkki         merkki jonka kohdalta katkaistaan
1061   * @param oletus         arvo jota käytetään jos palasta ei saa reaalilukua
1062   * @return               merkkiä edeltävä jono
1063   * @see #erota(StringBuffer jono, char merkki, String oletus)
1064   *
1065   * @example
1066   * <pre name="test">
1067   * // Testataan polymorfista erota-metodia
1068   *  StringBuffer jono = new StringBuffer(" Volvo    145 |  12300 e | 1 kpl");
1069   *  String s=""; double d=0.0; int i=0;
1070   *  erota(jono,'|',s) === "Volvo 145"; 
1071   *  erota(jono,'|',d) ~~~ 12300.0;
1072   *  erota(jono,'|',i) === 1;
1073   *  erota(jono,'|',"a") === "a";
1074   * </pre>
1075   */
1076  public static int erota(StringBuffer jono, char merkki, int oletus) {
1077    String pala = erota(jono,merkki,false);
1078    return erotaInt(pala,oletus);
1079  }
1080
1081
1082  /**
1083   * Ottaa merkkijonosta ensin seuraavan palasen merkki-parametriin
1084   * saakka ja sitten ottaa tästä palasta kokonaisluvun
1085   * @param jono           jono jota pilkotaan
1086   * @param merkki         merkki jonka kohdalta katkaistaan
1087   * @param oletus         arvo jota käytetään jos palasta ei saa reaalilukua
1088   * @return               merkkiä edeltävä jono
1089   * @see #erota(StringBuilder jono, char merkki, String oletus)
1090   *
1091   * @example
1092   * <pre name="test">
1093   * // Testataan polymorfista erota-metodia
1094   *  StringBuilder jono = new StringBuilder(" Volvo    145 |  12300 e | 1 kpl");
1095   *  String s=""; double d=0.0; int i=0;
1096   *  erota(jono,'|',s) === "Volvo 145"; 
1097   *  erota(jono,'|',d) ~~~ 12300.0;
1098   *  erota(jono,'|',i) === 1;
1099   *  erota(jono,'|',"a") === "a";
1100   * </pre>
1101   */
1102  public static int erota(StringBuilder jono, char merkki, int oletus) {
1103    String pala = erota(jono,merkki,false);
1104    return erotaInt(pala,oletus);
1105  }
1106
1107
1108  /**
1109   * Erottaa jonosta valitun merkin kohdalta alkuosan ja loppuosan.
1110   * Jono trimmataan ennen palautusta (kaikki tyhjät pois)
1111   * Heittää poikkeuksen jos jono on tyhjä
1112   * Tehty lähinnä "kaveriksi" vastaaville int ja double funktiolle,
1113   * jotta funktiopolymorfismin avulla saadaan symmetrisiä aliohjelmia
1114   * jolloin kutsussa on helppo vaihtaa parametrin tyyppi
1115   * <pre>
1116   *   String s = null;
1117   *   double d = 0.0;
1118   *   try {
1119   *     s = erotaEx(jono,'|',s);
1120   *     d = erotaEx(jono,'|',d);
1121   *   } catch ( NumberFormatException ex ) {
1122   *     System.out.println(ex.getMessage());
1123   *   }
1124   * </pre>
1125   * @param jono           jono jota pilkotaan
1126   * @param merkki         merkki jonka kohdalta katkaistaan
1127   * @param oletus         arvo mikäli tulos olisi tyhjä
1128   * @return               merkkiä edeltävä jono
1129   * @throws NumberFormatException jos palaa ei saada
1130   * @see #erota(StringBuffer jono, char merkki, boolean etsitakaperin)
1131   * 
1132   * @example
1133   * <pre name="test">
1134   *   StringBuffer jono;
1135   *   jono = new StringBuffer($jono1); erotaEx(jono,' ',"!") === $s; jono.toString() === $jono2
1136   *   
1137   *    $jono1    |  $s     | $jono2
1138   *  ----------------------------------
1139   *  " 12.34 km" | "!"     | "12.34 km"
1140   *  ---         | "12.34" | "km"
1141   *  ---         | "km"    | ""
1142   *  ---         | ""      | ---    #THROWS NumberFormatException
1143   *  "Kissa"     | "Kissa" | ""       
1144   *  ---         | ""      | ---    #THROWS NumberFormatException  
1145   *  
1146   *  erotaEx(new StringBuffer(";"),';',null) === "";
1147   * </pre>
1148   */
1149  public static String erotaEx(StringBuffer jono, char merkki, String oletus) throws NumberFormatException {
1150    if ( (jono == null) || jono.length()==0 )
1151      throw new NumberFormatException("jono = \"\"");
1152    String pala = erota(jono,merkki,false);
1153    if ( pala.length() == 0 ) pala = oletus;
1154    if ( pala == null ) pala = "";
1155    return poista_2_tyhjat(pala.trim());
1156  }
1157
1158  
1159  /**
1160   * Erottaa jonosta valitun merkin kohdalta alkuosan ja loppuosan.
1161   * Jono trimmataan ennen palautusta (kaikki tyhjät pois)
1162   * Heittää poikkeuksen jos jono on tyhjä
1163   * Tehty lähinnä "kaveriksi" vastaaville int ja double funktiolle,
1164   * jotta funktiopolymorfismin avulla saadaan symmetrisiä aliohjelmia
1165   * jolloin kutsussa on helppo vaihtaa parametrin tyyppi
1166   * <pre>
1167   *   String s = null;
1168   *   double d = 0.0;
1169   *   try {
1170   *     s = erotaEx(jono,'|',s);
1171   *     d = erotaEx(jono,'|',d);
1172   *   } catch ( NumberFormatException ex ) {
1173   *     System.out.println(ex.getMessage());
1174   *   }
1175   * </pre>
1176   * @param jono           jono jota pilkotaan
1177   * @param merkki         merkki jonka kohdalta katkaistaan
1178   * @param oletus         arvo mikäli tulos olisi tyhjä
1179   * @return               merkkiä edeltävä jono
1180   * @throws NumberFormatException jos palaa ei saada
1181   * @see #erota(StringBuilder jono, char merkki, boolean etsitakaperin)
1182   * 
1183   * @example
1184   * <pre name="test">
1185   *   StringBuilder jono;
1186   *   jono = new StringBuilder($jono1); erotaEx(jono,' ',"!") === $s; jono.toString() === $jono2;
1187   *   
1188   *    $jono1    |  $s     | $jono2
1189   *  ----------------------------------
1190   *  " 12.34 km" | "!"     | "12.34 km"
1191   *  ---         | "12.34" | "km"
1192   *  ---         | "km"    | ""
1193   *  ---         | ""      | ---     #THROWS NumberFormatException
1194   *  "Kissa"     | "Kissa" | ""       
1195   *  ---         | ""      | ---     #THROWS NumberFormatException
1196   *    
1197   *  erotaEx(new StringBuilder(";"),';',null) === "";
1198   * </pre>
1199   */
1200  public static String erotaEx(StringBuilder jono, char merkki, String oletus) throws NumberFormatException {
1201    if ( (jono == null) || jono.length()==0 )
1202      throw new NumberFormatException("jono = \"\"");
1203    String pala = erota(jono,merkki,false);
1204    if ( pala.length() == 0 ) pala = oletus;
1205    if ( pala == null ) pala = "";
1206    return poista_2_tyhjat(pala.trim());
1207  }
1208
1209  
1210  /**
1211   * Ottaa merkkijonosta ensin seuraavan palasen merkki-parametriin
1212   * saakka ja sitten ottaa tästä palasta reaaliluvun.
1213   * @param jono           jono jota pilkotaan
1214   * @param merkki         merkki jonka kohdalta katkaistaan
1215   * @param oletus         tuo vain tiedon palautettavasta tyypistä
1216   * @return               merkkiä edeltävä jono
1217   * @throws NumberFormatException jos reaalilukua ei saada
1218   * @see #erotaEx(StringBuffer jono, char merkki, String oletus)
1219   * 
1220   * @example
1221   * <pre name="test">
1222   *   StringBuffer jono=new StringBuffer(); // turha alustus jotta ei varoituksia --- kohdalla
1223   *   jono = new StringBuffer($jono1); erotaEx(jono,' ',3.14) ~~~ $d; jono.toString() === $jono2;
1224   *   
1225   *    $jono1    |  $d     | $jono2
1226   *  ----------------------------------
1227   *  " 12.34 km" | 0.0     | ---         #THROWS NumberFormatException  
1228   *  ---         | ---     | "12.34 km"
1229   *  ---         | 12.34   | "km"
1230   *  ---         | 0.0     | ---         #THROWS NumberFormatException
1231   *  ---         | ---     | ""
1232   *  ---         | 0.0     | ---         #THROWS NumberFormatException
1233   *  
1234   *   jono = new StringBuffer($jono1); erotaEx(jono,',',3.14) ~~~ $d; jono.toString() === $jono2;
1235   *   
1236   *    $jono1    |  $d     | $jono2
1237   *  ----------------------------------
1238   *  " 1.2, 3.4" | 1.2     | " 3.4" 
1239   *  ---         | 3.4     | ""
1240   *  ---         | 0.0     | ---         #THROWS NumberFormatException
1241   *  "1.2,k,3.4" | 1.2     | "k,3.4" 
1242   *  ---         | 0.0     | ---         #THROWS NumberFormatException
1243   *  ---         | ---     | "3.4"
1244   *  ---         | 3.4     | ""
1245   * </pre>
1246   */
1247  @SuppressWarnings("unused")
1248  public static double erotaEx(StringBuffer jono, char merkki, double oletus) throws NumberFormatException {
1249    String pala = erota(jono,merkki,false);
1250    double d = erotaDouble(pala,Double.MIN_VALUE);
1251    if ( d == Double.MIN_VALUE )
1252      throw new NumberFormatException("jono = \"" + pala + "\""); // NOPMD - ei jaksa tehdä vakiota
1253    return d;
1254  }
1255
1256
1257  /**
1258   * Ottaa merkkijonosta ensin seuraavan palasen merkki-parametriin
1259   * saakka ja sitten ottaa tästä palasta reaaliluvun.
1260   * @param jono           jono jota pilkotaan
1261   * @param merkki         merkki jonka kohdalta katkaistaan
1262   * @param oletus         tuo vain tiedon palautettavasta tyypistä
1263   * @return               merkkiä edeltävä jono
1264   * @throws NumberFormatException jos reaalilukua ei saada
1265   * @see #erotaEx(StringBuilder jono, char merkki, String oletus)
1266   * 
1267   * @example
1268   * <pre name="test">
1269   *   StringBuilder jono=new StringBuilder(); // turha alustus jotta ei varoituksia --- kohdalla
1270   *   jono = new StringBuilder($jono1); erotaEx(jono,' ',3.14) ~~~ $d; jono.toString() === $jono2;
1271   *   
1272   *    $jono1    |  $d     | $jono2
1273   *  ----------------------------------
1274   *  " 12.34 km" | 0.0     | ---        #THROWS NumberFormatException 
1275   *  ---         | ---     | "12.34 km"
1276   *  ---         | 12.34   | "km"
1277   *  ---         | 0.0     | ---        #THROWS NumberFormatException
1278   *  ---         | ---     | ""
1279   *  ---         | 0.0     | ---        #THROWS NumberFormatException
1280   *  
1281   *   jono = new StringBuilder($jono1); erotaEx(jono,',',3.14) ~~~ $d; jono.toString() === $jono2;
1282   *   
1283   *    $jono1    |  $d     | $jono2
1284   *  ----------------------------------
1285   *  " 1.2, 3.4" | 1.2     | " 3.4" 
1286   *  ---         | 3.4     | ""
1287   *  ---         | 0.0     | ---      #THROWS NumberFormatException
1288   *  "1.2,k,3.4" | 1.2     | "k,3.4" 
1289   *  ---         | 0.0     | ---      #THROWS NumberFormatException
1290   *  ---         | ---     | "3.4"
1291   *  ---         | 3.4     | ""
1292   * </pre>
1293   */
1294  @SuppressWarnings("unused")
1295  public static double erotaEx(StringBuilder jono, char merkki, double oletus) throws NumberFormatException {
1296    String pala = erota(jono,merkki,false);
1297    double d = erotaDouble(pala,Double.MIN_VALUE);
1298    if ( d == Double.MIN_VALUE )
1299      throw new NumberFormatException("jono = \"" + pala + "\"");
1300    return d;
1301  }
1302
1303
1304  /**
1305   * Ottaa merkkijonosta ensin seuraavan palasen merkki-parametriin
1306   * saakka ja sitten ottaa tästä palasta kokonaisluvun
1307   * @param jono           jono jota pilkotaan
1308   * @param merkki         merkki jonka kohdalta katkaistaan
1309   * @param oletus         tuo vain tiedon palautettavasta tyypistä
1310   * @return               merkkiä edeltävä jono
1311   * @throws NumberFormatException jos kokonaislukua ei saada
1312   * @see #erotaEx(StringBuffer jono, char merkki, String oletus)
1313   * 
1314   * @example
1315   * <pre name="test">
1316   *   StringBuffer jono=new StringBuffer(); // turha alustus jotta ei varoituksia --- kohdalla
1317   *   jono = new StringBuffer($jono1); erotaEx(jono,' ',314) === $i; jono.toString() === $jono2;
1318   *   
1319   *    $jono1    |  $i     | $jono2
1320   *  ----------------------------------
1321   *  " 12.34 km" | 0       | ---    #THROWS NumberFormatException 
1322   *  ---         | ---     | "12.34 km"
1323   *  ---         | 12      | "km"
1324   *  ---         | 0       | ---    #THROWS NumberFormatException
1325   *  ---         | 0       | ---    #THROWS NumberFormatException
1326   *  
1327   *   jono = new StringBuffer($jono1); erotaEx(jono,',',314) === $i; jono.toString() === $jono2;
1328   *   
1329   *    $jono1    |  $i     | $jono2
1330   *  ----------------------------------
1331   *  " 1.2, 3.4" | 1       | " 3.4" 
1332   *  ---         | 3       | ""
1333   *  ---         | 0       | ---        #THROWS NumberFormatException
1334   *  "1,2,3"     | 1       | "2,3"
1335   *  ---         | 2       | "3"
1336   *  ---         | 3       | ""
1337   *  ---         | 0       | ---        #THROWS NumberFormatException
1338   *  "1,k,3"     | 1       | "k,3"      
1339   *  ---         | 0       | ---        #THROWS NumberFormatException 
1340   *  ---         | ---     | "3"
1341   *  ---         | 3       | ""
1342   *  ---         | 0       | ---        #THROWS NumberFormatException
1343   * </pre>
1344   */
1345  @SuppressWarnings("unused")
1346  public static int erotaEx(StringBuffer jono, char merkki, int oletus) throws NumberFormatException {
1347    String pala = erota(jono,merkki,false);
1348    int i = erotaInt(pala,Integer.MIN_VALUE);
1349    if ( i == Integer.MIN_VALUE )
1350      throw new NumberFormatException("jono = \"" + pala + "\"");
1351    return i;
1352  }
1353
1354
1355  /**
1356   * Ottaa merkkijonosta ensin seuraavan palasen merkki-parametriin
1357   * saakka ja sitten ottaa tästä palasta kokonaisluvun
1358   * @param jono           jono jota pilkotaan
1359   * @param merkki         merkki jonka kohdalta katkaistaan
1360   * @param oletus         tuo vain tiedon palautettavasta tyypistä
1361   * @return               merkkiä edeltävä jono
1362   * @throws NumberFormatException jos kokonaislukua ei saada
1363   * @see #erotaEx(StringBuilder jono, char merkki, String oletus)
1364   * 
1365   * @example
1366   * <pre name="test">
1367   *   StringBuilder jono=new StringBuilder(); // turha alustus jotta ei varoituksia --- kohdalla
1368   *   jono = new StringBuilder($jono1); erotaEx(jono,' ',314) === $i; jono.toString() === $jono2;
1369   *   
1370   *    $jono1    |  $i     | $jono2
1371   *  ----------------------------------
1372   *  " 12.34 km" | 0       | ---        #THROWS NumberFormatException 
1373   *  ---         | ---     | "12.34 km"
1374   *  ---         | 12      | "km"
1375   *  ---         | 0       | ---        #THROWS NumberFormatException
1376   *  ---         | 0       | ---        #THROWS NumberFormatException
1377   *  
1378   *   jono = new StringBuilder($jono1); erotaEx(jono,',',314) === $i; jono.toString() === $jono2;
1379   *   
1380   *    $jono1    |  $i     | $jono2
1381   *  ----------------------------------
1382   *  " 1.2, 3.4" | 1       | " 3.4" 
1383   *  ---         | 3       | ""
1384   *  ---         | 0       | ---        #THROWS NumberFormatException
1385   *  "1,2,3"     | 1       | "2,3"
1386   *  ---         | 2       | "3"
1387   *  ---         | 3       | ""
1388   *  ---         | 0       | ---        #THROWS NumberFormatException
1389   *  "1,k,3"     | 1       | "k,3"      
1390   *  ---         | 0       | ---        #THROWS NumberFormatException 
1391   *  ---         | ---     | "3"
1392   *  ---         | 3       | ""
1393   *  ---         | 0       | ---        #THROWS NumberFormatException
1394   * </pre>
1395   */
1396  @SuppressWarnings("unused")
1397  public static int erotaEx(StringBuilder jono, char merkki, int oletus) throws NumberFormatException {
1398    String pala = erota(jono,merkki,false);
1399    int i = erotaInt(pala,Integer.MIN_VALUE);
1400    if ( i == Integer.MIN_VALUE )
1401      throw new NumberFormatException("jono = \"" + pala + "\"");
1402    return i;
1403  }
1404
1405
1406
1407  /****************************************************************************
1408
1409
1410  private static void tulostaViiva(String s) {
1411    System.out.println("");
1412    System.out.println("=====================================================");
1413    System.out.println(s);
1414    System.out.println("=====================================================");
1415  }
1416
1417  /**
1418   * Testataan Mjonot-luokkaa. 
1419   * @param args Ei käytössä
1420   *
1421  public static void main(String[] args) { // NOPMD
1422      
1423    tulostaViiva("Testataan erota-metodia.");
1424    StringBuffer jono = new StringBuffer("1 2 3");
1425    while ( jono.length() > 0 ) {
1426      System.out.print(erota(jono)+",");
1427    }
1428    System.out.println("");
1429
1430    tulostaViiva("Testataan erotaDouble ja erotaInt-metodeja");
1431    String testi[] = {" 12.34 km", "12k34", "k12.34", "12.34.56", ".34 km" };
1432    for ( int i = 0; i < testi.length; i++ ) {
1433      StringBuffer jono2 = new StringBuffer(testi[i]); // NOPMD
1434      double d = erotaDouble(jono2,0);
1435      System.out.println(fmt("\""+testi[i] + "\"",-15) + fmt(" d=" + d,-10) +
1436                             " jono = \"" + jono2+ "\"");
1437    }
1438    for ( int i = 0; i < testi.length; i++ ) {
1439      StringBuffer jono2 = new StringBuffer(testi[i]); // NOPMD
1440      int d = erotaInt(jono2,99);
1441      System.out.println(fmt("\""+testi[i] + "\"",-15) + fmt(" i=" + d,-10) +
1442                             " jono = \"" + jono2+ "\"");
1443    }
1444
1445    tulostaViiva("Testataan tayta-metodia");
1446    for (int i=0; i<17; i++)
1447      System.out.println(tayta("kissa",i));
1448
1449    tulostaViiva("Testataan fmt-metodia");
1450    for (int i=3; i<10; i++) System.out.println(fmt(1.23456,i,3));
1451    for (int i=3; i<7; i++) System.out.println(fmt(-1.23456,i,0));
1452    for (int i=9; i<14; i++) System.out.println(fmt(1234567.89,i,3));
1453
1454    tulostaViiva("Testataan polymorfista erota-metodia");
1455    StringBuffer jono3 = new StringBuffer(" Volvo    145 |  12300 e | 1 kpl");
1456    String s=""; double d=0.0; int i=0;
1457    s = erota(jono3,'|',s);
1458    d = erota(jono3,'|',d);
1459    i = erota(jono3,'|',i);
1460    System.out.println("'"+s+"'  " + fmt(d,4,2) + "   " + i);
1461
1462    tulostaViiva("Testataan polymorfista erotaEx-metodia");
1463    StringBuffer jono4 = new StringBuffer(" 23.4 | 12 | kala | 99");
1464    d = 0;
1465
1466    for (i=0; i<5; i++ ) {
1467      try {
1468        d = erotaEx(jono4,'|',d);
1469      } catch (NumberFormatException ex) {
1470        System.out.println("Virhe: " + ex.getMessage());
1471      }
1472      System.out.println("d = " + fmt(d,4,2) + "  jono = \"" + jono4 + "\"");
1473    }
1474
1475
1476  }
1477  */
1478}
1479