I have this bit of code that is being converted from vb6 to vb.net. I need to know what LenB is doing in this bit of code.
Dim singleValue As Single 'var for conversion use(4byte -> 1single)'
Dim bytes() As Byte
Dim valueB() As Byte 'this gets set elsewhere and is redim-d to its size'
For n = 0 To CDbl(ItemNumberCombo.Text) - 1
'bytes() -> single'
'UPGRADE_ISSUE: LenB function is not supported.'
ReDim bytes(LenB(singleValue) - 1)
bytes(3) = valueB(n * 4)
bytes(2) = valueB(n * 4 + 1)
bytes(1) = valueB(n * 4 + 2)
bytes(0) = valueB(n * 4 + 3)
'UPGRADE_ISSUE: LenB function is not supported.'
'UPGRADE_ISSUE: VarPtr function is not supported. '
Call memcpy(VarPtr(singleValue), VarPtr(bytes(0)), LenB(singleValue))
'display the result'
DText(n).Text = VB6.Format(singleValue, "0.000000E+00") 'CStr(singleValue)'
If DataSaveCheckBox.CheckState = 1 And FileNameText.Text <> "" Then
csvOutput = csvOutput & DText(n).Text & ","
End If
Next n
Am I right in thinking that bytes is always ReDim'ed to the same size? By the looks of it 4 elements.
Why then use LenB to ReDim if you could just use a number? And why ReDim in the loop at all?
LenB() returns the length in bytes of a variable. The most common example is for strings, where it returns the size of the string in bytes rather than the number of characters, regardless of character encoding. For other types it returns the size of an object- the size of a single being 4. The reason they would do this is that they wanted the code to survive if a future version of visual basic ever changed the size of a single (never mind hard-coding the number 4 when assigning to the byte array).
When upgrading LenB() to .Net, for strings use System.Text.Encoding.Unicode.GetBytes() to get an array already populated with your string text bytes. Remember that .Net always uses Unicode for strings internally. If you really need a different encoding there are a number of alternatives in the Encoding namespace. For other types use the BitConverter class. Either way, don't go line by line as the newer methods take away a lot of the busy work.
Here — I'll help you out with the conversion some:
(earlier)
Dim csvOutput As New StringBuilder()
(later)
Dim valueB() As Byte 'this gets set elsewhere and is redim-d to its size'
Dim singleValue As Single 'var for conversion
' Included because the original developer was concerned the size of a single could change
Dim singleSize As Integer = BitConverter.GetBytes(singleValue).Length
Dim NumberItems As Double
If Double.TryParse(ItemNumberCombo.Text, NumberItems) Then
For n As Integer = 0 To NumberItems - 1
singleValue = BitConverter.ToSingle(valueB, n * singleSize)
'display the result
DText(n).Text = singleValue.ToString("E6") 'CStr(singleValue)
If DataSaveCheckBox.CheckState = 1 AndAlso Not String.IsNullOrEmpty(FileNameText.Text) Then
csvOutput.Append(DText(n).Text & ",")
End If
Next n
Else
' Handle Invalid ComboBox value here- may not be an issue for you
End If
Note that this code also demonstrates a StringBuilder as a much better way to build your csv data, the AndAlso operator, the .TryParse() methods, String.IsNullOrEmpty(), and Standard Format Strings, all of which are intended to replace constructs or techniques from vb6.
Trying to explain bad code... is just an effort in futility.
Interesting way to fill a Single by loading a byte array.
The LenB function gives you the length in bytes of a variable.
Yes it will always return 4 when passed a Single variable type.
My guess for the redim is so the array gets initialized instead of preserved.
But since it then assigns all 4 bytes, it isn't technically needed and is probably just defensive programming. Defensive programming might also explain the LenB. In case Single changes size in the future.
Related
Currently I have these data inside my textfile.txt:
I want to split them up into a 2D array when a comma is met. How do I do so?
This is my code for now. Please do point out the mistakes I made.
Dim priceArray(5, 2) As String
Dim i, j As Integer
Dim data As String
Dim oilpriceFile As System.IO.StreamReader
oilpriceFile = New System.IO.StreamReader("C:\Users\zack\OneDrive\Desktop\oilprice.txt")
For i = 0 To UBound(priceArray)
data = oilpriceFile.ReadLine()
For j = 0 To UBound(priceArray)
priceArray(i, j) = data.Split(",") //there's an error stating "value of type string() cannot be converted into string"
j = j + 1
Next
i = i + 1
Next
There are several things you are doing incorrectly.
First turn on Option Strict in the Project Properties and also under Options on the Tools menu.
You do not declare the increment variables used in For loops.
StreanReader needs to be disposed. You should know this because you always check the documentation before you use an unfamiliar framework class. When you do this you will see a Dispose method. When you see this, it needs to be called when you are through with using it. See Using...End Using.
You don't have to deal with Dispose if you use File.ReadAllLines(). This returns an array of the lines in the file.
A For loop increments the value of the first variable automatically. You do not increment it explicitly or you will skip values.
You have defined a 2 dimensional array. When you call UBound on the array, which dimension are you calling it on?? You must indicate which dimension you are asking about.
UBound(priceArray, 1) and UBound(priceArray, 2)
Where 1 and 2 designate the dimension you are getting.
This is the old vb6 way to get this value. The .net framework provides GetUpperBound() for the same purpose. This method uses the .net zero based rank where GetUpperBound(0) will return upper bound of the first dimension of the array.
The next problem is the use of Spilt. Split returns an array of strings and you are trying to assign it to a single string. It takes a Char as a parameter. You have passed a String. To tell the compiler that you intend a Char follow the String by a lower case c.
A side note. // is the comment indicator in C#. In vb.net use the single quote '.
Private Sub OPCode()
Dim priceArray(5, 2) As String
Dim lines = File.ReadAllLines("C:\Users\zack\OneDrive\Desktop\oilprice.txt")
For i = 0 To priceArray.GetUpperBound(0)
Dim data = lines(i)
Dim splits = data.Split(","c)
For j = 0 To priceArray.GetUpperBound(1)
priceArray(i, j) = splits(j)
Next
Next
End Sub
So i want to perform some code N times. N is textbox's value (e.g: 12).
I have no idea how to accomplish this, but something like this is on my mind:
For Each i as 1 in textbox1.text
'some code
Next
or
dim num1 as integer = 0
While num1 < textbox1.text
'some code
num1 += 1
Next
Those were just some ideas that were on my mind when i though about this question, none of above is tested nor tried to code.
Any ideas?
First and foremost, turn on Option Strict. This will save you time in the long run by converting possible runtime errors into compiler errors. At the top of the code file:
Option Strict On
It can also be set for the entire project:
Project Properties -> Compile Tab -> Option Strict selector: On
You can also make it the default for all new projects via:
Tools -> Options -> Projects and Solutions -> VB Defaults
What it Does
TextBox.Text always contains text (hence the clever names). "12" is just a string and is not the same as 12. So, before you can use it, you need to convert from string to integer. Note: If you want to restrict user input to numbers consider using a NumericUpDown.
There are several ways to convert, but considering that the data comes from a user, we have to allow that they may enter "I like pie" instead of numerals. So, we want to use the safest method which in this case is Integer.TryParse:
' declare int var to hold the result
Dim LoopCount As Integer
If Integer.TryParse(TextBox132.Text, LoopCount) Then
' success! LoopCOunt contains the integer value of the Text control
For n As Integer = 0 To LoopCount - 1
' some code to do something
Next
Else
' failed - scold the user with a MessageBox
End if
The comments in the code explain, but first you declare an integer variable to hold the converted value. Integer.TryParse is a function which will return True/False. If it succeeds, your variable will hold the integer value.
See Converting DataTypes for Option Strict for other convert methods and cases where they are appropriate.
This might work, I haven't tried:
Dim repeat_times as Integer = 0
Do Until repeat_times = 10 'times you want to repeat
repeat_times = repeat_times + 1
Console.WriteLine("Hello World") 'or anything you want
Loop
For n As Int32 = 0 To TextBox1.text - 1 was an answer for my question.
I am new to VB and have a simple program. I just want the program to display in a message box the number of characters in a long variable. I am using the Len() function. The code is as follows.
Try
Dim num As Long = 1230456985623145
Dim numLength As Long
numLength = Len(num)
MessageBox.Show(numLength.ToString())
Catch ex As Exception
End Try
Simple. However when i run the function, it returns a value of 8 instead of the actual value. Can anyone tell me what i'm doing wrong. Do i need to add anything else to obtain the right value
It should be like this:
Dim num As Long = 1230456985623145
Dim numLength As Long
numLength = Len(num.ToString())
MessageBox.Show(numLength.ToString())
If you forgot to use ToString(), Len function returns the number of bytes required to store the variable, which is 8 because a Long variable requires 8 byte to store.
Definition of Len function in MSDN:
Returns an integer containing either the number of characters in a
string or the nominal number of bytes required to store a variable.
In your original code (before your edit):
You use Name as a parameter in your Len function. Since your code is a WinForm, the Name is a property of the Form. Check the value of the Name using:
MessageBox.Show(Name)
String.Length
Using the Length property of a string is more preferable. Like Adrian Wragg said, it's easier to convert your codes between the languages which are supported by .Net (C#, VB and F#).
Hey guys I'm trying to make a program that helps people encrypt messages and decrypt messages using the Caesar shift cipher, I know it's probably already been done, I want to have a go myself though.
The problem I've been having is when it comes to encrypting the text. The user selects a number (between 1-25) and then the application will change the letters corresponding to the number chosen, e.g. if the user inputs "HI" and selects 2, both characters are moved two places down the alphabet outputting "JK". My main problem is the replacing characters though, mostly because I've set up the program to be able to encrypt large blocks of text, because my code is:
If cmbxKey.Text = "1" Then
If txtOutput.Text.Contains("a") Then
sOutput = txtOutput.Text.Replace("a", "b")
txtOutput.Text = sOutput
End If
If txtOutput.Text.Contains("b") Then
sOutput = txtOutput.Text.Replace("b", "c")
txtOutput.Text = sOutput
End If
End If
This means if the user inputs "HAY" it will change it to "HBY" and then because of the second if statement it will change it to "HCY" but I only want it to be changed once. Any suggestions to avoid this???? Thanks guys
Since you want to shift all characters, start out by looping though the characters using something like ToArray:
For each s as string in txtOutput.Text.ToArray
'This will be here for each character in the string, even spaces
Next
Then, rather than having cases for every letter, look at it's ascii number:
ACS(s)
...and shift it by the number you want to. Keep in mind that if the number is greater than (I don't know if you want upper/lower case) 122, you want to subtract 65 to get you back to "A".
Then you can convert it back into a character using:
CHR(?)
So this might look something like this:
Dim sb as new text.StringBuilder()
For each s as string in txtOutput.Text.ToArray
If asc(s) > 122 Then
sb.append(CHR(ASC(s) + ?YourShift? - 65)
Else
sb.append(CHR(ASC(s) + ?YourShift?)
END IF
Next
txtOutput.Text = sb.ToString
A very simple method of changing your application while keeping your strategy is to replace the lower case characters with upper case characters. Then they won't be recognized by the Replace method anymore.
Obviously, the problem is that you want to implement an algorithm. In general, an algorithm should be smart in the sense that you don't have to do the grunt work. That's why a method such as the one presented by Steve is smarter; it doesn't require you to map each character separately, which is tedious, and - as most tedious tasks - error prone.
One big issue arise when you're facing a String that the basic Alphanumeric table can't handle. A String that contains words like :
"Déja vu" -> The "é" is going to be what ?
And also, how about encoding the string "I'm Aaron Mbilébé" if you use .ToUpper().
.ToUpper returns "I'M AARON MBILÉBÉ".
You've lost the casing, and how do you handle the shifting of "É" ?
Of course, a code should be smart as pointed above, and I was used to deal with strings just by using the System.Text.ASCIIEncoding to make things easier. But from the moment I started to use large amount of textual datas, sources from the web, files (...) I was forced to dig deeper, and seriously consider string encoding (and System Endianness by the way, when coding and decoding string to/from array of bytes)
Re-think of what do you really want in the end. If you're the only one to use your code, and you're certain that you'll only use A..Z, 0..9, a..z, space and a fixed amount of allowed characters (like puntuation) then, just build a Table containing each of those chars.
Private _AllowedChars As Char() = { "A"c, "B"c, ... "0"c, "1"c, .. "."c, ","c ... }
or
Private _AllowedChars As Char() = "ABCDEF....012...abcd..xyz.;,?:/".ToCharArray()
Then use
Private Function ShiftChars(ByVal CurrentString As String, ByVal ShiftValue As Integer) As String
Dim AllChars As Char() = CurrentString.ToCharArray()
Dim FinalChars As Char()
Dim i As Integer
FinalChars = New Char(AllChars.Length - 1) {} ' It's VB : UpperBound is n+1 item.
' so n items is UpperBound - 1
For i = 0 To AllChars.Length - 1
FinalChars(i) = _AllowedChars((Array.IndexOf(_AllowedChars, AllChars(i)) + ShiftValue) Mod _AllowedChars.Length)
Next
Return New String(FinalChars)
End Function
And
Private Function UnShiftChars(ByVal CurrentString As String, ByVal ShiftValue As Integer) As String
' ... the same code until :
FinalChars(i) = _AllowedChars((Array.IndexOf(_AllowedChars, AllChars(i)) - ShiftValue + _AllowedChars.Length) Mod _AllowedChars.Length)
' ...
End Function
^^ Assuming ShiftValue is always positive (defined once)
But again, this only works when you have a predefined set of allowed characters. If you want a more flexible tool, you ought to start dealing with encodings, array of byte, BitConverter and have a look at system endianness. That's why I asked if someone else is goind to use your application : let's try this string :
"Xin chào thế giới" ' which is Hello World in vietnamese (Google Trad)
In that case, you may give up..? No ! You ALWAYS have a trick in your cards !
Just create your allowed chars on the fly
Private _AllowedChars As New SortedList(Of Char, Char)
-> get the string to encode (shift)
Private Function ShiftChars(ByVal CurrentString As String, ByVal ShiftValue As Integer) As String
Dim AllChars As Char() = CurrentString.ToCharArray()
Dim FinalChars As Char()
Dim i As Integer
' Build your list of allowed chars...
_AllowedChars.Clear()
For i = 0 To AllChars.Length - 1
If Not _AllowedChars.ContainsKey(AllChars(i)) Then
_AllowedChars.Add(AllChars(i), AllChars(i))
End If
Next
' Then, encode...
FinalChars = New Char(AllChars.Length - 1) {}
For i = 0 To AllChars.Length - 1
FinalChars(i) = _AllowedChars.Keys.Item((_AllowedChars.IndexOfKey(AllChars(i)) + ShiftValue) Mod _AllowedChars.Count)
Next
Return New String(FinalChars)
End Function
The same for Unshift/decode.
Note : in foreing languages, the resulting string is pure garbage and totally unreadable, unless you (un)shift the chars again.
However, the main limitation of this workaround is the same as the fixed chars array above : Once you encode your string, and add a char in your encoded string that doesn't exists in the initial generated allowed chars, then you've nuked your data and you won't be able to decode your string. All you'll have is pure garbage.
So one day... one day maybe, you'll have to dig deeper at the byte level of the thing, in a defined extended encoding (Unicode/UTF8/16) to secure the integrity of your data.
this is my code to convert string to hex
Function StringToHex(ByVal text As String) As String
Dim xhex As String
For i As Integer = 0 To text.Length - 1
xhex &= Asc(text.Substring(i, 1)).ToString("x").ToUpper
Next
Return xhex
End Function
I convert string file to hex with this code, but if size file more than 1MB my program is not responding
how to make this code more efficient for size file more than 1MB sorry my english is bad
As I said in my initial comment, your current approach is creating a new string each time you go through the For loop. Strings are immutable (can't be changed) in .NET - so for example if you have 3000 characters in the string, xHex = &a is going to create 3,000 strings, and that's just for the first part. Then you have a Substring, then a ToString and finally a ToUpper - so if my math is right, you're creating 4 strings for every character in the input string (so if you have 3,000 characters that 12,000 additional strings).
The call to Substring is unnecessary - you can treat the string as an array and access each character in the string as an array index, so now you would have:
xhex &= Asc(text(i)).ToString("x").ToUpper
You can also get rid of the call .ToUpper() by using an uppercase "X" in the call to .ToString() - so now you have:
xhex &= Asc(text(i)).ToString("X")
You could also make xhex a StringBuilder, and then you'd only be creating one additional string each time through the loop (the call to .ToString()). Putting that all together gives you this:
Dim xhex As StringBuilder = New StringBuilder()
For i As Integer = 0 To text.Length - 1
xhex.Append(Asc(text(i).ToString("X"))
Next
Return xhex.ToString()
That may help with the process, but if the string is really large you may still run into memory issues. IF the file is really large I'd recommend reading it using a Stream and processing the Stream one byte at a time (or several bytes at time, your choice).
I would also suggest Googling for VB.NET convert string to hex, as there are many examples of other ways to do this.