001package fi.jyu.mit.ohj2;
002
003import java.text.DecimalFormat;
004import java.text.DecimalFormatSymbols;
005
006/**
007 * Joukko merkkijonoaliohjelmia Ohjelmointi 2-kurssin käyttöön
008 * @author Vesa Lappalainen
009 * @version 1.0, 07.01.2003
010 * @version 1.1, 09.03.2002
011 * @version 1.2, 30.09.2007 / vl, testi
012 * @version 1.3, 12.08.2008 / vl, StringBuilder
013 * @since 1.5
014 */
015
016public class Mjonot { // NOPMD
017
018  //****************************************************************************
019    
020  /**
021   * Palauttaa jonon, jossa on monistettuna jono s n-kertaa
022   * <pre> tayta("kissa",3)  => "kissakissakissa"</pre>
023   * Tuplataan jonon pituus joka kerta => 100 monistusta vaatii 7 kierrosta
024   * @param s monistettava jono
025   * @param n kuinka monta kertaa monistetaan
026   * @return s monistettuna n kertaa
027   * 
028   * @example
029   * <pre name="testTayta">
030   * tayta($jono,$n) === $tulos
031   * 
032   *    $jono   | $n | $tulos
033   *  -------------------------------
034   *    "kissa" |  3 | "kissakissakissa"
035   *    ""      | 10 | ""
036   *    "kissa" |  0 | ""     
037   *    "kissa" |  1 | "kissa"
038   *    "a"     | 10 | "aaaaaaaaaa"     
039   * </pre>
040   */
041  public static String tayta(String s, int n) {
042    int pituus = n*s.length();
043    if ( pituus == 0 ) return "";
044    StringBuilder jono = new StringBuilder(pituus);
045    jono.append(s);
046    while ( 2*jono.length() < pituus  ) jono.append(jono);
047    jono.append(jono.substring(0,pituus-jono.length()));
048    return jono.toString();
049  }
050
051
052  /** Palauttaa merkkijonon jossa on n kappaletta välilyöntejä
053   * @param n montako välilyöntiä tarvitaan
054   * @return jono, jossa on n kpl välilyöntejä
055   * 
056   *  @example
057   * <pre name="test">
058   * tyhja(0) === ""
059   * tyhja(1) === " "
060   * tyhja(2) === "  "
061   * tyhja(10) === "          ";
062   * tyhja(1000).length() === 1000; 
063   * </pre>
064   */
065  public static String tyhja(int n) {
066    StringBuilder fill = new StringBuilder(40+n); // NOPMD sopivan kokoinen
067    while ( fill.length() < n ) fill.append("                                ");
068    fill.delete(n,fill.length());
069    return fill.toString();
070  }
071
072  
073  /**
074   * Palauttaa jonon s muotoiltuna vähintään len-pituiseksi
075   * <pre>
076   * Esim:  fmt("2",3,'0')  => "002"
077   *        fmt("2",-3,' ') => "2  "
078   * </pre>
079   * @param s      muotoiltava jono
080   * @param len    pituus, negatiivisella vasempaan laitaan, pos. oikeaan
081   * @param fillch merkki jolla täytetään
082   * @return       muotoiltu jono
083   * 
084   * @example
085   * <pre name="test">
086   *   fmt("",3,' ')     === "   "  
087   *   fmt("",3,'0')     === "000"  
088   *   fmt("2",3,'0')    === "002"  
089   *   fmt("2",-3,' ')   === "2  "
090   *   fmt("1234",3,'0') === "1234" 
091   * </pre>
092   */
093  public static String fmt(String s,int len,char fillch) {
094    int needs = Math.abs(len) - s.length();
095    if ( needs <= 0 ) return s;
096    String fill = tayta(""+fillch,needs);
097    if ( len < 0 ) return s + fill;
098    return fill + s;
099  }
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}