Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Looping for user input in a textbox

10 views
Skip to first unread message

Robert

unread,
Nov 3, 2003, 2:17:27โ€ฏAM11/3/03
to
Thanks to anyone who has time to reply with some good advice or
indications. I posted this message to a visual basic group and was
kindly redirected here by an MVP, explaining that visual basic.net is
quite different to visual basic previous versions. Before anyone feels
tempted to flame or to scorn, I have RTFM, in fact various FM's and
nothing seems to help here. I have little experience of visual
basic.net at all, but I've been experimenting with this problem for
some time without making much headway.

A simple Roman numeral calculator.
>
>More help appreciated if anyone has a few moments. Thanks.
>
>Below is the code for textbox1 (without all the processing in each
>case statement, of course, to make things clearer and omitting all
the
>declarations to keep it shorter).
>
>At the moment ๅƒง' or another Roman letter typed in textbox1 produces
>1000 in textbox2 or the corresponding value of that Roman letter.
>
>ๅƒงm' typed in textbox1 produces 0 in textbox2 but with a ็คŽackspace'
>to ๅƒง' you get 2000 in textbox2. The logic of this is clear,
>naturally.
>
>However I would like ๅƒงm' in textbox1 to produce 2000, ๅƒงmc' to
>produce 2100.
>
>I thought the answer might lie in something like textbox1_keypress
>with which I have been experimenting but cannot get this to work at
>all.
>
>Private Sub TextBox1_TextChanged(ByVal sender As System.Object, ByVal
>e As System.EventArgs) Handles TextBox1.TextChanged
>
> ROMAN = TextBox1.Text
> ROMAN = UCase(ROMAN)
>
> Select Case ROMAN
>
> Case Is = "M"
> NEWNUMBER = 1000
>
> Case Is = "D"
> NEWNUMBER = 500
>
> Case Is = "C"
> NEWNUMBER = 100
>
> Case Is = "L"
> NEWNUMBER = 50
>
> Case Is = "X"
> NEWNUMBER = 10
>
> Case Is = "V"
> NEWNUMBER = 5
>
> Case Is = "I"
> NEWNUMBER = 1
>
> Case Else
> NEWNUMBER = 0
>
> End Select
>
> SUM = SUM + NEWNUMBER
> TextBox2.Text = SUM
>
>
> End Sub
>
>Thanks for any help or indications

Bob

Sergey Poberezovskiy

unread,
Nov 3, 2003, 3:26:52โ€ฏAM11/3/03
to
Robert,

I could not quite understand why you compare the
whole .Text property to one character - should not you
analyze all the characters in the TextBox1?
You could either iterate through TextBox1.Text.Chars array
or use SubString method to get to individual character as
String.

Hope this helps...

>>At the moment 'm' or another Roman letter typed in

textbox1 produces
>>1000 in textbox2 or the corresponding value of that
Roman letter.
>>

>>'mm' typed in textbox1 produces 0 in textbox2 but with
a 'backspace'
>>to 'm' you get 2000 in textbox2. The logic of this is
clear,
>>naturally.
>>
>>However I would like 'mm' in textbox1 to produce
2000, 'mmc' to

>.
>

Cor

unread,
Nov 3, 2003, 3:30:06โ€ฏAM11/3/03
to
Hi Robert,
This kind of things are always funny to do

I did make this, I don't know if I did make the sequence well.
I thought it was that a character before a higher character was a minus
character and that there only could be 1 minus character before a plus
character, but from that I am not sure of. So I did not test that and also
that is the only thing which is used.

But you have a lot of examples now.

It needs 1 button and 1 textbox on a form
\\\
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
///

I hope this helps a little bit?

Cor


Fergus Cooney

unread,
Nov 3, 2003, 3:50:34โ€ฏAM11/3/03
to
Hi Robert,

I'm a bit puzzled why the MVP would send you scooting - this isn't a
language problem - it's a programming problem.

I'm also puzzled where 'flame'and 'scorn' come into it. Nor do I know what
RTFM or FM mean!

But who cares about that. ;-)

My advice is simple. Take the calculation out of the UI and put it
somewhere like a routine in Module RomanNumerals. A Roman numeral is
calculated as a unit - you can't do it piecemeal because the order of the
digits is important - "IX" versus "XI", for instance.

Thus, you would send the <entire> string to the converter (calculator is
too strong a word - keep it in reserve until you start proper adding - "XIV"
to "MCX")

Remember that low digits before a high digit detract while those following
cause addition.

Lol. I've just remembered what an FM is. Is there one for converting Roman
Numerals? Yes, and code too - you can do a Google for
Roman Numerals "VB.NET"
or
Roman Numerals VB 'This will get more.

But you may prefer the challenge of doing it yourself first. And you can
always bring it back here, too. ;-)

Regards,
Fergus

Cor

unread,
Nov 3, 2003, 4:10:36โ€ฏAM11/3/03
to
Hi Fergus,
Good morning

So check that chalenge I took.

Make a nice Crom(RomanString) from it

What will Conan think about that?

I need to go on for my rectangle first.

:-))

Cor


Fergus Cooney

unread,
Nov 3, 2003, 4:46:54โ€ฏAM11/3/03
to
Morning Cor,

ROFL. Maybe I should go to bed - this one has me beaten!

Crom? Conan?? Rectangle ???

But I saw the challenge. ;-)

[Pause ... head scratch ... ponder ...]

I think I might know the Rectangle - was it red and moveable/zoomable by
any chance?

Regards,
Fergus


Cor

unread,
Nov 3, 2003, 5:02:28โ€ฏAM11/3/03
to
Hi Fergus,
CRom Convert Roman to integer (a nice function)
Conan Crom is the sword of Conan
Rectangle You are right I am busy to put it in a class but piece by
piece, I still don't know for myself if it will be a class or a custom
control.

Cor

> Crom? Conan?? Rectangle ???
>


Fergus Cooney

unread,
Nov 3, 2003, 5:39:31โ€ฏAM11/3/03
to
Hi Cor,

|| Make a nice Crom(RomanString) from it
|| What will Conan think about that?

Lol. I think he'll ask what the strange marks on his sword are. ;-)

|| class or a custom control.

Now that's a good question. Perhaps 'twill be both with the UC using the
Class?

Regards,
Fergus


Cor

unread,
Nov 3, 2003, 6:11:05โ€ฏAM11/3/03
to
Fergus,

>
> Now that's a good question. Perhaps 'twill be both with the UC using
the
> Class?
>
You are right, I think that is the route to go

Cor


Cor

unread,
Nov 3, 2003, 6:49:33โ€ฏAM11/3/03
to
Hi Herfried,
I made this, but I don't know anymore how it was exactly with Roman figurs.
Is it so that XXC can exist or has it to be LXXX. ?
Cor

Fergus Cooney

unread,
Nov 3, 2003, 6:55:50โ€ฏAM11/3/03
to
Hi Cor,

LXXX

According to Cor,


|| there only could be 1 minus character before a plus character

and I think he's right.;-)

Regards,
Fergus

'there can only be 1 minus character before a plus character


Robert

unread,
Nov 3, 2003, 3:17:16โ€ฏPM11/3/03
to
"Sergey Poberezovskiy" <se...@compros.com.au> wrote in message news:<0a3a01c3a1e4$3bdc13c0$a101...@phx.gbl>...

> Robert,
>
> I could not quite understand why you compare the
> whole .Text property to one character - should not you
> analyze all the characters in the TextBox1?
> You could either iterate through TextBox1.Text.Chars array
> or use SubString method to get to individual character as
> String.
>
> Hope this helps...
>
It does in a way ,thanks and thank you to the others who wrote in with
chunks of code.

I very much want to analyze all the characters entered in textbox1.
I'm doing this exercise to learn vb.net and I read the codes posted
with great interest.

What I'm trying to control is slightly different and it's this:

Immediately as a user enters a character in textbox1 then this
character is converted and displayed in textbox2 without having to
press an ๅ‰K' or a ็ฅ–onvert' button in sort of ๅ–ชeal-time' - updating
on the fly. (If I used a cmd button I could send the complete string
to a module for validation and processing.)

So,

M produces 1000
MM produces 2000
C produces 100
I produces 1
II produces 2

but VV would produce an immediate error message saying the data
entered in textbox1 was incorrect and the display in textbox1 and
textbox2 WOULD REMAIN UNCHANGED. (caps for emphasis not for shouting)

In short, I would like the NEW string the user is attempting to type
in textbox1, in this case ่†ณV', to be available for validation and
processing.

In pseudocode

Get a new user roman letter
Validate the resulting string
Convert
Display

And all without the enter button!

Thanks

Bob

Fergus Cooney

unread,
Nov 3, 2003, 3:22:23โ€ฏPM11/3/03
to
Hi Robert,

Then it's the TextChanged event that you want to be handling.

Regards,
Fergus


Slonocode

unread,
Nov 3, 2003, 3:25:37โ€ฏPM11/3/03
to
Robert wrote:
> "Sergey Poberezovskiy" <se...@compros.com.au> wrote in message
> news:<0a3a01c3a1e4$3bdc13c0$a101...@phx.gbl>...
>> Robert,
>>
>> I could not quite understand why you compare the
>> whole .Text property to one character - should not you
>> analyze all the characters in the TextBox1?
>> You could either iterate through TextBox1.Text.Chars array
>> or use SubString method to get to individual character as
>> String.
>>
>> Hope this helps...
>>
> It does in a way ,thanks and thank you to the others who wrote in with
> chunks of code.
>
> I very much want to analyze all the characters entered in textbox1.
> I'm doing this exercise to learn vb.net and I read the codes posted
> with great interest.
>
> What I'm trying to control is slightly different and it's this:
>
> Immediately as a user enters a character in textbox1 then this
> character is converted and displayed in textbox2 without having to
> press an 'OK' or a 'convert' button in sort of 'real-time' - updating

> on the fly. (If I used a cmd button I could send the complete string
> to a module for validation and processing.)
>
> So,
>
> M produces 1000
> MM produces 2000
> C produces 100
> I produces 1
> II produces 2
>
> but VV would produce an immediate error message saying the data
> entered in textbox1 was incorrect and the display in textbox1 and
> textbox2 WOULD REMAIN UNCHANGED. (caps for emphasis not for shouting)
>
> In short, I would like the NEW string the user is attempting to type
> in textbox1, in this case 'VV', to be available for validation and

> processing.
>
> In pseudocode
>
> Get a new user roman letter
> Validate the resulting string
> Convert
> Display
>
> And all without the enter button!
>
> Thanks
>
> Bob

I'm not sure I understand completely what you are trying to do but...
Couldn't you handle the text_changed event of textbox1 and send the entire
string everytime it fires for validation.
This would eliminate having a cmd button.

--
Slonocode

"I've got a fever...and the only prescripiton is more cowbell"

Fergus Cooney

unread,
Nov 3, 2003, 3:31:16โ€ฏPM11/3/03
to
Hi Roberts

Forget that last post. - incomplete.

Then it <is> the TextChanged event that you want to be handling because
all sorts of things can cause a change which you don't want to have to handle
yourself - eg cut and paste.

This means that you'll be accepting changed text and validating it. Then,
if it's invalid, you have to change it back again. This will cause your
handler to be called again, but as you will be replacing a bad RomanNum with
the previous good 'un, it will validate and all's fine .

In order to set it back to it's previous good value, you need to <have>
that value. So you'll have a separate variable.

Incomplete code.

Private sPrevGoodUn As String
Sub TextChanged (..)
Value = EvaluateRomanNum (sender.Text) '-1 = Err
If Value > -1 Then
TextBox2.Text = Value
sPrevGoodUn = sender.Text
Else
sender.Text = sPrevGoodUn

Kind of thing.

Regards,
Fergus


Scott Metzger

unread,
Nov 3, 2003, 3:58:21โ€ฏPM11/3/03
to
Cor wrote:
> Conan Crom is the sword of Conan

Actually Crom is Conan's god.

Cor

unread,
Nov 3, 2003, 4:02:19โ€ฏPM11/3/03
to
Hi Scott,
Thank you I thought his God was his Sword
I believe you are right,
by Crom
:-))
Cor


Fergus Cooney

unread,
Nov 3, 2003, 4:48:00โ€ฏPM11/3/03
to
LOL


Robert

unread,
Nov 5, 2003, 8:37:21โ€ฏAM11/5/03
to
Thanks

Fergus (and others)

Buried under with work so I haven't had more than 20 minutes to have a
go at solving this. (made no progress at all, alas) I think I don't
properly understand the event side of visual basic.net no matter how
hard I read the texts. In the late 14th century when I last did a
little programming, you input a string at a prompt and could then
process/validate and then "print" the result.

What I want to do is test ? (? wildcard) then test ?? then test ??? as
the user inputs the Roman numerals, character by character, in
textbox1. Could I trouble you to expand a bit on your sub?

Thanks again

Bob


"Fergus Cooney" <fil...@post.com> wrote in message news:<etNqPsko...@TK2MSFTNGP10.phx.gbl>...

Cor

unread,
Nov 5, 2003, 9:09:18โ€ฏAM11/5/03
to
Robert,
I did give you all about that roman problem, loops everything, not one piece
of answer.
Cor


Slonocode

unread,
Nov 5, 2003, 2:01:11โ€ฏPM11/5/03
to
Robert wrote:
> Thanks
>
> Fergus (and others)
>
> Buried under with work so I haven't had more than 20 minutes to have a
> go at solving this. (made no progress at all, alas) I think I don't
> properly understand the event side of visual basic.net no matter how
> hard I read the texts. In the late 14th century when I last did a
> little programming, you input a string at a prompt and could then
> process/validate and then "print" the result.
>
> What I want to do is test ? (? wildcard) then test ?? then test ??? as
> the user inputs the Roman numerals, character by character, in
> textbox1. Could I trouble you to expand a bit on your sub?
>
> Thanks again
>
> Bob

Well the logic works like this. You write a function that does the testing.
The function accepts a string as a parameter.

The textbox has an event that is fired(triggered) every time the text inside
it changes. Meaning as the user types in ? the event is triggered. Then
with the next ? it is triggered.

So with the Text_Changed event of the textbox you will call your function
and pass it the string inside the textbox.


Robert

unread,
Nov 5, 2003, 3:30:00โ€ฏPM11/5/03
to
"Cor" <n...@non.com> wrote in message news:<ORVn9Z6o...@tk2msftngp13.phx.gbl>...


Thanks Cor for that. It was appreciated.

I'm trying to build my own solution and it's in building it that I'm
trying to learn visual basic.net. Your code looks good but many lines
are still way over my head, quite frankly.

My own code so far is this: (please excuse this rather long posting).
It has the advantage of being easy to read and the disadvantage of not
working.

Thanks again for posting your code.

Dim ROMAN As String
' ROMAN NUMBER TYPED

Dim SUM As Integer
' RUNNING ARABIC TOTAL

Dim NEWNUMBER As Integer
' CONVERTED ROMAN FIGURE

Dim CCOUNT As Integer
' COUNTER FOR C

Dim XCOUNT As Integer
' COUNTER FOR X

Dim ICOUNT As Integer
' COUNTER FOR I

Dim DCOUNT As Integer
' COUNTER FOR D

Dim LCOUNT As Integer
' COUNTER FOR L

Dim VCOUNT As Integer
' COUNTER FOR V

Dim RANKING As Integer
' TO PREVENT illegal ROMAN NUMERAL REPETITION M as 7 etc.

Dim LASTNUMBER As String

Dim flag As Boolean = True



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

ROMAN = TextBox1.Text
ROMAN = UCase(ROMAN)

Select Case ROMAN

Case Is = "M"
NEWNUMBER = 1000

RANKING = 7
flag = True

Case Is = "D"
NEWNUMBER = 500

RANKING = 6
DCOUNT = DCOUNT + 1
flag = True
If DCOUNT > 1 Then flag = False

Case Is = "C"
NEWNUMBER = 100

RANKING = 5
CCOUNT = CCOUNT + 1
flag = True
If CCOUNT > 4 Then flag = False

Case Is = "L"
NEWNUMBER = 50

RANKING = 4
LCOUNT = LCOUNT + 1
flag = True
If LCOUNT > 1 Then flag = False

Case Is = "X"
NEWNUMBER = 10

RANKING = 3
XCOUNT = XCOUNT + 1
flag = True
If XCOUNT > 4 Then flag = False

Case Is = "V"
NEWNUMBER = 5

RANKING = 2
VCOUNT = VCOUNT + 1
flag = True
If VCOUNT > 1 Then flag = False

Case Is = "I"
NEWNUMBER = 1

RANKING = 1
ICOUNT = ICOUNT + 1
flag = True
If ICOUNT > 4 Then flag = False

Case Else
NEWNUMBER = 0

End Select

if lastnumber>ranking then flag=false

If flag = True Then LASTNUMBER = RANKING
If flag = True Then SUM = SUM + NEWNUMBER

TextBox2.Text = SUM

End Sub

Bob

Tom Leylan

unread,
Nov 5, 2003, 5:51:37โ€ฏPM11/5/03
to
"Robert" <showopen...@yahoo.co.uk> wrote...

Hi Robert... I think this is an excellent way to learn particularly if you
believe in learning as an iterative process. Hope you don't mind my review
of your coding style.

One of the things that helps locate errors is to "reduce the noise." While
we don't need to be unreadably terse there is nothing gained by doing the
following
as the code says the same thing as the comment.:

' set x to 0
x = 0

In your example you wrote:

> Dim XCOUNT As Integer
> ' COUNTER FOR X

where Dim XCounter As Integer should suffice. Also almost nobody uses all
UPPERCASE to denote variables. In many languages this is used to denote a
constant.

and in the following case you didn't comment about what the test is doing
(or why) and it is not plainly obvious.

> if lastnumber>ranking then flag=false


You placed the code that processes the conversion directly into the
TextChanged event. That makes it particularly hard to reuse somewhere else
or programmatically if you wanted to convert values in a file for instance.
Consider making it a function (at least) and a Class if you feel up to the
task. This should eliminate all the variable declarations also which you
have to remember to setup any time you want to use the code. These can be
made private to the Class and exposed through properties as necessary.

> Private Sub TextBox1_text

You also should avoid renaming the event if you have no good reason to do so


> ROMAN = TextBox1.Text
> ROMAN = UCase(ROMAN)

Don't hesitate to combine easily understood functions

ROMAN = UCase(TextBox1.Text)

> DCOUNT = DCOUNT + 1

Don't hesitate to use increment (and decrement) operators

DCOUNT += 1

> flag = True
> If DCOUNT > 1 Then flag = False

Don't hesitate to assign the result of logical expressions

flag = (DCOUNT <= 1)

or if you prefer

flag = (NOT (DCOUNT > 1))


> If flag = True Then LASTNUMBER = RANKING
> If flag = True Then SUM = SUM + NEWNUMBER

if flag then
LASTNUMBER = RANKING
SUM += NEWNUMBER
endif

Basically it is hard to follow because you aren't actually writing a Roman
Numeral Converter but rather writing some code that converts Roman Numerals.
There is a difference, one is a nicely self-contained unit and one is
spaghetti.


You might try pseudocoding the entire thing first. Pseudocode acts as a
good guide and tells other people what the code is supposed to be doing. It
is much easier to tell if the code is actually doing what it is supposed to
be doing at that point.

Hope this helps in some way.

Robert

unread,
Nov 6, 2003, 12:36:30โ€ฏAM11/6/03
to
Two points to ask about and many thanks to convey for the help.

1. Thank you for those ideas and neat changes, which I have now
implemented and perhaps more importantly understood. I have the
feeling I am nearer a solution but cannot test it because something
new and trying has appeared.

No matter where I position

Private Sub TextBox2_TextChanged(ByVal sender As System.Object,
ByVal e As System.EventArgs) Handles TextBox2.TextChanged

I get

"Statement cannot appear within a method body. End of method assumed."

If only I could get the code to compile I could trace the logic
errors.

My revised code now reads:

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load ' set up the form

End Sub

Private Sub TextBox1_text(ByVal sender As System.Object, ByVal e

As System.EventArgs) Handles TextBox1.TextChanged ๅฃฎet up textbox1 for
input

Dim sum As Integer
TextBox2.Text = sum
End

Private Sub TextBox2_TextChanged(ByVal sender As System.Object,
ByVal e As System.EventArgs) Handles TextBox2.TextChanged ๅฃฎet up
textbox2 for output

End Sub

Function conversion(ByVal sum) As Integer ' sum is running Arabic
total

Dim roman As String
' Roman character typed

Dim newnumber As Integer
'result of user keypress

Dim ccount As Integer
' counter for C

Dim xcount As Integer
' counter for X

Dim icount As Integer
' counter for I

Dim dcount As Integer
' counter for D

Dim lcount As Integer
' counter for L

Dim vcount As Integer
' counter for V

Dim ranking As Integer
' Do not accept ascending Roman numerals

Dim lastnumber As String

Dim flag As Boolean = True

roman = UCase(TextBox1.Text)

Select Case roman

Case Is = "M"
newnumber = 1000
ranking = 7
flag = True

Case Is = "D"
newnumber = 500
ranking = 6
dcount = dcount + 1
flag = (dcount <= 1)

Case Is = "C"
newnumber = 100
ranking = 5
ccount = ccount + 1
flag = (ccount <= 4)

Case Is = "L"
newnumber = 50
ranking = 4
lcount = lcount + 1
flag = (lcount <= 1)

Case Is = "X"
newnumber = 10
ranking = 3
xcount = xcount + 1
flag = (xcount <= 4)

Case Is = "V"
newnumber = 5
ranking = 2
vcount = vcount + 1
flag = (vcount <= 4)

Case Is = "I"
newnumber = 1
ranking = 1
icount = icount + 1
flag = (icount <= 4)

Case Else
newnumber = 0

End Select

If lastnumber > ranking Then flag = False 'do not accept
ascending roman numerals

If flag Then
lastnumber = ranking
sum += newnumber
End If

Return sum

End Function


End Class

2. "So with the Text_Changed event of the textbox you will call your
function and pass it the string inside the textbox." Another writer
helpfully wrote.

I cannot help but feel that I haven't got this quite right in the code
above. I should appreciate it if you could point out where I've gone
wrong above.

Thanks


Bob

Slonocode

unread,
Nov 6, 2003, 1:39:44โ€ฏAM11/6/03
to
Robert wrote:
> Two points to ask about and many thanks to convey for the help.
>
> 1. Thank you for those ideas and neat changes, which I have now
> implemented and perhaps more importantly understood. I have the
> feeling I am nearer a solution but cannot test it because something
> new and trying has appeared.
>
> No matter where I position
>
> Private Sub TextBox2_TextChanged(ByVal sender As System.Object,
> ByVal e As System.EventArgs) Handles TextBox2.TextChanged
>
> I get
>
> "Statement cannot appear within a method body. End of method assumed."
>
> If only I could get the code to compile I could trace the logic
> errors.
>
> My revised code now reads:
>
> Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
> System.EventArgs) Handles MyBase.Load ' set up the form
>
> End Sub
>
> Private Sub TextBox1_text(ByVal sender As System.Object, ByVal e
> As System.EventArgs) Handles TextBox1.TextChanged 'set up textbox1 for

> input
>
> Dim sum As Integer
> TextBox2.Text = sum
> End
>
> Private Sub TextBox2_TextChanged(ByVal sender As System.Object,
> ByVal e As System.EventArgs) Handles TextBox2.TextChanged 'set up


Hello Bob

I would suggest a couple of things.
1. I would implement the conversion function in a different way. I would
write it such that it will calculate the arabic number from the complete
string in Textbox1 and not just character by character.

Meaning if V is in textbox1 the conversion function will return the
appropriate value 5.
if VIII is in the textbox then the conversion function will return 8
and so on.

2. In the textbox1_textchanged event you will call the conversion function
and send it the entire string.

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

textbox2.text = conversion(textbox1.text).tostring
End Sub

3. There is quite a few different ways you could handle checking to make
sure that the roman numeral string is valid.

a) You could write a separate function and pass the string similar to
the way the conversion function works and then alert the user if they enter
an invalid roman numeral.

b) You could incorporate the checking into the conversion function

c) You could capture keystrokes in the textbox1_textchanged event and
do your checking there.

4. You need to remember what types of variables you are using and remember
to cast them if neccessary.

For instance you are passing a string into the conversion function
called sum. later in the conversion function you are trying to add the
string sum to an integer called newnumber. This throws an exception because
you can't add a string to an integer.

Slonocode

unread,
Nov 6, 2003, 2:02:10โ€ฏAM11/6/03
to
As a follow up of my previous post for clarification.

The logic might be something like this:

Whenever the text in textbox1 changes
check the string to make sure it is a valid roman numeral and if not alert
the user or don't accept that input.
If the roman numeral is valid then send it to the conversion function which
will return the arabic value.

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

If ValidateRomanNumeral(TextBox1.Text) Then

TextBox2.Text = Conversion(TextBox1.Text).ToString

End If

End Sub

Private Function ValidateRomanNumeral(byval numeral as string) as boolean

' write code to check whether the numeral is valid
'Return true or false

End Function


Private Function Conversion(byval numeral as string) as integer

'write code to convert the entire numeral to arabic equivalent
'Return the arabic equivalent

End Function


Tom Leylan

unread,
Nov 6, 2003, 1:59:18โ€ฏAM11/6/03
to
"Robert" <showopen...@yahoo.co.uk> wrote...

Hi Robert... you have to keep simplifying. You are still getting caught up
in the event handlers. Seriously what the "project" is is a Roman Numeral
Converter... and to use it you have to create a user interface. But to
actually operate it does not need a UI. The key to writing these kinds of
functions is to concentrate on the function and then decide how you want it
to appear. Again, how it ultimately appears doesn't influence
RomanConvert().

> No matter where I position
>
> Private Sub TextBox2_TextChanged(ByVal sender As System.Object,
> ByVal e As System.EventArgs) Handles TextBox2.TextChanged
>
> I get
>
> "Statement cannot appear within a method body. End of method assumed."

I'm going to guess it isn't "no matter where" and that you haven't yet moved
it out of some other subroutine or function. I think you have this nested
inside another Sub.


Is anything happening in "Load"? You don't need this.

> Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
> System.EventArgs) Handles MyBase.Load ' set up the form
>
> End Sub


Notice you still call this one TextBox1_text
Also go to the project properties "build" and change Option Strict to "on"
as you are assigning an integer to a textbox string. That should fail, try
not to rely on this stuff being handled automatically. And while I'm
picking on this one, drop the comment. You aren't setting it up for input,
it's a Textbox1.TextChanged.event handler we can see that by it's
declaration. You could input into the textbox even if this handler were
removed. And you've declared a local integer "sum" that isn't ever going to
change value right?

> Private Sub TextBox1_text(ByVal sender As System.Object, ByVal e

> As System.EventArgs) Handles TextBox1.TextChanged 'set up textbox1 for


> input
>
> Dim sum As Integer
> TextBox2.Text = sum
> End

This one doesn't do anything and I assume you are going to simply assign the
results of the conversion to the textbox so you don't need to and don't want
to handle this event.

> Private Sub TextBox2_TextChanged(ByVal sender As System.Object,

> ByVal e As System.EventArgs) Handles TextBox2.TextChanged 'set up


> textbox2 for output
>
> End Sub


This function is only going to convert a roman numeral in the form of a
string into an integer (I've made it a long) value so you might try the
following:

Private Function RomanConvert( ByVal rn As String) As Long
Dim Ret as Long = 0

' add pseudocode in here

Return Ret
End Function

Note that it doesn't require a UI? You can call it from the command prompt
to test it.

So now think about what it takes to convert Roman Numerals. The string has
to contain only valid RN characters... you have to think what you would
return if it didn't (I'll suggest zero or raise an error). Also the code
you have written appears to handle "VI" (6) but not "IV" which is 4 of
course.

You are also going to convert a "string" not a character at a time. You
can't... a Roman Numeral can be III and you have to produce 3. You can
convert it upon the input of each character but you are going to convert the
entire string each time. So when "I" is passed it will return 1 (which is
correct), when it sees "II" it will return 2 and when it finally gets "III"
it will return 3. If the user backspaces and erases an "I" it will return 2
again. If the user keys "XIX" it will return 10, then 11, and finally 19.

I just noticed you are referencing the TextBox1.Text within the conversion
function. You've eliminated the possibility of testing it from the debugger
or having it read values from a text file or to get a string from any other
source (like if name my textbox "Input1" or you decide to have two textboxes
both of which could convert Roman Numerals.)

Pass a string in, get a value out.

> 2. "So with the Text_Changed event of the textbox you will call your
> function and pass it the string inside the textbox." Another writer
> helpfully wrote.

Exactly.

> I cannot help but feel that I haven't got this quite right in the code
> above. I should appreciate it if you could point out where I've gone
> wrong above.

It looks like you started writing VB code in the hope that you could write
enough to make it convert roman numerals :-) That's why I suggest you
create the basic structure see "RomanConvert" above. And then using
comments only insert English-like instructions to model what you intend to
do. As I pointed out you've coded something but it can't handle "IV" or
"XIX". You aren't a few dozen additional lines of code away from having it
handle these values, you are potentially days away and when it finally has
enough code to handle (what you believe to be) every situation it will look
like spaghetti code.

If you write pseudocode "fake code like English"

' if it isn't an empty string
' uppercase the string
' get the first character
' if it is an "M" then
etc.

That way you don't have to worry about "syntax" you only have to worry about
the algorithm. Proper VB isn't the problem at the moment, it's divining the
methodology that is the trick. And bonus... if you start with pseudocode
you could convert the routine to VB.Net, C#, or even VB6 because
fundamentally you would be translating the English "if it isn't an empty
string" into whatever language you felt like knowing it will work when you
are done.

Keep trying and post your results. And remember when the function is
finished you can add text boxes, buttons and stuff to the form. Who cares
if the textboxes are aligned at this point?

Tom

Tom Leylan

unread,
Nov 6, 2003, 2:06:16โ€ฏAM11/6/03
to
"Slonocode" <stillv...@yahoo.com> wrote...

> As a follow up of my previous post for clarification.
> The logic might be something like this:

Hi... I thought I'd put my 2 cents in here also and caution Robert against
adding more tests before he gets the basics done. So far he can't convert
"XIX"... detecting "R" would be nice but he'll write that one because it is
easy before he can actually convert the roman numeral.

It will also turn out (I believe) that it cannot reasonably be a separate
function due to the nature of non roman numeralsim :-) It could catch an
"R" or a "B" easy enough but it has to also catch "XVXV" and hundreds of
other combinations. It won't know if some of these are invalid until it
attempts to convert them.

Tom

keyur shah

unread,
Nov 6, 2003, 2:15:11โ€ฏAM11/6/03
to
Convert this logic to vb.net you would be fine.

Function ConvertNumberToRoman(ByVal intIn As Integer) As String
' Comments : converts a number to Roman numerals
' Parameters: intIn - value to convert
' Returns : String
'
Const Digits = "IVXLCDM"
Dim intCounter As Integer
Dim intDigit As Integer
Dim strTmp As String

intCounter = 1

Do While intIn > 0

intDigit = intIn Mod 10
intIn = intIn \ 10

Select Case intDigit
Case 1: strTmp = Mid(Digits, intCounter, 1) & strTmp
Case 2: strTmp = Mid(Digits, intCounter, 1) & Mid(Digits, intCounter, 1)
& strTmp
Case 3: strTmp = Mid(Digits, intCounter, 1) & Mid(Digits, intCounter, 1)
& Mid(Digits, intCounter, 1) & strTmp
Case 4: strTmp = Mid(Digits, intCounter, 2) & strTmp
Case 5: strTmp = Mid(Digits, intCounter + 1, 1) & strTmp
Case 6: strTmp = Mid(Digits, intCounter + 1, 1) & Mid(Digits,
intCounter, 1) & strTmp
Case 7: strTmp = Mid(Digits, intCounter + 1, 1) & Mid(Digits,
intCounter, 1) & Mid(Digits, intCounter, 1) & strTmp
Case 8: strTmp = Mid(Digits, intCounter + 1, 1) & Mid(Digits,
intCounter, 1) & Mid(Digits, intCounter, 1) & Mid(Digits, intCounter, 1)
& strTmp
Case 9: strTmp = Mid(Digits, intCounter, 1) & Mid(Digits, intCounter +
2, 1) & strTmp
End Select

intCounter = intCounter + 2

Loop

ConvertNumberToRoman = strTmp

End Function


Keyur Shah
Verizon Communications
732-423-0745

*** Sent via Developersdex http://www.developersdex.com ***
Don't just participate in USENET...get rewarded for it!

Cor

unread,
Nov 6, 2003, 3:02:51โ€ฏAM11/6/03
to
Hi Robert,

Rather than looking at your code, I will describe what the code that I did
make do.
I saw so many comments that goes in this direction.

The code is not ment that you would use it, but as an example from whichi
you could use parts and therefore I did left all the things with textboxes
and so out, but I comment beneath a little bit how you can do that also.

Some things are mainly because you don't keep track of the minus in the
Roman value and that will be very difficult in the way you are doing it.

The comments are every time below the lines

>Private Sub Button1_Click(ByVal sender As Object, _

>ByVal e As System.EventArgs) Handles Button1.Click

I did all in a Button click event. It can better done using a keyup (and a
keyup because then the value is written or you can use a textchange, but I
prefer for this the keyup). I would make another textbox where the value is
written everytime.

>Dim TestString As String = "IVXLCDM"

I did make a string with all the possibilities of Roman numbers I did put it
in top of the sub because I find that nicer, it is for testing the
characters you see it in some lines

>Dim i As Integer

I created an i as an integer, that I use always as a standard indexer

>TextBox1.Text = TextBox1.Text.ToUpper

I converted all characters in the textbox to uppercase I find that better
than giving a message that somebody has to do that

>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

Everytime the characters in the textbox are checked if they contain a non
Roman Character. This looks a little bit strange, I would evaluate it if I
was you. It had to be a little bit reversal because now we can check only
for the characters which has to be.
I used the same textbox but better is to add a label to your form for giving
the error.

>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,")

Then I did do the replacing using the stringbuilder, a new function which is
very fast, not really necessary for this but I did use it because it is an
example.

It replaces the Roman values for the decimal values as a string, with every
time a value with a comma behind it. So it becomes a kind of comma
seperated string. CSV

>Dim romanstr As String = roman.ToString.Substring(0, roman.Length - 1)

The row above is only to remove the last comma

>Dim romanarr As String() = Split(romanstr, ",")

With this command we make from the string an array of decimal values

>For i = 0 To romanarr.Length - 2
>If CInt(romanarr(i)) < CInt(romanarr(i + 1)) Then
>romanarr(i) = "-" & romanarr(i)
>End If
>Next

Because the first higher value before a lower is a minus I added a "-"
character
I did not test for another higher value before a lower, that should be done,
because that will give errors

>Dim result As Integer
>For i = 0 To romanarr.Length - 1
>result += CInt(romanarr(i))
>Next

>his calculate the Roman value

>TextBox1.Text = TextBox1.Text & "=" & result.ToString

This stores it back in the textbox a second textbox would be nicer.

>End Sub
///

I hope you can implement some parts in your sollution?

Cor

"Robert" <showopen...@yahoo.co.uk> schreef in bericht
news:95c0dd51.03110...@posting.google.com...

EricJ

unread,
Nov 6, 2003, 3:25:19โ€ฏAM11/6/03
to
i think you forgot an end sub (you only put end here) c below

> No matter where I position
>
> Private Sub TextBox2_TextChanged(ByVal sender As System.Object,
> ByVal e As System.EventArgs) Handles TextBox2.TextChanged
>
> I get
>
> "Statement cannot appear within a method body. End of method assumed."

> Private Sub TextBox1_text(ByVal sender As System.Object, ByVal e
> As System.EventArgs) Handles TextBox1.TextChanged 'set up textbox1 for


> input
>
> Dim sum As Integer
> TextBox2.Text = sum
> End

put sub behind the end :)


Tom Leylan

unread,
Nov 6, 2003, 9:37:50โ€ฏAM11/6/03
to
"keyur shah" <ke...@softwareklinic.com> wrote...

> Convert this logic to vb.net you would be fine.

> Function ConvertNumberToRoman(ByVal intIn As Integer) As String
> ' Comments : converts a number to Roman numerals
> ' Parameters: intIn - value to convert
> ' Returns : String

Actually I believe he will end up with the same Roman numeral he was trying
to convert :-) Unless I'm crazy (always a possibility) he wants to convert
the other direction.

He also wants to "write it" I think.


Robert

unread,
Nov 7, 2003, 12:09:45โ€ฏAM11/7/03
to
Many thanks to those who have posted code and advice. It's kind of you
to take the time like this.

I've decided to go down the 'validate then convert route' using a
separate function for each; thus, taking the validation part first...

On trying to implement it I have come against a problem, or rather
two.

I thought I'd start modestly enough by checking simply that a single
letter typed into textbox1 was any one of MDCLXVI returning TRUE from
the function and FALSE were another letter entered. However,

'End If' must be preceded by a matching 'If'

appears as a warning message in the private sub below and I don't
understand why it should at all, I'm afraid.

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

If validation(TextBox1.Text) Then TextBox2.Text =
validation(TextBox1.Text).ToString
flag = False
end if

End Sub

The second problem is that the validation function returns TRUE for
everything.

Function validation(ByVal numeral As String) As Boolean


roman = UCase(TextBox1.Text)
Select Case roman
Case Is = "M"

flag = True
Case Is = "D"
flag = True

Case Is = "C"
flag = True
Case Is = "L"
flag = True
Case Is = "X"
flag = True
Case Is = "V"
flag = True
Case Is = "I"
flag = True
Case Else
flag = False
End Select
Return flag
End Function


Bob

Slonocode

unread,
Nov 7, 2003, 1:03:13โ€ฏAM11/7/03
to
Robert wrote:
> 'End If' must be preceded by a matching 'If'
>
> appears as a warning message in the private sub below and I don't
> understand why it should at all, I'm afraid.
>
> Private Sub TextBox1_text(ByVal sender As System.Object, ByVal e As
> System.EventArgs) Handles TextBox1.TextChanged
>
> If validation(TextBox1.Text) Then TextBox2.Text =
> validation(TextBox1.Text).ToString
> flag = False
> end if


This code seems to be missing a THEN.
IF ....... THEN

END IF

> Function validation(ByVal numeral As String) As Boolean
> roman = UCase(TextBox1.Text)
> Select Case roman
> Case Is = "M"
> flag = True
> Case Is = "D"
> flag = True
> Case Is = "C"
> flag = True
> Case Is = "L"
> flag = True
> Case Is = "X"
> flag = True
> Case Is = "V"
> flag = True
> Case Is = "I"
> flag = True
> Case Else
> flag = False
> End Select
> Return flag
> End Function

Here you are passing in the value of textbox1.text as the parameter numeral.
So you can use that instead of a new variable roman.


Also as more characters get entered into the textbox1 it will be passing the
entire string to the function each time. So the user enters M and the
function validates M. Then the user enters D and the string MD gets passed.
So the function will need to validate the entire string MD. And so on.

You could perhaps do something like this inside the validate function:

Quickly check the entire string for any characters that arent a valid roman
numeral.

Then check the string to make sure that no "higher order" numerals come
after a "lower order" numeral.

This would eliminate having to keep track of each character somewhere
outside of the function.

HTH

Slonocode

unread,
Nov 7, 2003, 1:12:59โ€ฏAM11/7/03
to
>
> Then check the string to make sure that no "higher order" numerals
> come after a "lower order" numeral.
>
> This would eliminate having to keep track of each character somewhere
> outside of the function.
>
> HTH

Hmmm I think this will not work.

As Tom points out

> It will also turn out (I believe) that it cannot reasonably be a
> separate function due to the nature of non roman numeralsim :-) It
> could catch an "R" or a "B" easy enough but it has to also catch
> "XVXV" and hundreds of other combinations. It won't know if some of
> these are invalid until it attempts to convert them.


This will be a much harder algorithm to implement.

May have to think a little more on this.

EricJ

unread,
Nov 7, 2003, 3:30:35โ€ฏAM11/7/03
to

> If validation(TextBox1.Text) Then TextBox2.Text =
> validation(TextBox1.Text).ToString
> flag = False
> end if
>
> End Sub
>

if boolean then
code here
end if
or
if boolean then 1line of code

don't mix the 2

> The second problem is that the validation function returns TRUE for
> everything.
>
> Function validation(ByVal numeral As String) As Boolean
> roman = UCase(TextBox1.Text)
> Select Case roman
> Case Is = "M"

instaid of select case roman use

Select Case numeral 'as that is the string you are passing

and there is 1 more thing fundamentally wrong w your concept (if you don't
mind me saying and this goos a way back) you are always testing the intire
text of the textbox against a single letter (ex "MM" = "M" this will never
work). You should test every letter of the string you could try a loop

'code out of head not tested
private Function validation(ByVal numeral As String) As Boolean
dim flag as boolean
for i as integer = 0 to (numeral.length -1)
Select case numeral.substring(i,1)


Case Is = "M"
flag = True
Case Is = "D"
flag = True
Case Is = "C"
flag = True
Case Is = "L"
flag = True
Case Is = "X"
flag = True
Case Is = "V"
flag = True
Case Is = "I"
flag = True
Case Else
flag = False
End Select

next
return flag
end function

eric


Cor

unread,
Nov 7, 2003, 4:32:21โ€ฏAM11/7/03
to
Hi EricJ,

I did make this routine for that when I saw it, is it really that dificult?

Dim TestString As String = "IVXLCDM"

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

Cor


EricJ

unread,
Nov 7, 2003, 5:01:33โ€ฏAM11/7/03
to
not for me but i can imagine it could be.
i've been following this thread for a while each time thinking everithing
has been said. but some problems remaind in roberts posts, i thought he
might have overlooked something and wanted to point it out.
(original post) --> ... I have little experience of visual basic.net at all,
...
if you keep that in mind your routine was probably to difficult at that
time. I imagine robert has learned some things w this thread and maybe if he
looks back at it now it would make more sence, but that yust a thought ;)

eric

"Cor" <n...@non.com> wrote in message

news:%23spnjIR...@TK2MSFTNGP12.phx.gbl...

Tom Leylan

unread,
Nov 7, 2003, 9:51:33โ€ฏAM11/7/03
to
"Robert" <showopen...@yahoo.co.uk> wrote...

> I've decided to go down the 'validate then convert route' using a
> separate function for each; thus, taking the validation part first...

Hi Robert... you've chosen the road that leads to a dead end. :-) On the
other hand if you want to walk a little further down the trail (before you
turn around) consider naming the trail something relevant. Not validation()
but IsValid() or IsRomanNumeral() that way (without reading a comment or the
code) we know that it is supposed to be testing whether the string is a
Roman numeral.

Still if you at some point decide to take my advice :-) you'll stop writing
code and start thinking about what a Roman numeral is? Your validation code
isn't close to answering the question if the string is a Roman numeral, even
if it worked presently. VVVV is not a Roman numeral

I believe it was Cor who posted some code (I can't recall) it looked
interesting in that it converted the individual characters and then
preformed math on them but (without seeing it I'll admit) I don't think that
will work. Again because: IIX is not an alternative way to write the
number 8.

I can give you a hint on how to solve it but so far you are taking
potshots... and if you think this one is tricky wait until you try the
potshot method on a really hard problem. So, try to take off the
"programmer hat" and put on the scientist hat... when you know how to solve
the problem convert the solution to VB.Net.

I'm not trying to annoy you but consider that for all the code (and select
case statements) you've written that you are no closer to finishing the
function than I am and I haven't written "any" code. I think this is a good
project for you because the answer isn't self-evident... ask yourself basic
questions like "what possible ways can I process the string" and it turns
out there aren't that many ways.

Keep working on it!

Cor

unread,
Nov 7, 2003, 10:36:00โ€ฏAM11/7/03
to
Hi Tom,

I did write to Robert, that one of the things I left to him was to check for
this because this is an error.


>
> I believe it was Cor who posted some code (I can't recall) it looked
> interesting in that it converted the individual characters and then
> preformed math on them but (without seeing it I'll admit) I don't think
that
> will work. Again because: IIX is not an alternative way to write the
> number 8.

And for the rest it works as far as I can see complete.

If you want to go to Rome someday, you can use normal arabic decimal values
now in Rome. But if you want me to do that last part, I will do it for you.

:-))

Cor


Cor

unread,
Nov 7, 2003, 11:22:46โ€ฏAM11/7/03
to
Tom,
To make it more clear the code makes from IX a 9 but IIX is not alowed in
the Roman counting system. I was not absolute sure of it, but Fergus said it
also.
Cor


Robert

unread,
Nov 7, 2003, 2:52:17โ€ฏPM11/7/03
to
Tom

Yours is sound advice and welcomed. Thank you.

May I say though, it isn't so much the solution I'm seeking but to
learn visual basic.net syntax and language. I wrote out an algorithm
in pseudocode which I desk-checked before I sat down to code and which
appeared to work. Admittedly it didn't address the problem of letter
precedence but I thought that might be too tricky for me. When I sat
down at the keyboard I found there was so much I didn't understand
about visual basic itself I was stumped. (cf. walking into a French
bar and saying "I'd like an ostrich sandwich" in French. A week ago I
couldn't say the I the โ€˜d or any of it so it's a kind of progress. At
least it's French and you're asking for something to eat.) None of
this, of course, gainsays your good advice getting to a solution.

Without wishing to sound obsequious I should like to thank again the
people who are making these helpful postings. As someone commented, I
am learning from this (slowly, as might be apparent from MY postings),
which is and was my intention in tackling a visual basic project. I am
reluctant to simply paste code in unless I understand what it's doing.
(But please keep posting code and advice, if you have the time!)

Ever the optimist, I feel that a solution is close to at least
returning TRUE or FALSE if a non-Roman character is entered in
textbox1.

M now returns TRUE, as does MM or MMM (good). However, once set to
TRUE then any keyed entry in Textbox1 returns TRUE. I've tried
resetting the FLAG to FALSE in two places without success.

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

If IsRomanNumeral(TextBox1.Text) Then TextBox2.Text = IsRomanNumeral
(TextBox1.Text).ToString

flag = False

End Sub

Private Function IsRomanNumeral (ByVal numeral As String) As
Boolean

Dim i As Integer

numeral = UCase(TextBox1.Text)

flag = False

For i = 0 To (numeral.Length - 1)

Select Case numeral.Substring(i, 1)


Case Is = "M"
flag = True
Case Is = "D"
flag = True
Case Is = "C"
flag = True
Case Is = "L"
flag = True
Case Is = "X"
flag = True
Case Is = "V"
flag = True
Case Is = "I"
flag = True
Case Else
flag = False
End Select

Next

Tom Leylan

unread,
Nov 7, 2003, 5:27:16โ€ฏPM11/7/03
to
"Robert" <showopen...@yahoo.co.uk> wrote...

> May I say though, it isn't so much the solution I'm seeking but to
> learn visual basic.net syntax and language.

You picked quite a challenge for this :-)

Here is where you are at present:

You still have the event handler named "_text" rather than _TextChanged" not
wrong but it will only confuse you at this point.

You testing IsRomanNumeral() twice for no good reason. Once to see if you
should change the textbox value and once to get the "True" returned again.

If you are only going to change the textbox value when the function returns
true it is safe bet that asking it to convert .ToString it will return
"True"

This is also why it never returns "False" because you told it not to update
the value in that case.

To eliminate the double call consider simply assigning "True" or "False" or
store the value from the first call and use that, i.e.

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

The flag = false in your error handler does nothing and should be causing an
error. That it doesn't and that you can reference it in IsRomanNumeral with
declaring it suggests you've initialized it somewhere... it doesn't belong
there wherever it that is..

> Private Function IsRomanNumeral (ByVal numeral As String) As Boolean

You're still passing in a string and then referencing the textbox directly
in the function.

Consider not naming the return value "flag"... IsRomanNumeral can be used as
boolean, it is automatically defined or define one named "ret" or something
else but not "flag" which implies it is a "flag" and it isn't.

I believe your code will fail given an empty string.

The syntax Case Is = "M" should simply be Case "M" and since you want to
return the same thing in every case you can write

Case "M", "D", "C", "L", "X", "V", "I"
ret = True

You are resetting the flag to true even if some bogus value appears in the
middle of the string. So "Hey Bob 123 X" should pass your test upon
entering the "X".


Fun huh? :-)

Fergus Cooney

unread,
Nov 7, 2003, 4:09:58โ€ฏPM11/7/03
to
Hi Bob,

I know you've just said that bit about cut and paste, but I see nothing
wrong with giving you an alternative to what you've already done.

Personally I hate things that look like the code below because there are
two blocks of 'meaning' shuffled together - the conditions and the actions.
In working with it I have to pick my way carefully from line to line.

Select Case numeral.Substring(i, 1)
Case Is = "M"
flag = True
Case Is = "D"
flag = True
Case Is = "C"
flag = True
Case Is = "L"
flag = True
Case Is = "X"
flag = True

Case Else
flag = False
End Select

I always take advantage of the comand separator (colon) in these
situations.

Select Case numeral.Substring(i, 1)
Case Is = "M": flag = True
Case Is = "D": flag = True
Case Is = "C": flag = True
Case Is = "L": flag = True
Case Is = "X": flag = True

Case Else


flag = False
End Select

That, to me, looks <much> clearer. You can immediately see that
everything is True except the Else. And it's also very easy to run down the
list of Roman Digits and check them.

Now, notice that I said Roman Digit there. Here's some pseudo-code for
your numeral checker:

For each character in the input string:
If it's not a Roman Digit,
Return False
Next
Return True

That's five lines and it's complete. As soon as a single character has
been found unworthy, it exits.

Let's look at the pseudo-code for what you've got.

For each character in the input string:
If it's a Roman Digit,
Set the flag to True
Else
Set the flag to False
Next
Return the flag.

Now you can see that whatever happens - every character is going to be
tested. And the flag is always valid for the <last character checked>. This
is much more obvious from the pseudo-code than from the code that you
actually have.

One reason is the quantity of code. Notice how, in both versions, the
checking of the digit has been assumed as a unit. Why not code it as a unit
too?

This time, however, we'll take advantage of the fact that this function
does only one very simple thing. It doesn't need any variables - it can just
return its value.

Private Function IsRomanDigit (ByVal Digit As String) As Boolean


Select Case Digit
Case "M": Return True
Case "D": Return True
'More cases ...
End Select

Return False
End Function

Note that no Case Else is used. (I prefer having a Return at the bottom
of the function.)

Now this will simplify IsRomanNumeral and give you a clearer picture.
(It will also be handy when you reach the end of that road that Tom
mentioned ;-) and dump IsRomanNumeral for EvaluateRomanNumeral. You can
still use IsRomanDigit there - and in your TextBox_KeyPress, if you wish to
play with that).

Regards,
Fergus


Tom Leylan

unread,
Nov 7, 2003, 8:06:37โ€ฏPM11/7/03
to
Ok Robert...

You've got the weekend to figure this out as I have the answer... :-) I can
give it to you in chunks or I can post it all at one time. Personally I
think chunk mode might be fun but you might not. The trouble with posting
long listings (particularly if you are learning VB.Net) is that it can look
like "just a lot of code" and sometimes what it is doing and why it is doing
it isn't so easy to decipher.

Let me know,
Tom

Fergus Cooney

unread,
Nov 7, 2003, 10:11:52โ€ฏPM11/7/03
to
Hi Tom, Robert

Cheers
Cheeks
Checks
Chucks
+Chunks+
Thunks
Thanks. ;-)

I'm going to second guess you Robert and reckon you'll say chunks because you've
already said this is a VB.NET learning experience.

I'd like to have the lot though, if you wouldn't mind, Tom: fil...@post.com

Regards,
Fergus


Robert

unread,
Nov 9, 2003, 12:36:54โ€ฏAM11/9/03
to
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

Tom Leylan

unread,
Nov 9, 2003, 2:11:13โ€ฏAM11/9/03
to
"Robert" <showopen...@yahoo.co.uk> wrote...

> 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" <n...@non.com>

' if there is a bug I introduced it in the tidying/adjusting phase
' "tom leylan" <tle...@leylan.com>

' 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" <ke...@softwareklinic.com>

' if there is a bug I introduced it in the tidying/adjusting phase
' "tom leylan" <tle...@leylan.com>

' 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

Fergus Cooney

unread,
Nov 9, 2003, 4:07:23โ€ฏAM11/9/03
to
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.
==================================================


Cor

unread,
Nov 9, 2003, 5:39:47โ€ฏAM11/9/03
to
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


Cor

unread,
Nov 9, 2003, 5:44:22โ€ฏAM11/9/03
to
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


Fergus Cooney

unread,
Nov 9, 2003, 6:17:35โ€ฏAM11/9/03
to
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.


Cor

unread,
Nov 9, 2003, 6:40:32โ€ฏAM11/9/03
to
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


Fergus Cooney

unread,
Nov 9, 2003, 7:11:58โ€ฏAM11/9/03
to
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


Cor

unread,
Nov 9, 2003, 7:26:25โ€ฏAM11/9/03
to
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

Fergus Cooney

unread,
Nov 9, 2003, 8:22:27โ€ฏAM11/9/03
to
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


Herfried K. Wagner [MVP]

unread,
Nov 9, 2003, 8:48:27โ€ฏAM11/9/03
to
* "Fergus Cooney" <fil...@post.com> scripsit:

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.

--
Herfried K. Wagner
MVP ยท VB Classic, VB.NET
<http://www.mvps.org/dotnet>

Robert

unread,
Nov 9, 2003, 9:49:52โ€ฏAM11/9/03
to
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

Tom Leylan

unread,
Nov 9, 2003, 11:50:23โ€ฏAM11/9/03
to
"Tom Leylan" <g...@iamtiredofspam.com> wrote...
<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" <n...@non.com>

' if there is a bug I introduced it in the tidying/adjusting phase
' "tom leylan" <tle...@leylan.com>

' the return value
ToArabic = 0

End Function

Shared Function ToRoman(ByVal iValue As Integer) As String

' based upon a posting by:
' "keyur shah" <ke...@softwareklinic.com>

' if there is a bug I introduced it in the tidying/adjusting phase
' "tom leylan" <tle...@leylan.com>

' 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 = ""

Do While (iValue > 0)

Loop

End Function

End Class


Tom Leylan

unread,
Nov 9, 2003, 11:52:42โ€ฏAM11/9/03
to
"Fergus Cooney" <fil...@post.com> wrote...

> 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


Tom Leylan

unread,
Nov 9, 2003, 12:01:11โ€ฏPM11/9/03
to
"Cor" <n...@non.com> wrote...

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.

> > 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.

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


Cor

unread,
Nov 9, 2003, 12:29:05โ€ฏPM11/9/03
to
Thanks Tom


Cor

unread,
Nov 9, 2003, 12:48:36โ€ฏPM11/9/03
to
Hi Tom,

I think it will work like this (not tested)


> > > For i = 0 To (numeral.Length - 1)
> > > Select Case numeral.Substring(i, 1)
> > > Case "M", "D", "C", "L", "X", "V", "I"

> > > Case Else
TextBox1.Text = "Error:" & numeral & " in
pos:" & i+1.tostring
Exit Sub 'or whatever
> > > End Select

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


Robert

unread,
Nov 10, 2003, 3:03:08โ€ฏPM11/10/03
to
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:

Do While (iValue > 0)

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

Tom Leylan

unread,
Nov 10, 2003, 3:37:12โ€ฏPM11/10/03
to
"Robert" <showopen...@yahoo.co.uk> wrote...

> 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.

0 new messages