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; s === $s;
355    *   
356    *   $jono1     | $merkki | $suunta | $jono2   | $s
357    *   ---------------------------------------------------
358    *   "123"      | ' '     | false   | ""       | "123"
359    *   ---        | ' '     | false   | ""       | ""
360    *   ---        | ' '     | false   | ""       | ""
361    *   "123 456"  | ' '     | false   | "456"    | "123"
362    *   ---        | ' '     | false   | ""       | "456"
363    *   ---        | ' '     | false   | ""       | ""
364    *   "12 34 6"  | ' '     | false   | "34 6"   | "12"   
365    *   ---        | ' '     | false   | "6"      | "34"
366    *   ---        | ' '     | false   | ""       | "6"
367    *   ---        | ' '     | false   | ""       | ""
368    *   "12 34 6"  | ' '     | true    | "6"      | "12 34"
369    *   ---        | ' '     | true    | ""       | "6"
370    *   ---        | ' '     | true    | ""       | ""
371    * 
372    *   erota((StringBuffer)null,' ',false) === "";
373    * </pre>
374    */
375   public static String erota(StringBuffer jono, char merkki, boolean etsitakaperin) {
376     if ( jono == null ) return "";
377     int p;
378     if ( etsitakaperin ) p = jono.lastIndexOf(""+merkki);
379     else p = jono.indexOf(""+merkki);
380     String alku;
381     if ( p < 0 ) {
382       alku = jono.toString();
383       jono.delete(0,jono.length());
384       return alku;
385     }
386     alku = jono.substring(0,p);
387     jono.delete(0,p+1);
388     return alku;
389   }
390 
391   
392   //****************************************************************************
393   /**
394    * Erottaa jonosta valitun merkin kohdalta alkuosan ja loppuosan.
395    * Alkuosa palautetaan funktion nimessä ja loppuosa jätetään
396    * jonoon.  Merkin etsimissuunta voidaan valita (oletuksena alusta päin).
397    * Jos merkkiä ei löydy, palautetaan koko jono ja tyhjennetään jono.
398    * <pre>
399    * Käyttöesimerkki: olkoon aluksi string jono,s;
400    *  1)  jono = "123 456";  s = erota(jono);   => jono == "456"  s == "123"
401    *  2)  jono = "123";      s = erota(jono);   => jono == ""     s == "123"
402    *  3)  jono = "1 2 3";
403    *  while ( jono.length() > 0 ) System.out.print(erota(jono)+",");
404    *           => tulostaa 1,2,3,
405    * </pre>
406    * 
407    * @param jono           jono jota pilkotaan
408    * @param merkki         merkki jonka kohdalta katkaistaan
409    * @param etsitakaperin  etsitäänkö merkki oikealta vasemmalle
410    * @return               merkkiä edeltävä jono
411    * 
412    * @example
413    * <pre name="test">
414    *   StringBuilder jono= new StringBuilder("123 456"); String s;
415    *   s = erota(jono); jono.toString() === "456"; s === "123";
416    * 
417    *   jono = new StringBuilder($jono1); 
418    *   s = erota(jono,$merkki,$suunta);
419    *   jono.toString() === $jono2; s === $s;
420    *   
421    *   $jono1     | $merkki | $suunta | $jono2   | $s
422    *   ---------------------------------------------------
423    *   "123"      | ' '     | false   | ""       | "123"
424    *   ---        | ' '     | false   | ""       | ""
425    *   ---        | ' '     | false   | ""       | ""
426    *   "123 456"  | ' '     | false   | "456"    | "123"
427    *   ---        | ' '     | false   | ""       | "456"
428    *   ---        | ' '     | false   | ""       | ""
429    *   "12 34 6"  | ' '     | false   | "34 6"   | "12"   
430    *   ---        | ' '     | false   | "6"      | "34"
431    *   ---        | ' '     | false   | ""       | "6"
432    *   ---        | ' '     | false   | ""       | ""
433    *   "12 34 6"  | ' '     | true    | "6"      | "12 34"
434    *   ---        | ' '     | true    | ""       | "6"
435    *   ---        | ' '     | true    | ""       | ""
436    * 
437    *   erota((StringBuilder)null,' ',false) === "";
438    * </pre>
439    */
440   public static String erota(StringBuilder jono, char merkki, boolean etsitakaperin) {
441     if ( jono == null ) return "";
442     int p;
443     if ( etsitakaperin ) p = jono.lastIndexOf(""+merkki);
444     else p = jono.indexOf(""+merkki);
445     String alku;
446     if ( p < 0 ) {
447       alku = jono.toString();
448       jono.delete(0,jono.length());
449       return alku;
450     }
451     alku = jono.substring(0,p);
452     jono.delete(0,p+1);
453     return alku;
454   }
455 
456   
457   /**
458    * Erottaa jonosta valitun merkin kohdalta alkuosan ja loppuosan.
459    * @param jono           jono jota pilkotaan
460    * @param merkki         merkki jonka kohdalta katkaistaan
461    * @return               merkkiä edeltävä jono
462    * @example
463    * <pre name="test">
464    *   StringBuffer jono= new StringBuffer("123 456"); String s;
465    *   s = erota(jono,' '); jono.toString() === "456"; s === "123";
466    * </pre>  
467    */
468   public static String erota(StringBuffer jono, char merkki) {
469     return erota(jono,merkki,false);
470   }
471 
472   
473   /** Erottaa jonosta välilyönnin kohdalta alkuosan ja loppuosan.
474    * @param jono jono jota pilkotaan
475    * @return     merkkiä edeltävä jono
476    */
477   public static String erota(StringBuffer jono) {
478     return erota(jono,' ',false);
479   }
480 
481   
482   /**
483    * Erottaa jonosta valitun merkin kohdalta alkuosan ja loppuosan.
484    * @param jono           jono jota pilkotaan
485    * @param merkki         merkki jonka kohdalta katkaistaan
486    * @return               merkkiä edeltävä jono
487    * @example
488    * <pre name="test">
489    *   StringBuilder jono= new StringBuilder("123 456"); String s;
490    *   s = erota(jono,' '); jono.toString() === "456"; s === "123";
491    * </pre>  
492    */
493   public static String erota(StringBuilder jono, char merkki) {
494     return erota(jono,merkki,false);
495   }
496 
497   
498   /** Erottaa jonosta välilyönnin kohdalta alkuosan ja loppuosan.
499    * @param jono jono jota pilkotaan
500    * @return     merkkiä edeltävä jono
501    */
502   public static String erota(StringBuilder jono) {
503     return erota(jono,' ',false);
504   }
505 
506   
507   //****************************************************************************
508 
509   /**
510    * Tunnetut numeromerkit
511    */
512   public static final String NUMEROT = "0123456789";
513   
514   /**
515    * Käytetty desimaalisymboli
516    */
517   public static final char DESIMAALI = '.';
518   
519   /**
520    * Käytetty desimaalisymboli
521    */
522   public static final char ETUMERKKI = '-';
523   
524   /**
525    * Tunnetut reaaliluvun merkit
526    */
527   public static final String DOUBLEMERKIT = ETUMERKKI + NUMEROT + DESIMAALI;
528 
529   /**
530    * Tunnetut kokonaisluvun merkit
531    */
532   public static final String INTMERKIT = ETUMERKKI + NUMEROT;
533 
534   //****************************************************************************
535 
536   /**
537    * Erottaa merkkijonosta seuraavan reaaliluvun.  Jos lukua ei voida erottaa
538    * niin palautetaan oletus
539    * <pre>
540    * jono = " 12.34 km"; d = erotaDouble(jono,0);  => d = 12.34  jono = " km"
541    * jono = "12k34 km"; d = erotaDouble(jono,0);  => d = 12  jono = "k34 km"
542    * jono = "k12.34 km"; d = erotaDouble(jono,0); => d = 0  jono = "k12.34 km"
543    * </pre>
544    * @param jono merkkijono josta luku otetaan, jono lyhenee
545    * @param oletus arvo jota käytetään jos jonossa ei ole yhtään numeroa
546    * @param numerot aluksi sallitut numerot
547    * @return otettu reaaliluku
548    * 
549    * @example
550    * <pre name="test">
551    *   StringBuffer jono;
552    *   jono = new StringBuffer($jono1); erotaDouble(jono,0) ~~~ $d; jono.toString() === $jono2;
553    *   
554    *    $jono1    |  $d   | $jono2
555    *  ----------------------------------
556    *  " 12.34 km" | 12.34 | " km" 
557    *  "12k34 km"  | 12    | "k34 km"
558    *  "k12.34 km" | 0     | "k12.34 km"
559    *  "1.2 3.4"   | 1.2   | " 3.4"
560    *   ---        | 3.4   | ""
561    *  "-1.2 -3.4" | -1.2  | " -3.4"
562    *   ---        | -3.4  | ""
563    *  "-1-2 -3.4" | -1    | "-2 -3.4"
564    *   ---        | -2    | " -3.4"
565    *  ".2"        | 0.2   | ""
566    *  "-.2"       | -0.2  | ""
567    *  ".-2"       | 0.0   | "-2"
568    *  "- 2"       | 0.0   | " 2"
569    *  ""          | 0     | ""
570    *
571    *   jono = new StringBuffer("2112233451232"); 
572    *   erotaDouble(jono,0,"123") ~~~ 2112233.0; 
573    *   erotaDouble(jono,0,null) ~~~ 451232.0; 
574    *   erotaDouble((StringBuffer)null,0,null) ~~~ 0.0; 
575    *   
576    * </pre>
577    */
578   public static double erotaDouble(StringBuffer jono, double oletus, String numerot) { // NOPMD onhan se monimutkainen mutta...
579     if ( jono == null ) return oletus;
580     String num = numerot;
581     if ( num == null ) num = DOUBLEMERKIT;
582     int alku = 0; int i; boolean alkuws = true;
583     for (i=0; i < jono.length(); i++) {
584       char c = jono.charAt(i);
585       if ( alkuws && Character.isWhitespace(c) ) { alku++; continue; }
586       if ( num.indexOf(c) < 0 ) break;
587       if ( c == DESIMAALI ) num = NUMEROT;
588       int p = num.indexOf(ETUMERKKI);
589       if ( p >= 0 ) num = num.substring(0,p) + num.substring(p+1); // ei enää etumerkkiä
590       alkuws = false; // enää ei saa olla ws-merkkiä
591     }
592 
593     if ( i == 0 ) return oletus;
594     num = jono.substring(alku,i);
595     jono.delete(0,i);
596     try {
597       return Double.parseDouble(num);
598     } catch (NumberFormatException ex) {
599       return oletus;
600     }
601 
602   }
603 
604 
605   /**
606    * Erottaa merkkijonosta seuraavan reaaliluvun.  Jos lukua ei voida erottaa
607    * niin palautetaan oletus
608    * <pre>
609    * jono = " 12.34 km"; d = erotaDouble(jono,0);  => d = 12.34  jono = " km"
610    * jono = "12k34 km"; d = erotaDouble(jono,0);  => d = 12  jono = "k34 km"
611    * jono = "k12.34 km"; d = erotaDouble(jono,0); => d = 0  jono = "k12.34 km"
612    * </pre>
613    * @param jono merkkijono josta luku otetaan, jono lyhenee
614    * @param oletus arvo jota käytetään jos jonossa ei ole yhtään numeroa
615    * @param numerot aluksi sallitut numerot
616    * @return otettu reaaliluku
617    * 
618    * @example
619    * <pre name="test">
620    *   StringBuilder jono;
621    *   jono = new StringBuilder($jono1); erotaDouble(jono,0) ~~~ $d; jono.toString() === $jono2;
622    *   
623    *    $jono1    |  $d   | $jono2
624    *  ----------------------------------
625    *  " 12.34 km" | 12.34 | " km" 
626    *  "12k34 km"  | 12    | "k34 km"
627    *  "k12.34 km" | 0     | "k12.34 km"
628    *  "1.2 3.4"   | 1.2   | " 3.4"
629    *   ---        | 3.4   | ""
630    *  "-1.2 -3.4" | -1.2  | " -3.4"
631    *   ---        | -3.4  | ""
632    *  "-1-2 -3.4" | -1    | "-2 -3.4"
633    *   ---        | -2    | " -3.4"
634    *  ".2"        | 0.2   | ""
635    *  "-.2"       | -0.2  | ""
636    *  ".-2"       | 0.0   | "-2"
637    *  "- 2"       | 0.0   | " 2"
638    *  ""          | 0     | ""
639    *
640    *   jono = new StringBuilder("2112233451232"); 
641    *   erotaDouble(jono,0,"123") ~~~ 2112233.0; 
642    *   erotaDouble(jono,0,null) ~~~ 451232.0; 
643    *   erotaDouble((StringBuilder)null,0,"123") ~~~ 0.0; 
644    *   
645    * </pre>
646    */
647   public static double erotaDouble(StringBuilder jono, double oletus, String numerot) { // NOPMD onhan se monimutkainen mutta...
648     if ( jono == null ) return oletus;
649     String num = numerot;
650     if ( num == null ) num = DOUBLEMERKIT;
651     int alku = 0; int i; boolean alkuws = true;
652     for (i=0; i < jono.length(); i++) {
653       char c = jono.charAt(i);
654       if ( alkuws && Character.isWhitespace(c) ) { alku++; continue; }
655       if ( num.indexOf(c) < 0 ) break;
656       if ( c == DESIMAALI ) num = NUMEROT;
657       int p = num.indexOf(ETUMERKKI);
658       if ( p >= 0 ) num = num.substring(0,p) + num.substring(p+1); // ei enää etumerkkiä
659       alkuws = false; // enää ei saa olla ws-merkkiä
660     }
661 
662     if ( i == 0 ) return oletus;
663     num = jono.substring(alku,i);
664     jono.delete(0,i);
665     try {
666       return Double.parseDouble(num);
667     } catch (NumberFormatException ex) {
668       return oletus;
669     }
670 
671   }
672 
673 
674   /**
675    * Erottaa merkkijonosta seuraavan reaaliluvun.  Jos lukua ei voida erottaa
676    * niin palautetaan oletus
677    * <pre>
678    * jono = " 12.34 km"; d = erotaDouble(jono,0);  => d = 12.34  jono = " km"
679    * jono = "12k34 km"; d = erotaDouble(jono,0);  => d = 12  jono = "k34 km"
680    * jono = "k12.34 km"; d = erotaDouble(jono,0); => d = 0  jono = "k12.34 km"
681    * </pre>
682    * @param jono merkkijono josta luku otetaan, jono lyhenee
683    * @param oletus arvo jota käytetään jos jonossa ei ole yhtään numeroa
684    * @return otettu reaaliluku
685    * @see #erotaDouble(StringBuffer jono, double oletus, String numerot)
686    * @example
687    * <pre name="test">
688    *   StringBuffer jono;
689    *   jono = new StringBuffer(" 12.34 km"); erotaDouble(jono,0) ~~~ 12.34; jono.toString() === " km"; 
690    *   jono = new StringBuffer(" 12k34 km"); erotaDouble(jono,0) ~~~ 12.00; jono.toString() === "k34 km"; 
691    *   jono = new StringBuffer("k12.34 km"); erotaDouble(jono,0) ~~~  0.0;  jono.toString() === "k12.34 km"; 
692    * </pre>
693    */
694   public static double erotaDouble(StringBuffer jono, double oletus) {
695     return erotaDouble(jono,oletus,DOUBLEMERKIT);
696   }
697 
698 
699   /**
700    * Erottaa merkkijonosta seuraavan reaaliluvun.  Jos lukua ei voida erottaa
701    * niin palautetaan oletus
702    * <pre>
703    * jono = " 12.34 km"; d = erotaDouble(jono,0);  => d = 12.34  jono = " km"
704    * jono = "12k34 km"; d = erotaDouble(jono,0);  => d = 12  jono = "k34 km"
705    * jono = "k12.34 km"; d = erotaDouble(jono,0); => d = 0  jono = "k12.34 km"
706    * </pre>
707    * @param jono merkkijono josta luku otetaan, jono lyhenee
708    * @param oletus arvo jota käytetään jos jonossa ei ole yhtään numeroa
709    * @return otettu reaaliluku
710    * @see #erotaDouble(StringBuilder jono, double oletus, String numerot)
711    * @example
712    * <pre name="test">
713    *   StringBuilder jono;
714    *   jono = new StringBuilder(" 12.34 km"); erotaDouble(jono,0) ~~~ 12.34; jono.toString() === " km"; 
715    *   jono = new StringBuilder(" 12k34 km"); erotaDouble(jono,0) ~~~ 12.00; jono.toString() === "k34 km"; 
716    *   jono = new StringBuilder("k12.34 km"); erotaDouble(jono,0) ~~~  0.0;  jono.toString() === "k12.34 km"; 
717    * </pre>
718    */
719   public static double erotaDouble(StringBuilder jono, double oletus) {
720     return erotaDouble(jono,oletus,DOUBLEMERKIT);
721   }
722 
723 
724   /**
725    * Ottaa merkkijonosta seuraavan kokonaisluvun
726    * @param jono merkkijono josta luku otetaan, jono lyhenee
727    * @param oletus arvo jota käytetään jos jonossa ei ole yhtään numeroa
728    * @return otettu kokonaisluku
729    * @see #erotaDouble(StringBuffer jono, double oletus)
730    * 
731    * @example
732    * <pre name="test">
733    *   StringBuffer jono;
734    *   jono = new StringBuffer($jono1); erotaInt(jono,0) === $i; jono.toString() === $jono2;
735    *   
736    *    $jono1    |  $i   | $jono2
737    *  ----------------------------------
738    *  " 12.34 km" | 12    | ".34 km" 
739    *  "12k34 km"  | 12    | "k34 km"
740    *  "k12.34 km" | 0     | "k12.34 km"
741    *  "1.2 3.4"   | 1     | ".2 3.4"
742    *   ---        | 0     | ".2 3.4"
743    *  ""          | 0     | ""
744    *  " 1 2 3 "   | 1     | " 2 3 "
745    *  ---         | 2     | " 3 "
746    *  ---         | 3     | " "
747    *  ---         | 0     | ""
748    *  " -1 -2 3 " | -1    | " -2 3 "
749    *  ---         | -2    | " 3 "
750    *  ---         | 3     | " "
751    *
752    *   jono = new StringBuffer("2112233451232"); 
753    *   erotaInt(jono,0,"123") === 2112233; 
754    * </pre>
755    */
756   public static int erotaInt(StringBuffer jono, int oletus) {
757     return (int)Math.round(erotaDouble(jono,oletus,INTMERKIT));
758   }
759 
760   
761   /**
762    * Ottaa merkkijonosta seuraavan kokonaisluvun
763    * @param jono merkkijono josta luku otetaan, jono lyhenee
764    * @param oletus arvo jota käytetään jos jonossa ei ole yhtään numeroa
765    * @return otettu kokonaisluku
766    * @see #erotaDouble(StringBuffer jono, double oletus)
767    * 
768    * @example
769    * <pre name="test">
770    *   StringBuilder jono;
771    *   jono = new StringBuilder($jono1); erotaInt(jono,0) === $i; jono.toString() === $jono2;
772    *   
773    *    $jono1    |  $i   | $jono2
774    *  ----------------------------------
775    *  " 12.34 km" | 12    | ".34 km" 
776    *  "12k34 km"  | 12    | "k34 km"
777    *  "k12.34 km" | 0     | "k12.34 km"
778    *  "1.2 3.4"   | 1     | ".2 3.4"
779    *   ---        | 0     | ".2 3.4"
780    *  ""          | 0     | ""
781    *  " 1 2 3 "   | 1     | " 2 3 "
782    *  ---         | 2     | " 3 "
783    *  ---         | 3     | " "
784    *  ---         | 0     | ""
785    *  " -1 -2 3 " | -1    | " -2 3 "
786    *  ---         | -2    | " 3 "
787    *  ---         | 3     | " "
788    *
789    *   jono = new StringBuilder("2112233451232"); 
790    *   erotaInt(jono,0,"123") === 2112233; 
791    * </pre>
792    */
793   public static int erotaInt(StringBuilder jono, int oletus) {
794     return (int)Math.round(erotaDouble(jono,oletus,INTMERKIT));
795   }
796 
797   
798   /**
799    * Ottaa merkkijonosta seuraavan kokonaisluvun
800    * @param jono merkkijono josta luku otetaan, jono lyhenee
801    * @param oletus arvo jota käytetään jos jonossa ei ole yhtään numeroa
802    * @param numerot numero jotka sallitaan lukuun
803    * @return otettu kokonaisluku
804    * @see #erotaDouble(StringBuffer jono, double oletus, String numerot)
805    * 
806    * @example
807    * <pre name="test">
808    *   StringBuffer jono;
809    *   jono = new StringBuffer("211223345"); 
810    *   erotaInt(jono,0,"123") === 2112233; 
811    * </pre>
812    */
813   public static int erotaInt(StringBuffer jono, int oletus, String numerot) {
814       return (int)Math.round(erotaDouble(jono,oletus,numerot));
815   }
816 
817   
818   /**
819    * Ottaa merkkijonosta seuraavan kokonaisluvun
820    * @param jono merkkijono josta luku otetaan, jono lyhenee
821    * @param oletus arvo jota käytetään jos jonossa ei ole yhtään numeroa
822    * @param numerot numero jotka sallitaan lukuun
823    * @return otettu kokonaisluku
824    * @see #erotaDouble(StringBuilder jono, double oletus, String numerot)
825    * 
826    * @example
827    * <pre name="test">
828    *   StringBuilder jono;
829    *   jono = new StringBuilder("211223345"); 
830    *   erotaInt(jono,0,"123") === 2112233; 
831    * </pre>
832    */
833   public static int erotaInt(StringBuilder jono, int oletus, String numerot) {
834       return (int)Math.round(erotaDouble(jono,oletus,numerot));
835   }
836 
837   
838   /**
839    * Erottaa merkkijonosta seuraavan reaaliluvun.
840    * @param jono merkkijono josta luku otetaan, jono ei muutu
841    * @param oletus arvo jota käytetään jos jonossa ei ole yhtään numeroa
842    * @return otettu reaaliluku
843    * @see #erotaDouble(StringBuilder jono, double oletus)
844    * @example
845    * <pre name="test">
846    *   erotaDouble(" 12.34 km",0) ~~~ 12.34;  
847    *   erotaDouble(" 12k34 km",0) ~~~ 12.00;  
848    *   erotaDouble("k12.34 km",0) ~~~  0.0;   
849    *   erotaDouble((String)null,2) ~~~  2.0;   
850    * </pre>
851    */
852   public static double erotaDouble(String jono, double oletus) {
853     if ( jono == null ) return oletus;
854     return erotaDouble(new StringBuilder(jono),oletus);
855   }
856 
857   
858   /**
859    * Ottaa merkkijonosta seuraavan kokonaisluvun
860    * @param jono merkkijono josta luku otetaan, jono ei muutu
861    * @param oletus arvo jota käytetään jos jonossa ei ole yhtään numeroa
862    * @return otettu kokonaisluku
863    * @see #erotaInt(StringBuilder jono, int oletus)
864    * @example
865    * <pre name="test">
866    *   erotaInt(" 123k",12)  === 123; 
867    *   erotaInt(" k123k",12) === 12;
868    *   erotaInt((String)null,2) === 2; 
869    * </pre>
870    */
871   public static int erotaInt(String jono, int oletus) {
872     if ( jono == null ) return oletus;
873     return erotaInt(new StringBuilder(jono),oletus);
874   }
875 
876   
877   /**
878    * Ottaa merkkijonosta seuraavan merkin
879    * @param jono merkkijono josta merkki otetaan
880    * @param oletus arvo jota käytetään jos jonossa ei ole yhtään merkkiä
881    * @return otettu merkki
882    * 
883    * @example
884    * <pre name="test">
885    *   StringBuffer jono;
886    *   jono = new StringBuffer($jono1); erotaChar(jono,'!') === $c; jono.toString() === $jono2;
887    *   
888    *    $jono1    |  $c   | $jono2
889    *  ----------------------------------
890    *  " 12 "      | ' '   | "12 " 
891    *   ---        | '1'   | "2 "
892    *   ---        | '2'   | " "
893    *   ---        | ' '   | ""
894    *   ---        | '!'   | ""
895    *    
896    *  erotaChar((StringBuffer)null,'a') === 'a'  
897    * </pre>
898    */
899   public static char erotaChar(StringBuffer jono, char oletus) {
900     if ( jono == null ) return oletus;
901     if ( jono.length() == 0 ) return oletus;
902     char c = jono.charAt(0);
903     jono.delete(0,1);
904     return c;
905   }
906 
907   /**
908    * Ottaa merkkijonosta seuraavan merkin
909    * @param jono merkkijono josta merkki otetaan
910    * @param oletus arvo jota käytetään jos jonossa ei ole yhtään merkkiä
911    * @return otettu merkki
912    * 
913    * @example
914    * <pre name="test">
915    *   StringBuilder jono;
916    *   jono = new StringBuilder($jono1); erotaChar(jono,'!') === $c; jono.toString() === $jono2;
917    *   
918    *    $jono1    |  $c   | $jono2
919    *  ----------------------------------
920    *  " 12 "      | ' '   | "12 " 
921    *   ---        | '1'   | "2 "
922    *   ---        | '2'   | " "
923    *   ---        | ' '   | ""
924    *   ---        | '!'   | ""
925    *    
926    *  erotaChar((StringBuilder)null,'a') === 'a'  
927    * </pre>
928    */
929   public static char erotaChar(StringBuilder jono, char oletus) {
930     if ( jono == null ) return oletus;
931     if ( jono.length() == 0 ) return oletus;
932     char c = jono.charAt(0);
933     jono.delete(0,1);
934     return c;
935   }
936 
937   /**
938    * Erottaa jonosta valitun merkin kohdalta alkuosan ja loppuosan.
939    * Jono trimmataan ennen palautusta (kaikki tyhjät pois)
940    * Käyttää oletusta jos jono on tyhjä.
941    * Tehty lähinnä "kaveriksi" vastaaville int ja double funktiolle,
942    * jotta funktiopolymorfismin avulla saadaan symmetrisiä aliohjelmia
943    * jolloin kutsussa on helppo vaihtaa parametrin tyyppi
944    * <pre>
945    *   String s = erota(jono,'|',"");
946    *   double d = erota(jono,'|',0.0);
947    *   s = erota(jono,'|',s);
948    *   d = erota(jono,'|',d);
949    * </pre>
950    * @param jono           jono jota pilkotaan
951    * @param merkki         merkki jonka kohdalta katkaistaan
952    * @param oletus         arvo jota käytetään jos palasesta tulee tyhjä
953    * @return               merkkiä edeltävä jono
954    * @see #erota(StringBuffer jono, char merkki, boolean etsitakaperin)
955    * 
956    * @example
957    * <pre name="test">
958    * // Testataan merkkijono erota-metodia
959    *  StringBuffer jono = new StringBuffer(" Volvo    145 |  12300 e | 1 kpl");
960    *  erota(jono,'|',"!") === "Volvo 145"; 
961    *  erota(jono,'|',"!") === "12300 e";
962    *  erota(jono,'|',"!") === "1 kpl";
963    *  erota(jono,'|',"!") === "!";
964    *  erota(jono,'|',null) === "";
965    *
966    * </pre>
967    */
968   public static String erota(StringBuffer jono, char merkki, String oletus) {
969     String pala = erota(jono,merkki,false);
970     if ( pala.length() == 0 ) pala = oletus;
971     if ( pala == null ) pala = "";
972     return poista_2_tyhjat(pala.trim());
973   }
974 
975   /**
976    * Erottaa jonosta valitun merkin kohdalta alkuosan ja loppuosan.
977    * Jono trimmataan ennen palautusta (kaikki tyhjät pois)
978    * Käyttää oletusta jos jono on tyhjä.
979    * Tehty lähinnä "kaveriksi" vastaaville int ja double funktiolle,
980    * jotta funktiopolymorfismin avulla saadaan symmetrisiä aliohjelmia
981    * jolloin kutsussa on helppo vaihtaa parametrin tyyppi
982    * <pre>
983    *   String s = erota(jono,'|',"");
984    *   double d = erota(jono,'|',0.0);
985    *   s = erota(jono,'|',s);
986    *   d = erota(jono,'|',d);
987    * </pre>
988    * @param jono           jono jota pilkotaan
989    * @param merkki         merkki jonka kohdalta katkaistaan
990    * @param oletus         arvo jota käytetään jos palasesta tulee tyhjä
991    * @return               merkkiä edeltävä jono
992    * @see #erota(StringBuilder jono, char merkki, boolean etsitakaperin)
993    * 
994    * @example
995    * <pre name="test">
996    * // Testataan merkkijono erota-metodia
997    *  StringBuilder jono = new StringBuilder(" Volvo    145 |  12300 e | 1 kpl");
998    *  erota(jono,'|',"!") === "Volvo 145"; 
999    *  erota(jono,'|',"!") === "12300 e";
1000   *  erota(jono,'|',"!") === "1 kpl";
1001   *  erota(jono,'|',"!") === "!";
1002   *  erota(jono,'|',null) === "";
1003   *
1004   * </pre>
1005   */
1006  public static String erota(StringBuilder jono, char merkki, String oletus) {
1007    String pala = erota(jono,merkki,false);
1008    if ( pala.length() == 0 ) pala = oletus;
1009    if ( pala == null ) pala = "";
1010    return poista_2_tyhjat(pala.trim());
1011  }
1012
1013  /**
1014   * Ottaa merkkijonosta ensin seuraavan palasen merkki-parametriin
1015   * saakka ja sitten ottaa tästä palasta reaaliluvun
1016   * @param jono           jono jota pilkotaan
1017   * @param merkki         merkki jonka kohdalta katkaistaan
1018   * @param oletus         arvo jota käytetään jos palasta ei saa reaalilukua
1019   * @return               merkkiä edeltävä jono
1020   * @see #erota(StringBuffer jono, char merkki, String oletus)
1021   * @example
1022   * <pre name="test">
1023   *   StringBuffer jono;
1024   *   jono = new StringBuffer("12.3,45"); erota(jono,',',9.0) ~~~ 12.3; erota(jono,',',9.0) ~~~ 45.0;
1025   *   jono = new StringBuffer("k,45");    erota(jono,',',9.0) ~~~ 9.0;  erota(jono,',',9.0) ~~~ 45.0;
1026   * </pre>
1027   */
1028  public static double erota(StringBuffer jono, char merkki, double oletus) {
1029    String pala = erota(jono,merkki,false);
1030    return erotaDouble(pala,oletus);
1031  }
1032
1033
1034  /**
1035   * Ottaa merkkijonosta ensin seuraavan palasen merkki-parametriin
1036   * saakka ja sitten ottaa tästä palasta reaaliluvun
1037   * @param jono           jono jota pilkotaan
1038   * @param merkki         merkki jonka kohdalta katkaistaan
1039   * @param oletus         arvo jota käytetään jos palasta ei saa reaalilukua
1040   * @return               merkkiä edeltävä jono
1041   * @see #erota(StringBuilder jono, char merkki, String oletus)
1042   * @example
1043   * <pre name="test">
1044   *   StringBuilder jono;
1045   *   jono = new StringBuilder("12.3,45"); erota(jono,',',9.0) ~~~ 12.3; erota(jono,',',9.0) ~~~ 45.0;
1046   *   jono = new StringBuilder("k,45");    erota(jono,',',9.0) ~~~ 9.0;  erota(jono,',',9.0) ~~~ 45.0;
1047   * </pre>
1048   */
1049  public static double erota(StringBuilder jono, char merkki, double oletus) {
1050    String pala = erota(jono,merkki,false);
1051    return erotaDouble(pala,oletus);
1052  }
1053
1054
1055  /**
1056   * Ottaa merkkijonosta ensin seuraavan palasen merkki-parametriin
1057   * saakka ja sitten ottaa tästä palasta kokonaisluvun
1058   * @param jono           jono jota pilkotaan
1059   * @param merkki         merkki jonka kohdalta katkaistaan
1060   * @param oletus         arvo jota käytetään jos palasta ei saa reaalilukua
1061   * @return               merkkiä edeltävä jono
1062   * @see #erota(StringBuffer jono, char merkki, String oletus)
1063   *
1064   * @example
1065   * <pre name="test">
1066   * // Testataan polymorfista erota-metodia
1067   *  StringBuffer jono = new StringBuffer(" Volvo    145 |  12300 e | 1 kpl");
1068   *  String s=""; double d=0.0; int i=0;
1069   *  erota(jono,'|',s) === "Volvo 145"; 
1070   *  erota(jono,'|',d) ~~~ 12300.0;
1071   *  erota(jono,'|',i) === 1;
1072   *  erota(jono,'|',"a") === "a";
1073   * </pre>
1074   */
1075  public static int erota(StringBuffer jono, char merkki, int oletus) {
1076    String pala = erota(jono,merkki,false);
1077    return erotaInt(pala,oletus);
1078  }
1079
1080
1081  /**
1082   * Ottaa merkkijonosta ensin seuraavan palasen merkki-parametriin
1083   * saakka ja sitten ottaa tästä palasta kokonaisluvun
1084   * @param jono           jono jota pilkotaan
1085   * @param merkki         merkki jonka kohdalta katkaistaan
1086   * @param oletus         arvo jota käytetään jos palasta ei saa reaalilukua
1087   * @return               merkkiä edeltävä jono
1088   * @see #erota(StringBuilder jono, char merkki, String oletus)
1089   *
1090   * @example
1091   * <pre name="test">
1092   * // Testataan polymorfista erota-metodia
1093   *  StringBuilder jono = new StringBuilder(" Volvo    145 |  12300 e | 1 kpl");
1094   *  String s=""; double d=0.0; int i=0;
1095   *  erota(jono,'|',s) === "Volvo 145"; 
1096   *  erota(jono,'|',d) ~~~ 12300.0;
1097   *  erota(jono,'|',i) === 1;
1098   *  erota(jono,'|',"a") === "a";
1099   * </pre>
1100   */
1101  public static int erota(StringBuilder jono, char merkki, int oletus) {
1102    String pala = erota(jono,merkki,false);
1103    return erotaInt(pala,oletus);
1104  }
1105
1106
1107  /**
1108   * Erottaa jonosta valitun merkin kohdalta alkuosan ja loppuosan.
1109   * Jono trimmataan ennen palautusta (kaikki tyhjät pois)
1110   * Heittää poikkeuksen jos jono on tyhjä
1111   * Tehty lähinnä "kaveriksi" vastaaville int ja double funktiolle,
1112   * jotta funktiopolymorfismin avulla saadaan symmetrisiä aliohjelmia
1113   * jolloin kutsussa on helppo vaihtaa parametrin tyyppi
1114   * <pre>
1115   *   String s = null;
1116   *   double d = 0.0;
1117   *   try {
1118   *     s = erotaEx(jono,'|',s);
1119   *     d = erotaEx(jono,'|',d);
1120   *   } catch ( NumberFormatException ex ) {
1121   *     System.out.println(ex.getMessage());
1122   *   }
1123   * </pre>
1124   * @param jono           jono jota pilkotaan
1125   * @param merkki         merkki jonka kohdalta katkaistaan
1126   * @param oletus         arvo mikäli tulos olisi tyhjä
1127   * @return               merkkiä edeltävä jono
1128   * @throws NumberFormatException jos palaa ei saada
1129   * @see #erota(StringBuffer jono, char merkki, boolean etsitakaperin)
1130   * 
1131   * @example
1132   * <pre name="test">
1133   *   StringBuffer jono;
1134   *   jono = new StringBuffer($jono1); erotaEx(jono,' ',"!") === $s; jono.toString() === $jono2
1135   *   
1136   *    $jono1    |  $s     | $jono2
1137   *  ----------------------------------
1138   *  " 12.34 km" | "!"     | "12.34 km"
1139   *  ---         | "12.34" | "km"
1140   *  ---         | "km"    | ""
1141   *  ---         | ""      | ---    #THROWS NumberFormatException
1142   *  "Kissa"     | "Kissa" | ""       
1143   *  ---         | ""      | ---    #THROWS NumberFormatException  
1144   *  
1145   *  erotaEx(new StringBuffer(";"),';',null) === "";
1146   * </pre>
1147   */
1148  public static String erotaEx(StringBuffer jono, char merkki, String oletus) throws NumberFormatException {
1149    if ( (jono == null) || jono.length()==0 )
1150      throw new NumberFormatException("jono = \"\"");
1151    String pala = erota(jono,merkki,false);
1152    if ( pala.length() == 0 ) pala = oletus;
1153    if ( pala == null ) pala = "";
1154    return poista_2_tyhjat(pala.trim());
1155  }
1156
1157  
1158  /**
1159   * Erottaa jonosta valitun merkin kohdalta alkuosan ja loppuosan.
1160   * Jono trimmataan ennen palautusta (kaikki tyhjät pois)
1161   * Heittää poikkeuksen jos jono on tyhjä
1162   * Tehty lähinnä "kaveriksi" vastaaville int ja double funktiolle,
1163   * jotta funktiopolymorfismin avulla saadaan symmetrisiä aliohjelmia
1164   * jolloin kutsussa on helppo vaihtaa parametrin tyyppi
1165   * <pre>
1166   *   String s = null;
1167   *   double d = 0.0;
1168   *   try {
1169   *     s = erotaEx(jono,'|',s);
1170   *     d = erotaEx(jono,'|',d);
1171   *   } catch ( NumberFormatException ex ) {
1172   *     System.out.println(ex.getMessage());
1173   *   }
1174   * </pre>
1175   * @param jono           jono jota pilkotaan
1176   * @param merkki         merkki jonka kohdalta katkaistaan
1177   * @param oletus         arvo mikäli tulos olisi tyhjä
1178   * @return               merkkiä edeltävä jono
1179   * @throws NumberFormatException jos palaa ei saada
1180   * @see #erota(StringBuilder jono, char merkki, boolean etsitakaperin)
1181   * 
1182   * @example
1183   * <pre name="test">
1184   *   StringBuilder jono;
1185   *   jono = new StringBuilder($jono1); erotaEx(jono,' ',"!") === $s; jono.toString() === $jono2;
1186   *   
1187   *    $jono1    |  $s     | $jono2
1188   *  ----------------------------------
1189   *  " 12.34 km" | "!"     | "12.34 km"
1190   *  ---         | "12.34" | "km"
1191   *  ---         | "km"    | ""
1192   *  ---         | ""      | ---     #THROWS NumberFormatException
1193   *  "Kissa"     | "Kissa" | ""       
1194   *  ---         | ""      | ---     #THROWS NumberFormatException
1195   *    
1196   *  erotaEx(new StringBuilder(";"),';',null) === "";
1197   * </pre>
1198   */
1199  public static String erotaEx(StringBuilder jono, char merkki, String oletus) throws NumberFormatException {
1200    if ( (jono == null) || jono.length()==0 )
1201      throw new NumberFormatException("jono = \"\"");
1202    String pala = erota(jono,merkki,false);
1203    if ( pala.length() == 0 ) pala = oletus;
1204    if ( pala == null ) pala = "";
1205    return poista_2_tyhjat(pala.trim());
1206  }
1207
1208  
1209  /**
1210   * Ottaa merkkijonosta ensin seuraavan palasen merkki-parametriin
1211   * saakka ja sitten ottaa tästä palasta reaaliluvun.
1212   * @param jono           jono jota pilkotaan
1213   * @param merkki         merkki jonka kohdalta katkaistaan
1214   * @param oletus         tuo vain tiedon palautettavasta tyypistä
1215   * @return               merkkiä edeltävä jono
1216   * @throws NumberFormatException jos reaalilukua ei saada
1217   * @see #erotaEx(StringBuffer jono, char merkki, String oletus)
1218   * 
1219   * @example
1220   * <pre name="test">
1221   *   StringBuffer jono=null;
1222   *   jono = new StringBuffer($jono1); erotaEx(jono,' ',3.14) ~~~ $d; jono.toString() === $jono2;
1223   *   
1224   *    $jono1    |  $d     | $jono2
1225   *  ----------------------------------
1226   *  " 12.34 km" | 0.0     | ---         #THROWS NumberFormatException  
1227   *  ---         | ---     | "12.34 km"
1228   *  ---         | 12.34   | "km"
1229   *  ---         | 0.0     | ---         #THROWS NumberFormatException
1230   *  ---         | ---     | ""
1231   *  ---         | 0.0     | ---         #THROWS NumberFormatException
1232   *  
1233   *   jono = new StringBuffer($jono1); erotaEx(jono,',',3.14) ~~~ $d; jono.toString() === $jono2;
1234   *   
1235   *    $jono1    |  $d     | $jono2
1236   *  ----------------------------------
1237   *  " 1.2, 3.4" | 1.2     | " 3.4" 
1238   *  ---         | 3.4     | ""
1239   *  ---         | 0.0     | ---         #THROWS NumberFormatException
1240   *  "1.2,k,3.4" | 1.2     | "k,3.4" 
1241   *  ---         | 0.0     | ---         #THROWS NumberFormatException
1242   *  ---         | ---     | "3.4"
1243   *  ---         | 3.4     | ""
1244   * </pre>
1245   */
1246  public static double erotaEx(StringBuffer jono, char merkki, double oletus) throws NumberFormatException {
1247    String pala = erota(jono,merkki,false);
1248    double d = erotaDouble(pala,Double.MIN_VALUE);
1249    if ( d == Double.MIN_VALUE )
1250      throw new NumberFormatException("jono = \"" + pala + "\""); // NOPMD - ei jaksa tehdä vakiota
1251    return d;
1252  }
1253
1254
1255  /**
1256   * Ottaa merkkijonosta ensin seuraavan palasen merkki-parametriin
1257   * saakka ja sitten ottaa tästä palasta reaaliluvun.
1258   * @param jono           jono jota pilkotaan
1259   * @param merkki         merkki jonka kohdalta katkaistaan
1260   * @param oletus         tuo vain tiedon palautettavasta tyypistä
1261   * @return               merkkiä edeltävä jono
1262   * @throws NumberFormatException jos reaalilukua ei saada
1263   * @see #erotaEx(StringBuilder jono, char merkki, String oletus)
1264   * 
1265   * @example
1266   * <pre name="test">
1267   *   StringBuilder jono=null;
1268   *   jono = new StringBuilder($jono1); erotaEx(jono,' ',3.14) ~~~ $d; jono.toString() === $jono2;
1269   *   
1270   *    $jono1    |  $d     | $jono2
1271   *  ----------------------------------
1272   *  " 12.34 km" | 0.0     | ---        #THROWS NumberFormatException 
1273   *  ---         | ---     | "12.34 km"
1274   *  ---         | 12.34   | "km"
1275   *  ---         | 0.0     | ---        #THROWS NumberFormatException
1276   *  ---         | ---     | ""
1277   *  ---         | 0.0     | ---        #THROWS NumberFormatException
1278   *  
1279   *   jono = new StringBuilder($jono1); erotaEx(jono,',',3.14) ~~~ $d; jono.toString() === $jono2;
1280   *   
1281   *    $jono1    |  $d     | $jono2
1282   *  ----------------------------------
1283   *  " 1.2, 3.4" | 1.2     | " 3.4" 
1284   *  ---         | 3.4     | ""
1285   *  ---         | 0.0     | ---      #THROWS NumberFormatException
1286   *  "1.2,k,3.4" | 1.2     | "k,3.4" 
1287   *  ---         | 0.0     | ---      #THROWS NumberFormatException
1288   *  ---         | ---     | "3.4"
1289   *  ---         | 3.4     | ""
1290   * </pre>
1291   */
1292  public static double erotaEx(StringBuilder jono, char merkki, double oletus) throws NumberFormatException {
1293    String pala = erota(jono,merkki,false);
1294    double d = erotaDouble(pala,Double.MIN_VALUE);
1295    if ( d == Double.MIN_VALUE )
1296      throw new NumberFormatException("jono = \"" + pala + "\"");
1297    return d;
1298  }
1299
1300
1301  /**
1302   * Ottaa merkkijonosta ensin seuraavan palasen merkki-parametriin
1303   * saakka ja sitten ottaa tästä palasta kokonaisluvun
1304   * @param jono           jono jota pilkotaan
1305   * @param merkki         merkki jonka kohdalta katkaistaan
1306   * @param oletus         tuo vain tiedon palautettavasta tyypistä
1307   * @return               merkkiä edeltävä jono
1308   * @throws NumberFormatException jos kokonaislukua ei saada
1309   * @see #erotaEx(StringBuffer jono, char merkki, String oletus)
1310   * 
1311   * @example
1312   * <pre name="test">
1313   *   StringBuffer jono=null;
1314   *   jono = new StringBuffer($jono1); erotaEx(jono,' ',314) === $i; jono.toString() === $jono2;
1315   *   
1316   *    $jono1    |  $i     | $jono2
1317   *  ----------------------------------
1318   *  " 12.34 km" | 0       | ---    #THROWS NumberFormatException 
1319   *  ---         | ---     | "12.34 km"
1320   *  ---         | 12      | "km"
1321   *  ---         | 0       | ---    #THROWS NumberFormatException
1322   *  ---         | 0       | ---    #THROWS NumberFormatException
1323   *  
1324   *   jono = new StringBuffer($jono1); erotaEx(jono,',',314) === $i; jono.toString() === $jono2;
1325   *   
1326   *    $jono1    |  $i     | $jono2
1327   *  ----------------------------------
1328   *  " 1.2, 3.4" | 1       | " 3.4" 
1329   *  ---         | 3       | ""
1330   *  ---         | 0       | ---        #THROWS NumberFormatException
1331   *  "1,2,3"     | 1       | "2,3"
1332   *  ---         | 2       | "3"
1333   *  ---         | 3       | ""
1334   *  ---         | 0       | ---        #THROWS NumberFormatException
1335   *  "1,k,3"     | 1       | "k,3"      
1336   *  ---         | 0       | ---        #THROWS NumberFormatException 
1337   *  ---         | ---     | "3"
1338   *  ---         | 3       | ""
1339   *  ---         | 0       | ---        #THROWS NumberFormatException
1340   * </pre>
1341   */
1342  public static int erotaEx(StringBuffer jono, char merkki, int oletus) throws NumberFormatException {
1343    String pala = erota(jono,merkki,false);
1344    int i = erotaInt(pala,Integer.MIN_VALUE);
1345    if ( i == Integer.MIN_VALUE )
1346      throw new NumberFormatException("jono = \"" + pala + "\"");
1347    return i;
1348  }
1349
1350
1351  /**
1352   * Ottaa merkkijonosta ensin seuraavan palasen merkki-parametriin
1353   * saakka ja sitten ottaa tästä palasta kokonaisluvun
1354   * @param jono           jono jota pilkotaan
1355   * @param merkki         merkki jonka kohdalta katkaistaan
1356   * @param oletus         tuo vain tiedon palautettavasta tyypistä
1357   * @return               merkkiä edeltävä jono
1358   * @throws NumberFormatException jos kokonaislukua ei saada
1359   * @see #erotaEx(StringBuilder jono, char merkki, String oletus)
1360   * 
1361   * @example
1362   * <pre name="test">
1363   *   StringBuilder jono=null;
1364   *   jono = new StringBuilder($jono1); erotaEx(jono,' ',314) === $i; jono.toString() === $jono2;
1365   *   
1366   *    $jono1    |  $i     | $jono2
1367   *  ----------------------------------
1368   *  " 12.34 km" | 0       | ---        #THROWS NumberFormatException 
1369   *  ---         | ---     | "12.34 km"
1370   *  ---         | 12      | "km"
1371   *  ---         | 0       | ---        #THROWS NumberFormatException
1372   *  ---         | 0       | ---        #THROWS NumberFormatException
1373   *  
1374   *   jono = new StringBuilder($jono1); erotaEx(jono,',',314) === $i; jono.toString() === $jono2;
1375   *   
1376   *    $jono1    |  $i     | $jono2
1377   *  ----------------------------------
1378   *  " 1.2, 3.4" | 1       | " 3.4" 
1379   *  ---         | 3       | ""
1380   *  ---         | 0       | ---        #THROWS NumberFormatException
1381   *  "1,2,3"     | 1       | "2,3"
1382   *  ---         | 2       | "3"
1383   *  ---         | 3       | ""
1384   *  ---         | 0       | ---        #THROWS NumberFormatException
1385   *  "1,k,3"     | 1       | "k,3"      
1386   *  ---         | 0       | ---        #THROWS NumberFormatException 
1387   *  ---         | ---     | "3"
1388   *  ---         | 3       | ""
1389   *  ---         | 0       | ---        #THROWS NumberFormatException
1390   * </pre>
1391   */
1392  public static int erotaEx(StringBuilder jono, char merkki, int oletus) throws NumberFormatException {
1393    String pala = erota(jono,merkki,false);
1394    int i = erotaInt(pala,Integer.MIN_VALUE);
1395    if ( i == Integer.MIN_VALUE )
1396      throw new NumberFormatException("jono = \"" + pala + "\"");
1397    return i;
1398  }
1399
1400
1401
1402  /****************************************************************************
1403
1404
1405  private static void tulostaViiva(String s) {
1406    System.out.println("");
1407    System.out.println("=====================================================");
1408    System.out.println(s);
1409    System.out.println("=====================================================");
1410  }
1411
1412  /**
1413   * Testataan Mjonot-luokkaa. 
1414   * @param args Ei käytössä
1415   *
1416  public static void main(String[] args) { // NOPMD
1417      
1418    tulostaViiva("Testataan erota-metodia.");
1419    StringBuffer jono = new StringBuffer("1 2 3");
1420    while ( jono.length() > 0 ) {
1421      System.out.print(erota(jono)+",");
1422    }
1423    System.out.println("");
1424
1425    tulostaViiva("Testataan erotaDouble ja erotaInt-metodeja");
1426    String testi[] = {" 12.34 km", "12k34", "k12.34", "12.34.56", ".34 km" };
1427    for ( int i = 0; i < testi.length; i++ ) {
1428      StringBuffer jono2 = new StringBuffer(testi[i]); // NOPMD
1429      double d = erotaDouble(jono2,0);
1430      System.out.println(fmt("\""+testi[i] + "\"",-15) + fmt(" d=" + d,-10) +
1431                             " jono = \"" + jono2+ "\"");
1432    }
1433    for ( int i = 0; i < testi.length; i++ ) {
1434      StringBuffer jono2 = new StringBuffer(testi[i]); // NOPMD
1435      int d = erotaInt(jono2,99);
1436      System.out.println(fmt("\""+testi[i] + "\"",-15) + fmt(" i=" + d,-10) +
1437                             " jono = \"" + jono2+ "\"");
1438    }
1439
1440    tulostaViiva("Testataan tayta-metodia");
1441    for (int i=0; i<17; i++)
1442      System.out.println(tayta("kissa",i));
1443
1444    tulostaViiva("Testataan fmt-metodia");
1445    for (int i=3; i<10; i++) System.out.println(fmt(1.23456,i,3));
1446    for (int i=3; i<7; i++) System.out.println(fmt(-1.23456,i,0));
1447    for (int i=9; i<14; i++) System.out.println(fmt(1234567.89,i,3));
1448
1449    tulostaViiva("Testataan polymorfista erota-metodia");
1450    StringBuffer jono3 = new StringBuffer(" Volvo    145 |  12300 e | 1 kpl");
1451    String s=""; double d=0.0; int i=0;
1452    s = erota(jono3,'|',s);
1453    d = erota(jono3,'|',d);
1454    i = erota(jono3,'|',i);
1455    System.out.println("'"+s+"'  " + fmt(d,4,2) + "   " + i);
1456
1457    tulostaViiva("Testataan polymorfista erotaEx-metodia");
1458    StringBuffer jono4 = new StringBuffer(" 23.4 | 12 | kala | 99");
1459    d = 0;
1460
1461    for (i=0; i<5; i++ ) {
1462      try {
1463        d = erotaEx(jono4,'|',d);
1464      } catch (NumberFormatException ex) {
1465        System.out.println("Virhe: " + ex.getMessage());
1466      }
1467      System.out.println("d = " + fmt(d,4,2) + "  jono = \"" + jono4 + "\"");
1468    }
1469
1470
1471  }
1472  */
1473}
1474