Home > Back-end >  Basic Calculator: How to script a function for deleting digits one by one? (GDScript)
Basic Calculator: How to script a function for deleting digits one by one? (GDScript)

Time:12-12

I've looked around for a few hours now and cant still find a helpful answer so I've decided to ask here- How am I supposed to code a button that deletes digits in a basic calculator one by one?

Heres my script so far!: https://pastebin.com/xLj2iCHU

func _on_BDeleteDigit_pressed():
    var numberAdded
    var numberBefore = $NumberStuffs.get_text()
    numberAdded = numberAdded.length() - 1
    numberAdded[numberBefore]=("")
    $Outputlabel.set_text(str(numberAdded))

This is also the error when the delete button is pressed: https://i.stack.imgur.com/8OJTI.png

I was wondering how I may make this entire thing more optimized/shorter too but maybe that's for a different question altogether,,

CodePudding user response:

Explaining the error

I'll start with the error. It says

Nonexistent function 'length' in base 'Nil'

The error is telling you that you are trying call a function called length on something that is Nil, but Nil does not have a function called length.

The problem is that you are trying to call something on Nil. What are you trying to call? length. So where is that? That is here:

numberAdded = numberAdded.length() - 1

So, numberAdded is Nil. The next question is why. So, let us see where numberAdded got its value…

So you declare it here:

var numberAdded

Then we have this line that has nothing to do with it:

var numberBefore = $NumberStuffs.get_text()

And then the line with the error:

numberAdded = numberAdded.length() - 1

What did you expect numberAdded.length() to be, if numberAdded does not have a value? Of course that is an error.


By the way, the code suggests that you expected numberAdded to be, well, a number. Which makes me wonder what you expected from this:

numberAdded[numberBefore]=("")

Yes you can do the inverted indexing thing in C or C , because it is just adding pointers. But not GDScript, you don't.


I suspect that using types would help you. For example declare numberAdded to be an integer like this: var numberAdded:int. Yes, GDScript has types, use them.


How to delete the last character

Let me take as reference how you add a digit:

func _on_Button1_pressed():
    var currentNumber = $NumberStuffs.get_text()
    
    currentNumber = currentNumber   "1"
    $NumberStuffs.set_text(currentNumber)

Alright, we are storing a string on the text property of the node $NumberStuffs. And we add a digit by concatenating to it.

The above code should be is equivalent to this:

func _on_Button1_pressed():
    $NumberStuffs.text  = "1"

If get_text and set_text are custom functions in GDScript, you may want to look into setget.


Thus, the question is how to remove the last character of a string. There are several ways!

One way would be using erase:

func _on_BDeleteDigit_pressed():
    var text := $NumberStuffs.text
    var length := text.length()
    text.erase(length - 1, 1)
    $NumberStuffs.text = text

Note that erase is modifying the string, but the string is a copy we got from reading $NumberStuffs.text (or calling $NumberStuffs.get_text), which is why we need to set to $NumberStuffs.text (or call $NumberStuffs.set_text) anyway.

Or if you prefer:

func _on_BDeleteDigit_pressed():
    var text := $NumberStuffs.get_text()
    var length := text.length()
    text.erase(length - 1, 1)
    $NumberStuffs.set_text(text)

Alternatively, we might get a string which is like the one we have except lacking the last character. We can do that with left (which lets you get a portion of the string from the left, there is also a right function that does the same but from the right):

func _on_BDeleteDigit_pressed():
    var length := $NumberStuffs.text.length()
    $NumberStuffs.text = $NumberStuffs.text.left(length - 1)

Or, if you prefer:

func _on_BDeleteDigit_pressed():
    var text := $NumberStuffs.get_text()
    var length := text.length()
    $NumberStuffs.set_text(text.left(length - 1))

In general we can get a string containing a portion of another string with substr:

func _on_BDeleteDigit_pressed():
    var length := $NumberStuffs.text.length()
    $NumberStuffs.text = $NumberStuffs.text.substr(0, length - 1)

Or, if you prefer:

func _on_BDeleteDigit_pressed():
    var text := $NumberStuffs.get_text()
    var length := text.length()
    $NumberStuffs.set_text(text.substr(0, length - 1))

And yes, you can modify the string by indexing it, which I believe is what you were trying. For example:

$NumberStuffs.text[-1] = "a"

Which is equivalent to:

var length := $NumberStuffs.text.length()
$NumberStuffs.text[length - 1] = "a"

Which is equivalent to:

var text := $NumberStuffs.get_text()
var length := text.length()
text[length - 1] = "a"
$NumberStuffs.set_text(text)

Will replace the last character with an "a". And yes, you could remove by doing that. That would be:

$NumberStuffs.text[-1] = ""

Which is equivalent to:

var length := $NumberStuffs.text.length()
$NumberStuffs.text[length - 1] = ""

Which is equivalent to:

var text := $NumberStuffs.get_text()
var length := text.length()
text[length - 1] = ""
$NumberStuffs.set_text(text)

By the way, I have been using := when declaring the variables. That declares the variable of the type of whatever I'm using to initialize them.

  • Related