I struggling to convert back the BCD to STR, if anyone quickly knows how to do it I really appreciate it.
Public Function strBCDToStr(ByVal shIn As Short) As String
'BCD to Text
Dim m_strTemp As String = ""
For m_iLoop As Integer = 1 To 4
m_strTemp = Chr((shIn Mod 16) + 48) & m_strTemp
shIn = (shIn \ (16S))
Next
strBCDToStr = m_strTemp
End Function
Since we're only dealing with short this works out as a simple mapping to standard hex notation. We can reverse it like this:
Public Function StrToShort(bcd As String) As Short
bcd = bcd.Replace(":", "A").Replace(";", "B").Replace("<", "C").Replace("=","D").Replace(">", "E").Replace("?", "F")
Return Convert.ToInt16(bcd, 16)
End Function
Technically I could even combine those two statements and make this method a one-liner.
See it here for every possible input up to the limit of fiddle:
https://dotnetfiddle.net/bvmdKC
We can also simplify the original code like so:
Public Function ShortToHexStr(input As Short) As String
Return input.ToString("X").
Replace("A", ":").
Replace("B", ";").
Replace("C", "<").
Replace("D", "=").
Replace("E", ">").
Replace("F", "?").
PadLeft( 4, "0"c)
End Function
Related
I hope the title of the post isn't too much of a mess. I'm reviewing some course material from last week, and there is just one thing I don't understand in regard to this particular structure and the add and subtract functions in it:
Structure ComNum
Dim Re As Double
Dim Im As Double
Function add(ByVal br As ComNum) As ComNum
add.Re = br.Re + Re
add.Im = br.Im + Im
End Function
Function subt(ByVal br As ComNum) As ComNum
subt.Re = br.Re - Re
subt.Im = br.Im - Im
End Function
End Structure
Sub Main()
Dim a, b, c As ComNum
a.Re = 2
a.Im = 3
b.Re = 4
b.Im = 5
c = a.add(b).add(b).subt(b)
Console.WriteLine("The second number added twice and subtracted once from the first number gives {0}+{1}i", c.Re, c.Im)
End Sub
Now, the way I understand functions is that once anything is returned from it, execution of the function stops at that exact line where the value is returned and nothing after it gets executed. According to that, it should add the real part and exit the function.
I know I'm missing a key thing here and I'd appreciate it if someone could explain this to me.
The way you have this setup those functions are creating a new, empty ComNum structure each time you call them (named either add or subt based on the function name). Unless you manually return them early it will just default to returning the function named structure.
Function add(ByVal br As ComNum) As ComNum
add.Re = br.Re + Re
add.Im = br.Im + Im
End Function
Is basically doing the equivalent of:
Dim add As New ComNum
add.Re = br.Re + Re
add.Im = br.Im + Im
Return add
Though like Lars pointed out I'm not sure why you'd want this to be a function vs a sub. Using it the way you have it setup now requires you to do something like this to get the add/subtract values because you need to capture the returned ComNum object.
Dim a As New ComNum With {.Im = 1, .Re = 1}
'Im = 6, Re = 6
a = a.add(New ComNum With {.Im = 5, .Re = 5})
Doing something like this makes more sense to me.
Structure ComNum
Dim Re As Double
Dim Im As Double
Sub add(ByVal br As ComNum)
Re += br.Re
Im += br.Im
End Sub
Sub subt(ByVal br As ComNum)
Re -= br.Re
Im -= br.Im
End Sub
End Structure
Then you could just call it this way to update the struct without having to capture the returned values.
a.add(New ComNum With {.Im = 5, .Re = 5})
Edit: Knowing more now how the exercise is supposed to be performed I'd suggest something like this for the struct:
Public Overrides Function ToString() As String
Return String.Format("Re: {0} Im: {1}", Re, Im)
End Function
Then you could call the .ToString() method like this. Though, just a thought.
Console.WriteLine("The second number added twice and subtracted once from the first number gives {0}", c.ToString())
In my class today I was told change some of my sub-procedures to functions, and when I asked why it's better my teacher struggled to answer, generally, i've always thought that functions should only really be used when a value is returned. In the two examples below; is there one method that should be used over the other, or does it not matter? And if it does matter why?
Thanks in advance.
Method 1 (Sub-Proc):
Sub EncryptString(ByVal unkString, ByRef encryptedString)
For i = 1 To Len(unkString)
encryptedString += "*"
Next
End Sub
Method 2 (Function):
[In main I assign the variable "encryptedString" to this function].
Function encryptString(ByVal unkString) As String
For i = 1 To Len(unkString)
encryptString += "*"
Next
End Function
You've misunderstood what they're trying to tell you. In your Function example there is no difference. What your teacher is expecting is like this:
Function EncryptString(ByVal unkString) As String
Dim encryptedString As String = ""
For i = 1 To Len(unkString)
encryptedString += "*"
Next
Return encryptedString
End Function
This is a cleaner and more reusable way than modifying a field, an argument passed ByRef, or the underlying variable of the function
Your example show one of the multiple reason, who initialize the data is unclear. With your sample code, the first option would append to the passed string while the second would create a new string.
The first method would have to specify if it needs an empty string or explain why it appends. While the second method clearly show that a new string will be returned.
Sub Main()
Dim u, e As String
u = "123"
e = "123"
EncryptString1(u, e)
Console.WriteLine(e) ' Display: 123***
u = "123"
e = "123"
e = encryptString2(u)
Console.WriteLine(e) ' Display: ***
Console.ReadLine()
End Sub
Sub EncryptString1(ByVal unkString As String, ByRef encryptedString As String)
For i As Integer = 1 To Len(unkString)
encryptedString += "*"
Next
End Sub
Function encryptString2(ByVal unkString As String) As String
encryptString2 = ""
For i As Integer = 1 To Len(unkString)
encryptString2 += "*"
Next
End Function
Please have option strict on. Also, personally, I rather create a variable instead of using the function name, use .Length instead of Len() and concatenate with & instead of +.
Function encryptString3(ByVal unkString As String) As String
Dim encryptedString As String = ""
For i As Integer = 1 To unkString.Length
encryptedString &= "*"
Next
Return encryptedString
End Function
Or just use the New operator of the String class.
Dim encryptedString as New String("*"c, unkString.Length)
Well, when I was learning this stuff, it was always to use functions to calculate values and subs to do other stuff. I guess for something very general, it doesn't really matter which methodology you use, as you have illustrated in your example. See the link below for further discussion on this topic.
http://analystcave.com/vba-function-vs-vba-sub-procedures/
I'm looking for a function that will take two parameters (a string and an integer) and print the string on a new line for each count of the integer.
For example, the parameters ("test", 2) would return:
test
test
I'm sure this is a simple bit of code, but I have never worked with VB before.
Any help is greatly appreciated!
#Constuntine had put me on the right path. The code I ended up using was:
Public Function printText(text As String, number As Integer)
dim index as integer
dim s as string = ""
for index = 0 to number
if index = number
s = s + text
else
s = s + text + VBCRLF
end if
Next index
return s
End Function
Here is a basic function that should accomplish what you need
Public Function printNumofTimes(text As String, number As Integer)
for index = 1 to number
Debug.Print text
Next index
End Function
This built-in method comes really close. You just have to provide the "print" action.
Strings.StrDup(count, text + vbCrLf)
I have looked on the web and I cannot find anything that helps me, all I can find is changing the characters into ASCII or Hexadecimal. However I would like to do it a different way. For example, say the string that got passed in was abcdef, I would like to have a key which changes these characters into another string such as qwpolz. Is there an easier way than declaring each character in the alphabet to be another character like:
Dim sText As String = "Hello"
Dim sEncode As String = ""
Dim iLength As Integer
Dim i As Integer
iLength = Len(sText)
For i = 1 To iLength
sEncode = sEncode ????
Next
Return sEncode
And then have a very lengthy loop which checks for these loops? There must be a much simpler way. Can anybody help by pointing me in the right direction?
Edit: Why downvote? Seriously, it's a legitimate question. Instead of downvoting for no reason, just move onto another question.
Well actually, this sounds like a Caesar sipher
Private Overloads Shared Function Encrypt(ByVal ch As Char, ByVal code As Integer) As Char
If Not Char.IsLetter(ch) Then
Return ch
End If
Dim offset As Char = IIf(Char.IsUpper(ch), "A", "a")
Return CType((((ch + (code - offset)) Mod 26) + offset),Char)
End Function
Private Overloads Shared Function Encrypt(ByVal input As String, ByVal code As Integer) As String
Return New String(input.ToCharArray.Select(() => { }, Encrypt(ch, code)).ToArray)
End Function
Private Shared Function Decrypt(ByVal input As String, ByVal code As Integer) As String
Return Encrypt(input, (26 - code))
End Function
Note that this assumes, that you use English alphabet. In general case where for example you have 'ä', 'ö', 'š', 'ž', 'ß', 'õ', 'ü' etc. this would not work. In that case it is simpler to just create a list/dictionary of your ordered alphabet and use it.
Example use:
encrypted = Encrypt(sText, 5)
decypted = Decrypt(encrypted, 5)
Sounds as if you want to modify a string by replacing each character with a different character according to a mapping table. An efficient approach is to use a Dictionary(Of Char, Char). But easier to write and maintain is something like this:
Shared ReadOnly replaceChars As String = "abcdef"
Shared ReadOnly withChars As String = "qwpolz"
Public Shared Function ReplaceAll(input As String) As String
Dim newChars = From c In input
Let index = replaceChars.IndexOf(c)
Select If(index >= 0, withChars(index), c)
Return String.Concat(newChars)
End Function
So the first string contains the chars that you want to replace and the second the replacement characters. Both strings must have the same length.
If you want to support case insensitivity:
Public Shared Function ReplaceAll(input As String, comparison As StringComparison) As String
Dim newChars = From c In input
Let index = replaceChars.IndexOf(c.ToString(), comparison)
Select If(index >= 0, withChars(index), c)
Return String.Concat(newChars)
End Function
Note that this is also a loop. There is no way to avoid some kind of loops if you want to replace multiple characters or strings.
I'm simply wondering what symbol/character I can use to define any character in a string...
Basically I have a number of records with RR 2, RR#2, RR1, RR 1, etc. and I want to use a symbol that will define anything after the RR and replace it with nothing "". I know in SQL it's the "%" symbol, but not sure in VBA.
I am using the Replace function in ArcGIS field calculator.
I tried searching but cannot come up with the right question to find the answer I'm looking for.
Any ideas?
Since it's unclear if you want VBA or VB.Net,
Here's a VBA answer just use the ChopString function using the format shown in the Test sub:
Function ChopString(str As String, after As String, Optional caseInsensitive As Boolean = True) As String
Dim x As Long
If caseInsensitive Then
x = InStr(1, str, after, vbTextCompare)
Else
x = InStr(1, str, after, vbBinaryCompare)
End If
If x Then
str = Left(str, x + Len(after) - 1)
End If
ChopString = str
End Function
Sub Test()
Dim OriginalString As String
Dim choppedString As String
OriginalString = "1234RR this will be chopped"
choppedString = ChopString(OriginalString, "RR")
MsgBox choppedString
End Sub
Sadly the .net REPLACE() function doesn't support wildcard characters, you can use a function as described here but it's a bit long winded.