In the code is one minor problem which I'm trying to solve but have not yet found the solution.
This code is for the calculator.
It is doing right calculations.
But when I press "clear" button, in front of new calculation remains "0".
For example: I press "clear" and after "2". On the screen will appear "02".
I would be very grateful if someone would look at the code and see the solution.
import UIKit
import AVFoundation
class ViewController: UIViewController {
#IBOutlet weak var outputLbl: UILabel!
var btnSound: AVAudioPlayer!
#IBAction func clearBtnPressed(_ sender: Any) {
playSound()
runningNumber = ""
leftValStr = ""
outputLbl.text = ""
currentOperation = Operation.Empty
}
enum Operation: String {
case Divide = "/"
case Multiply = "*"
case Subtract = "-"
case Add = "+"
case Empty = "Empty"
}
var currentOperation = Operation.Empty
var runningNumber = ""
var leftValStr = ""
var rightValStr = ""
var result = ""
override func viewDidLoad() {
super.viewDidLoad()
let path = Bundle.main.path(forResource: "btn", ofType: "wav")
let soundURL = URL(fileURLWithPath: path!)
do {
try btnSound = AVAudioPlayer(contentsOf: soundURL)
btnSound.prepareToPlay()
} catch let err as NSError {
print(err.debugDescription)
}
outputLbl.text = ""
}
#IBAction func numberPressed(sender: UIButton) {
playSound()
runningNumber += "\(sender.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(operation: currentOperation)
}
func playSound() {
if btnSound.isPlaying {
btnSound.stop()
}
btnSound.play()
}
func processOperation(operation: Operation) {
playSound()
if currentOperation != Operation.Empty {
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)!)"
}
leftValStr = result
outputLbl.text = result
}
currentOperation = operation
} else {
leftValStr = runningNumber
runningNumber = ""
currentOperation = operation
}
}
}
Check you IBOutlets (maybe you have clear button that is also
binded to numberPressed method)
Check tags of your buttons
Add log inside numberPressed() to check if something goes wrong with
runningNumber
0 came from Operation.Empty
I solved this problem in the following way:
if (runningNumber == "0") {
runningNumber.remove(at: runningNumber.startIndex)
}
I'm not sure that this solution is optimal but now the calculator works perfect
I thank everyone who took the time to help. Thank you, guys!
Related
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.
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.
I got an "Class "View controller" has no initializers" error.
I tried to initialize all variables but the error keeps appearing.
Hear is the code:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var Screen: UILabel!
var primerNum = Float()
var segundoNum = Float()
var result = Float()
var operat = ""
var isTypingNumber = false
var num: Int?
var coma: Int?
#IBAction func num(sender: AnyObject) {
var num = sender.currentTitle
if isTypingNumber == true {
Screen.text = Screen.text! + num!!
} else {
Screen.text = num
}
isTypingNumber = true
}
#IBAction func coma(sender: AnyObject) {
var coma = sender.currentTitle
Screen.text = Screen.text! + coma!!
}
#IBAction func operat(sender: AnyObject) {
operat = sender.currentTitle!!
primerNum = (Screen.text! as NSString).floatValue
}
#IBAction func igual(sender: AnyObject) {
segundoNum = (Screen.text! as NSString).floatValue
if operat == "+" {
result = primerNum + segundoNum
} else if operat == "-" {
result = primerNum - segundoNum
} else if operat == "x" {
result = primerNum * segundoNum
} else if operat == "/" {
result = primerNum / segundoNum
} else if operat == "%" {
result = (primerNum * segundoNum) / 100
}
Screen.text = "\(result)"
}
#IBAction func clear(sender: AnyObject) {
primerNum = 0
segundoNum = 0
result = 0
Screen.text = "\(result)"
}
}
Thank you in advance!!
That looks correct, and also compiles fine for me locally. Did you try Cleaning and rebuilding (command-shift-K, then command-b)? Alternatively, restart Xcode.
I am following the Stanford iOS Swift development course and have to make my displayValue an optional double, I assign a value to displayValue func performOperation but the getter for var displayValue: Double? reads it as nil, I have even hardcoded var displayValue: Double? to be 81 (example) but it is still read as nil, has anyone got any ideas? (I didn't want to post my whole code but if I've missed something out let me know!), thanks!
EDIT: here is my whole code now!
import UIKit
class ViewController: UIViewController {
var isThereApoint = true
var openStack = Array<Double?>()
var count = 0
#IBOutlet weak var history: UILabel!
#IBOutlet weak var calcView: UILabel!
var historyStack = Array<String>()
var userIsTyping = false
#IBAction func numberButton(sender: UIButton) {
let numberButton = sender.currentTitle!
if calcView.text!.rangeOfString("=") != nil{
calcView.text! = ""
}
if userIsTyping{
calcView.text! = calcView.text! + numberButton
}
else {
calcView.text! = numberButton
userIsTyping = true
}
}
#IBAction func decimalPoint(sender: AnyObject) {
if isThereApoint == true {
calcView.text! = calcView.text! + "."
isThereApoint = false
}
}
var displayValue: Double? {
get{
if NSNumberFormatter().numberFromString(calcView.text!) != nil{
return NSNumberFormatter().numberFromString(calcView.text!)!.doubleValue
}
else {
println("calc view in getter: \(calcView.text!)")
return 0
}
}
set{
calcView.text! = "\(newValue)"
userIsTyping = false
}
}
#IBAction func operate(sender: UIButton) {
let operation = sender.currentTitle!
switch operation{
case "×": performOperation ("×, ", {$0 * $1})
case "÷": performOperation ("÷, ",{$1 / $0})
case "+": performOperation ("+, ", {$0 + $1})
case "−": performOperation ("−, ", {$1 - $0})
case "√": performOperation ("√, ", {sqrt($0)})
case "Cos": performOperation ("Cos, ", {cos($0)})
case "Sin": performOperation("Sin, ", {sin($0)})
case "PI": displayValue! = M_PI
enter()
default: break
}
}
func performOperation(operatorSymbol: String, operation: (Double, Double) -> Double) {
if openStack.count >= 2 {
println("\(operatorSymbol)")
displayValue = operation(openStack.removeLast()!, openStack.removeLast()!)
println("display value : \(displayValue!)")
var displayAnswer = displayValue!
history.text! = history.text! + operatorSymbol
calcView.text! = "= \(displayAnswer)"
enter()
//calcView.text! = "= \(displayAnswer)"
}
}
#IBAction func positiveOrNegative(sender: AnyObject) {
if (calcView.text!.rangeOfString("-") != nil) {
calcView.text! = dropFirst(calcView.text!)
}
else {
calcView.text! = "-\(calcView.text!)"
}
}
func performOperation(operatorSymbol: String, operation: Double -> Double) {
if openStack.count >= 1 {
displayValue = operation(openStack.removeLast()!)
var displayAnswer = displayValue!
history.text! = history.text! + operatorSymbol
enter()
calcView.text! = "= \(displayAnswer)"
}
}
#IBAction func clearButton() {
history.text! = ""
for item in openStack{
openStack.removeLast()
}
calcView.text! = ""
}
#IBAction func backspace(sender: AnyObject) {
if countElements(calcView.text!) > 0 {
calcView.text! = dropLast(calcView.text!)
}
}
#IBAction func enter() {
isThereApoint = true
if history.text! == "History"{
history.text! = ""
}
openStack.append(displayValue!)
var userIsTyping = false
println("openStack = \(openStack)")
history.text! = history.text! + "\(displayValue!)" + ", "
calcView.text! = ""
}
}
Your problem is that you are setting calcView.text to "Optional(81.0)". You need to unwrap the Double? that is in newValue inside of set for displayValue:
set {
calcView.text = "\(newValue!)"
userIsTyping = false
}
Because the displayValue was "Optional(81.0)", NSNumberFormatter couldn't convert the value, so it returns nil.
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.