giovedì 18 ottobre 2007

Esprimere un numero in lettere

Oggi ho dovuto scrivere un modulo per la compilazione e la stampa automatica di assegni, nulla di che, uno di quei compiti poco stimolanti che si svolgono col cervello in standby e lo sguardo perso nel nulla. E poi odio avere a che fare con le stampanti, forse perchè tutte le stampanti che ho avuto mi hanno puntualmente abbandonato il giorno prima della consegna di qualche tesina. Ad essere sincero però, devo ammettere che cinque minuti di piacere me li sono ritagliati, ed è stato quando ho dovuto scrivere una funzione che mi permettesse di esprimere l'importo dell'assegno in lettere. Un momento di piacere che definirei dal sapore nostalgico! Non so perchè, ma mentre scrivevo la funzione mi sono venuti in mente i primi anni dell'università, quando studiavo Pascal e implementavo il BubbleSort piuttosto che la Torre di Hanoi o robe del genere. A volte il cervello fa collegamenti strani, forse dovrei smettere di bere caffè..


Public Class bcc_NumeriInLettere

Private mTabella1() As String = {"uno", _
"due", _
"tre", _
"quattro", _
"cinque", _
"sei", _
"sette", _
"otto", _
"nove", _
"dieci", _
"undici", _
"dodici", _
"tredici", _
"quattordici", _
"quindici", _
"sedici", _
"diciassette", _
"diciotto", _
"diciannove"}

Private mTabella2() As String = {"venti", _
"trenta", _
"quaranta", _
"cinquanta", _
"sessanta", _
"settanta", _
"ottanta", _
"novanta"}


Private Function m_FiniscePerVocale(ByVal tmp As String) As Boolean

Return
tmp.EndsWith("a") Or _
tmp.EndsWith("e") Or _
tmp.EndsWith("i") Or _
tmp.EndsWith("o") Or _
tmp.EndsWith("u")

End Function

Private Function
m_IniziaPerVocale(ByVal tmp As String) As Boolean

Return
tmp.StartsWith("a") Or _
tmp.StartsWith("e") Or _
tmp.StartsWith("i") Or _
tmp.StartsWith("o") Or _
tmp.StartsWith("u")

End Function

Private Function
m_da1a999(ByVal strval As String) As String

Dim
l As Int16 = strval.Length
Dim i, j, k As Int16

Dim tmp, dec, uni As String
Dim
c As String

tmp = ""
j = 0

For i = l To 1 Step -1

c = strval.Chars(j)
j = j + 1

If c <> "0" Then

Select Case i

Case 3

If c = "1" Then

tmp &= "cento"

Else

k = CInt(c) - 1
tmp &= mTabella1(k) & "cento"

End If

Case 2

' controlla se è un numero conosciuto
k = CInt(c & strval.Chars(j))

If k < color="blue">Then


tmp &= mTabella1(k - 1)

ElseIf (k Mod 10) = 0 Then

' venti, trenta, quaranta...
tmp &= mTabella2((k / 10) - 2)

Else

' ventuno, ventidue, ventitre..
k -= k Mod 10
k = (k / 10) - 2
dec = mTabella2(k)

k = CInt(strval.Chars(j).ToString) - 1
uni = mTabella1(k)

If m_FiniscePerVocale(dec) And m_IniziaPerVocale(uni) Then

' per esempio ventuno, ventotto
' tronchiamo venti a vent e concateniamo uno, otto..

dec = dec.SubString(0, dec.Length - 1)

End If

tmp &= dec & uni

End If

Return tmp

Case 1

' basta tradurre l'unita
k = CInt(c) - 1
tmp &= mTabella1(k)

End Select

End If

Next

Return
tmp

End Function

Public Function
NumeriInLettere(ByVal strval As String) As String

Dim
part1 As String
Dim
part2 As String
Dim
tmp As String
Dim
rv As String
Dim
len As Int16
Dim i As Int16

part1 = strval
part2 = ""
tmp = ""
rv = ""

i = strval.IndexOf(",")
If i <> -1 Then

part1 = strval.SubString(0, i)
part2 = strval.SubString(i + 1)

End If

While True


len = part1.Length
If len > 12 Then

' ci fermiamo solo ai miliardi..
Return
"numero troppo grande"

ElseIf (12 >= len) And (len > 9) Then

' miliardi
i = len - 9
tmp = part1.SubString(0, i)
part1 = part1.SubString(i)

tmp = m_da1a999(tmp)
rv = IIf(tmp = "uno", "unmiliardo", tmp & "miliardi")

ElseIf (9 >= len) And (len > 6) Then

' milioni
i = len - 6
tmp = part1.SubString(0, i)
part1 = part1.SubString(i)

tmp = m_da1a999(tmp)
rv &= IIf(tmp = "uno", "unmilione", tmp & "milioni")

ElseIf (6 >= len) And (len > 3) Then

i = len - 3
tmp = part1.SubString(0, i)
part1 = part1.SubString(i)

tmp = m_da1a999(tmp)
rv &= IIf(tmp = "uno", "mille", tmp & "mila")

Else

tmp = m_da1a999(part1)
rv &= tmp & "/" & IIf(part2 <> "", part2, "00")
Return rv

End If

End While

End Function

End Class


1 commento:

Anonimo ha detto...

imparato molto