Add a decimal to calculator app swift 4 - ios

I need help where to add the decimal function in the following code? I found the same question that had the same code but the corrections did not work. Looking for any help here!
Here is my code:
#IBOutlet weak var label: UILabel!
#IBAction func numbers(_ sender: UIButton) {
if performingMath == true {
label.text = String(sender.tag-1)
numberOnScreen = Double(label.text!)!
performingMath = false
}
else {
label.text = label.text! + String(sender.tag-1)
numberOnScreen = Double(label.text!)!
}
}
#IBAction func buttons(_ sender: UIButton) {
if label.text != "" && sender.tag != 11 && sender.tag != 16{
previousNumber = Double(label.text!)!
if sender.tag == 12 { //Divide
label.text = "/";
}
}
There is more code below with the other func buttons (multiply, add, subtract, etc...)
I appreciate any help!

I would add another button for the decimal point. You would need to check that pressing a decimal point made sense. For example:
if label.text == "" {
// Decimal at the start means add a zero
label.text = "0."
} else if label.text.contains(".") {
// Don’t add another decimal point!
}
// To get number from label
if let number = Double(label.text) {
// Use the number here
}

Related

Making a calculator in Swift

My problem is that I can click and input multiple numbers for my first value but then after I used a math operator (ex. +,-,*,/) it only allows me to input a single value unlike the first time running it.
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var Label: UILabel!
var secondNumber: Double = 0;
var firstNumber: Double = 0;
var performingMath = false
var operatorUsed = 0;
#IBAction func cleartext(_ sender: UIButton) {
Label.text = ""
performingMath = false
}
#IBAction func Numbers(_ sender: UIButton) {
if performingMath {
Label.text = String(sender.tag - 1)
secondNumber = Double(Label.text!)!
performingMath = true
} else {
Label.text = Label.text! + String(sender.tag - 1)
secondNumber = Double(Label.text!)!
}
}
#IBAction func Operators(_ sender: UIButton) {
if Label.text != " " && sender.tag != 11 {
firstNumber = Double(Label.text!)!
if sender.tag == 12 {
Label.text = "+"
} else if sender.tag == 13 {
Label.text = "-"
} else if sender.tag == 14 {
Label.text = "*"
} else if sender.tag == 15 {
Label.text = "/"
}
operatorUsed = sender.tag
performingMath = true
} else if sender.tag == 11 {
if operatorUsed == 12 {
Label.text = String(firstNumber + secondNumber)
}
if operatorUsed == 13 {
Label.text = String(firstNumber - secondNumber)
}
if operatorUsed == 14 {
Label.text = String(firstNumber * secondNumber)
}
if operatorUsed == 15 {
Label.text = String(firstNumber / secondNumber)
}
}
}
}
I expect the that I can input many values as possible after I used a math operator (ex. +-*/)
When you update the label's text when performingMath is true, you just assign the new value instead of adding the value to the existing one (see line 3)
#IBAction func Numbers(_ sender: UIButton) {
if performingMath {
Label.text = String(sender.tag - 1) // !! HERE !!
secondNumber = Double(Label.text!)!
performingMath = true
} else {
Label.text = Label.text! + String(sender.tag - 1)
secondNumber = Double(Label.text!)!
}
}
This should perform the same action as when performingMath is false, so you just need to update this line with:
Label.text = Label.text! + String(sender.tag - 1)

check the text of the buttons in the array

I have 5 buttons and they are in an array. While text of the buttons unequal to cevapLabel.Text, I want to hide them randomize. how to check all buttons text?
like this;
while allButtonsText != cevapLabel.Text {}
Here is my code:
#IBAction func eliminateChoiceClicked(_ sender: Any) {
let num = Int(arc4random_uniform(5))
let buttons:[UIButton] = [buttonA,buttonB,buttonC,buttonD,buttonE]
while buttons != cevapLabel.text {
buttons[num].isHidden = !buttons[num].isHidden
}
}
in this code its show this error: " Binary operator '!=' cannot be applied to operands of type '[UIButton]' and 'String?' "
---EDITED---
I had to make a few changes in my project.
Here is the code:
#IBAction func eliminateChoiceClicked(_ sender: Any) {
var buttons: [UIButton] = [buttonA,buttonB,buttonC,buttonD,buttonE]
for _ in 1...3 {
let randomNumber = Int(arc4random_uniform(UInt32(buttons.count)))
let button = buttons.remove(at: randomNumber)
button.isHidden = true
}
for button in buttons {
button.isHidden = false
}
}
I tried like this:
#IBAction func eliminateChoiceClicked(_ sender: Any) {
var buttons: [UIButton] = [buttonA,buttonB,buttonC,buttonD,buttonE]
for x in buttons {
if x.titleLabel?.text != cevapLabel.text {
for _ in 1...3 {
let randomNumber = Int(arc4random_uniform(UInt32(buttons.count)))
let button = buttons.remove(at: randomNumber)
button.isHidden = true
}
}
else {
for button in buttons {
button.isHidden = false
}
}
}
}
And i got that error: "Thread 1: Fatal error: Index out of range"
The issue occurs because you're comparing an array of UIButtons with a String.
You can fix your issue by creating a func returning a Bool and calling it in your while statement like so:
#IBAction func eliminateChoiceClicked(_ sender: Any) {
let num = Int(arc4random_uniform(5))
let buttons:[UIButton] = [buttonA,buttonB,buttonC,buttonD,buttonE]
while !isStringContainedInButtons(buttons) {
buttons[num].isHidden = !buttons[num].isHidden
}
}
func isStringContainedInButtons(buttons: [UIButton]) -> Bool {
for (button in buttons) {
if (button.titleLabel?.text == cevapLabel.text) {
return true
}
}
return false
}
I don’t understand the need for the while loop, I would replace it with
if buttons.map($0.title).filter($0 == cevapLabel.text).count == 0 {
buttons[num].isHidden = !buttons[num].isHidden
}
Swift 4
for button in buttons {
if button.title(for: .normal) == cevapLevel.text {
//your code
}
}

Swift 4 - Quiz App Random Questions

I'm a beginner to Swift and generally Xcode. Thank you in advance for your time and help :)
I am doing a Quiz App, and I try to have random questions... I have a function to generate random numbers that I tried to apply in viewDidLoad()... unfortunately I can not guess how to use that information in his variable "var currentQuestion = 0"
This is the code:
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
generateRandomNumber(0, 9, 10)
}
override func viewDidAppear(_ animated: Bool) {
newQuestion()
}
// Quiz//
let questions = ["Q1","Q2","Q3","Q4","Q5"]
let answers = [["A","2","3"],["B","2","3"],["C","2","3"],["D","2","3"],["E","2","3"]]
//Variables
var currentQuestion = 0
var rightAnswerPlacement:UInt32 = 0
//Generate Random Numbers
func generateRandomNumber(_ from:Int, _ to:Int, _ qut:Int?) -> [Int] {
var myRandomNumbers = [Int]() //All our generated numbers
var numberOfNumbers = qut //How many numbers to generate
let lower = UInt32(from) //Generate from this number..
let higher = UInt32(to+1) //To this one
if numberOfNumbers == nil || numberOfNumbers! > (to-from) + 1 {
numberOfNumbers = (to-from) + 1
}
while myRandomNumbers.count != numberOfNumbers {
let myNumber = arc4random_uniform(higher - lower) + lower
if !myRandomNumbers.contains(Int(myNumber)) {
myRandomNumbers.append(Int(myNumber))
}
}
return myRandomNumbers
}
//Label
#IBOutlet weak var lbl: UILabel!
//Button
#IBAction func action(_ sender: AnyObject) {
if (sender.tag == Int(rightAnswerPlacement)) {
print ("RIGHT!")
} else {
print ("WRONG!!!!!!")
}
if (currentQuestion != questions.count) {
newQuestion()
} else {
}
}
//Function that displays new question
func newQuestion() {
lbl.text = questions[currentQuestion]
rightAnswerPlacement = arc4random_uniform(3)+1
//Create a button
var button:UIButton = UIButton()
var x = 1
for i in 1...3 {
//Create a button
button = view.viewWithTag(i) as! UIButton
if (i == Int(rightAnswerPlacement)) {
button.setTitle(answers[currentQuestion][0], for: .normal)
} else {
button.setTitle(answers[currentQuestion][x], for: .normal)
x = 2
}
}
currentQuestion += 1
}
Any idea that how will be possible to resolve?
First you need to store the array of random questions that you generate (side note you appear to try to generate 10 random numbers but have only 5 questions).
Then instead of using the currentQuestion directly you use that to access the question in the array.
So change it to this:
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
questionArray = generateRandomNumber(0, 9, 10)
}
override func viewDidAppear(_ animated: Bool) {
newQuestion()
}
// Quiz//
let questions = ["Q1","Q2","Q3","Q4","Q5"]
let answers = [["A","2","3"],["B","2","3"],["C","2","3"],["D","2","3"],["E","2","3"]]
//Variables
var currentQuestion = 0
var rightAnswerPlacement:UInt32 = 0
var questionArray: [Int] = [] // Just an initial value
//Generate Random Numbers
func generateRandomNumber(_ from:Int, _ to:Int, _ qut:Int?) -> [Int] {
var myRandomNumbers = [Int]() //All our generated numbers
var numberOfNumbers = qut //How many numbers to generate
let lower = UInt32(from) //Generate from this number..
let higher = UInt32(to+1) //To this one
if numberOfNumbers == nil || numberOfNumbers! > (to-from) + 1 {
numberOfNumbers = (to-from) + 1
}
while myRandomNumbers.count != numberOfNumbers {
let myNumber = arc4random_uniform(higher - lower) + lower
if !myRandomNumbers.contains(Int(myNumber)) {
myRandomNumbers.append(Int(myNumber))
}
}
return myRandomNumbers
}
//Label
#IBOutlet weak var lbl: UILabel!
//Button
#IBAction func action(_ sender: AnyObject) {
if (sender.tag == Int(rightAnswerPlacement)) {
print ("RIGHT!")
} else {
print ("WRONG!!!!!!")
}
if (currentQuestion != questions.count) {
newQuestion()
} else {
}
}
//Function that displays new question
func newQuestion() {
lbl.text = questions[questionArray[currentQuestion]]
rightAnswerPlacement = arc4random_uniform(3)+1
//Create a button
var button:UIButton = UIButton()
var x = 1
for i in 1...3 {
//Create a button
button = view.viewWithTag(i) as! UIButton
if (i == Int(rightAnswerPlacement)) {
button.setTitle(answers[questionArray[currentQuestion]][0], for: .normal)
} else {
button.setTitle(answers[questionArray[currentQuestion]][x], for: .normal)
x = 2
}
}
currentQuestion += 1
}
(I think the code is correct but I'm currently running some tests in Xcode so can't check. If there is a problem leave a comment.)

How to remove "..." from my array?

In my calculator app I ran into a problem where I want ... to show in my array but only when the if statement for resultIsPending is true. Then after that I want the ... to be deleted. How can I do this in Swift? Here is the code of my ViewController.swift:
#IBOutlet weak var sequence: UILabel!
#IBOutlet weak var display: UILabel!
var userInTheMiddleOfTyping = false
var resultIsPending:Bool = false
var elements = [String]()
//var sequenceArray:Array = []
#IBAction func clear(_ sender: Any) {
display.text = " "
elements.removeAll()
elements = elements.filter{$0 != "\(String(describing: display.text))"}
sequence.text = elements.joined()
}
override func viewDidLoad() {
}
#IBAction func touchDigit(_ sender: UIButton) {
let digit = sender.currentTitle!
elements.append(digit)
combineToMakeOperationHistory()
if userInTheMiddleOfTyping{
let textCurrentlyInDisplay = display!.text!
display!.text = textCurrentlyInDisplay + digit
} else {
display!.text = digit
userInTheMiddleOfTyping = true
}
}
var displayValue: Double{
get{
return Double(display.text!)!
}
set{
display.text = String(newValue)
}
}
private var brain = CalculatorBrain()
#IBAction func performOperation(_ sender: UIButton) {
let perSender = sender.currentTitle!
elements.append(perSender)
combineToMakeOperationHistory()
if perSender == "+" || perSender == "÷" || perSender == "×" || perSender == "-" || perSender == "^"{
resultIsPending = true
}
if userInTheMiddleOfTyping{
brain.setOperand(displayValue)
userInTheMiddleOfTyping = false
}
userInTheMiddleOfTyping = false
if let mathematicalSymbol = sender.currentTitle{
brain.performOperation(mathematicalSymbol)
}
if brain.result != nil{
displayValue = brain.result!
}
}
func combineToMakeOperationHistory() {
if resultIsPending{ // this is the if statement
elements.append("...")
}else if resultIsPending == false{
}
sequence.text = elements.joined()
}
You can filter your elements array and remove the "...".
elements = elements.filter({ $0 != "..." })
Whenever you want to remove the occurrence of a String value.
you can uses something like hat
var resultIsPending:Bool = false{
didSet(isPending) {
if isPending {
elements.append("...")
} else {
elements.dropLast()
}
}
}
Don't combine data that are not of the same type. There is no reason to put ... into the array of elements:
func combineToMakeOperationHistory() {
var sequenceText: String = elements.joined()
if (resultIsPending) {
sequenceText += "..."
}
sequence.text = sequenceText
}
Since we are not appending ... to the array, we don't have to remove it.

How to code a calculator that adds, numbers consecutively (Swift)

This is my code for the calculator, right now I can only add 2 numbers consecutively before hitting the equals sign, I want to make where I can add More than two Numbers before hitting the equals button. (Written in Swift)
import UIKit
class CalcControl: UIView {
var firstEntry = ""
var isUserInMiddleOfTypingNumbers:Bool?
var didUserPressedOperation:Bool?
var op:String?
#IBOutlet var displayLabel: UILabel!
#IBAction func digitPressed(sender: UIButton) {
if (didUserPressedOperation == nil) {
//displayLabel.text = ""
didUserPressedOperation = nil
}
if (isUserInMiddleOfTypingNumbers == nil) {
displayLabel.text = displayLabel.text! + sender.currentTitle!
} else {
displayLabel.text = sender.currentTitle
isUserInMiddleOfTypingNumbers = true
}
}
#IBAction func operationPressed(sender: UIButton) {
op = sender.currentTitle
firstEntry = displayLabel.text!
didUserPressedOperation = true
displayLabel.text = ""
}
#IBAction func clearPressed(sender: UIButton) {
self.clear()
}
func clear() {
firstEntry = ""
isUserInMiddleOfTypingNumbers = nil
didUserPressedOperation = nil
displayLabel.text = ""
}
#IBAction func equalPressed(sender: UIButton) {
var secondEntry:NSString = displayLabel.text!
println((firstEntry))
println((secondEntry))
if(op == "+") {
displayLabel.text = (((firstEntry as NSString!).doubleValue + (secondEntry as NSString).doubleValue) as NSNumber).stringValue
} else if(op == "-") {
displayLabel.text = (((firstEntry as NSString!).doubleValue - (secondEntry as NSString).doubleValue) as NSNumber).stringValue
} else if(op == "x") {
displayLabel.text = (((firstEntry as NSString!).doubleValue * (secondEntry as NSString).doubleValue) as NSNumber).stringValue
} else if(op == "/") {
displayLabel.text = (((firstEntry as NSString!).doubleValue / (secondEntry as NSString).doubleValue) as NSNumber).stringValue
}
firstEntry = ""
isUserInMiddleOfTypingNumbers = nil
didUserPressedOperation = nil
}
}
I would adjust your logic so that:
There is an IB Action that all the operator keys (+, -, x, /) are tied to. In this IB Action any time it is activated, there are two choices: a) prepare for another number to be entered or b) the previous key sequence was a number followed by an operator symbol and the button is the same as an Enter.
An IB Action for the delete key. Obvious role.
An IB Action for the Enter key.

Resources