Looping for user input in a textbox

  • Thread starter Thread starter Robert
  • Start date Start date
Tom

That's very kind of you. I'd like the whole lot at once so I can pick
over it.

Pushing my luck a bit (no, too much really) at your generosity, could
you post, separately, code that does NOT tackle the problem of letter
precedence? That is to say; combinations such as IV are NOT permitted
(this would be input as IIII).

I'd like to examine, if I could, such code too in order to see whether
I could adapt it to obey the principle of letter precedence.

Many domestic routines got in the way yesterday of my trying to code
the right solution to the problem of rejecting non-Roman characters
but a couple of hours of thinking (Why so long? A lot of mulling over
the manuals and the postings between keystrokes) produced this.

Private Sub TextBox1_textChanged(ByVal sender As System.Object,
ByVal e As System.EventArgs) Handles TextBox1.TextChanged

Dim b As Boolean = IsRomanNumeral(TextBox1.Text)
TextBox2.Text = b.ToString

End Sub

Private Function IsRomanNumeral(ByVal numeral As String) As
Boolean
Dim i As Integer

numeral = UCase(numeral)

For i = 0 To (numeral.Length - 1)
Select Case numeral.Substring(i, 1)
Case "M", "D", "C", "L", "X", "V", "I"
IsRomanNumeral = True
Case Else
IsRomanNumeral = False : TextBox1.Text = numeral

End Select
Next
End Function

Although it "works" returning TRUE or FALSE on cue I know that it's
defective and do not doubt your belief that I'm charging up the wrong
path anyway. However, I was pleased to have produced it nonetheless.
Even more thanks to you (and Fergus) for helping me with this.

In the glorious tradition of "a bad workman always blames his tools" I
can't let one more day go by without passing comment on computer
manuals in general. I've got 4 about visual basic, no less. All
written by enthusiasts, what computer manuals share in common is the
cheerfulness of the first chapter as you ponder their "Hello World!"
program -

"Congratulations! You've written your first program in Mugwump 6++",

giving way with all too cruel speed to something completely arcane.
"Polymorphism" makes its appearance in chapter 3 (!) in one book I've
got. On second thoughts, it could be, of course, that my learning
curve is far too flat these days...

Thanks to all who've helped so far.

Bob
 
Robert said:
I'd like the whole lot at once so I can pick over it.

Sounds fine. Remember to not just pick over the code. That's certainly
part of it (a necessary part) but the algorithm is the key. The problem
could be rewritten in C# of course but also just as easily in Java, Clipper
and what have you.

Originally it was my plan to parse the input string to arrive at the answer
but it would add a lot of extra code and the answer wouldn't be any more
right. :-) The syntax rules for Roman numerals are fairly odd. As you know
they consist of the characters "IVXLCDM" (and with lines over them to create
larger numbers.) Generally speaking the largest number you can write is
MMMCMXCIX (3999) and there is no zero and of course no negative numbers.
There also can't be more than 3 "I", "X", "C" or "M" characters in a row and
no more than one "V", "L" or "D" in a row.
I'd like to examine, if I could, such code too in order to see whether
I could adapt it to obey the principle of letter precedence.

I took Cor's routine which converted the Roman numerals but which did
minimal error checking, turned it into a function and tidied it up a bit and
combined it with the routine that "Keyur Shah" posted. That one converted
from Arabic to Roman (which wasn't what you wanted) but... it turns out to
the perfect way to detect bogus Roman numeral strings. If converting the
Arabic value back to Roman doesn't yield the original Roman string then the
original was bogus. I modified Keyur's code a bit to standardize it and
make it a bit more readable.

You will see that all it takes to check what you've called "letter
precedence" was a quick conversion using ToArabic() at the end of ToRoman().
Private Function IsRomanNumeral(ByVal numeral As String) As Boolean
Although it "works" returning TRUE or FALSE on cue...

But it still returns "True" eventually if you input "123XYX-M"

I don't convert on every keystroke... you can add that feature if you like.
In order to test the code as written create a form and drop two textboxes
along with one button on it. Name the boxes TextIn and TextOut and the
button Button1.

Cut and paste the code into form class (be careful to get it above the "End
Class" line and don't overwrite anything important. Then run it, key a
Roman numeral into the TextIn box and press the command button.

Note that nothing in the functions is relying on the roman numeral being in
a text box and the routine doesn't place the answer into another text box.
This is all handled by the button click event handler. That way the code
can get the values from any source. It returns the answer to whatever
routine asked for the conversion.


Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
txtOut.Text = ToArabic(txtIn.Text).ToString
End Sub

Function ToArabic(ByVal sValue As String) As Integer

' based upon a posting by:
' "Cor" <[email protected]>

' if there is a bug I introduced it in the tidying/adjusting phase
' "tom leylan" <[email protected]>

' the roman numeral characters
Const ROMANS As String = "IVXLCDM"

' the return value
ToArabic = 0

' exit if a blank string parameter
If (sValue = "") Then
Exit Function
End If

' upper case just to be sure
sValue = sValue.ToUpper

' exit if any character is not a roman numeral character
Dim i As Integer
For i = 0 To sValue.Length - 1
If ROMANS.IndexOf(sValue.Substring(i, 1)) = -1 Then
Exit Function
End If
Next

' as Cor pointed out
' if you convert the roman characters to their individual values
Dim sTmp As New System.Text.StringBuilder(sValue)

sTmp = sTmp.Replace("I", "1,")
sTmp = sTmp.Replace("V", "5,")
sTmp = sTmp.Replace("X", "10,")
sTmp = sTmp.Replace("L", "50,")
sTmp = sTmp.Replace("C", "100,")
sTmp = sTmp.Replace("D", "500,")
sTmp = sTmp.Replace("M", "1000,")

' and create an array of the values
' notice the final comma is removed with Substring
Dim aRoman As String() = Split(sTmp.ToString.Substring(0,
sTmp.Length - 1), ",")

' you can check to see if this value is higher or lower than
' the next one, if it is lower then you subtract this value
For i = 0 To aRoman.Length - 2
If CInt(aRoman(i)) < CInt(aRoman(i + 1)) Then
ToArabic -= CInt(aRoman(i))
Else
ToArabic += CInt(aRoman(i))
End If
Next

' the last element doesn't have a "next" element so you just add it
ToArabic += CInt(aRoman(aRoman.Length - 1))

' and this does a final check to see if original Roman numeral was
valid
' by converting it back to a Roman numeral and seeing if it matches
the original
If (ToRoman(ToArabic) <> sValue) Then
ToArabic = 0
End If

End Function

Function ToRoman(ByVal iValue As Integer) As String

' based upon a posting by:
' "keyur shah" <[email protected]>

' if there is a bug I introduced it in the tidying/adjusting phase
' "tom leylan" <[email protected]>

' note that I am relying on the fact that mid() does not return an
error
' when the start length is past the end of the string
' which happens when iBase = 7

' the roman numeral characters
Const ROMANS As String = "IVXLCDM"

' the return value
ToRoman = ""

' exit if value is out of range
If (iValue <= 0 Or iValue > 3999) Then
Exit Function
End If

' some variables to represent the characters
' which change at each loop due to the "base" position incrementing
Dim rc1, rc4, rc5, rc9 As String
Dim iBase As Integer = 1

Do While (iValue > 0)

' depending upon iBase these variables will be
' I, IV, V and IX or
' X, XL, L and XC or
' C, CD, D and MC or
' M, M, "" and ""
rc1 = Mid(ROMANS, iBase, 1)
rc4 = Mid(ROMANS, iBase, 2)
rc5 = Mid(ROMANS, iBase + 1, 1)
rc9 = Mid(ROMANS, iBase + 2, 1)

' build the Roman numeral from right to left
Select Case (iValue Mod 10)
Case 1
ToRoman = rc1 & ToRoman
Case 2
ToRoman = rc1 & rc1 & ToRoman
Case 3
ToRoman = rc1 & rc1 & rc1 & ToRoman
Case 4
ToRoman = rc4 & ToRoman
Case 5
ToRoman = rc5 & ToRoman
Case 6
ToRoman = rc5 & rc1 & ToRoman
Case 7
ToRoman = rc5 & rc1 & rc1 & ToRoman
Case 8
ToRoman = rc5 & rc1 & rc1 & rc1 & ToRoman
Case 9
ToRoman = rc1 & rc9 & ToRoman
End Select

' subtract what we have so far and loop until finished
iValue \= 10
iBase += 2

Loop

End Function
 
Hi Tom,

And it works beautifully. I looked over the code to see what
I could see. There's nothing even worth nit-picking over. ;-))

I have little patience with unindented code with no spaces - too
unreadable, so unfortunately I didn't get to see that Cor's routine
was a solution. But my hat off to Cor for that when your revamp
made it clear. I think the use of Keyur's method is an excellent idea.
(Why dig a new ditch?)

So my hat off to you, too, for putting it together.

Regards,
Fergus

--
(Please ignore this - there's a feud going on)
==================================================
Quote of the day
Herfried:
I don't need/want human interaction.
==================================================
 
Hi Robert,

Tom figured it out for you. but some little things from this post I did not
see in Toms answer. (If I missed it, sorry Tom)
Pushing my luck a bit (no, too much really) at your generosity, could
you post, separately, code that does NOT tackle the problem of letter
precedence? That is to say; combinations such as IV are NOT permitted
(this would be input as IIII).

IIII is not permitted. It has to be IV, I don't know where you live, but in
Europe is on almost every old church tower the date written in Roman figurs.
For i = 0 To (numeral.Length - 1)
Select Case numeral.Substring(i, 1)
Case "M", "D", "C", "L", "X", "V", "I"
IsRomanNumeral = True
Case Else
IsRomanNumeral = False : TextBox1.Text = numeral
End Select

This is a very nice routine, I use that also but strange enough not in my
example for you. I find this better than my example, because it shows more
clear what you are doing.

Cor
 
Hi Fergus,

A little bit of thread.

That code with no spaces, I made that HKW project really, one of the things
in it is that I allign all code to the left. When you past it then in your
IDE it will be in the same form you like. And the code works as a train (a
French train not a British one)

Just paste it in, one button and one textbox.

And than adding the check from Tom for the false placed figurs.

:-)

Cor
 
Hi Cor

|| That code with no spaces, I made that HKW project really

Please, Cor, it's offensive to use swear words.

|| one of the things in it is that I allign all code to the left.

You lose the indentation deliberately? It's a shame - it reduces the
readability considerably for me. I would guess also for the VB newbies.

|| When you paste it then in your IDE it will be in the same form you like.

I'm not sure I understand how. Much re-tabbing is required when I paste
it in.

|| And the code works as a train (a French train not a British one)

LOL. Definitely not a British one! ;-)

Regards,
Fergus

|| When you paste it then in your IDE it will be in the same form you like.

When you paste it in your IDE then it will (can?) be in whatever form you like.
 
Hi Fergus,
I pasted this

Private Sub Button1_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles Button1.Click
Dim TestString As String = "IVXLCDM"
Dim i As Integer
TextBox1.Text = TextBox1.Text.ToUpper
For i = 0 To TextBox1.Text.Length - 1
If TestString.IndexOf(TextBox1.Text.Substring(i, 1)) = -1 Then
TextBox1.Text = TextBox1.Text & " Contains a not Roman value"
Exit Sub
End If
Next
Dim roman As New System.Text.StringBuilder(TextBox1.Text.ToUpper)
roman = roman.Replace("I", "1,")
roman = roman.Replace("V", "5,")
roman = roman.Replace("X", "10,")
roman = roman.Replace("L", "50,")
roman = roman.Replace("C", "100,")
roman = roman.Replace("D", "500,")
roman = roman.Replace("M", "1000,")
Dim romanstr As String = roman.ToString.Substring(0, roman.Length - 1)
Dim romanarr As String() = Split(romanstr, ",")
For i = 0 To romanarr.Length - 2
If CInt(romanarr(i)) < CInt(romanarr(i + 1)) Then
romanarr(i) = "-" & romanarr(i)
End If
Next
Dim result As Integer
For i = 0 To romanarr.Length - 1
result += CInt(romanarr(i))
Next
TextBox1.Text = TextBox1.Text & "=" & result.ToString
End Sub

Into my IDE and then it did look like this

Private Sub Button1_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles Button1.Click
Dim TestString As String = "IVXLCDM"
Dim i As Integer
TextBox1.Text = TextBox1.Text.ToUpper
For i = 0 To TextBox1.Text.Length - 1
If TestString.IndexOf(TextBox1.Text.Substring(i, 1)) = -1 Then
TextBox1.Text = TextBox1.Text & " Contains a not Roman
value"
Exit Sub
End If
Next
Dim roman As New System.Text.StringBuilder(TextBox1.Text.ToUpper)
roman = roman.Replace("I", "1,")
roman = roman.Replace("V", "5,")
roman = roman.Replace("X", "10,")
roman = roman.Replace("L", "50,")
roman = roman.Replace("C", "100,")
roman = roman.Replace("D", "500,")
roman = roman.Replace("M", "1000,")
Dim romanstr As String = roman.ToString.Substring(0, roman.Length -
1)
Dim romanarr As String() = Split(romanstr, ",")
For i = 0 To romanarr.Length - 2
If CInt(romanarr(i)) < CInt(romanarr(i + 1)) Then
romanarr(i) = "-" & romanarr(i)
End If
Next
Dim result As Integer
For i = 0 To romanarr.Length - 1
result += CInt(romanarr(i))
Next
TextBox1.Text = TextBox1.Text & "=" & result.ToString
End Sub

Do you think this is nicer, I hate always when you have those strange
carriage returns?

Cor
 
Howdy Cor,

How did your IDE add all the indentation back in?? When I paste that
same code it looks exactly as it does in the posted message - flat left margin.

But my main point is that it's difficult to read within the message itself.
I always copy code from my project into NotePad, then replace the tabs
with spaces and then copy it into the message. Indentation intact and no
extra lines.

Regards,
Fergus
 
Hi Fergus,

I am using 2003 but I think it is in 2002 also.

It is an option in the text Basic Tabs I thought "indenting smart and insert
spaces"

I think we know it when Herfried gives an exact answer to me :-))

Cor
 
Hi Cor,

You mean the 'messify' option. I have it switched off because it is as dodgy
as that swear word you keep using. For some reason, with it on, tab becomes
back tab at times. It's most disconcerting and I find it quicker and easier to do
my own formatting as I'm forever undoing what it does and reformatting. It's a
shame these formatter things can't be customised. I've never found a good one.

Regards,
Fergus
 
* "Fergus Cooney said:
You mean the 'messify' option. I have it switched off because it is as dodgy
as that swear word you keep using. For some reason, with it on, tab becomes
back tab at times. It's most disconcerting and I find it quicker and easier to do
my own formatting as I'm forever undoing what it does and reformatting. It's a
shame these formatter things can't be customised. I've never found a good one.

Mhm...

I am working with "Indentation" = "Block" and "Insert Spaces" set. This
allows a lot fo flexibility and will do some simple formatting
automatically. But an option for adding the loop variables at the end
of a 'For...Next' loop would be nice.
 
Tom

Thanks for taking the time and trouble to write and post this. It's
kind of you.

The coding is more complex than I had expected and will take me some
time to "read". I can see the solution works well though I do not
quite follow how some of it works yet.

Thanks also to all the others not least Cor, Fergus and Keyur Shah.

Regards

Bob
 
<two functions related to Roman Numerals snipped...>

Hate to do it but this one is better. Now that the basic functionality is
in place it is time to think about "packaging" and generally speaking a pair
of loose functions isn't the best way. So we would like a Class instead.
I've packaged it into a class and made the two functions "Shared" which
means it is no harder to use the Class since it does not require an object
be instantiated in order to use it. I also added another function IsRoman()
which like the other two do not require an actual object.

What you might consider doing Robert... is taking the RomanNumeral Class and
placing it into a .DLL project, call it "RobertsLib" or something and use
that as a place to store things you want to keep. You can develop things
outside of it but if it might be useful add it to your .DLL. Then with any
project that you write in the future you simply reference RobertsLib and
those classes become available to you.

If you do it this way the only code you would actually see in your UI form
would be the single "Click" event for the button. Everything else would be
safely tucked away from prying eyes (and fingers) and you wouldn't be
cutting and pasting code all over the place. Here then is the Class
version. I didn't want to leave it unfinished because these messages get
archived by Google. The two function version works in non-OOP languages but
the OOP developers may as well take advantage of what is available.

In your form you can test it by adding another textbox named txtValid and
modifying the button click event

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
txtOut.Text = RomanNumeral.ToArabic(txtIn.Text).ToString
txtValid.Text = RomanNumeral.IsRoman(txtIn.Text).ToString
End Sub


Note that this is a complete separate class right? We've moved the constant
declaration as a result. You can paste it into your UI project but it has
to be outside the Form Class code. It is a completely standalone Class now.

Public Class RomanNumeral

' the roman numeral characters
Const ROMANS As String = "IVXLCDM"

Shared Function IsRoman(ByVal sValue As String) As Boolean
IsRoman = (ToArabic(sValue) > 0)
End Function

Shared Function ToArabic(ByVal sValue As String) As Integer

' based upon a posting by:
' "Cor" <[email protected]>

' if there is a bug I introduced it in the tidying/adjusting phase
' "tom leylan" <[email protected]>

' the return value
ToArabic = 0

' exit if a blank string parameter
If (sValue = "") Then
Exit Function
End If

' upper case just to be sure
sValue = sValue.ToUpper

' exit if any character is not a roman numeral character
Dim i As Integer
For i = 0 To sValue.Length - 1
If ROMANS.IndexOf(sValue.Substring(i, 1)) = -1 Then
Exit Function
End If
Next

' as Cor pointed out
' if you convert the roman characters to their individual values
Dim sTmp As New System.Text.StringBuilder(sValue)

sTmp = sTmp.Replace("I", "1,")
sTmp = sTmp.Replace("V", "5,")
sTmp = sTmp.Replace("X", "10,")
sTmp = sTmp.Replace("L", "50,")
sTmp = sTmp.Replace("C", "100,")
sTmp = sTmp.Replace("D", "500,")
sTmp = sTmp.Replace("M", "1000,")

' and create an array of the values
' notice the final comma is removed with Substring
Dim aRoman As String() = Split(sTmp.ToString.Substring(0,
sTmp.Length - 1), ",")

' you can check to see if this value is higher or lower than
' the next one, if it is lower then you subtract this value
For i = 0 To aRoman.Length - 2
If CInt(aRoman(i)) < CInt(aRoman(i + 1)) Then
ToArabic -= CInt(aRoman(i))
Else
ToArabic += CInt(aRoman(i))
End If
Next

' the last element doesn't have a "next" element so you just add it
ToArabic += CInt(aRoman(aRoman.Length - 1))

' and this does a final check to see if original Roman numeral was
valid
' by converting it back to a Roman numeral and seeing if it matches
the original
If (ToRoman(ToArabic) <> sValue) Then
ToArabic = 0
End If

End Function

Shared Function ToRoman(ByVal iValue As Integer) As String

' based upon a posting by:
' "keyur shah" <[email protected]>

' if there is a bug I introduced it in the tidying/adjusting phase
' "tom leylan" <[email protected]>

' note that I am relying on the fact that mid() does not return an
error
' when the start length is past the end of the string
' which happens when iBase = 7

' the return value
ToRoman = ""

' exit if value is out of range
If (iValue <= 0 Or iValue > 3999) Then
Exit Function
End If

' some variables to represent the characters
' which change at each loop due to the "base" position incrementing
Dim rc1, rc4, rc5, rc9 As String
Dim iBase As Integer = 1

Do While (iValue > 0)

' depending upon iBase these variables will be
' I, IV, V and IX or
' X, XL, L and XC or
' C, CD, D and MC or
' M, M, "" and ""
rc1 = Mid(ROMANS, iBase, 1)
rc4 = Mid(ROMANS, iBase, 2)
rc5 = Mid(ROMANS, iBase + 1, 1)
rc9 = Mid(ROMANS, iBase + 2, 1)

' build the Roman numeral from right to left
Select Case (iValue Mod 10)
Case 1
ToRoman = rc1 & ToRoman
Case 2
ToRoman = rc1 & rc1 & ToRoman
Case 3
ToRoman = rc1 & rc1 & rc1 & ToRoman
Case 4
ToRoman = rc4 & ToRoman
Case 5
ToRoman = rc5 & ToRoman
Case 6
ToRoman = rc5 & rc1 & ToRoman
Case 7
ToRoman = rc5 & rc1 & rc1 & ToRoman
Case 8
ToRoman = rc5 & rc1 & rc1 & rc1 & ToRoman
Case 9
ToRoman = rc1 & rc9 & ToRoman
End Select

' subtract what we have so far and loop until finished
iValue \= 10
iBase += 2

Loop

End Function

End Class
 
Fergus Cooney said:
And it works beautifully. I looked over the code to see what
I could see. There's nothing even worth nit-picking over. ;-))

Thanks. I added a range check in ToRoman which I don't think the version I
sent you had.. .and comments. Also I just think it works better as a class
so with my last posting this project should be done.

Tom
 
Hi Cor,
IIII is not permitted. It has to be IV, I don't know where you live, but in
Europe is on almost every old church tower the date written in Roman
figurs.

I think Robert was considering adding more validation tests to trap this
kind of thing... it turns out that there is no simple way (that I could
find) except to see if the computer would form the same string. It run's
faster (with much less code) an you get a Roman numeral generator as a side
benefit.
This is a very nice routine, I use that also but strange enough not in my
example for you. I find this better than my example, because it shows more
clear what you are doing.

I wrote the same loop as you did in my code Cor. It is a standard loop for
testing any string against any set of characters and for that reason I
believe it is the superior solution. The one that Robert has (I mentioned
the comma-separated values) was meant as a replacement for his multi-case
version. Both his original and this replacement suffer a small problem...
they don't work :-) So long as the last character in the test string is
Roman it will return True.

Tom
 
Hi Tom,

I think it will work like this (not tested)TextBox1.Text = "Error:" & numeral & " in
pos:" & i+1.tostring
Exit Sub 'or whatever
I saw this and all those long other ones which where made before this, I did
want to give a very positive contribution.

And now the one that I made first is as good readable as this, but
afterwards for the example to Robert I think that I had better could use
this one because he was on that route.

Cor
 
Tom et al

At the risk of exasperating you all I'm afraid I simply do not follow
some of the code you posted. If you will remember my aim is to
understand what is going on in Visual Basic and learn it a bit rather
than arrive at a solution to this Roman numeral problem.

I'm still attempting to write my own solution rather than paste in
what I don't understand and what has been written by someone else. My
own coding has gone through a dozen unsuccessful revisions today as I
tried to incorporate the ideas I've seen in the thread.

The hardest bit (and that's up against some pretty stiff competition)
of what you coded for me, to understand is:

Dim rc1, rc4, rc5, rc9 As String
Dim iBase As Integer = 1

Do While (iValue > 0)

' depending upon iBase these variables will be
' I, IV, V and IX or
' X, XL, L and XC or
' C, CD, D and MC or
' M, M, "" and ""
rc1 = Mid(ROMANS, iBase, 1)
rc4 = Mid(ROMANS, iBase, 2)
rc5 = Mid(ROMANS, iBase + 1, 1)
rc9 = Mid(ROMANS, iBase + 2, 1)

' build the Roman numeral from right to left
Select Case (iValue Mod 10)
Case 1
ToRoman = rc1 & ToRoman
Case 2
ToRoman = rc1 & rc1 & ToRoman
Case 3
ToRoman = rc1 & rc1 & rc1 & ToRoman
Case 4
ToRoman = rc4 & ToRoman
Case 5
ToRoman = rc5 & ToRoman
Case 6
ToRoman = rc5 & rc1 & ToRoman
Case 7
ToRoman = rc5 & rc1 & rc1 & ToRoman
Case 8
ToRoman = rc5 & rc1 & rc1 & rc1 & ToRoman
Case 9
ToRoman = rc1 & rc9 & ToRoman
End Select

What is the purpose of rc1, rc2 etc.? Sorry, but what on earth is
going on here? BTW, i am stl gtng usd to abrvatig evythg in prgmg,
anyway.

P.S. If it can't be put any simpler then please do not trouble
yourself. I quite understand. Your assistance has been valuable and
much appreciated whatever.

Bob
 
Robert said:
Dim rc1, rc4, rc5, rc9 As String
rc1 = Mid(ROMANS, iBase, 1)
rc4 = Mid(ROMANS, iBase, 2)
rc5 = Mid(ROMANS, iBase + 1, 1)
rc9 = Mid(ROMANS, iBase + 2, 1)
Case 3
ToRoman = rc1 & rc1 & rc1 & ToRoman
What is the purpose of rc1, rc2 etc.? Sorry, but what on earth is
going on here? BTW, i am stl gtng usd to abrvatig evythg in prgmg,
anyway.

I implemented "rc" meaning "roman character" and chose 1, 4, 5 and 9 because
those will be the base numbers. They shift as it runs through the loop but
it is (sort of) the 1s, 4s, etc. position.

The original posting didn't include them but chose instead to repeat the
Mid() function repeatedly in the case statements. Notice where I
concatenate rc1 three times in order to get "III" or "XXX" or "CCC" ? In
the original posting it called the Mid() function three times on that line.
It can't change between calls so I saved the results once and used it
instead.

It turns out that there is a pattern on the conversion to Roman (from
Arabic) that the case statement demonstrates. The same cannot be said for
turning Roman into Arabic.

Look at the way case 3 looks... if you get a 3 back then create a string
with rc1 & rc1 & rc1 which would be "III" if it was working on the ones
column at that point. It always adds whatever was already converted (that's
the & ToRoman part) because the exact same thing has to happen when it gets
to the 10's except rc1 will be an "X" so if you get 3 as an answer it will
require "XXX" in that spot.

I made a point of noting BTW that in the last loop iBase + 1, and IBase + 2
will actually be beyond the end of the string. Ordinarily I would never do
this but it turns out that VB doesn't bomb and the function returns an empty
string which is fine. Even rc4 is a duplicate of the value "M" (in rc1)
again just a side effect but not a fatal one so rather that try to add tests
to prevent it I decided to ignore it.

Some languages (C comes to mind) would return undefined "junk" if such a
construct were used but VB is forgiving. I took advantage of it and saved
some lines of code.
 
Back
Top