The discussion revolves around troubleshooting a Visual Basic function designed to copy the contents of a file while removing a specified item from a list. The user is experiencing issues where the function does not correctly exclude the desired item, often resulting in the last item being deleted instead. Suggestions include ensuring case insensitivity and trimming whitespace during string comparisons, as well as adjusting the loop to start from zero instead of one. The code logic is clarified, emphasizing that the removePlayer function should process the existing array rather than reading the file again. The conversation highlights the need for precise debugging to identify why the function behaves unexpectedly.
I've only been coding for a few months. While I do enjoy it, my professor dampens my motivation with ruthless grading practices. Thankfully programming is not my major. I didn't even want to learn VB. I was expecting him to teach C++, but whatever.
I'm not even sure where to look for VB debugging tutorials. Any advice?
Advice: what @jtbell said. For your problem debug.print or Console.WriteLine should be sufficient. There are more sophisticated debugging tools in Visual Studio, but I don't have any experience with them.
It looks like you are using Visual Studio.net. I am familiar with VB6. The syntax may vary but the concepts are the same. In VB6 the statement: msgbox("caption", datavariablename1, "; caption2: " & datavariablename2 ...etc. ) will stop execution and bring up a message box with the caption and data as it exists at that point in the program. Press "OK" to continue. You will be able to see what is going on. Just comment it out when you figure out what is wrong and get it running.
Is there a reason to dimension an array here? If all you are doing is copying a file and checking it line by line, you don't need to dimension an array. Just do it line by line: input a line from the source file, check it and decide whether to print it and discard or print it to the output file; then get the next line from the source file; continue until end of the source file (use a do/while loop as has been suggested). It is much simpler and a more general way to do it. Just a suggestion.
AM
#33
phion
Gold Member
175
39
Andrew Mason said:
It looks like you are using Visual Studio.net. I am familiar with VB6. The syntax may vary but the concepts are the same. In VB6 the statement: msgbox("caption", datavariablename1, "; caption2: " & datavariablename2 ...etc. ) will stop execution and bring up a message box with the caption and data as it exists at that point in the program. Press "OK" to continue. You will be able to see what is going on. Just comment it out when you figure out what is wrong and get it running.
Is there a reason to dimension an array here? If all you are doing is copying a file and checking it line by line, you don't need to dimension an array. Just do it line by line: input a line from the source file, check it and decide whether to print it and discard or print it to the output file; then get the next line from the source file; continue until end of the source file (use a do/while loop as has been suggested). It is much simpler and a more general way to do it. Just a suggestion.
As I say, I've only used that in Excel VBA and I've never used VB.net. Might be worth investigating however - you'll only waste a couple of minutes if it doesn't work, and it's quite powerful if it does work.
#35
phion
Gold Member
175
39
Ibix said:
I've only used VBA, but a quick Google suggests that the simple debugging method I use in that ought to work here too.
As I say, I've only used that in Excel VBA and I've never used VB.net. Might be worth investigating however - you'll only waste a couple of minutes if it doesn't work, and it's quite powerful if it does work.
I mean, it's pretty clear that the issue resides in the loops I'm using.
Andrew Mason said:
Is there a reason to dimension an array here? If all you are doing is copying a file and checking it line by line, you don't need to dimension an array. Just do it line by line: input a line from the source file, check it and decide whether to print it and discard or print it to the output file; then get the next line from the source file; continue until end of the source file (use a do/while loop as has been suggested). It is much simpler and a more general way to do it. Just a suggestion.
AM
When I remove the arrays and the for loop and do as you say, the same exact behavior results. Regardless of the name I type to be removed, the last name in the list is removed instead.
Code:
Console.WriteLine("Which player would you like to remove?")
player = Console.ReadLine()
While Not inFile.EndOfStream
copyPlayer = inFile.ReadLine()
If player <> copyPlayer Then
outFile.WriteLine(copyPlayer)
End If
End While
phion, there were so many suggestions to check what happens in the code, why don't you follow them? You keep running the whole code and describing the output with words that can be unclear. That is very inefficient.
I mean, it's pretty clear that the issue resides in the loops I'm using.
When I remove the arrays and the for loop and do as you say, the same exact behavior results. Regardless of the name I type to be removed, the last name in the list is removed instead.
So get the computer to step through the code one instruction at a time. You'll be able to see what's going on in the middle of program execution.
Dumb question - does inFile.ReadLine() strip the newline character? Does Console.ReadLine()? If one is stripping it and one isn't, that would mean that the two strings never match.
#38
phion
Gold Member
175
39
mfb said:
phion, there were so many suggestions to check what happens in the code, why don't you follow them? You keep running the whole code and describing the output with words that can be unclear. That is very inefficient.
I don't know how!
#39
phion
Gold Member
175
39
Ibix said:
Dumb question - does inFile.readLine() strip the newline character? Does Console.readLine()?
I couldn't tell you the answer to that, but it seems important.
You don't know how to add output to your code? You already have that, just not at the places suggested here.
Using a debugger would be even better, with the descriptions how given above. It is not necessary here, however.
"How to test and debug my code" should be the second step after getting a hello world program running.
I couldn't tell you the answer to that, but it seems important.
Text processing is a pain because of details like this. It may or may not be relevant.
Seriously - open the program you just posted in Visual Studio, display the "locals" window, set a breakpoint on the first line and then step through the program. Each time you go round the loop you'll be able to see what's being read in from the file and see if it is what you expected.
The problem at the moment is that you don't know where to look. There's a bug in there...somewhere. If you step through the program you can see what it's got in memory at the point when something goes wrong. That'll help a lot to tell you why it's going wrong.
#42
TurtleMeister
897
90
Some of your functions are making changes to playerList array. By default Visual Basic passes variables by value. That means that the playerList array in the function is just a copy of the playerList array that was sent in the argument list, and any changes made within the function affect only that copy of the original. When the program exits the function the copy is lost. I'm not sure if this is what's causing the problem you're having, but it appears that some of your functions should be passing the playerList array by reference instead of by value.
Some of your functions are making changes to playerList array. By default Visual Basic passes variables by value. That means that the playerList array in the function is just a copy of the playerList array that was sent in the argument list, and any changes made within the function affect only that copy of the original. When the program exits the function the copy is lost. I'm not sure if this is what's causing the problem you're having, but it appears that some of your functions should be passing the playerList array by reference instead of by value.
That could be the problem.
It certainly would explain the behavior of removePlayer described at the start of the thread:
phion said:
Now what it's doing is deleting the last item in the list regardless of what name I specify to be deleted. Strange.
The last item in the list is deleted because he substracts 1 from numPlayers in removePlayers, but the array itself is unchanged..
But it then begs the question why his other methods (that also use the array as a "ByVal" argument) apparently work correctly.
EDIT: Apparently, when you pass an array as argument (even as ByVal), you can still modify the array element apparently.
This means that when you pass a reference type by value, the procedure code has a pointer to the underlying element's data, even though it cannot access the underlying element itself. For example, if the element is an array variable, the procedure code does not have access to the variable itself, but it can access the array members.
And specifically for an array passed "ByVal":
The procedure cannot change the variable but can change members of the instance to which it points.
There really is no alternative but for @phion to correct the obvious errors in his code, and then debug the program using one of the techniques mentioned above.
I mean, it's pretty clear that the issue resides in the loops I'm using.
That may be the case, but don't assume it, debug to make sure.
phion said:
When I remove the arrays and the for loop and do as you say, the same exact behavior results. Regardless of the name I type to be removed, the last name in the list is removed instead.
Code:
Console.WriteLine("Which player would you like to remove?")
player = Console.ReadLine()
While Not inFile.EndOfStream
copyPlayer = inFile.ReadLine()
If player <> copyPlayer Then
outFile.WriteLine(copyPlayer)
End If
End While
This makes sense. You don't touch your array in this modified code. Now this is not the whole removePlayer function. If your modified version still contains the updatedPlayers = numPlayers - 1 instruction, this will obviously make it appear as if the last name of the array is removed, as you won't reach it when you loop the array.
I know you hope someone here will post a working removePlayer function.
Problem is we don't know what removePlayer is supposed to do exactly: reload the file and remove a name from that list, remove a name from the array already in memory, something else?
What you could do is first clarify for yourself (in words, not in code), what removePlayer is supposed to do exactly.
Then you can adapt your code and start debugging.
One way to debug could be to first hard code the name to be removed instead of using user input. Say the list is "John", "Rita", "Jim", "Alex".
Set the name to be deleted from the list to "Rita". Now run your program and adapt it until it does what you want.
Once it works for "Rita", test if for "John" (first name on the list), "Alex" (last name on the list) and "Samy" (name not on the list). In each case correct the code if it doesn't work.
When you correct the code, don't just try something until it works. Be sure you understand why the program didn't work in this specific case and why your modification will solve the present problem without breaking the code that worked before.
Once you are done with a hard coded name, try it with a name entered by the user. If now it again doesn't work, you have isolated the problem and can deal with it.
Last edited:
#45
Silicon Waffle
160
203
phion said:
[...]
I'm not even sure where to look for VB debugging tutorials. Any advice?
https://support.microsoft.com/en-us/kb/142999
An array requires a fixed size of a contiguous block of memory. So if the input element number is less than the array size, all the unused elements are assigned to "Nothing" and that (long) block of memory becomes redundant. .
Instead of using arrays, why don't you try out either List (Of String) or ArrayList which is more easy to handle and would free you from such an overhead. You can also use a Collection as in the following code I rewrite for you. This is worse than that being used with either List or ArrayList though.
PHP:
Module Module1
Dim numPlayers As Integer
Dim playerListTmp As New Collection
Sub Main()
Dim playerList, tempPlayerList As New Collection()
numPlayers = loadList(playerList)
numPlayers = addPlayers(playerList, numPlayers)
displayList(playerList, numPlayers)
numPlayers = removePlayer(playerList, numPlayers)
displayList(playerList, numPlayers)
saveList(playerList, numPlayers)
Console.WriteLine("List saved successfully!")
End Sub
Function loadList(playerList As Collection
) As Integer
Dim fileName As String = "playerList.txt"
numPlayers = 0
If File.Exists(fileName) Then
Dim inFile As New StreamReader(fileName)
While Not inFile.EndOfStream
playerList.Add(inFile.ReadLine(), numPlayers)
numPlayers += 1
End While
inFile.Close()
Else
Console.WriteLine("Could Not Open " & fileName)
End If
Return numPlayers
End Function
Function addPlayers(playerList As Collection, numPlayers As Integer) As Integer
Dim newPlayer As String
Dim fileName As String = "playerList.txt"
Dim inFile As New StreamWriter(fileName, True)
Console.Write("Enter player name ('exit' to quit): ")
newPlayer = Console.ReadLine()
While newPlayer <> "exit"
inFile.WriteLine(newPlayer)
playerList.Add(newPlayer, numPlayers)
numPlayers += 1
Console.Write("Enter player name ('exit' to quit): ")
newPlayer = Console.ReadLine()
End While
inFile.Close()
Return numPlayers
End Function
Sub displayList(playerList As Collection, numPlayers As Integer)
Dim i As Integer
For i = 1 To numPlayers
Console.WriteLine("Player " & i & ": " & playerList.Item(i).ToString())
Next
End Sub
Function removePlayer(playerList As Collection, numPlayers As Integer) As Integer
Dim player As String
Dim fileName As String = "playerList.txt"
Dim tempFileName As String = "tempPlayerList.txt"
Dim inFile As New StreamReader(fileName)
Dim outFile As New StreamWriter(tempFileName)
Dim playerTmp As String
Dim count As Integer = 0
Console.WriteLine("Which player would you like to remove?")
player = Console.ReadLine() For i = 1 To numPlayers
playerTmp = inFile.ReadLine()
If player <> playerTmp Then
playerListTmp.Add(playerTmp, i)
outFile.WriteLine(playerTmp)
count += 1
End If
Next
inFile.Close()
outFile.Close()
File.Delete("playerList.txt")
My.Computer.FileSystem.RenameFile("tempPlayerList.txt", "playerList.txt")
File.Create("tempPlayerList.txt")
playerList.Clear()
For i = 1 To count
playerList.Add(playerListTmp.Item(i), i)
Next
Return count
End Function
Sub saveList(playerList As Collection, numPlayers As Integer)
Dim fileName As String = "playerList.txt"
Dim outFile As New StreamWriter(fileName)
For i = 1 To numPlayers
outFile.WriteLine(playerList(i))
Next
outFile.Close()
End SubEnd Module
Last edited by a moderator:
#46
phion
Gold Member
175
39
Samy_A said:
What you could do is first clarify for yourself (in words, not in code), what removePlayer is supposed to do exactly.
I'm sorry, I thought this was made clear. This code is for a VB console program designed to manipulate data, namely "wins," "losses," "skill," "name," etc. which are stored in both arrays and text files. The remove player function should modify the playerList text file, and the playerList array I suppose, so that a player specified by the user is removed from the list, as well as all of their other corresponding data stored in separate arrays. This way, when the user chooses the menu option to view records of all the players, the proper data is displayed.
#47
phion
Gold Member
175
39
Ok, I think I just figured it out. I need to sort the list such that the player specified by the user is in the last position of the list before copying over the contents of the file. Does this make sense?
I'm sorry, I thought this was made clear. This code is for a VB console program designed to manipulate data, namely "wins," "losses," "skill," "name," etc. which are stored in both arrays and text files. The remove player function should modify the playerList text file, and the playerList array I suppose, so that a player specified by the user is removed from the list, as well as all of their other corresponding data stored in separate arrays. This way, when the user chooses the menu option to view records of all the players, the proper data is displayed.
Do you see the ambiguity in your reply? "The remove player function should modify the playerList text file, and the playerList array I suppose".
Your current code doesn't use the array in memory, but reads the file into the array, including the player to be removed. It the saves the list without the removed player to the file (at least that is what it seems to do, but you say it doesn't work).
Try to define precisely what you want removePlayer to do, and then write and test the procedure as has been suggested by a number of people in this thread.
phion said:
Ok, I think I just figured it out. I need to sort the list such that the player specified by the user is in the last position of the list before copying over the contents of the file. Does this make sense?
Not really, no.
Try to analyze your code and understand why it doesn't do what you want.
Sorting the list with the player in the last position has nothing to do with what you want to achieve or with the reason it doesn't work.
#49
phion
Gold Member
175
39
Samy_A said:
Do you see the ambiguity in your reply?
Yes, I am aware. You're probably pretty used to customers being frustratingly ambiguous I bet.
I'm working on the others suggestions, but I do feel like keeping this thread alive in the process. Setting breakpoints is something I have not yet done.
Yes, I am aware. You're probably pretty used to customers being frustratingly ambiguous I bet.
I'm working on the others suggestions, but I do feel like keeping this thread alive in the process. Setting breakpoints is not something I have not yet done.
No problem. Just try to be systematic in your work.
#51
phion
Gold Member
175
39
Samy_A said:
No problem. Just try to be systematic in your work.
I appreciate the guidance.
#52
phion
Gold Member
175
39
Ok, it works now. Duh.
#53
TurtleMeister
897
90
Samy_A said:
EDIT: Apparently, when you pass an array as argument (even as ByVal), you can still modify the array element apparently.
Yes, that is true. My post #42 is incorrect. ByVal only applies to value types. Arrays are reference types. And I guess it's a good thing because it would be pretty inefficient to copy an entire array and all it's elements every time you passed it as an argument.