This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
Cranium's profile picture

Break not working like I need

Started by Cranium, 12 November 2012 - 03:23 PM
Cranium #1
Posted 12 November 2012 - 04:23 PM
I've got a block of code in my script here that is supposed to log in to my system. However, it is not leaving the loop I created. It does successfully log in when I enter the credentials, but then it restarts the loop. It's supposed to leave the loop as soon as it's logged in. What did I do wrong?


-- starting script
bootUp()
logged = false
if userExists == false then
smartAPI.userCreate(2)
end
--login script
local attempt = 1
logged = false
while logged == false do
local user, pass = login()
local tUsers = smartAPI.loadUsers()
for i = 1, #tUsers do
if tUsers[i].username == user and tUsers[i].password == pass then
logged = true
end
end
if attempt >= 5 then
smartAPI.errorHandle("LOCK")
elseif logged == true then
break
elseif logged == false then
smartAPI.errorHandle("Username or password is incorrect")
attempt = attempt + 1
end
end
D3matt #2
Posted 12 November 2012 - 04:44 PM
Your break is breaking out of your if/then comparison, not out of the loop, I think. Make it a function and use return?
XoX #3
Posted 12 November 2012 - 05:04 PM
It should work just fine.
Lyqyd #4
Posted 12 November 2012 - 05:04 PM
Your break is breaking out of your if/then comparison, not out of the loop, I think. Make it a function and use return?

This is incorrect.

Break has some weird rules. It can only be the last statement of a block. Try this instead:


-- starting script
bootUp()
logged = false
if userExists == false then
smartAPI.userCreate(2)
end
--login script
local attempt = 1
local logged = false
while not logged do
	local user, pass = login()
	local tUsers = smartAPI.loadUsers()
	for i = 1, #tUsers do
		if tUsers[i].username == user and tUsers[i].password == pass then
			logged = true
		end
	end
	if attempt >= 5 then
		smartAPI.errorHandle("LOCK")
	elseif logged == false then
		smartAPI.errorHandle("Username or password is incorrect")
		attempt = attempt + 1
	elseif logged == true then
		break
	end
end
Cranium #5
Posted 12 November 2012 - 05:25 PM
Your break is breaking out of your if/then comparison, not out of the loop, I think. Make it a function and use return?

This is incorrect.

Break has some weird rules. It can only be the last statement of a block. Try this instead:


-- starting script
bootUp()
logged = false
if userExists == false then
smartAPI.userCreate(2)
end
--login script
local attempt = 1
local logged = false
while not logged do
	local user, pass = login()
	local tUsers = smartAPI.loadUsers()
	for i = 1, #tUsers do
		if tUsers[i].username == user and tUsers[i].password == pass then
			logged = true
		end
	end
	if attempt >= 5 then
		smartAPI.errorHandle("LOCK")
	elseif logged == false then
		smartAPI.errorHandle("Username or password is incorrect")
		attempt = attempt + 1
	elseif logged == true then
		break
	end
end
I've tried that, and a few other variations of the same thing. It doesn't work though, and I don't know why…
Lyqyd #6
Posted 12 November 2012 - 05:50 PM
Then you'll need to post the whole code.
Cranium #7
Posted 12 November 2012 - 06:03 PM
eh…..how fun. I'll give you the startup link, the rest should run automatically.
http://pastebin.com/GWUUfNeh
cheekycharlie101 #8
Posted 12 November 2012 - 06:59 PM
try this. this is how i use loops for logins. at the top define a varible. like this


locked = true
while locked do
-- code

then when you login to break the loop just do this.


locked = false
its a basic method and works for me really well. try i. its kinda what you have done just a little less typing and it may work.
ChunLing #9
Posted 12 November 2012 - 09:47 PM
Use repeat … until logged, not while not logged do … end. That eliminates the need for break.
Espen #10
Posted 13 November 2012 - 12:58 AM
Just want to chip in with some general info about break vs. return:
If you use break, then you will break out of the first loop (while, for, etc.) is in, but the program will then just continue to run any code that comes after the loop.
If you want the program to end instead, then you could us return, as that will either return from the function is was executed in, or return from your program (thus ending it) if it was executed outside of any function.

while true do
  print("In the infinite loop that actually won't loop.^^")
  break
end
print("This WILL be printed after the break.")

while true do
  print("In the infinite loop that actually won't loop.^^")
  return
end
print("This will NOT be printed after the return.")

But as mentioned above, ending your program with return won't work if you're returning from a function.
Then it might be better to return a boolean value and make the check outside of the function:

function foo()
  while true do
    print("In the infinite loop that actually won't loop.^^")
    return false
  end

  print("This will NOT be printed after the break.")
  return true  -- pro forma, but not really of use in this example; if unclear, don´t hesitate to ask :P/>/>
end

if not foo() then
  return
end
print("This will NOT be printed after foo() returns.")
Sarcastic_Bannana #11
Posted 13 November 2012 - 03:53 AM
Forgive me if I'm wrong but I experienced a similar problem of not being able to break out of a loop however I got arround that by using break end:

i=1
while i=1 do

…my code…

if nOption == 4 then
term.clear()
term.setCursorPos(1, 1)
break end

That broke my loop, not sure if it'll apply to you :P/>/>
Cranium #12
Posted 13 November 2012 - 04:44 AM
I updated the code to work with repeat until logged == true, but it does not work. It will break out of the loop if I enter the user/pass correctly twice, but I shouldn't have to do that….
Fiery Arcanine #13
Posted 13 November 2012 - 06:35 AM
Now, tell me. What does it need to do?
Stop after first one correct?

By the way add this script in the beginning:

local pullEvent = os.pullEvent
os.pullEvent = os.pullEventRaw
and at the end of the code (when the password is correct)

os.pullEvent = pullEvent
It will prevent people from terminating the program
Source (CC wiki)
remiX #14
Posted 13 November 2012 - 07:58 AM
Now, tell me. What does it need to do?
Stop after first one correct?

By the way add this script in the beginning:

local pullEvent = os.pullEvent
os.pullEvent = os.pullEventRaw
and at the end of the code (when the password is correct)

os.pullEvent = pullEvent
It will prevent people from terminating the program
Source (CC wiki)

I'd think he left it out for now so he can terminate if the program bugs and doesn't want to return to console
Fiery Arcanine #15
Posted 13 November 2012 - 08:18 AM
Now, tell me. What does it need to do?
Stop after first one correct?

By the way add this script in the beginning:

local pullEvent = os.pullEvent
os.pullEvent = os.pullEventRaw
and at the end of the code (when the password is correct)

os.pullEvent = pullEvent
It will prevent people from terminating the program
Source (CC wiki)

I'd think he left it out for now so he can terminate if the program bugs and doesn't want to return to console

It was supposed to for later, as you stated.
Cranium #16
Posted 13 November 2012 - 12:39 PM
I already do use ctrl t prevention on it. But that's not hte issue I'm having. I need to know why it wants to loop repeatedly even after logging in successfully.
cheekycharlie101 #17
Posted 13 November 2012 - 07:37 PM
i know this is NOT the answer you want. but no one can really find an answer. maybe you should just make a more simple lock. i know this is not the right way of dealing with program problems but if "lua pro's" cant even get it working then i dont think you will find a problem.
Lyqyd #18
Posted 13 November 2012 - 07:45 PM
i know this is NOT the answer you want. but no one can really find an answer. maybe you should just make a more simple lock. i know this is not the right way of dealing with program problems but if "lua pro's" cant even get it working then i dont think you will find a problem.

I'm not sure the fix I suggested was actually even tried. I'm also not going to go through the effort of trying to download and run the installer script onto a fresh computer in minecraft just to look at the rest of the code, when it could easily have all been posted in the first place.
cheekycharlie101 #19
Posted 13 November 2012 - 08:46 PM
i know this is NOT the answer you want. but no one can really find an answer. maybe you should just make a more simple lock. i know this is not the right way of dealing with program problems but if "lua pro's" cant even get it working then i dont think you will find a problem.

I'm not sure the fix I suggested was actually even tried. I'm also not going to go through the effort of trying to download and run the installer script onto a fresh computer in minecraft just to look at the rest of the code, when it could easily have all been posted in the first place.
thats fair enough. i just think that what is the point of having an error in your program thats really hard to solve and you can just write a easier script that does the same thing and does work. i just think its a slight waste of time thats all.
Espen #20
Posted 13 November 2012 - 10:46 PM
@Cranium:
SpoilerI'm suspecting your problem has to do with #tUsers never returning anything else than 0 in this part:
for i = 1, #tUsers do
	if tUsers[i].username == user and tUsers[i].password == pass then
		logged = true
	end
end
The #-symbol only counts indexed table entries.
That means that any custom keys in your tUsers table won't be counted by it.
Now if you don't have any indexed-only entries in your tUsers table, then the for loop will never be run and thus logged will always remain false.
Possible solutions are either to not use custom keys for the username and password in order for # to work, or to iterate through the table with pairs().

But that depends on how your tUsers table looks, so could you perhaps post an example of a "userList" file?

P.S.: I'm aware that it looks like you have indexed entries, since you're trying to access them via tUsers, but as I mentioned, as long as we don't know exactly what tUsers looks like, that can only be speculation on our part.^^
Ok, scratch everything I just said. I've downloaded your program in the meantime and played around with it. It's not your tables, they seem to be fine.
In fact, there is absolutely no problem if I run this startup program manually (after making sure the automatic update doesn't overwrite it again of course).
What happens is that as soon as you enter a correct user and password, the startup program seems to run again.
That is, it does indeed exit the loop, but for some reason the whole program is being run again.

I then tried to run your startup-code from the startup-file via shell.run(), instead of having the code itself in there.
That somehow didn't work though, which really puzzles me. When I tried os.run() instead, then it works without a hitch, but then it still has the same problem as before, i.e. it runs two times in a row.

I did get it working with shell.run() only if I removed everything but the login procedure.
So I suspect there's something fishy going on within your APIs, where you have some proram logic that somehow causes the whole script to run at least one more time after it has ended.

I haven't really looked through the rest of your code, as it is quite a lot of files and code, so I have no idea where this might be happening.
But rest assured that is has nothing to do with break.
It works fine… just two times in a row. :P/>/>
Edited on 13 November 2012 - 11:46 PM
Cranium #21
Posted 14 November 2012 - 05:47 AM
…….I feel like an idiot. This has absolutely nothing to do with the files or anything else with the loop. This is because I loaded the startup file AS AN API at the top of the code…..So of course it would run twice….
All I had to do was change part of my install block install everything, but only load the actual APIs as an API, skipping the startup.
My new code for the startup is as follows:

local function getVersion()
return 1.038
end
os.pullEvent = os.pullEventRaw
local defaultUser = "Admin"
local defaultPass = "Password"
local updateTable = {}
updateTable[1] = {code = "GWUUfNeh", filename = "startup"}
updateTable[2] = {code = "vphtijAh", filename = ".smartOS/smartAPI"}
updateTable[3] = {code = "dXamY7Jc", filename = ".smartOS/smartWrite"}
updateTable[4] = {code = "PFZXduDm", filename = ".smartOS/smartGUI"}
updateTable[5] = {code = "iMZH1L6p", filename = ".smartOS/smartFile"}
--file integrity check
if not fs.exists(".smartOS") then
fs.makeDir(".smartOS")
elseif not fs.exists(".smartOS/userList") then
local tUsers = {}
tUsers[1] = {}
tUsers[1].username = defaultUser
tUsers[1].password = defaultPass
tUsers[1].tZ = "utc"
tUsers[1].level = 1
local userFile = fs.open(".smartOS/userList","w")
userFile.write(textutils.serialize(tUsers))
userFile.close()
userExists = false
end
for i = 1, #updateTable do  --this is the block I had to change
if not fs.exists(updateTable[i].filename) then
  local updateSite = http.get("http://pastebin.com/raw.php?i="..updateTable[i].code)
  local siteFile = updateSite.readAll()
  local writeFile = fs.open(updateTable[i].filename,"w")
  writeFile.write(siteFile)
  writeFile.close()
  if not updateTable[i] == "startup" then
   os.unloadAPI(updateTable[i].filename)
   os.loadAPI(updateTable[i].filename)
  end
else
  if not updateTable[i] == "startup" then
   os.unloadAPI(updateTable[i].filename)
   os.loadAPI(updateTable[i].filename)
  end
end
end
-- boot screen
local function bootUp()
smartGUI.splash()
term.setCursorPos(4,15)
write("Checking HTTP connection...")
if http then
httpStatus = true
write("Connected")
else
httpStatus = false
write("No connection")
end
term.setCursorPos(4,16)
write("Checking for peripherals...")
smartAPI.pDetect()
write("Complete")
term.setCursorPos(4,17)
write("Checking for updates...")
local updateNum = 0
for i = 1, #updateTable do
local _update = smartAPI.update(updateTable[i].code, updateTable[i].filename)
if _update == true then
  updateNum = updateNum + 1
elseif _update == "Error" then
  term.setCursorPos(26,17)
  write(_update)
end
term.setCursorPos(26,17)
write("Updates found: "..updateNum)
end
if updateNum > 0 then
local query = smartAPI.errorHandle("Would you like to restart now?", "Yes", "No")
if query == 1 then os.reboot() end
end
end
--login
local function login()
term.clear()
term.setCursorPos(1,1)
for i = 1, #smartGUI.loginTab do
print(smartGUI.loginTab[i])
end
term.setCursorPos(20,9)
local inputUser = smartWrite.limitRead(17)
term.setCursorPos(20,10)
local inputPass = smartWrite.limitRead(17, "*")
return inputUser, inputPass
end
-- starting script
bootUp()
logged = false
if userExists == false then
smartAPI.userCreate(2)
end
--login script
local attempt = 1
local logged = false
repeat
local user, pass = login()
local tUsers = smartAPI.loadUsers()
for i = 1, #tUsers do
  if tUsers[i].username == user and tUsers[i].password == pass then
   logged = true
   break
  end
end
if attempt >= 5 then
  smartAPI.errorHandle("LOCK")
elseif logged == false then
  smartAPI.errorHandle("Username or password is incorrect")
  attempt = attempt + 1
end
until logged == true
Edited on 14 November 2012 - 04:48 AM
Cranium #22
Posted 14 November 2012 - 05:49 AM
i know this is NOT the answer you want. but no one can really find an answer. maybe you should just make a more simple lock. i know this is not the right way of dealing with program problems but if "lua pro's" cant even get it working then i dont think you will find a problem.
It wasn't that they can't get it working, it was that I was being an idiot in the first place trying to simplify some of my code earlier on.