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

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.

Related

Add a decimal to calculator app swift 4

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
}

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.

Create calculator history array swift

I have created a calculator and have created a Model.swift to handle all of my calculations. Then everything else is handled in my ViewController.swift. I'm trying to add another functionality, I am looking to create a history of all the operations performed in my calculator i have made and store them in an array.
Here is my code so far:
ViewController.swift
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var displayLabel: UILabel!
#IBOutlet weak var HistoryLabel: UILabel!
var historyArray: [String] = []
var userIsTypingNumbers = false
var firstNumber = 0
var secondNumber = 0
#IBAction private func NumbersEntered(_ sender: UIButton) {
//know what number is being pressed
/*let digit = sender.currentTitle!
//if user is typing a number, do this.
if userIsTypingNumbers{
//specify what number is being pressed
let textCurrentDisplay = displayLabel.text!
//append the another number onto the previous number.
displayLabel.text = textCurrentDisplay + digit
} else {
displayLabel.text = digit
}
userIsTypingNumbers = true*/
/*addToHistory(recordToAddToHistory: digit)*/
let number = sender.currentTitle
if userIsTypingNumbers {
displayLabel.text = displayLabel.text! + number!
} else {
displayLabel.text = number
userIsTypingNumbers = true
}
}
var displayValue: Double {
get {
return Double(displayLabel.text!)!
}
set {
displayLabel.text = String(newValue)
}
}
private var calculations = PerformCalculations()
#IBAction func Enter(_ sender: UIButton) {
//perform the calculations
if userIsTypingNumbers{
calculations.setOperand(operand: displayValue)
userIsTypingNumbers = false
}
if let mathematicalSymbol = sender.currentTitle {
calculations.performOperation(symbol: mathematicalSymbol)
/*addToHistory(recordToAddToHistory: String(mathematicalSymbol))*/
}
/*HistoryLabel.text = HistoryLabel.text! + String(sender.currentTitle!)*/
displayValue = calculations.result
/*HistoryLabel.text = HistoryLabel.text! + String(displayValue)*/
/*historyArray.append("\(String(describing: HistoryLabel.text))")*/
}
#IBAction func Clear(_ sender: UIButton) {
//clear display to 0.
displayLabel.text = "0"
HistoryLabel.text = ""
}
#IBAction func Delete(_ sender: UIButton) {
//deleting last typed number, if user messed up.
let name: String = self.displayLabel.text!
//count number of characters.
let stringLength = name.characters.count
let substringIndex = stringLength - 1
displayLabel.text = (name as NSString).substring(to: substringIndex)
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
/*override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if (segue.identifier == "History"){
if let destinationVC = segue.destination as? HistoryClassViewController{
destinationVC.someData = HistoryLabel.text
}
}
}*/
}
Model.swift
import Foundation
enum Optional<T>{
case None
case Some(T)
}
class PerformCalculations {
private var accumulator = 0.0
func setOperand(operand: Double){
accumulator = operand
}
//performing the operations for various operands
private var operations: Dictionary<String, Operation> = [
"√" : Operation.UnaryOperation(sqrt), //sqrt,
"×": Operation.BinaryOperation({$0 * $1}),
"+": Operation.BinaryOperation({$0 + $1}),
"-": Operation.BinaryOperation({$0 - $1}),
"÷": Operation.BinaryOperation({$0 / $1}),
"=": Operation.Equals
]
//case for various operands
private enum Operation{
case Constant(Double)
case UnaryOperation((Double) -> Double)
case BinaryOperation((Double, Double) -> Double)
case Equals
}
//switch case to actually perform the operations
func performOperation(symbol: String){
if let operation = operations[symbol]{
switch operation{
case .Constant(let value): accumulator = value
case .BinaryOperation(let function):
executePendingBinaryOperation()
pendingVar = PendingBianryOperationInfo(binaryFunction: function, firstOperand: accumulator)
case .UnaryOperation(let foo): accumulator = foo(accumulator)
case .Equals:
executePendingBinaryOperation()
}
}
}
private func executePendingBinaryOperation(){
if pendingVar != nil{
accumulator = pendingVar!.binaryFunction(pendingVar!.firstOperand,accumulator)
pendingVar = nil
}
}
private var pendingVar: PendingBianryOperationInfo?
private struct PendingBianryOperationInfo{
var binaryFunction: (Double, Double) -> Double
var firstOperand: Double
}
var result: Double{
get{
return accumulator
}
}
}
Any help would be appreciated, thank you very much!
I have solved my problem. Here is the updated code, incase it ever comes in handy for someone.
ViewController.swift
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var displayLabel: UILabel!
#IBOutlet weak var HistoryLabel: UILabel!
var historyArray: [String] = []
var userIsTypingNumbers = false
var firstNumber = 0
var secondNumber = 0
var operation = ""
var result = 0.0
#IBAction private func NumbersEntered(_ sender: UIButton) {
//know what number is being pressed
let number = sender.currentTitle
//if user is typing number, do this.
if userIsTypingNumbers {
//specify what number is being pressed.
//append the number onto the previous number.
displayLabel.text = displayLabel.text! + number!
} else {
displayLabel.text = number
userIsTypingNumbers = true
}
}
var displayValue: Double {
get {
return Double(displayLabel.text!)!
}
set {
displayLabel.text = String(newValue)
}
}
private var calculations = PerformCalculations()
#IBAction func OperationsPressed(_ sender: UIButton) {
userIsTypingNumbers = false
firstNumber = Int(Double(displayLabel.text!)!)
operation = sender.currentTitle!
if operation == "√" {
result = (PerformCalculations().squareroot(a: Double(firstNumber)))
displayLabel.text = String(result)
}
}
#IBAction func Enter(_ sender: UIButton) {
userIsTypingNumbers = false
secondNumber = Int(Double(displayLabel.text!)!)
if operation == "+" {
result = (PerformCalculations().add(a: Double(firstNumber), b: Double(secondNumber)))
} else if operation == "÷" {
result = (PerformCalculations().division(a: Double(firstNumber), b: Double(secondNumber)))
} else if operation == "×" {
result = (PerformCalculations().multiplication(a: Double(firstNumber), b: Double(secondNumber)))
} else if operation == "-" {
result = (PerformCalculations().subtract(a: Double(firstNumber), b: Double(secondNumber)))
}
displayLabel.text = String(result)
historyArray.append("\(firstNumber) \(operation) \(secondNumber) = \(result)")
userIsTypingNumbers = false
//self.performSegue(withIdentifier: "History", sender: self)
}
#IBAction func Clear(_ sender: UIButton) {
//clear display to 0.
displayLabel.text = "0"
}
#IBAction func Delete(_ sender: UIButton) {
//deleting last typed number, if user messed up.
let name: String = self.displayLabel.text!
//count number of characters.
let stringLength = name.characters.count
let substringIndex = stringLength - 1
displayLabel.text = (name as NSString).substring(to: substringIndex)
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
/*override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "History" {
if let destinationVC = segue.destination as? TableTableViewController {
destinationVC.dataString = historyArray.description
}
}
}*/
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let destViewController : TableTableViewController = segue.destination as! TableTableViewController
destViewController.dataString = historyArray.description
}
}
Model.swift
import Foundation
class PerformCalculations {
func add(a: Double, b: Double) -> Double {
let result = a + b
return result
}
func division(a: Double, b: Double) -> Double {
let result = a / b
return result
}
func subtract(a: Double, b: Double) -> Double {
let result = a - b
return result
}
func multiplication(a: Double, b: Double) -> Double {
let result = a * b
return result
}
func squareroot(a: Double) -> Double {
let result = sqrt(a)
return result
}
}

clear button in calculator not responding

Trying to make my Clear button work but as a fresh programmer I still have some logic finding issues.
Calculator is working perfectly but when i press Clear nothing id happening.
class ViewController: UIViewController {
enum Operation: String {
case Divide = "/"
case Multiply = "*"
case Subtract = "-"
case Add = "+"
case Empty = "Empty"
}
#IBOutlet weak var outputLbl: UILabel!
var btnSound: AVAudioPlayer!
var runningNumber = ""
var leftValStr = ""
var rightValStr = ""
var currentOperation: Operation = Operation.Empty
var result = ""
override func viewDidLoad() {
super.viewDidLoad()
let path = NSBundle.mainBundle().pathForResource("btn", ofType: "wav")
let soundUrl = NSURL(fileURLWithPath: path!)
do{
try btnSound = AVAudioPlayer(contentsOfURL: soundUrl)
btnSound.prepareToPlay()
} catch let err as NSError{
print(err.debugDescription)
}
}
#IBAction func numberPressed(btn: UIButton!){
playSound()
runningNumber += "\(btn.tag)"
outputLbl.text = runningNumber
}
#IBAction func onDividePressed(sender: AnyObject) {
processOperation(Operation.Divide)
}
#IBAction func onMultiplyPressed(sender: AnyObject) {
processOperation(Operation.Multiply)
}
#IBAction func onSubtractPressed(sender: AnyObject) {
processOperation(Operation.Subtract)
}
#IBAction func onAddPressed(sender: AnyObject) {
processOperation(Operation.Add)
}
#IBAction func onEqualPressed(sender: AnyObject) {
processOperation(currentOperation)
}
#IBAction func onClearPressed(sender: AnyObject) {
processOperation(Operation.Empty)
}
func processOperation(op: Operation) {
playSound()
if currentOperation != Operation.Empty{
//run math
//a user selected an operator, but then selected another operator without
//first entering a number
if runningNumber != ""{
rightValStr = runningNumber
runningNumber = ""
if currentOperation == Operation.Multiply{
result = "\(Double(leftValStr)! * Double(rightValStr)!)"
} else if currentOperation == Operation.Divide{
result = "\(Double(leftValStr)! / Double(rightValStr)!)"
} else if currentOperation == Operation.Subtract{
result = "\(Double(leftValStr)! - Double(rightValStr)!)"
} else if currentOperation == Operation.Add{
result = "\(Double(leftValStr)! + Double(rightValStr)!)"
} else if currentOperation == Operation.Empty{
result = ""
outputLbl.text = result
}
leftValStr = result
outputLbl.text = result
}
currentOperation = op
}else{
//first time its been pressed
leftValStr = runningNumber
runningNumber = ""
currentOperation = op
}
}
func playSound() {
if btnSound.playing{
btnSound.stop()
}
btnSound.play()
}
}
i am not sure about this but try this code
may be it help you
#IBAction func onClearPressed(sender: AnyObject)
{
outputLbl.text = #"";
//processOperation(Operation.Empty)
}
Look at your code again - You have a check:
if currentOperation != Operation.Empty { ...
and then
... else if currentOperation == Operation.Empty {
The body of the second if will never be executed!
else{
//first time its been pressed
leftValStr = runningNumber
runningNumber = ""
currentOperation = op
outputLbl.text = ""
}
In your else part you have to clear the label. First you have checked for the operation to not be Empty and the defined the same in the body.

Resources