Lisp: `stringtype nil` error trying to get info from a dialogue box and add it with other strings - string

The program basically gets info from a points description and gets the text from a text item and adds the text item to the points description. The dialogue boxes allow for the user to select some parameters, like is it for lots, lots and blocks, or other. I have been working on this program for multiple days now and it is so close to working. I can get through the dialogue boxes with no problem, and I can get the desired effect with some of the trees (ones where it is simply just getting the info from the point and text item and adding them together like lots). The problem comes when I ask the user to input a number (in this case it is a block number I.E. Block 1) Upon putting in the number and selecting the point and a text item, I get string type nil error. Right now I think it could be due to trying to add a string which contains a space " " or the input on the dialogue box maybe isn't a string
Here is strcat function I am referencing:
(vlax-put-property p_obj 'rawdescription (strcat p_desc " BLOCK " type1 " " obj))
And here is the program getting the info from the box:
(action_tile "type1" "(setq type1 $value)")
Below are the relevant snippets of the code, not the entire program
Here is the combining function
(defun c:txcm_block ( / c_doc p_desc p_obj t_obj t1 t_strg text1 ts obj type1 number)
(vl-load-com)
(while
(setq c_doc (vla-get-ActiveDocument (vlax-get-acad-object))
p_obj (vlax-ename->vla-object (car (entsel "\nSelect Point: ")))
t_strg (vlax-ename->vla-object (car (entsel "\nPick Text.. "))))
(setq obj (vla-get-textstring t_strg))
(setq p_desc(vlax-get p_obj 'rawdescription))
(vlax-put-property p_obj 'rawdescription (strcat p_desc " BLOCK " type1 " " obj))
)
(princ)
)
Here is the Dialogue Function:
(defun c:nest2 ( / dcl_id2 number1 flag2)
(setq dcl_id2 (load_dialog "textcombine(input).dcl"))
(setq flag2 4)
(if (not (new_dialog "nest2" dcl_id2)) (exit))
(while (> flag2 2)
(set_tile "type1" "Enter Block Number")
(mode_tile "type1" 2)
(action_tile "type1" "(setq type1 $value)")
(action_tile
"accept"
"(done_dialog 4)"
)
(action_tile
"cancel"
"(done_dialog 0)
(setq result nil)
(c:txcm)"
)
(setq flag2 (start_dialog))
(if (= flag2 4)
(progn
(setq result T)
(c:txcm_block)
)
)
)
(unload_dialog dcl_id2)
)
And here is the nested DCL Code:
nest2 : dialog {
label = "Block Number";
: edit_box
{
label = "Enter Block Number: ";
mnemonic = "N";
key = "type1";
alighnment = centered;
edit_limit = 30;
edit_width = 30;
}
: button
{
key = "accept";
label = "Ok";
is_default = true;
fixed_width = true;
alignment = right;
allow_accept = true;
}
: button
{
key = "cancel";
label = "Go Back";
fixed_width = true;
alignment = centered;
}
: errtile
{
width = 17;
}
}
Any help would be appreciated! I have been all over the internet, but I feel like I am stuck. If you need more info, let me know!

You do seem to be setting the variable type1 inside your (c:nest2), and you do call (c:txcm_block) from (c:nest2), but (c:txcm_block) declares type1 as its local variable, so type1 is set to NIL on entry to (c:txcm_block).
NIL is not a string, so strcat naturally complains and bails.
Remove type1 from the local variables declaration list in (c:txcm_block) and put it on the local variables declaration list in (c:nest2).
In general, to deal with such situations, use your debugger to "break on error", then inspect the execution trace and check the current values of the variables of interest (like type1) at that point.

Related

how to ask user input for list of strings

I wanna know how to ask user input for a string. For example:
when user input is asked "lruud" is entered
Enter letters: lruud
and I want it the return should be:
Left
right
up
up
down
left = l, right = r, etc.
So basically it should return the result in the order the letters are entered.
The code below is what I have tried where al() is move left, ar() is move right etc
def move(s: String) {
if(s == "l"){
al()
}else if(s == "r"){
ar()
}else if(s == "u"){
au()
}else if(s == "d"){
ad()
}
}
You can read in a string from standard input using
val s = scala.io.StdIn.readLine()
Scala implicitly considers String to be a Scala collection, in particular an IndexedSeq which means you can call standard collections methods on it such as map to transform it. For example
def move(s: Char): String = {
if (s == 'l') "left"
else if (s == 'r') "right"
else if (s == 'u') "up"
else if (s == 'd') "down"
else throw new RuntimeException("Bad input")
}
"lruud".map(move)
// res4: IndexedSeq[String] = ArraySeq(left, right, up, up, down)
Mapping over a String reads each Char in the string and passes it to the move method for transformation.
Here's one way to go about this.
val action :Map[Char,String] =
Map('d'->"down",'l'->"left",'r'->"right",'u'->"up")
.withDefault(c => s"$c?")
val moves :Seq[String] =
io.StdIn.readLine("Enter letters: ").map(c =>action(c.toLower))
println("\ndirections:\n" + moves.mkString(" ","\n ",""))
testing:
Enter letters: lLdRbu
directions:
left
left
down
right
b?
up

Type mismatch in AutoHotkey Excel

I am trying to get input from a user, lookup the input value in an Excel column and return the value of the cell on the right side of the matching value.
This is what I came up with. As long as I replace %index% with a number, it will return a value from the Excel file.
The error I receive tells me there is a 'type mismatch' where I use %index% in
value := workbook.Sheets("Sheet1").Cells(%index%, 1).Value
Any ideas how to fix the type mismatch?
#a::
workbook := ComObjGet("somepath\tester.xlsx")
InputBox, OutputVar, Question 1, What are you looking for?
if (OutputVar)
MsgBox, Let me do this for you.
intent = OutputVar
index = 1
value = ""
Loop {
index := %index% + 1
value := workbook.Sheets("Sheet1").Cells(%index%, 1).Value
}
Until %intent% = %value%
SendInput, workbook.Sheets("Sheet1").Cells(%index%, 2).Value
Return
Use index, not %index%, in expressions. Also, you can use the built-in A_INDEX variable inside of loops
Here's your corrected code:
#a::
workbook := ComObjGet("somepath\tester.xlsx")
MAX_ROWS := 10
InputBox intent, Question 1, What are you looking for?
if ( ErrorLevel == 0 && intent ) {
Loop %MAX_ROWS% {
if ( intent == workbook.Sheets("Sheet1").Cells(A_Index, 1).Value ) {
SendInput % workbook.Sheets("Sheet1").Cells(A_Index, 2).Value
return
}
}
MsgBox 48, Not Found, "%intent%" not found in column a
}
return
Notes:
You cannot use substitution when a command takes an expression
ErrorLevel == 0 means OK was pressed. See InputBox
SendInput % makes the line use expression mode; everything following "% " is evaluated as an expression
Your loop never exits if intent is not found in the spreadsheet

UltiSnips - Create argument list with placeholders

I am trying to create a way in UltiSnip to take a list of variable names and transform them into a line delimited list of strings (like
you would see in AngularJS). So you type each arg, jump to next placeholder, and above the function is filled in with what you want.
Start with this:
function(FirstArg, SecondArg, ThirdArg)
Hit the CTRL-J (next placeholder)
And Final Result:
[
'FirstArg',
'SecondArg',
'ThridArg',
function(FirstArg, SecondArg, ThirdArg) {
// ... cursor here after hitting CTRL-J
// this would be $0
}
]
Any hints would be great!
Simpler then I thought. This is the function
global !p
def varDeps(args):
result = ""
argList = args.split(",")
for arg in argList:
dep = " " + "'" + arg.strip() + "',\n"
result = result + dep
return result.rstrip()
endglobal
Then use something like this (where this is the third placeholder)
`!p snip.rv = varDeps(t[3])`
function($scope, ${3:deps}) {
//....
}

Java Eclipse console terminates program before comparing values of user input and string value

So I'm making this program for my younger brother and I ran into a problem. The program is suppose to ask for the user's input and then compare it to multiple string values through a series of "if" statements. What happens instead is the user provides their input and then the program instantly terminates. I've been at this for hours and am starting to get pretty ticked about it. Here's the code that I've typed so far:
package package1;
import java.util.Scanner;
public class Psychic_Calculator {
#SuppressWarnings("resource")
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.println("Hello user, please type your name below:");
String a = scan.nextLine();
System.out.println("Welcome " + a + ", think of a number. Once you have your number, type 'okay' below!");
String b = scan.nextLine();
if (b == "okay"){
System.out.println("Now, add '11' to your number and type 'okay' below.");
}
else if (b == "Okay"){
System.out.println("Please don't capitalize 'okay', try typing it again!");
String c = scan.nextLine();
if (c == "okay"){
System.out.println("Now, add '11' to your number and type 'okay' below.");
String d = scan.nextLine();
if (d == "okay"){
System.out.println("Now, add '2' to your new number, then type 'okay' below.");
String e = scan.nextLine();
if (e == "okay"){
System.out.println("Now, subtract your original number from your new number, then type 'okay' below.");
String f = scan.nextLine();
if (f == "okay"){
System.out.println("Your new number is '13'. Don't even try denying it.");
}
}
}
}
if (c == "Okay"){
System.out.println("I already told you not to capitalize 'okay', try typing it again, you idiot!");
String g = scan.nextLine();
if (g == "okay"){
System.out.println("Now, add '11' to your number and type 'okay' below.");
String h = scan.nextLine();
if (h == "okay"){
System.out.println("Now, add '2' to your new number, then type 'okay' below.");
String i = scan.nextLine();
if (i == "okay"){
System.out.println("Now, subtract your original number from your new number, then type 'okay' below.");
String j = scan.nextLine();
if (j == "okay"){
System.out.println("Your new number is '13'. Don't even try denying it.");
}
}
}
}
}
if (c != "okay") {
while (c != "okay") {
System.out.println("Do you even know how to spell 'okay'?" + "'" + c + "' does not spell 'okay', you moron! Try typing 'okay' again.");
String n = scan.nextLine();
if (n == "okay"){
System.out.println("Finally, you learned how to spell 'okay'. Your vocabulary is now one word larger, you're welcome. Now, please add '11' to your number and then type 'okay'(correctly this time).");
String k = scan.nextLine();
if (k == "okay"){
System.out.println("Now, add '2' to your new number, then type 'okay' below.");
String l = scan.nextLine();
if (l == "okay"){
System.out.println("Now, subtract your original number from your new number, then type 'okay' below.");
String m = scan.nextLine();
if (m == "okay"){
System.out.println("Your new number is '13'. Don't even try denying it.");
}
}
}
}
else {
System.out.println(a + ", " + "you have failed to type 'okay' too many times! You have no idea how to spell 'okay' you electricutin' motherboarder! Go shove your face in a pile of computer chips and grow a pair!");
System.out.println("(of RAM cartriges...I meant to say RAM cartriges).");
}
}
}
}
}
}
The problem is how you're comparing the strings. Change b == "okay" to b.equals("okay")
Change all the == comparisons to .equals() or .equalsIgnoreCase().
For negations, use (!(c.equals("okay"))
In Java, == will compare primitive types by value but will compare objects by memory address. In other words, when you say b == "okay" its not doing a value comparison, its checking to see whether or not those two objects point to the same memory address, which of course is false.
Update: Just a few things about the way you're going about writing this program.
1) You're creating a lot of string objects needlessly. You're better off re-using one string object until you absolutely need another one. This applies to any object you're using. Try not allocate objects needlessly.
2) Instead of all the if-statements, you can define an array of instructions, like such and condense your code:
String [] instr = {"Add 2", "Add 11", "Subtract Original"};//array of directions
String [] invalidResp = {"Wrong", "You can't spell", "Try Again", "No"};//array of responses to print if user doesnt type 'okay' properly
int instrCounter = 0;//you don't really need this but it helps with readability
String userInput = "";//only string object you'll need =)
while (instrCounter < instr.length){//I couldve just as easily used a for loop instead.
userInput = scan.nextLine();
while (!userInput.equals("okay")){
userInput = scan.nextLine();
System.out.println(invalidResp[(int) (Math.random()*invalidResp.length)]);
//will print a random invalid response from the invalidResp array
System.out.println(userInput + " is not how you spell okay");
}//end while
System.out.println("Great, now, " + instr[instrCounter]);
instrCounter++;
}//end outer while
Remember, when you write code, you want it to be fairly generic and flexible. The way I wrote my code, I can add to the instr array or add more invalid responses and im not needlessly creating objects.
Like I said in the inline comment, I could've just as easily used a for loop for the outer loop but for the sake of readability and making sure you understood what I was doing, I used a while loop as I believe they're more intuitive to read.
GAME:
while(running) {
System.out.println("---------------------------");
continue GAME;
//Name the while loop and then you can break; out.

Return to menu language GO

I have a menu option with two options: add and substract. When I choose one it runs ok but the program closes. I would like to know how to make it go back to the menu after an operation ends to select another one
package main
import (
"fmt"
)
func main() {
var n1, n2, s, r float64
var op, ns int
fmt.Println("\n\tWelcome")
fmt.Println("Chose an option")
fmt.Println("1.-Add")
fmt.Println("2.-Substract")
fmt.Scan(&op)
if op == 1 {
fmt.Printf("\n\tAdd")
fmt.Printf("\nHow many numbers you add? ")
fmt.Scan(&ns)
if ns <= 1 {
fmt.Print("You can not add just a number")
} else {
for i := 0; i < ns; i++ {
fmt.Printf("\nType the number %d: ", i+1)
fmt.Scan(&n1)
s += n1
}
fmt.Println("\nThe sum is: ", s)
//How to return to the menu?
}
} else if op == 2 {
fmt.Printf("\n\tSubtraction")
fmt.Printf("\nType the first number: ")
fmt.Scan(&n1)
fmt.Printf("\nType the second number: ")
fmt.Scan(&n2)
r = n1 - n2
fmt.Println("\nSubstraction is: ", r)
}
}
Just wrap the whole thing in
for {
}
Use break to exit the loop or continue to go back to the top.
It's hard to tell exactly without seeing your code, but I may assume you should use operator for ;; {} and put inside your menu with the appropriate if/else statements.

Resources