2009-04-28 15 views
6

Sto scrivendo una funzione utilizzando ICU per analizzare una stringa Unicode che consiste di caratteri numerici kanji e desidera restituire il valore intero della stringa.Come analizzare i caratteri numerici kanji usando ICU?

"五" => 5
"三十 一" => 31
"五千 九百 七 十二" => 5972

sto impostazione della localizzazione su Locale :: getJapan () e usando NumberFormat :: parse() per analizzare la stringa di caratteri. Tuttavia, ogni volta che gli passiamo dei caratteri Kanji, il metodo parse() restituisce U_INVALID_FORMAT_ERROR.

Qualcuno sa se l'ICU supporta le stringhe di caratteri Kanji nel metodo NumberFormat :: parse()? Speravo che dal momento che sto impostando il Locale in giapponese, sarebbe in grado di analizzare i valori numerici Kanji.

Grazie!

#include <iostream> 
#include <unicode/numfmt.h> 

using namespace std; 

int main(int argc, char **argv) { 
    const Locale &jaLocale = Locale::getJapan(); 
    UErrorCode status = U_ZERO_ERROR; 
    NumberFormat *nf = NumberFormat::createInstance(jaLocale, status); 

    UChar number[] = {0x4E94}; // Character for '5' in Japanese '五' 
    UnicodeString numStr(number); 
    Formattable formattable; 
    nf->parse(numStr, formattable, status); 
    if (U_FAILURE(status)) { 
     cout << "error parsing as number: " << u_errorName(status) << endl; 
     return(1); 
    } 
    cout << "long value: " << formattable.getLong() << endl; 
} 
+1

Non so, ma è una domanda interessante, non vedo l'ora di ricevere una risposta. –

+0

chiedete dell'algoritmo su come risolvere il problema? o stai chiedendo di ottenere i codici dei caratteri per interpretarli (vale a dire il problema di codifica)? – hasen

+0

Grazie per tutte le risposte e i commenti! Per chiarire che cosa sto cercando è se l'ICU è in grado di analizzare correttamente le stringhe con valori numerici kanji e restituire il numero come numero intero. Mi limito a usare l'ICU e se l'ICU è in grado di farlo, allora non dovrei scrivere la mia routine per gestirlo. Sto sviluppando un programma per supportare questo per differenti impostazioni locali e preferisco non scrivere routine personalizzate per ogni locale. Idealmente, voglio solo passare le impostazioni internazionali e la stringa di dati in ICU, e farlo restituire il valore intero. –

risposta

1

Sono stato ispirato dalla tua domanda a solve this problem using Python.

Se non si trova una soluzione C++, non dovrebbe essere troppo difficile adattarlo a C++.

3

Ho creato un piccolo modulo perl per farlo un po 'di tempo fa. può convertire arabo < => giapponese e sebbene non l'abbia provato in modo esauriente, penso che sia abbastanza completo. sentiti libero di migliorarlo


package kanjiArabic; 
use strict; 
use warnings; 
our $VERSION = "1.00"; 
use utf8; 

our %big = (
    十 => 10,百 => 100,千 => 1000, 
    ); 
our %bigger = (
    万 => 10000,億 => 100000000, 
    兆 => 1000000000000,京 => 10000000000000000, 
    垓 => 100000000000000000000, 
    ); 
#precompile regexes                           
our $qr = qr/[0-9]/; 
our $bigqr = qr/[十百千]/; 
our $biggerqr = qr/[万億兆京垓]/; 

#this routine does most of the real work. 
sub kanji2arabic{ 
    $_ = shift; 

    tr/〇一二三四五六七八九//; 
    #optionally precompile for performance boost                    
    s/(?<=${qr})(${bigqr})/\*${1}/g; 
    s/(?<=${bigqr})(${bigqr})/\+${1}/g; 
    s/(${bigqr})(?=${qr})/${1}\+/g; 
    s/(${bigqr})(?=${bigqr})/${1}\+/g; 
    s/(${bigqr})/${big{$1}}/g; 

    s/([0-9\+\*]+)/\(${1}\)/g; 

    s/(? "〇", 1 => "一", 2 => "二", 3 => "三", 4 => "四", 
    5 => "五", 6 => "六", 7 => "七", 8 => "八", 9 => "九", 
    ); 
our %places = (
    1 => 10, 
    2 => 100, 
    3 => 1000, 
    4 => 10000, 
    8 => 100000000, 
    12 => 1000000000000, 
    16 => 10000000000000000, 
    20 => 100000000000000000000, 
    ); 
our %abig = (
    10 => "十", 
    100 => "百", 
    1000 => "千", 
    10000 => "万", 
    100000000 => "億", 
    1000000000000 => "兆", 
    10000000000000000 => "京", 
    100000000000000000000 => "垓", 
    ); 
our $MAX = 24; #We only support numbers up to 24 digits!                  


sub arabic2kanji{ 
    my @number = reverse(split(//,$_[0])); 
    my @kanji; 
    for(my $i=$#number;$i>=0;$i--){ 
     if($i==0){push(@kanji,$asmall{$number[$i]});} 
     elsif($i % 4 == 0){ 
      if($number[$i] !~ m/[01]/){ 
       push(@kanji,$asmall{$number[$i]}); 
      } 
      push(@kanji,$abig{$places{$i}}); 
    }else{ 
      my $p = $i % 4; 
      if($number[$i]==0){ 
       next; 
      }elsif($number[$i]==1){ 
       push(@kanji,$abig{$places{$p}}); 
      }else{ 
       push(@kanji,$asmall{$number[$i]}); 
     push(@kanji,$abig{$places{$p}}); 
      } 
    } 
    } 
    return join("",@kanji); 
} 


sub eval_k2a{ 
    #feed me utf-8!                           
    if($_[0] !~ m/^[〇一二三四五六七八九十百千万億兆京垓]+$/){ 
     print "Error: ".$_[0]. 
       " not a Kanji number.\n" if defined($_[1])&&$_[1]==1; 
     return -1; 
    } 
    my $expression = kanji2arabic($_[0]); 
    print $expression."\n" if defined($_[1])&&$_[1]==1; 
    return eval($expression); 
} 



1; 

si sarebbe quindi chiamare da un altro script in questo modo,


#!/usr/bin/perl -w 
use strict; 
use warnings; 
use Encode; 
use kanjiArabic; 

my $kanji = kanjiArabic::arabic2kanji($ARGV[0]); 
print "Kanji: ".encode("utf8",$kanji)."\n"; 
my $arabic = kanjiArabic::eval_k2a($kanji); 
print "Back to arabic...\n"; 
print "Arabic: ".$arabic."\n"; 

e utilizzare questo script in questo modo,


kettle:~/k2a$ ./k2a.pl 5000215 
Kanji: 五百万二百十五 
Back to arabic... 
Arabic: 5000215 

roccia.

5

È possibile utilizzare il modulo RBNF (Rule Based Number Format) ICU rbnf.h (C++) o C, in unum.h con l'opzione UNUM_SPELLOUT, entrambe con l'impostazione internazionale "ja" per il giapponese. Atryom fornisce una correzione al tuo codice per C++: new RuleBasedNumberFormat(URBNF_SPELLOUT,jaLocale, status);

+1

Questa è la risposta corretta: instread: 'NumberFormat :: createInstance (jaLocale, status);' usa 'new RuleBasedNumberFormat (URBNF_SPELLOUT, jaLocale, status);' – Artyom

0

Questo è in realtà abbastanza difficile, soprattutto se inizi a guardare il kanji obsucre per very large numbers.

In perl, esiste un'implementazione molto completa in Lingua::JA::Numbers. È source potrebbe essere di ispirazione se si desidera portarlo in C++.

Problemi correlati