Как правильно использовать try, do, catch в swift?
Помогите пожалуйста. Хочу сделать калькулятор разбора выражений используя Обратную польскую нотацию (Reverse polish notation). Мне нужно сделать так, что если пользователь ввел неправильное выражение сообщить об этом. Мне не нужно отловить ошибки а просто печатать "Error" Я сделал 2 стека(т.к это стековый калькулятор)
struct DoubleStack {
var items = [Double]()
mutating func push(_ item: Double) {
items.append(item)
}
mutating func pop() -> Double {
return items.removeLast()
}
mutating func empty() -> Bool{
if items.count == 0{
return true
} else {
return false
}
}
mutating func peek() -> Double{
return items.last!
}
}
struct CharactersStack {
var items = [Character]()
mutating func push(_ item: Character) {
items.append(item)
}
mutating func pop() -> Character {
return items.removeLast()
}
mutating func empty() -> Bool{
if items.count == 0{
return true
} else {
return false
}
}
mutating func peek() -> Character{
return items.last!
}
}
Мои функции разбора выражений expressionToRPN и RPNtoAnswer.
func isOper (c: Character) -> Bool {
if c == "+" || c == "-" || c == "*" || c == "/" || c == "^" || c == "×" || c == "÷" || c == "%"{
return true
}
return false
}
func getP(token: Character) -> Int8{
if token == "+" || token == "-" {
return 1
} else if token == "*" || token == "/" || token == "×" || token == "÷" || token == "%"{
return 2
} else if token == "^"{
return 3
}
return 0
}
func ExpressionToRpn(expr: [Character]) throws -> [Character]{
var current = [Character]()
var stack = CharactersStack()
var i: Int = 0
while i < expr.count {
if expr[i] == "-" {
if i == 0 || expr[i - 1] == "("{
current.append("(")
current.append(expr[i])
i = i + 1
while expr[i].isNumber || expr[i] == "." {
current.append(expr[i])
i += 1
}
current.append(")")
current.append(" ")
}
}
if expr[i].isNumber{
while (expr[i].isNumber || expr[i] == ".") {
current.append(expr[i])
i += 1
}
current.append(" ")
}
if expr[i] == "(" {
stack.push(expr[i])
}
if expr[i] == ")"{
while !stack.empty() && stack.peek() != "(" {
current.append(stack.pop())
current.append(" ")
}
stack.pop()
}
if isOper(c: expr[i]){
while !stack.empty() && getP(token: expr[i]) <= getP(token: stack.peek()) && stack.peek() != "(" {
current.append(stack.pop())
current.append(" ")
}
stack.push(expr[i])
}
i += 1
}
while (!stack.empty()){
current.append(stack.pop())
current.append(" ")
}
return current
}
func RPNtoAnswer(rpn: [Character]) throws -> Double{
var operand = [Character]()
var stack = DoubleStack()
var i: Int = 0
while i < rpn.count {
operand = []
if rpn[i] == " "{
i += 1
continue
}
if rpn[i].isNumber || rpn[i] == "." {
while rpn[i].isNumber || rpn[i] == "." {
operand.append(rpn[i])
i += 1
}
stack.push(Double(String(operand))!)
continue
}
if getP(token: rpn[i]) > 0{
let a: Double = stack.pop()
let b: Double = stack.pop()
if rpn[i] == "+" {
stack.push(a + b)
} else if rpn[i] == "-" {
stack.push(b - a)
} else if rpn[i] == "*" || rpn[i] == "×"{
stack.push(b * a)
} else if rpn[i] == "/" || rpn[i] == "÷"{
stack.push(b / a)
} else if rpn[i] == "%"{
stack.push(a * b / 100)
} else if rpn[i] == "^" {
stack.push(pow(b, a))
}
}
i += 1
}
return stack.pop()
}
И наконец то что я хочу вывести
var r: String = "(11+222-111+)"
var str: [Character] = r.compactMap{$0}
do{
let exprtorpn = try ExpressionToRpn(expr: str)
let answer = try RPNtoAnswer(rpn: exprtorpn)
print(answer)
} catch {
print ("Error!!!!!!!")
}
я получаю ошибку
Thread 1: Fatal error: Can't remove last element from an empty collection
в строке return items.removeLast()
mutating func pop() -> Double {
return items.removeLast()
}
Как мне просто вывести в консоль "Error" если код рухнет ? Заранее Благодарю !!!
Ответы (1 шт):
Пользуйтесь документацией. И это не сарказм, это единственный актуальный источник истины для разработчика. Для начала, просто выделите метод removeLast() (Cmd-Click) и посмотрите что написано:
Коллекция не должна быть пустой. Соответственно, если Вы хотите использовать do-try-catch, необходимо сделать так, чтобы выбрасывалась ошибка.
// Описываете ошибки, которые планируются
enum CalculationError: Error {
case emptyCollection
}
// Переписываете свой метод, чтобы он выбрасывал ошибку:
func pop() throws -> Double {
guard !items.isEmpty else {
throw CalculationError.emptyCollection
}
return items.removeLast()
}
и используете уже его try ....
Аналогично с остальными местами.

