Swift: Prime Number app: Variable initialisation - ios

Im quite new to programming, so hopefully someone can explain this to me in plain english..
Im trying to build an app in Swift that tells you wether the number inputted is a prime number or not. If it isn't prime, it should also tell you the factors of the numbers, e.x. if the user inputs 6, it tells you that 6 isn't a prime number, and apart from being divisible by 0, 1 and itself, its also divisible by 2 and 3. The code written until now is as follows:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var textField: UITextField!
#IBOutlet weak var outputMessage: UILabel!
#IBAction func checkButton(sender: AnyObject) {
var isPrime = true
var inputNumber = textField.text.toInt()
var multiples:Int
if (inputNumber != nil) {
if (inputNumber <= 0) {
outputMessage.text = "Neither 0 nor negative numbers are considered prime numbers!"
textField.resignFirstResponder()
} else {
if (inputNumber == 1) {
outputMessage.text = "1 isn't a prime number!"
textField.resignFirstResponder()
}
else {
for var i = 2; i < inputNumber; ++i {
if (inputNumber! % i == 0) {
// Number is not prime
isPrime = false
multiples = i
}
}
}
if (isPrime == true) {
outputMessage.text = "Yup, that's a prime number!"
textField.resignFirstResponder()
} else {
outputMessage.text = "That number isn't prime. Apart from 1, 0 and itself, the number is also divisible by \(multiples) "
textField.resignFirstResponder()
}
}
} else {
outputMessage.text = "Please enter a number!"
textField.resignFirstResponder()
}
}
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.
}
}
Towards the end, where the output message says "That isn't a prime. Apart from 0, 1 and itself, the number is divisible by (multiples)"
The code crashed here - it says Variable 'multiples' used before being initialized.
Can anyone help?
Thanks a lot!!

Error messages in Swift are frequently misleading. The real issue is that multiples is not initialized when you declare it.
In general, in Swift, variables need to be initialized when they are declared. There are a couple of exceptions: 1) optionals don't need to be initialized as they are nil if they are not explicitly initialized, 2) variables declared in a class can be initialized in the initializer.
To fix the error, assign multiples an initial value:
var multiples:Int = 0
This will only show you 1 multiple of the number. If you want all of them, make multiples an array:
var multiples:[Int] = []
Then append the values to the array when you have a new multiple:
multiples.append(i)

Related

Im trying to run my calculator

Im using swift code on Xcode 8. Can someone please help me out and figure out the error? It says the expression pattern of type 'string' cannot match values of type 'operation'. the error appeared at the switch operation and then the case that held × in it.
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var display: UILabel!
var userIsInTheMiddleOfTyping = false
#IBAction func Appenddigit(_ sender: UIButton) {
let digit = sender.currentTitle!
if userIsInTheMiddleOfTyping {
display.text = display.text! + digit
} else {
display.text = digit
userIsInTheMiddleOfTyping = true
}
}
#IBAction func operate(_ sender: UIButton) {
_ = sender.currentTitle!
if userIsInTheMiddleOfTyping{
enter()
}
switch Operation() {
case "×":
if operandStack.count >= 2 {
displayValue = operandStack.removeLast() * .operandStack.removeLast()
enter()
}
// case "÷":
// case "+":
// case "−":
default:
break
}
}
var operandStack: Array<Double> = []
#IBAction func enter() {
userIsInTheMiddleOfTyping = false
operandStack.append(displayValue)
print("operandStack = \(operandStack)")
}
var displayValue: Double {
get {
return NumberFormatter().number(from: display.text!)!.doubleValue
}
set {
display.text = "\(newValue)"
userIsInTheMiddleOfTyping = false
}
}
}
In Swift 3, Operation is the new name of the class NSOperation.
Your expression Operation() is creating an Operation object.
Whatever "Operation" is in your program, you need to rename it to something else. You should also explain what that code is supposed to be doing so we can help you fix it. The line
switch Operation()
Doesn't make sense to me.
Operation() is creating a new object of type Operation which cant be compared to "x"which is a string. What i think you want is to be calling a function called operation which would return a string.

Swift app for solving factors of numbers and display

i'm new the forum and also new to the swift language. I've been playing around with xcode and wanted to create an app that uses a fenceloop to display the factors of a number as a "solution." The app currently uses a label to display, a text for input, and a button to initiate. I have what i think to be functioning code but i can't see to get it to work because from what i understand, i have to convert the input that's a string into an int. If anyone has any ideas how to get this working; since i feel like i've done what i can.
The problem in particular i am getting is it is saying that "Cannot convert value of type 'UITextField!; to expected argument type 'Int'. What i intend to happen is that on the button click, it solves for the factors of whatever is in the text box and displays it as a string in the label. Any help is appreciated!
import UIKit
class ViewController: UIViewController {
#IBOutlet var input1 : UITextField!
#IBOutlet var label : UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
#IBAction func printFactors(n: Int) {
var result: String = ""
for i in 1...n {
guard n % i == 0 else {continue}
result += i == 1 ? "1" : " and \(i)"
}
print(result)
let outputText = printFactors(n: input1)
label.text = outputText
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
You have a lot of issues and confusion in your printFactors method. Lets split it up and setup things properly.
First, make a separate method to do the math:
func calculateFactors(n: Int) -> String {
var result: String = ""
for i in 1...n {
guard n % i == 0 else {continue}
result += i == 1 ? "1" : " and \(i)"
}
print(result)
return result
}
Now lets setup the button action:
#IBAction func factorAction(sender: UIButton) {
if let text = input1.text {
if let num = Int(text) {
let factor = calculateFactors(n: num)
label.text = factor
} else {
// Show the user that the entered text isn't a number
}
} else {
// There's no text
}
}
Setup your button to use the new factoryAction: method instead of the old printFactors: method.
Swift 3
Can reduce this code down to two lines with some functional magic.
func factors(of number: Int) -> [Int] {
return (1...number).filter { number % $0 == 0 }
}
print(factors(of: 24))

UILabel variable needs to be an Optional Double but I don't want the the label to display optional(valueOfNumber)

I'm trying to complete the CS193P Course independently. I am on assignment 2 of the course and part of the assignment asks for me to do the following:
"Change the computed instance variable displayValue to be an Optional Double rather than a Double"
I was able to change displayValue to be an Optional Double, but now my UILabel which shows the displayValue now will display the optional value instead of the double value (which makes sense).
Example:
5 (then press enter) will display a value of Optional(5.0) in the UILabel.
Here is what I tried:
I determined that result and displayValue! will return a double.
I tried changing display.text = result to display!.text! = result but that did not fix the issue.
Here is a snippet of my code, I think you shouldn't need any more but please comment if you think I should show something else!
P.S. the name of the display is display
#IBAction func enter() {
if let result = brain.pushOperand(displayValue!) {
displayValue = result
} else {
displayValue = 0
}
}
var displayValue: Double? {
get {
return NSNumberFormatter().numberFromString(display.text!)!.doubleValue
}
set{
display!.text! = "\(newValue)" //display is the UILabel
}
I believe the display is supposed to be blank when, for example, the stack cannot be evaluated to give a result.
So you can just use
var displayValue: Double? {
get { return NSNumberFormatter().numberFromString(display.text!)?.doubleValue }
set { if newValue != nil { display.text = "\(newValue!)" }
else { display.text = " " }
}
}
And then for "enter"
#IBAction func enter() {
if let dV = displayValue {
brain.pushOperand(dV)
displayValue = brain.evaluate()
}
userIsInTheMiddleOfTypingANumber = false
}
This solution worked for me. I am working through this course independently too. It is tricky and I have to listen to the lectures LOTS of times :-)
Jacki

Questions regarding to value setting and getters and setters in Swift

Hi I just picked up Swift and am following the Stanford open course. I was making this calculator and got a breakpoint at the line of userIsInTheMiddleOfTyping = false in the func enter part when I placed the line before operandStack.append(displayValue). After I placed the line at the bottom of the function, the problem was solved. But why?
Also, I don't get the part of get and set in displayValue part. Can anyone help to explain how this part is executed. And where is the newValue from? why does it represent whatever value on the display? The code is followed. I would appreciate any answers and comments!
class ViewController: UIViewController {
#IBOutlet weak var display: UILabel!
var userIsInTheMiddleOfTypingAnNumber = false
#IBAction func AppendDigit(sender: UIButton) {
let digit = sender.currentTitle!
if userIsInTheMiddleOfTypingAnNumber {
display.text = display.text! + digit
}
else{
display.text = digit
userIsInTheMiddleOfTypingAnNumber = true
}
}
var operandStack = Array<Double>()
#IBAction func enter() {
operandStack.append(displayValue)
println("operandStack=\(operandStack)")
userIsInTheMiddleOfTypingAnNumber = false
}
var displayValue: Double{
get{
return NSNumberFormatter().numberFromString(display.text!)!.doubleValue
}
set{
display.text = "\(newValue)"
userIsInTheMiddleOfTypingAnNumber = false
}
}
}
get and set are the keywords used in Swift to define custom getters and setters to a property.
newValue is the default name for the new value that will be assigned to the variable at the end of the setter, it allows you to check various things before assigning it.
For the first part of your question I don't quite understand what's not working for you.

Why does this swift code work when newValue has nothing assigned to it?

import UIKit
class ViewController: UIViewController {
#IBOutlet weak var display: UILabel!
var inMid = false
#IBAction func appendDigit(sender: UIButton) {
let digit = sender.currentTitle!
if inMid{
display.text = display.text! + digit
}else{
display.text = digit
inMid = true
}
}
var operandStack = Array<Double>()
#IBAction func enter() {
inMid = false
operandStack.append(displayValue)
println("operandStack = \(operandStack)")
}
var displayValue:Double{
get {
return NSNumberFormatter().numberFromString(display.text!)!.doubleValue
}
set{
display.text = "\(newValue)"
}
}
}
This is the part of code used in the latest Standford IOS 8 course using swift to build a calculator(Youtube address: https://www.youtube.com/watch?v=QLJtT7eSykg)
Every time I call enter() (press enter), a new number is supposed to be saved in a stack. For example: "8, enter()" --> {8}, "16, enter()" --> {8,16}.
I got confused about the computed property "displayValue" here. There is nothing assigned to the "newValue". If there is something like "displayValue = 8", then I know "newValue" is 8, and it all makes sense. But there is not such thing.
How come it still works?
(What I mean is not the name "newValue" itself,I know it is a default setting by Swift, instead, the missing of assigned value is the one that confuses me)
"newValue" is an implicitly defined variable in swift.
What he does is a very neat way of letting the label show the values of the double "displayValue" Every time displayValue is changed, the label is automatically updated with the newest (double) value.
Or when you write: displayValue = 45.0, the label will also show this value. Very handy when you constantly need to update textfield or labels with data you get from databases, rest interfaces, etc. What "newValue" does is taking the last "setter" value holding that.

Resources