Help creating a function

G

Gary Kahrau

I want to create a function and can only get half way to my goal.

dim sStr as string
sStr = Entry(2,"a,b,c,d") ' Sets sStr = "b"
Entry(2,sStr) = "B" ' Sets sStr = "a,B,c,d"


I tried create a public property. However, the Set does not allow
ByRef. How do I work around this?
 
G

Gary Kahrau

I am trying to create a function named Entry.

It has two parts to it.
Purpose: to extract a field from a delimited string.
Im my example below, the string is "a,b,c,d". This represents (4)
fields with a comma delimiter. Field #2 would = "b"

Setting field positions in the comma delimited string.
Entry(2,sStr) = "xxx" would place "xxx" n the second field position of
string varialbe (sStr) resulting string would be "a,xxx,c,d"

It's an automation of the split and join functions (less coding).

Hope that helps.


Could you be more specific as to what you are trying to do?
 
C

Cor Ligthert [MVP]

Gary,

Why should it be by ref, there are forever very few reasons to do it by Ref.

Every string operation creates a new string, that is something you cannot
avoid.

I hope this helps,

Cor
 
A

Armin Zingler

Gary Kahrau said:
I want to create a function and can only get half way to my goal.

dim sStr as string
sStr = Entry(2,"a,b,c,d") ' Sets sStr = "b"
Entry(2,sStr) = "B" ' Sets sStr = "a,B,c,d"


I tried create a public property. However, the Set does not allow
ByRef. How do I work around this?


As already mentioned, strings are immutable. Use an array of strings or an
arraylist instead if you want to work with an index. You can encapsulate
this in you own class.


Armin
 
P

Phill. W

Gary Kahrau said:
I am trying to create a function named Entry.

You'd be better off creating a little Class to wrap this all up and use
a property to access each element, something like

Class CommaList

Public Sub New( ByVal saText as String )
Me.Text = saText
End Sub

Public Property Entry( ByVal iaIndex as Integer ) as String
Get
Return m_sItems( iaIndex - 1 )
End Get
Set( Value as String )
m_sItems( iaIndex - 1 ) = Value
End Set
End Property

Public Property Text() as String
Get
Return [String].Join( ",", m_sItems )
End Get
Set( Value as String )
m_sItems = Value.Split( ","c )
End Set
End Property

Private m_sItems as String() = Nothing

End Class

.... then ...

Dim myList as New CommaList( "a,b,c,d" )
s = myList.Entry( 2 ) ' => "b"
myList.Entry( 2 ) = "B"
s = myList.Text ' => "a,B,c,d"

(If you ever need to extend this class to use delimiters of more than
one character (say, vbCrLf), use the Split() function in
Microsoft.VisualBasic.Strings. The System.String Split() method only
handles one character delimiters (like comma's).

HTH,
Phill W.
 
G

Gary Kahrau

Phil,

Thanks,
My actual program is similar. However I wanted to shorten it slightly.
I am porting a program from a 4GL and the Entry function is part of
their language.

Using a class requires as new instance each time and the extra step of
assigning the variable to the text property.

It seems like it is impossible to create a statement/function like
MID.

FirstWord = Mid(MyString, 1, 3)
Mid(MyString, 5, 3) = "fox"


Gary Kahrau said:
I am trying to create a function named Entry.

You'd be better off creating a little Class to wrap this all up and use
a property to access each element, something like

Class CommaList

Public Sub New( ByVal saText as String )
Me.Text = saText
End Sub

Public Property Entry( ByVal iaIndex as Integer ) as String
Get
Return m_sItems( iaIndex - 1 )
End Get
Set( Value as String )
m_sItems( iaIndex - 1 ) = Value
End Set
End Property

Public Property Text() as String
Get
Return [String].Join( ",", m_sItems )
End Get
Set( Value as String )
m_sItems = Value.Split( ","c )
End Set
End Property

Private m_sItems as String() = Nothing

End Class

... then ...

Dim myList as New CommaList( "a,b,c,d" )
s = myList.Entry( 2 ) ' => "b"
myList.Entry( 2 ) = "B"
s = myList.Text ' => "a,B,c,d"

(If you ever need to extend this class to use delimiters of more than
one character (say, vbCrLf), use the Split() function in
Microsoft.VisualBasic.Strings. The System.String Split() method only
handles one character delimiters (like comma's).

HTH,
Phill W.
 
G

Gary Kahrau

Cor,

I don't care about the programming technique.

It seems like it is impossible to create a statement/function like MID
with vb.net. The Entry Function/Statement that I am trying to create
is very much the the mid Function/Statement usage.

FirstWord = Mid(MyString, 1, 3)
Mid(MyString, 5, 3) = "fox"
 
P

Phill. W

Gary Kahrau said:
Using a class requires as new instance each time and the extra step
of assigning the variable to the text property.

It seems like it is impossible to create a statement/function like
MID.

In all fairness, VB 'Proper's Mid Statement/Function/Hybrid *is* a
bit of an curiousity. I've got into the habit of class-ing up functionality
like this just so it's more reusable but ... try this:

Public Shared Property Entry _
( ByRef srText as String _
, ByVal iaIndex as Integer _
) as String

Get
Return srText.Split( ","c )( iaIndex -1 )
End Get

Set( Value as String )
Dim s as String() = srtext.Split( ","c )
s.SetValue( Value, iaIndex - 1 )
srText = [String].Join( ",", s )
End Set

End Property

HTH,
Phill W.
 
C

Cor Ligthert [MVP]

Gary,

The mid function in VBNet is the same as in VB6

Dim myString As String = "The fox jumps over whatever"
Dim FirstWord As String = Mid(MyString, 1, 3)
MessageBox.Show(Mid(myString, 5, 3))

shows "fox"

Cor
 
P

Phill. W

Phill. W said:
In all fairness, VB 'Proper's Mid Statement/Function/Hybrid *is* a
bit of an curiousity. I've got into the habit of class-ing up functionality
like this just so it's more reusable but ... try this:

DRAT!
You're quite right - Properties can't have ByRef Arguments.
Public Shared Property Entry _
( ByRef srText as String _
, ByVal iaIndex as Integer _
) as String

Short of "box"ing the argument into a containing Object (with a String
property holding the string you want to manipulate, maybe you /can't/
do this...

Regards,
Phill W.
 
G

Gary Kahrau

Cor,

You missed the point!
I know they are the same in both versions.

It seems impossible to write the statement/function LIKE mid in
vb.net. Try to write your own Mid function.

Without ByRef, you can't write a statement LIKE mid.

Mid(MyString, 5, 3) = "fox"

If you review the thread, Phil W has come to the same conclusion.
 
A

Armin Zingler

Gary Kahrau said:
It seems impossible to write the statement/function LIKE mid in
vb.net. Try to write your own Mid function.


Yes, it's impossible, and that's good. The old syntax is only there for
historic reasons. I don't understand why they kept it. It makes you believe
you would change parts of a string, but it doesn't.


Armin
 
A

_AnonCoward

:
: I want to create a function and can only get half way to my goal.
:
: dim sStr as string
: sStr = Entry(2,"a,b,c,d") ' Sets sStr = "b"
: Entry(2,sStr) = "B" ' Sets sStr = "a,B,c,d"
:
:
: I tried create a public property. However, the Set does not allow
: ByRef. How do I work around this?


I think this is what you're looking for. Note how I changed 2nd line.
Also be aware, the arrays are 0 based, so the '2' will grab the *3rd*
element of the array, not the 2nd. If that won't do what you want,
you'll need to modify this code accordingly.


---------------------------------------------
Option Strict

Imports Microsoft.Visualbasic
Imports System

Public Module [module]
Public Sub Main
Dim sStr as string
sStr = Entry(2,"a,b,c,d")

Console.WriteLine(sStr)

'THIS HAS BEEN MODIFIED
'Entry(2,sStr) = "B"
sStr = "a,b,c,d"
Entry(2,sStr,"B")

Console.WriteLine(sStr)
End Sub

Public Function Entry(n As Integer, s As String) As String
Dim sArr() As String = s.split(","c)
If n > UBound(sArr) OrElse n < LBound(sArr) Then
Return ""
Else
Return sArr(n)
End If
End Function

Public Sub Entry(n As Integer, ByRef s As String, Value As String)
Dim sArr() As String = s.split(","c)
If n > UBound(sArr) OrElse n < LBound(sArr) Then
Return
Else
sArr(n) = Value
s = Join(sArr, ","c)
End If
End Sub
End Module
 
C

Cor Ligthert [MVP]

Gary,
You missed the point!
I know they are the same in both versions.

It seems impossible to write the statement/function LIKE mid in
vb.net. Try to write your own Mid function.

Without ByRef, you can't write a statement LIKE mid.

Mid(MyString, 5, 3) = "fox"

I think that you are right, that is not possible in any program language.

For others who read this thread, this would be more normal.

\\\
Private Sub mySub
MessageBox.Show(mymid("The fox jumps over whatever"))
End Sub
Public Function mymid(ByVal myString As String) As String
Return Mid(myString, 5, 3) 'where mid can be any code
End Function
///

This shows "fox" again

I hope this helps,

Cor
 
S

Stephany Young

How about a bit of overloading:

Public Shared Function Entry _
(ByVal index as integer, _
ByVal value as string) As String

Return value.Split(","c)(index - 1)

End Function

Public Shared Function Entry _
(ByVal index as integer, _
ByVal value as string, _
ByVal _newvalue as String) As String

Dim _s() As String = value.Split(","c)

_s.SetValue(value, index - 1)

Return = String.Join(",", _s)

End Function

Dim _s As String

_s = Entry(2, "a,b,c,d")

Console.Writeline(_s) ' Should be b

_s = Entry(2, "a,b,c,d", "B")

Console.Writeline(_s) ' Should be a,B,c,d
 
D

Dragon

It seems impossible to write the statement/function LIKE mid in
vb.net. Try to write your own Mid function.

"Assignmentish" use of Mid function is IMHO a terrible hack, which can't
(and must not) be recreated. Statement like:

~
Mid(MyString, 5, 3) = "fox"
~

is converted behind-the-scenes to:

~
CompilerServices.StringType.MidStmtStr(MyString, 5, 3, "fox")
~

Roman
 
J

Jay B. Harlow [MVP - Outlook]

Gary,
As I suspect you are figuring out.

Functions cannot be the target of an assignment! Period!

Although Mid looks like a function that is a target of an assignment, its
not, its a Statement!

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vblr7/html/vastmMid.asp

Statements: such as Mid, If, For are translated into specific IL
instructions by the compiler.

IMPORTANT: Do not confuse the above Mid Statement with the Mid function.

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vblr7/html/vafctMid.asp


My first thought was using a Shared Default property to update the string:

Public Class Entry
Public Default Shared Property Item(ByVal index As Integer, ByRef
input As String) As String
Get
...
End Get
Set(ByVal value As String)
...
End Set
End Property
End Class

| dim sStr as string
| sStr = Entry(2,"a,b,c,d") ' Sets sStr = "b"
| Entry(2,sStr) = "B" ' Sets sStr = "a,B,c,d"

Unfortunately Default properties cannot Shared, so you would need to
explicitly give the property name as in:

| dim sStr as string
| sStr = Entry.Item(2,"a,b,c,d") ' Sets sStr = "b"
| Entry.Item(2,sStr) = "B" ' Sets sStr = "a,B,c,d"

Further you cannot have a ByRef parameter on a property (as logically it
doesn't make sense). If String was mutable class then the property
Hack/trick might be an option...


In which case I would consider a Get & Set method, something like:

Public Class Entry

Public Shared Function [Get](ByVal index As Integer, ByVal input As
String) As String
Dim values() As String = input.Split(","c)
Return values(index - 1)
End Function

Public Shared Sub [Set](ByVal index As Integer, ByRef input As
String, ByVal value As String)
Dim values() As String = input.Split(","c)
values(index - 1) = value
input = String.Join(","c, values)
End Sub

End Class

Dim sStr, value As String
sStr = "a,b,c,d"
value = Entry.Get(2, sStr) ' Sets value = "b"
Entry.Set(2, sStr, "B") ' Sets sStr = "a,B,c,d"

Alternatively I would consider making sStr itself a class.

Public Class Entry

Dim values() As String

Public Sub New(ByVal input As String)
values = input.Split("c"c)
End Sub

Default Public Property Item(ByVal index As Integer) As String
Get
Return values(index - 1)
End Get
Set(ByVal value As String)
values(index - 1) = value
End Set
End Property

Public Overrides Function ToString() As String
Return String.Join(","c, values)
End Function

End Class


Dim sStr As New Entry("a,b,c,d")
Dim value As String
value = sStr(2) ' Sets sStr = "b"
sStr(2) = "B" ' Sets sStr = "a,B,c,d"

Especially if there was other behavior that could be assigned to the Entry
class.

Hope this helps
Jay

|I want to create a function and can only get half way to my goal.
|
| dim sStr as string
| sStr = Entry(2,"a,b,c,d") ' Sets sStr = "b"
| Entry(2,sStr) = "B" ' Sets sStr = "a,B,c,d"
|
|
| I tried create a public property. However, the Set does not allow
| ByRef. How do I work around this?
|
|
| -----------------------------------------------------------
| Gary Kahrau
| (e-mail address removed)
| -----------------------------------------------------------
 
J

Jay B. Harlow [MVP - Outlook]

Stephany,
The second overload would not need to be a Function, it could be a Sub, with
a ByRef parameter. To "maintain" the "original" syntax I would consider
making it a Sub.

| Public Shared Sub Entry _
| (ByVal index as integer, _
| ByRef value as string, _
| ByVal _newvalue as String)
|
| Dim _s() As String = value.Split(","c)
|
| _s.SetValue(value, index - 1)
|
| value = String.Join(",", _s)
|
| End Sub

| _s = "a,b,c,d"
| Entry(2, _s , "B")

Hope this helps
Jay


| How about a bit of overloading:
|
| Public Shared Function Entry _
| (ByVal index as integer, _
| ByVal value as string) As String
|
| Return value.Split(","c)(index - 1)
|
| End Function
|
| Public Shared Function Entry _
| (ByVal index as integer, _
| ByVal value as string, _
| ByVal _newvalue as String) As String
|
| Dim _s() As String = value.Split(","c)
|
| _s.SetValue(value, index - 1)
|
| Return = String.Join(",", _s)
|
| End Function
|
| Dim _s As String
|
| _s = Entry(2, "a,b,c,d")
|
| Console.Writeline(_s) ' Should be b
|
| _s = Entry(2, "a,b,c,d", "B")
|
| Console.Writeline(_s) ' Should be a,B,c,d
|
|
| | > | >> | >> > Using a class requires as new instance each time and the extra step
| >> > of assigning the variable to the text property.
| >> >
| >> > It seems like it is impossible to create a statement/function like
| >> > MID.
| >>
| >> In all fairness, VB 'Proper's Mid Statement/Function/Hybrid *is* a
| >> bit of an curiousity. I've got into the habit of class-ing up
| > functionality
| >> like this just so it's more reusable but ... try this:
| >
| > DRAT!
| > You're quite right - Properties can't have ByRef Arguments.
| >
| >> Public Shared Property Entry _
| >> ( ByRef srText as String _
| >> , ByVal iaIndex as Integer _
| >> ) as String
| >
| > Short of "box"ing the argument into a containing Object (with a String
| > property holding the string you want to manipulate, maybe you /can't/
| > do this...
| >
| > Regards,
| > Phill W.
| >
| >
|
|
 
A

_AnonCoward

:
: Cor,
:
: I don't care about the programming technique.
:
: It seems like it is impossible to create a statement/function like MID
: with vb.net. The Entry Function/Statement that I am trying to create
: is very much the the mid Function/Statement usage.
:
: FirstWord = Mid(MyString, 1, 3)
: Mid(MyString, 5, 3) = "fox"


Actually, you can mimic the MID statement of VB6. I'm not sure why you'd
want to do it, but it can be done. This example is not an exact replica
of the VB6 Mid$ statement, but it's similar enough to satisfy the
requirement that it be "like" Mid:


---------------------------------------
Option Strict

Imports Microsoft.Visualbasic
Imports System
Imports System.Text

Public Module [module]
Public Sub Main
Dim sStr as string = "abcdefgh"
Console.WriteLine(sStr)

MyMid(sStr, 2, "BCD")
Console.WriteLine(sStr)

MyMid(sStr, 2, 2, "bcd")
Console.WriteLine(sStr)

MyMid(sStr, 4, "wxyz")
Console.WriteLine(sStr)

MyMid(sStr, 7, "wxyz")
Console.WriteLine(sStr)

Console.WriteLine(MyMid(sStr, 3))
Console.WriteLine(MyMid(sStr, 3, 2))
End Sub

Public Function MyMid(ByRef [string] As String, _
start As Integer) As String
Return [string].substring(start - 1)
End Function

Public Function MyMid(ByRef [string] As String, _
start As Integer, _
length as Integer) As String
Return [string].substring(start - 1, length)
End Function

Public Sub MyMid(ByRef [string] As String, _
start As Integer, _
value As String)
MyMid([string], start, value.length, Value)
End Sub

Public Sub MyMid(ByRef [string] As String, _
start As Integer, _
length As Integer, _
value As String)
Dim index As Integer
Dim offset As Integer
Dim c() As Char = [string].toCharArray

start = start - 1
With New StringBuilder()
For index = 0 To c.Length - 1
If index < start Then
.Append(c(index))
ElseIf index > (start + length) Then
.Append(c(index))
Else
.Append(Left(value, length))
index += length
If index <= UBound(c) Then
.Append(c(index))
End If
End If
Next
If .Length > [string].length Then
.Length = [string].length
End If
[string] = .toString
End With
End Sub

End Module
---------------------------------------


<snip>


Ralf
--
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top