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

[Error] attempt to concatenate string and nil [SOLVED]

Started by Cranium, 11 August 2012 - 10:37 PM
Cranium #1
Posted 12 August 2012 - 12:37 AM
Ok, when trying to get away from global variables(thanks Lyqyd), I ran into a snag. I'm declaring properly, I think, but when it saves my variables to a file, I receive the above error. What the heck am I doing wrong?


--declaring variable
local deviceTable = {type="Lights"}
title()
print("Do you have lighting that you want to control?")
deviceTable.status = yN()
if deviceTable.status == "true" then
term.clear()
term.setCursorPos(1,9)
print("		   What color are you using?")
sleep(1.5)
deviceTable.color = colorConvert(opt(colorOpt))
deviceTable.status = "false"
table.insert(controlTable,deviceTable)
saveState(controlTable)
else deviceTable.status = "false"
deviceTable.color = "false"
table.insert(controlTable,deviceTable)
saveState(controlTable)
end

--referring back to this table for options
colorOpt={
"Redstone/Red alloy wire",
"White",
"Orange",
"Magenta",
"Light Blue",
"Yellow",
"Lime",
"Pink",
"Gray",
"Light Gray",
"Cyan",
"Purple",
"Blue",
"Brown",
"Green",
"Red",
"Black"
}

--this code to display the menu
function opt(m)
n=1
l=#m
while true do
term.clear()
term.setCursorPos(1,2)
for i=1, l, 1 do
if i==n then print(i, " ["..m[i].."]") else print(i, " ", m[i]) end
end
a, b= os.pullEventRaw()
if a == "key" then
if b==200 and n>1 then n=n-1 end
if b==208 and n<=l then n=n+1 end
if b==28 then break end
end
end
term.clear() term.setCursorPos(1,1)
return n
end

--this code to change to proper colors api format
function colorConvert(color)
if color > 1 then return tostring(2^(color - 2))
else return "0"
end
end

--and this for determining if true/false
function yN()
local n=1
while true do
local x, y=term.getCursorPos()
term.clearLine()
if n==1 then write(">YES<   NO") else write (" YES   >NO<") end
term.setCursorPos(x, y)
a, b=os.pullEvent()
while a~="key" do a, b=os.pullEvent() end
if b==203 and n==2 then n=1 end
if b==205 and n==1 then n=2 end
if b==28 then print("") break end
end
if n==1 then return "true" end
if n==2 then return "false" end
return false
end

I know it's a lot to read, but any help would be appreciated. This is really the only thing keeping me from continuing my project.
Lyqyd #2
Posted 12 August 2012 - 12:44 AM
Which code are you using to save it? It would be trying to concatenate the three variables, so if they've got different names in the saving code, it won't work.
Cranium #3
Posted 12 August 2012 - 12:52 AM
OMG….I forgot to put the code in that was actually throwing the error. My bad!

local function saveState(saveTable)
    local file = fs.open("status", "w")
    if file then
	    for eNum, eInfo in ipairs(saveTable) do
		    file.writeLine(eInfo.type..","..eInfo.color..","..eInfo.status)
	    end
	    file:close()
    end
end
Cranium #4
Posted 12 August 2012 - 12:54 AM
I did have to change the file.writeLine to be able to write each table as a new line, instead of all on the same line.
Lyqyd #5
Posted 12 August 2012 - 12:58 AM
If you're using the FS API instead of the IO API, you should change it from file:close() to file.close(). And that's surprising. Appending a newline should have fixed it.

Check the value you're getting back from the color picking/ color converting stuff. That may be the source of the problem. I'm not sure what it would be doing to screw things up, though. Everything else is declared explicitly, so it should be fine.
Cranium #6
Posted 12 August 2012 - 01:23 AM
I changed it around, but it's still not working… I have tried everything I can think of….to no avail. I'm just going to have to post my entire code, huh? well, here you go…again. :P/>/>

--Made by Craniumkid22
--This code is free to use, under a few conditions:
--1. DO NOT claim this as your own work!
--2. If you change this code, feel free to contact me on the CC forums, user-Craniumkid22.
--3. if you have questions about any of this code, feel free to contact me as well.
--Huge thanks to Lyqyd for pounding the necessity of local variables into my thick skull.
--screen functions
function title()
term.clear()
term.setCursorPos(1,1)
print("	 Welcome to Master Control initialization!")
print("	   Please read each selection carefully.")
print("		  If you mess up, press CTRL + T")
print("			 And run the wizard again.")
term.setCursorPos(1,9)
end
--end screen functions
-- variables
colorOpt={
"Redstone/Red alloy wire",
"White",
"Orange",
"Magenta",
"Light Blue",
"Yellow",
"Lime",
"Pink",
"Gray",
"Light Gray",
"Cyan",
"Purple",
"Blue",
"Brown",
"Green",
"Red",
"Black"
}
eType={
"None",
"BatBox",
"MFE",
"MFSU"
}
pType={
"None",
"Generator",
"Geothermal Generator",
"Water Mill",
"Wind Mill",
"Solar Panel",
"Nuclear Reactor",
"Redstone Engine",
"Steam Engine",
"Combustion Engine"
}
--end variables
function yN()
local n=1
while true do
local x, y=term.getCursorPos()
term.clearLine()
if n==1 then write(">YES<   NO") else write (" YES   >NO<") end
term.setCursorPos(x, y)
a, b=os.pullEvent()
while a~="key" do a, b=os.pullEvent() end
if b==203 and n==2 then n=1 end
if b==205 and n==1 then n=2 end
if b==28 then print("") break end
end
if n==1 then return "true" end
if n==2 then return "false" end
return false
end
function opt(m)
n=1
l=#m
while true do
term.clear()
term.setCursorPos(1,2)
for i=1, l, 1 do
if i==n then print(i, " ["..m[i].."]") else print(i, " ", m[i]) end
end
a, b= os.pullEventRaw()
if a == "key" then
if b==200 and n>1 then n=n-1 end
if b==208 and n<=l then n=n+1 end
if b==28 then break end
end
end
term.clear() term.setCursorPos(1,1)
return n
end
function colorConvert(color)
if color > 1 then return 2^(color - 2)
else return 0
end
end
function eConvert(e,m)
if e == "1" then r = m[1]
elseif e == "2" then r = m[2]
elseif e == "3" then r = m[3]
elseif e == "4" then r = m[4]
elseif e == "5" then r = m[4]
elseif e == "6" then r = m[6]
elseif e == "7" then r = m[7]
elseif e == "8" then r = m[8]
elseif e == "9" then r = m[9]
elseif e == "10" then r = m[10]
end
return tostring(r)
end
local function saveState(saveTable)
    local file = fs.open("status", "w")
    if file then
	    for eNum, eInfo in ipairs(saveTable) do
		    file.writeLine(eInfo.type..","..eInfo.color..","..eInfo.status)
	    end
	    file.close()
    end
end
local function saveProfile(saveTable)
    local file = fs.open("profile", "w")
    if file then
	    for eNum, eInfo in ipairs(saveTable) do
		    file.writeLine(eInfo.type..","..eInfo.name..","..eInfo.pass)
	    end
	    file.close()
    end
end
local function loadState()
    local loadTable = {}
    local file = fs.open("status", "r")
    if file then
	    readLine = file.read("*l")
	    while readLine do
		    local lineTable = {}
		    lineTable.type, lineTable.color, lineTable.status = string.match(readLine, "(%a+),(%a+),(%a+)")
		    if lineTable.type then
			    table.insert(loadTable, lineTable)
		    end
		    readLine = file.read("*l")
	    end
	    file.close()
    end
    return loadTable
end
--code start
local controlTable = {}
while true do
title()
local deviceTable = {type="Admin"}
while true do
print("Please enter Administrator name:")
deviceTable.name  = read()
  if deviceTable.name == "" then
  print("Admin name cannot be blank")
  sleep(1)
  title()
  else break
  end
end
title()
while true do
  while true do
  print("Please enter Administrator password:")
  tempadmin = read("*")
   if tempadmin == "" then
   print("Password cannot be blank")
   sleep(1)
   title()
   else break
   end
  end
  title()
  while true do
  print("Please re-enter password:")
  tempadmin2 = read("*")
   if tempadmin2 == "" then
   print("Password cannot be blank")
   sleep(1)
   title()
   else break
   end
  end
  title()
   if tempadmin ~= tempadmin2 then
   print("Passwords do not match. Please try again.")
   sleep(1)
   title()
   elseif tempadmin == tempadmin2 then
   deviceTable.pass = tempadmin break
   end
  end
  title()
  print("Thank you. Admin profile created.")
  sleep(1)
  table.insert(controlTable,deviceTable)
  saveProfile(controlTable)
  tempadmin = nil
  tempadmin2 = nil
  break
  end
local deviceTable = {type="User"}
while true do
title()
print("Please enter User name:")
tempusername = read()
if tempusername == adminname then
print("Cannot have User name the same as Administrator name.")
sleep(1)
title()
elseif tempusername == "" then
print("User name cannot be blank.")
sleep(1)
title()
else
deviceTable.name = tempusername
break
end
end
while true do
title()
while true do
  while true do
  print("Please enter User password:")
  tempuser = read("*")
   if tempuser == "" then
   print("Password cannot be blank.")
   sleep(1)
   title()
   else break
   end
  end
title()
  while true do
  title()
  print("Pleas re-enter password:")
  tempuser2 = read("*")
   if tempuser2 == "" then
   print("Password cannot be blank.")
   sleep(1)
   title()
   else break
   end
  end
  title()
  if tempuser ~= tempuser2 then
  print("Passwords do not match. Please try again.")
  sleep(1)
  title()
  elseif tempuser == tempuser2 then
  deviceTable.pass = tempuser break
  end
end
title()
print("Thank you. User profile created.")
sleep(1)
break
end
table.insert(controlTable,deviceTable)
saveProfile(controlTable)
tempuser = nil
tempuser2 = nil
--removed
local deviceTable = {type="Lights"}
title()
print("Do you have lighting that you want to control?")
deviceTable.status = yN()
if deviceTable.status == "true" then
term.clear()
term.setCursorPos(1,9)
print("		   What color are you using?")
sleep(1.5)
deviceTable.color = colorConvert(opt(colorOpt))
deviceTable.status = "false"
table.insert(controlTable,deviceTable)
saveState(controlTable)
else deviceTable.status = "false"
deviceTable.color = "false"
table.insert(controlTable,deviceTable)
saveState(controlTable)
end
title()
while true do
local deviceTable = {type="Power"}
print("What type of power are you using?")
sleep(2)
deviceTable.type = tostring(opt(pType))
if deviceTable.type == "7" then
deviceTable.color = "false"
table.insert(controlTable,deviceTable)
saveState(controlTable)
local deviceTable = {type="Reactor"}
title()
print("Do you want this computer to control your reactor?")
deviceTable.status = yN()
  if deviceTable.status == "true" then
  term.clear()
  term.setCursorPos(1,9)
  print("		   What color are you using?")
  sleep(1.5)
  deviceTable.color = colorConvert(opt(colorOpt))
  table.insert(controlTable,deviceTable)
  saveState(controlTable)
  else
  local deviceTable = {type="Reactor"}
  deviceTable.status = "false"
  deviceTable.color = "false"
  table.insert(controlTable,deviceTable)
  saveState(controlTable)
  end
local deviceTable = {type="Coolant"}
deviceTable.type = "Coolant"
title()
print("Do you have an independant coolant system?")
deviceTable.status = yN()
  if deviceTable.status == "true" then
  term.clear()
  term.setCursorPos(1,9)
  print("		   What color are you using?")
  sleep(1.5)
  deviceTable.color = colorConvert(opt(colorOpt))
  table.insert(controlTable,deviceTable)
  saveState(controlTable) break
  else
  deviceTable.status = "false"
  table.insert(controlTable,deviceTable)
  saveState(controlTable)
  end
elseif deviceTable.type == "1" then
local deviceTable = {type="Power"}
deviceTable.status = "false"
deviceTable.color = "false"
table.insert(controlTable,deviceTable)
saveState(controlTable)
local deviceTable = {type="Reactor"}
deviceTable.status = "false"
deviceTable.color = "false"
table.insert(controlTable,deviceTable)
saveState(controlTable)
local deviceTable = {type="Coolant"}
deviceTable.status = "false"
deviceTable.color = "false"
table.insert(controlTable,deviceTable)
saveState(controlTable)
else
term.clear()
term.setCursorPos(1,9)
print("		   What color are you using?")
sleep(1.5)
deviceTable.color = colorConvert(opt(colorOpt))
deviceTable.status ="false"
table.insert(controlTable,deviceTable)
saveState(controlTable)
local deviceTable = {type="Reactor"}
deviceTable.status = "false"
deviceTable.color = "false"
table.insert(controlTable,deviceTable)
saveState(controlTable)
local deviceTable = {type="Coolant"}
deviceTable.status = "false"
deviceTable.color = "false"
table.insert(controlTable,deviceTable)
saveState(controlTable)
end
break
end
while true do
local deviceTable = {type="Energy"}
title()
print("What type of energy storage are you using?")
sleep(2)
deviceTable.type = tostring(opt(eType))
if deviceTable.type ~= "1" then
term.clear()
term.setCursorPos(1,9)
print("		   What color are you using?")
sleep(1.5)
deviceTable.color = colorConvert(opt(colorOpt))
deviceTable.status = "nil"
table.insert(controlTable,deviceTable)
saveState(controlTable)
else
deviceTable.color = "false"
deviceTable.status = "false"
table.insert(controlTable,deviceTable)
saveState(controlTable)
end
break
end
while true do
local deviceTable = {type="Macerator"}
title()
print("Would you like to control an IC2 Macerator?")
deviceTable.status = yN()
if deviceTable.status == "true" then
term.clear()
term.setCursorPos(1,9)
print("		   What color are you using?")
sleep(1.5)
deviceTable.color = colorConvert(opt(colorOpt))
deviceTable.status = "false"
table.insert(controlTable,deviceTable)
saveState(controlTable)
break
else deviceTable.status = "false"
deviceTable.color = "false"
table.insert(controlTable,deviceTable)
saveState(controlTable)
break
end
end
while true do
local deviceTable = {type="Furnace"}
title()
print("Would you like to control an IC2 Furnace?")
furnace = yN()
if furnace == "true" then
term.clear()
term.setCursorPos(1,9)
print("		   What color are you using?")
sleep(1.5)
deviceTable.color = colorConvert(opt(colorOpt))
deviceTable.status = "false"
table.insert(controlTable,deviceTable)
saveState(controlTable)
break
else deviceTable.status = "false"
deviceTable.color = "false"
table.insert(controlTable,deviceTable)
saveState(controlTable)
break
end
end
while true do
local deviceTable = {type="Compressor"}
title()
print("Would you like to control an IC2 Compressor?")
deviceTable.status = yN()
if deviceTable.status == "true" then
term.clear()
term.setCursorPos(1,9)
print("		   What color are you using?")
sleep(1.5)
deviceTable.color = colorConvert(opt(colorOpt))
deviceTable.status = "false"
table.insert(controlTable,deviceTable)
saveState(controlTable)
break
else deviceTable.status = "false"
deviceTable.color = "false"
table.insert(controlTable,deviceTable)
saveState(controlTable)
break
end
end
while true do
local deviceTable = {type="Extractor"}
title()
print("Would you like to control an IC2 Extractor?")
extractor = yN()
if extractor == "true" then
term.clear()
term.setCursorPos(1,9)
print("		   What color are you using?")
sleep(1.5)
deviceTable.color = colorConvert(opt(colorOpt))
deviceTable.status = "false"
table.insert(controlTable,deviceTable)
saveState(controlTable)
break
else deviceTable.status = "false"
deviceTable.color = "false"
table.insert(controlTable,deviceTable)
saveState(controlTable)
break
end
end
Jarle212 #7
Posted 12 August 2012 - 01:35 AM
Can you post the error message? if it is "concatenate string and nil" the error is that you are writing a nil(a variable that dosn't exist) to a file, the screen or to a function that expects a string.
Cranium #8
Posted 12 August 2012 - 01:43 AM
Can you post the error message? if it is "concatenate string and nil" the error is that you are writing a nil(a variable that dosn't exist) to a file, the screen or to a function that expects a string.
firstrun:118: attempt to concatenate string and nil

I don't even know what "concatenate" means… I had to look it up, and I'm in college!
Cranium #9
Posted 12 August 2012 - 01:55 AM
HA! I fixed it! I was trying to break up the profiles into a separate file, but the previous saveState() was still waiting for the results of that table. Since there wasn't anything there, then it was trying to declare nil, and you cant concatenate nil. Problem SOLVED!
Lyqyd #10
Posted 12 August 2012 - 01:56 AM
Ah, I've got it. You use two separate functions for saving the profile data and the device data. That's fine, but you're also using the same table for both. So when it tries to save data the first time with saveState, it gets to the admin entry in the controlTable and it looks for the color and status fields and can't find them, only pass and name. You'd probably be better off with one save function:


local function saveState(saveTable)
    local file = fs.open("status", "w")
    if file then
        for eNum, eInfo in ipairs(saveTable) do
            if eInfo.type == "admin" or eInfo.type == "user" then
                file.writeLine(eInfo.type..","..eInfo.name..","..eInfo.pass)
            else
                file.writeLine(eInfo.type..","..eInfo.color..","..eInfo.status)
            end
        end
        file.close()
    end
end
Cranium #11
Posted 12 August 2012 - 02:25 AM
Yeah, I solved it on my own just as you were writing that. LOL. I just decided to call color instead of name, and status instead of pass. Easy enough once I figured out what I did wrong.