Swift TIL(72) - swift 로 알고리즘 풀기 걸음마(guard let 문을 return없이 쓰기)

웰디(Well-D)·2023년 11월 8일
0

Sweet & Soft, SWIFT

목록 보기
72/76

오늘은 맥북은 겨우 켠 날..하루종일 작업물 정리하고 겨우 매일의 루틴을 하고나니 잘시간이다(기절)

내일 알고리즘(발등에 불떨어짐) 스터디를 위해 내가 선택한 한줄로 서기 문제를 보았다.

싸피를 준비했을 당시 배웠던 개념을 쓰는 문제인 것은 이해했는데, (구현문제를 골랐다) swfit 나 코드로 구현하기가 어려웠다.

이럴땐 답지를 보는게 상책이라(처음엔 다 이런거 아니겠는가..) 고민을 조금 해보다가 답지를 검색했다.

살짝 힌트를 얻어봤는데 일단 한번 돌려봐야겠다 싶어서 swift로 풀어보기로 결정했다.

우선 터미널에서 입력값을 받아오는 기초부터 시작해보자(난 알고리즘 유치원생이니까)


결론은 아래 링크에서 swift 로 백준풀기 글을 그냥 보시면 됩니다.

학습

readLine() 이라는 유용한 이미 만들어진 메서드를 사용하면되는데 주의할점은 이 메서드의 리턴이 옵셔널 타입이라는 것이다.

func readLine(strippingNewline: Bool = true) -> String?
  • 보다시피 strippingNewline 파라미터는 true 로 디폴트 설정이 되어있어서 엔터를 신경쓰지 않는다면 따로 설정할필요가 없다고한다
    (공식문서 :
    strippingNewline
    => If true, newline characters and character combinations are stripped from the result; otherwise, newline characters or character combinations are preserved. The default is true)
    (true이면 결과에서 개행 문자 및 문자 조합이 제거되고, 그렇지 않으면 개행 문자 또는 문자 조합이 유지됩니다, 디폴트는true 입니다.)

(참고) 개행문자의 뜻

새줄 문자(newline)는,
텍스트의 한 줄이 끝남을 표시하는 문자 또는 문자열이다. 개행 문자, 줄바꿈 문자(line break), EOL(end-of-line)과 같은 뜻이다.

출처 : [https://adnetwork.tistory.com/18](개행 문자)

한마디로 엔터칠때 나타나는 문자를 표시해줄건지 말건지 인데, 디폴트인 true 로 두면(별다른 설정을 안하면) 제거한 값을 알려준다는 뜻이다.

여하튼 리턴값이 String? 으로 옵셔널인것이 여기서는 중요하다.

따라서 내가 참조한 블로그에서는 강제추출연산자 ! 를 사용해서 다음과 같이 옵셔널은 unwrapping 했다.

let input = readLine()!

하지만 궁금했다.

guard let 이나 if let 으로 unwrapping 하면 어떨까?

(왜 이러는거냐 도대체)

참고로 혹시 끝까지 읽으실 분들이 있다면 그냥 강제추출연산자로 벗기시는게 가장 합리적일 것 같다는 결론에 이르렀다는 것을 안내드립니다.
(혹시 댓글로 관련 의견이 있다면 꼭 부탁드립니다..)

에러가 났다.

guard let input = readLine() else { return } // 에러발생 

print(input)

에러

Return invalid outside of a func

이유를 스택오버플로우를 참조해서 얻을 수 있었다(공식문서에서도 얻을 수 있었을지도 모른다)

참고한 스택오버플로우

여기에 따르면

If the condition in your guard statement is not met, the else branch has to exit the current scope. return can only be used inside functions, as the error message shows, but return is not the only way to exit scope.you can use throw outside functions as well and if the guard statement is in a loop, you can also use break or continue.

라고 한다.
요약해보면
에러의 원인은 에러메시지에서 보듯 함수내에 있지 않은데 return 을 써서 이다.
당연히!(바보같은 실수였네 아이코) 반환은 함수 내부에서만 사용할 수 있다.

해결방법

글에 따르면
반환만이 범위를 종료하는 유일한 방법은 아니며, 함수 외부에서도 throw를 사용할 수 있고 가드 문이 루프에 있는 경우 break 또는 continue를 사용할 수도 있다고 한다.

나는 다른 것은 복잡해보여서 throw 를 써보았다.

guard let input = readLine(strippingNewline: false) else { throw NSError() }

(break, continue 는 for 문 내에서 사용해야하고, return 은 함수를 따로 만들어 줘야한다)

결과

print("입력: ", terminator: "")
guard let input = readLine() else { throw NSError() }

print(input)

참고로 개행문자(newline) 을 포함하면 (strippingNewline: false 설정)

print("입력: ", terminator: "")
guard let input = readLine(strippingNewline: false) else { throw NSError() }

print(input)

다음과 같이 출력된다.

참고로 사실 변수는 문자열 보간법으로 사용할 수 있으므로(차이를 느꼈던 적이 있는데 지금 정확히 기억이 안나서 슬프다)

굳이 guard let 을 쓸때의 코드는 다음의 코드가 더 정확하다고 생각한다

print("입력: ", terminator: "")
guard let input = readLine(strippingNewline: false) else { throw NSError() }

print("\(input)")

사실 제일 좋은 방법은 원 블로그처럼 강제추출연산자 ! 를 쓰는 것이다.
NSError()를 굳이 해주는건 누가봐도 좋지 않을 듯 하다(뭔가 사이드 이펙트가 있을듯)

어차피 무조건적인 입력이 들어갈 예정이니까 모두 ! 를 사용하는게 어떨까..


결론 : 아래 링크에서 swift 로 백준풀기 글을 그냥 보시면 됩니다.

우선 참조했던 자료들

백준 한줄로 서기 문제
파이썬 백준 한줄로 서기 풀이
스위프트로 백준풀기

나기님의 자료
Github PR관련

profile
Wellness 잘사는 것에 진심인 웰디입니다. 여러분의 몸과 마음, 통장의 건강을 수호하고싶어요. 느리더라도, 꾸준히

0개의 댓글