Answered Array Problems

  • Saturday, September 29, 2012 6:50 AM
     
     

    Hi there, pretty new to coding in small basic but I'm making some good progress. However I'm having trouble with using arrays. I want to compare the input from the user against the values in an array, and if they match to display a certain line of text, and if not to display a different line of text. Syntax wise there is no problem so I can't see the error. Any help appreciated.

    Code:

    TextWindow.Write("Login: ")
    loginfield = TextWindow.Read()

    login[0]["user1"]="root"
    login[0]["user2"]="su"
    login[0]["user3"]="admin"

    If loginfield = login[0] Then 
      TextWindow.WriteLine("Logged in...")
    Else
      TextWindow.WriteLine("Login failed...")
    EndIf

    • Edited by tem_php Saturday, September 29, 2012 6:57 AM
    •  

All Replies

  • Saturday, September 29, 2012 8:27 AM
    Answerer
     
     Answered

    Welcome tem_php!

    login is a 2D array variable; and login[0] is just 1 of its dimension.

    if you include -> TextWindow.WriteLine( login[0] ) in the end of code, you'll see this result:

    user1=root;user2=su;user3=admin;

    Obviously, loginfield would not be equal to that long string, 'cause no user would type that as login.  :P

    As you can see, in SB, arrays are nothing more than a big string after this model -> index=value; and so on.

    Now, SB provides a category to manipulate all things array -> the object Array.

    And among those, the one you need is this one -> Array.ContainsValue().

    Just replace If loginfield = login[0] Then with this one -> Array.ContainsValue( login[0]  loginfield ).

    It returns True if login[0] contains any value = loginfield inside it!

    Besides that, I'd also advise you to convert all of user typed into lower-case letters.

    Replace loginfield = TextWindow.Read() with this -> loginfield = Text.ConvertToLowerCase( TextWindow.Read() ).

    So you don't need to worry about whether user used Shift/Caps-Lock anymore.


    Click on "Propose As Answer" if some post solves your problem or "Vote As Helpful" if some post has been useful to you! (^_^)

  • Saturday, September 29, 2012 8:48 AM
     
     
    Thanks for the help, worked perfectly! Like I say I just started using sb recently (well about two days ago) so I'm sure I'll be on here frequently asking for help haha, but its a lot of fun learning about how programs work...in a previous iteration of this code I was just comparing the input to multiple individual values but having to write all that code seemed like a waste when you can parse using arrays. Anyway many thanks for the help again :)
  • Saturday, September 29, 2012 10:21 PM
     
     

    Alas I'm back with another query. I have two arrays, one with usernames array[0] and one with passwords array[1], if I want soemone to be able to login but only have certain username and password combinations availible how would I do that, I have some example code I wrote but it doesnt quite work...

    Code:

    'TextWindow Attributes
       TextWindow.Title="Terminal" 'Set TextWindow title
       TextWindow.ForegroundColor="Green" 'Set text in TextWindow to green
       
    'Login Array setup
       user[0]["rootuser"]="root"
       user[0]["superuser"]="su"
       user[0]["administrator"]="admin"
       
    'Password Array setup
       password[1]["rootuser"]="master"
       password[1]["superuser"]="super"
       password[1]["administrator"]="admin"
       
    'TextWindow welcome 
       TextWindow.WriteLine("Starting terminal...")
       TextWindow.WriteLine("")
       TextWindow.WriteLine(Clock.Date)
       TextWindow.WriteLine(Clock.WeekDay)
       TextWindow.WriteLine(Clock.Time)
       TextWindow.WriteLine("")
       TextWindow.WriteLine("Welcome to the VMachines Gateway. Please login to continue...")
       TextWindow.Write("Login: ")
       login = Text.ConvertToLowerCase(TextWindow.Read())
       TextWindow.Write("Password: ")
       password = Text.ConvertToLowerCase(TextWindow.Read())
       
    'Login conditions   
       If Array.ContainsValue(user[0]["rootuser"]login) And Array.ContainsValue(password[1]["rootuser"]password) Then
         Goto loginaccept
         ElseIf Array.ContainsValue(user[0]["superuser"]login) And Array.ContainsValue(password[1]["superuser"]password) Then
           Goto loginaccept 
           ElseIf Array.ContainsValue(user[0]["administrator"]login) And Array.ContainsValue(password[1]["administrator"]password) Then
             Goto loginaccept
           Else
             Goto loginreject
            EndIf 
             
    'Login welcome screen
        loginaccept: 
        TextWindow.WriteLine("Login successful, please wait...")

    'Login rejection screen
       loginreject: 
       TextWindow.WriteLine("Login rejected, closing terminal...") 

  • Sunday, September 30, 2012 7:37 AM
     
     

    Change my code a fair bit but still no results, new code:

    I just feel that this is too much code to have values in one array to match corresponding values in another array, I've tried lots of variations on this kind of code but to no avail, help desperately needed :)

                         

    'Login Array setup

       user[0]["root"]="root"
       user[1]["superuser"]="su"
       user[2]["administrator"]="admin"

    'Password Array setup
       password[4]["root"]="master"
       password[5]["superuser"]="super"
       password[6]["administrator"]="admin"

    'TextWindow welcome 
       TextWindow.WriteLine("Starting terminal...")
       TextWindow.WriteLine("")
       TextWindow.WriteLine(Clock.Date)
       TextWindow.WriteLine(Clock.WeekDay)
       TextWindow.WriteLine(Clock.Time)
       TextWindow.WriteLine("")
       TextWindow.WriteLine("Welcome to the VMachines Gateway. Please login to continue...")
       Goto logincon

    'Login conditions
       logincon:
       TextWindow.Write("Login: ")
       login = Text.ConvertToLowerCase(TextWindow.Read())
       If Array.ContainsValue(user[0]login) Then
         Goto pass0
       ElseIf Array.ContainsValue(user[1]login) Then
         Goto pass1
       ElseIf Array.ContainsValue(user[2]login) Then
         Goto pass2
       Else
         TextWindow.WriteLine("Invalid login...")
         Goto terminalclose
         EndIf




    'Password conditions
       pass0:
       TextWindow.Write("Password: ")
       password = Text.ConvertToLowerCase(TextWindow.Read())
       If Array.ContainsValue(password[4]password) Then
         Goto loginaccept
       Else
         Goto loginreject
         EndIf
       pass1:
       TextWindow.Write("Password: ")
       password = Text.ConvertToLowerCase(TextWindow.Read())
       If Array.ContainsValue(password[5]password) Then
         Goto loginaccept
       Else
         Goto loginreject
         EndIf
       pass2:
       TextWindow.Write("Password: ")
       password = Text.ConvertToLowerCase(TextWindow.Read())
       If Array.ContainsValue(password[6]password) Then
         Goto loginaccept
       Else
         Goto loginreject
         EndIf




    'Login welcome screen
       loginaccept: 
       TextWindow.WriteLine("Login successful, please wait...")
       Goto systemload

    'Login rejection screen
       loginreject: 
       TextWindow.WriteLine("Login rejected, closing terminal...")       
       Goto terminalclose

    'Terminal Close   
       terminalclose:
       Program.Delay(1000)
       Program.End()

  • Sunday, September 30, 2012 8:05 AM
     
     

    Just changed the password conditions code to this:

    The system works now, but I would really like to know if there is some way that I can condense the code down as the way it stands, there is so much code that it seems pointless to use arrays for the login names and passwords, as it would be similar amounts of code by asking if the user input matches an exact string ala If password = ("....")


    'Password conditions
       pass0:
       TextWindow.Write("Password: ")
       password0 = Text.ConvertToLowerCase(TextWindow.Read())
       If Array.ContainsValue(password[0]password0) Then
         Goto loginaccept
       Else
         Goto loginreject
         EndIf
       pass1:
       TextWindow.Write("Password: ")
       password1 = Text.ConvertToLowerCase(TextWindow.Read())
       If Array.ContainsValue(password[1]password1) Then
         Goto loginaccept
       Else
         Goto loginreject
         EndIf
       pass2:
       TextWindow.Write("Password: ")
       password2 = Text.ConvertToLowerCase(TextWindow.Read())
       If Array.ContainsValue(password[2]password2) Then
         Goto loginaccept
       Else
         Goto loginreject
         EndIf

  • Sunday, September 30, 2012 8:38 AM
    Answerer
     
     Answered Has Code

    Hey again!

    I still haven't taken the time to analyze your code. But with a quick look, I was able to spot some interesting issues:

    Most obvious one is that you use Goto to leap onto sections of your code!

    Goto is considered the bane of good programming for good reasons; for it creates what most programmers call spaghetti code! You lose track where the code have to return from after a task very easily.

    I see that your code is well organized in sections like: TextWindow welcome, Login conditions, Password conditions and so on.

    What's missing is that you turn all of them into subroutines! For that, you put that section of code within a block Sub ... EndSub. See the example below:

    Sub Welcome
    
       TextWindow.WriteLine("Starting terminal...")
       TextWindow.WriteLine("")
       TextWindow.WriteLine(Clock.Date)
       TextWindow.WriteLine(Clock.WeekDay)
       TextWindow.WriteLine(Clock.Time)
       TextWindow.WriteLine("")
       TextWindow.WriteLine("Welcome to the VMachines Gateway. Please login to continue...")
    
    EndSub

    Now, you just need to use Welcome() in any place within your program to call the code section above. After the subroutine finishes, execution returns right after the Welcome() line!


    Click on "Propose As Answer" if some post solves your problem or "Vote As Helpful" if some post has been useful to you! (^_^)

  • Sunday, September 30, 2012 8:57 AM
     
     

    Thanks for the Sub tip :) I've quickly realized that you really have to break a program up into many 'modules' of code to keep everything looking neat and manageble, the first iteration of this program was basically one long block of code with no breaks! I was using a lot of Goto statements because I was always thinking of the Goto (linenumber) command from the other more traditional BASIC languages, but I'll go back through and rewrite in those subroutines. I guess even though I am a beginner I just have the 'ambition' to try and make everything as concise and efficient as possible...I have read through the small basic literature from Microsoft but there are a lot of things I wish to do that they don't cover in as much detail as I hoped. Anyway back to the keyboard, thanks again...

    I could always send you the files for the program if you wanted to see in more detail.

    Many thanks!

    EDIT: Just wrote a tiny bit of code using the subroutine stuff to test it out, works very nice! Code:

    Sub Welcome
      TextWindow.WriteLine("Welcome to the system")
    EndSub

    Sub Goodbye
      TextWindow.WriteLine("Goodbye")
      EndSub

    TextWindow.Write("Login: ")
    login=TextWindow.Read()

    If login="happy" Then
      Welcome()
    Else
       Goodbye()
    EndIf

    • Edited by tem_php Sunday, September 30, 2012 9:21 AM
    •  
  • Sunday, September 30, 2012 10:05 AM
    Answerer
     
     Answered Has Code

    ... there is so much code that it seems pointless to use arrays for the login names and passwords, as it would be similar amounts of code by asking if the user input matches an exact string ala If password = ("....")

    Well, here comes 2nd part:

    Databases need some planning ahead to implement. Studying your code, I think you were intending to have 3 field categories -> user, pass & rank.

    Like this one -> "su" as user login, "super" as its password and "superuser" as its access rank or something like that.  :P

    So here's what I did to lay the idea:

    Sub Credentials
      
      logins[1]["user"] = "root"
      logins[2]["user"] = "su"
      logins[3]["user"] = "admin"
      
      logins[1]["rank"] = "root"
      logins[2]["rank"] = "superuser"
      logins[3]["rank"] = "administrator"
      
      logins[1]["pass"] = "master"
      logins[2]["pass"] = "super"
      logins[3]["pass"] = "admin"
      
      loginCount = Array.GetItemCount(logins)  '  <---  number of "system" user logins
      
    EndSub

    As you can see, each index number has 3 category fields -> ["user"], ["rank"] & ["pass"]

    loginCount stores the current number of users registered within system database logins[][].

    Now, the trick to check each one is to use a For ... EndFor loop w/ loginCount as the number of iterations:

    For index = 1 To loginCount
        
        If user = logins[index]["user"] Then
          hasFound = "True"   '  <---   flags we've found a match!
          index = loginCount  '  <---   a hack trick to make For Loop finish earlier!
        EndIf
        
    EndFor

    And finally the full source code. Study it & enjoy!

    '###################################################'
    ' Login Example
    
    ' http://social.msdn.microsoft.com/Forums/en-US/smallbasic
    '/thread/3355d96e-9eb6-48ab-9ec9-377f1024d04c
    '###################################################'
    
    '_________________________________________________________________________'
    TextWindow.ForegroundColor = "Black"
    TextWindow.BackgroundColor = "Yellow"
    TextWindow.Clear()
    TextWindow.Title = "Login Example"
    LF = Text.GetCharacter(10)
    
    Credentials()
    
    While isLogged <> "True"
      AskLogin()
    EndWhile
    
    TextWindow.WriteLine(LF + user + " logged in as " + rank + " class operator!" + LF)
    TextWindow.Title = user + " as " + rank
    '_________________________________________________________________________'
    Sub Credentials
      
      logins[1]["user"] = "root"
      logins[2]["user"] = "su"
      logins[3]["user"] = "admin"
      
      logins[1]["rank"] = "root"
      logins[2]["rank"] = "superuser"
      logins[3]["rank"] = "administrator"
      
      logins[1]["pass"] = "master"
      logins[2]["pass"] = "super"
      logins[3]["pass"] = "admin"
      
      loginCount = Array.GetItemCount(logins)  '  <---  number of "system" user logins
      
    EndSub
    '_________________________________________________________________________'
    Sub AskLogin
      
      TextWindow.WriteLine("Type in user: " + LF)
      user = Text.ConvertToLowerCase( TextWindow.Read() )
      hasFound = "False"
      
      For index = 1 To loginCount
        
        If user = logins[index]["user"] Then
          hasFound = "True"   '  <---   flags we've found a match!
          index = loginCount  '  <---   a hack trick to make For Loop finish earlier!
        EndIf
        
      EndFor
      
      If hasFound Then
        AskPassword()
      Else
        TextWindow.WriteLine(LF + user + " is not in our database!" + LF)
        Sound.PlayBellRing()
      EndIf
      
    EndSub
    '_________________________________________________________________________'
    Sub AskPassword
      
      TextWindow.WriteLine(LF + "Type in password: " + LF)  
      pass = Text.ConvertToLowerCase( TextWindow.Read() )
      hasFound = "False"
      
      For index = 1 To loginCount
        
        If pass = logins[index]["pass"] Then
          hasFound = "True"   '  <---   flags we've found a match!
          isLogged = "True"   '  <---  finally logged in!
          rank  = logins[index]["rank"]  '  <---  gets user's access rank
          Sound.PlayChime()
          index = loginCount  '  <---   a hack trick to make For Loop finish earlier!
        EndIf
        
      EndFor
      
      If hasFound <> "True" Then
        TextWindow.WriteLine(LF + "Wrong password ! You have to try again!!!" + LF)
        Sound.PlayBellRing()
      EndIf
      
    EndSub
    '_________________________________________________________________________'

    Click on "Propose As Answer" if some post solves your problem or "Vote As Helpful" if some post has been useful to you! (^_^)

  • Monday, October 01, 2012 6:23 AM
     
     

    Thanks for the sample code...had a pretty busy day today so I haven't had much time to go over it and investigate the structure but will sure implement this kind of code in my program. will probably post the rectified code tommorow sometime so watch out :)

    How long have you been programming using sb?

  • Thursday, October 18, 2012 2:53 AM
    Owner
     
     

    GoToLoop,

    You're doing a lot of great things in this forum. Please send me an email. It's edprice at Microsoft.

    Thanks!


    Ed Price (a.k.a User Ed), SQL Server Customer Program Manager (Blog, Twitter, Wiki)

  • Thursday, October 18, 2012 3:26 AM
    Answerer
     
     
    Just re-sent an e-mail for you again!

    Click on "Propose As Answer" if some post solves your problem or "Vote As Helpful" if some post has been useful to you! (^_^)