Всё. Разобрался.Olej писал(а): Легко видеть:
- здесь и 32-бит и 64-бит ...
- и ядра Linux от 2.6.32 до 3.17 ...
- и дистрибутивы от Fedora до Ubuntu ...
А результаты совершенно идентичные и верные.
Осталось разобраться в чём может выражаться разница в работе итератора Scanner.
Но для этого пришлось сделать отдельное приложение для проверок, чтоб не таскать за всеми изменениями большую задачу:
Код: Выделить всё
import java.io.*;
import java.util.*;
class sctest {
static String [] tests = {
"AB13 0JW,+57.1,-2.23,+38,+38,",
"AB13 xxx,+57.1,-2.23,+38,+38,-1,-1,-1,-1,-1,1",
"AB13 0JU,57.112005,-b.234087,385921,385921,",
"1.1, 4, 5.6,2,-4,-3.3",
};
static void parse( String line ) {
Scanner scan = new Scanner( line );
scan.useDelimiter( "," );
String code = "";
double x = -111.111, y = 111.111;
if( scan.hasNext() ) code = scan.next();
if( scan.hasNext() )
try { x = new Double( scan.next() ).doubleValue(); }
catch( java.lang.NumberFormatException ex ) { x = -999.999; }
if( scan.hasNext() )
try { y = new Double( scan.next() ).doubleValue(); }
catch( java.lang.NumberFormatException ex ) { y = -999.999; }
System.out.println( line + "\t=> " + code + "\t| " + x + "\t| " + y );
scan.close();
}
static void loop( String line ) {
Scanner scan = new Scanner( line );
scan.useDelimiter( "," );
while( scan.hasNext() ) {
boolean db = scan.hasNextDouble();
String code = scan.next();
System.out.print( "[" + ( db ? '+' : '-' ) + "] " + code + " | " );
}
System.out.println();
scan.close();
}
public static void main( String args[] ) {
Locale lc = Locale.getDefault();
String ls = lc.toString();
if( args.length > 0 ) {
lc = new Locale( "en", "US" );
Locale.setDefault( lc );
}
System.out.println( "locale: " + ls + " => " + lc );
/* Locale [] alc = Locale.getAvailableLocales();
for( Locale l : alc ) // просмотреть все локали
System.out.print( l + " " );
System.out.println(); */
for( String s : tests ) {
parse( s );
loop(s );
}
}
}
- parse - считывающий последовательно символьные токены (лексемы), а потом, если это возможно, 2-ю и 3-ю лексему преобразующий в double;
- loop - просто пытающийся в цикле перебрать все токены, и полагающийся в преобразованиях на то "само" ... что обычно прописывается в любом учебнике по Java:
Код: Выделить всё
if( scan.hasNextDouble() )
x = scan.nextDouble();
Не работает потому, что scan.hasNextDouble() может быть false для совершенно корректных вещественных изображений ... в зависимости от установленной локализации.
Т.е. в дефаултной установке англоязычного Linux всё будет работать ОК, а как только вы его перенесёте на Linux китайский (... или даже русский ) - всё разлетится вдребезги! (отличная перспектива, особенно в свете коммерческих экспортных поставок ).
А теперь смотрим, что оно так и есть:
Код: Выделить всё
[Olej@modules pcs]$ java sctest
locale: ru_RU => ru_RU
AB13 0JW,+57.1,-2.23,+38,+38, => AB13 0JW | 57.1 | -2.23
[-] AB13 0JW | [-] +57.1 | [-] -2.23 | [+] +38 | [+] +38 |
AB13 xxx,+57.1,-2.23,+38,+38,-1,-1,-1,-1,-1,1 => AB13 xxx | 57.1 | -2.23
[-] AB13 xxx | [-] +57.1 | [-] -2.23 | [+] +38 | [+] +38 | [+] -1 | [+] -1 | [+] -1 | [+] -1 | [+] -1 | [+] 1 |
AB13 0JU,57.112005,-b.234087,385921,385921, => AB13 0JU | 57.112005 | -999.999
[-] AB13 0JU | [-] 57.112005 | [-] -b.234087 | [+] 385921 | [+] 385921 |
1.1, 4, 5.6,2,-4,-3.3 => 1.1 | 4.0 | 5.6
[-] 1.1 | [-] 4 | [-] 5.6 | [+] 2 | [+] -4 | [-] -3.3 |
- корректные символьные изображения вещественных чисел признаются или нет таковыми ([+] или [-]) в совершенно хаотическом порядке;
- ещё одна особенность, если в последовательности ...,123,... стоит пробел до или после ',' - это hasNextDouble() не признаёт [-]
А теперь меняем локаль:
Код: Выделить всё
[Olej@modules pcs]$ java sctest !
locale: ru_RU => en_US
AB13 0JW,+57.1,-2.23,+38,+38, => AB13 0JW | 57.1 | -2.23
[-] AB13 0JW | [+] +57.1 | [+] -2.23 | [+] +38 | [+] +38 |
AB13 xxx,+57.1,-2.23,+38,+38,-1,-1,-1,-1,-1,1 => AB13 xxx | 57.1 | -2.23
[-] AB13 xxx | [+] +57.1 | [+] -2.23 | [+] +38 | [+] +38 | [+] -1 | [+] -1 | [+] -1 | [+] -1 | [+] -1 | [+] 1 |
AB13 0JU,57.112005,-b.234087,385921,385921, => AB13 0JU | 57.112005 | -999.999
[-] AB13 0JU | [+] 57.112005 | [-] -b.234087 | [+] 385921 | [+] 385921 |
1.1, 4, 5.6,2,-4,-3.3 => 1.1 | 4.0 | 5.6
[+] 1.1 | [-] 4 | [-] 5.6 | [+] 2 | [+] -4 | [+] -3.3 |
Это история довольно типична для форматирования и ввода в других языках, в том же C со scan() ... может только не так явно выражена.
Тем не менее, мне куда больше нравится "ручной" способ:
- сосчитать отдельный токен в виде как String ...
- а потом самому его преобразовать в double ... и решить что с ним делать (там в коде показана обработка ошибок преобразования)
- хотя бы и из-за проблемы с ведущими и завершающими пробелами.