[내일배움캠프][TIL] 23.12.18 (월) - 시저 암호, registerForActivityResult
1. 코드카타
오늘 푼 알고리즘 문제는 '시저 암호' 이다.
시저 암호 |
![]() |
![]() |
오늘의 문제는 한동안 접하지 못했던, 문자열에 관한 문제이다.
A 다음에 B이니 A를 한 칸 옮기면 B라는 사실은 누구나 다 알고 있지만, 이걸 컴퓨터에 그대로 적용시키는 건 또 다른 문제다.
왜냐하면 컴퓨터에다 A에 1을 더한다고 적어봤자 B가 되는 게 아니라 A+1이 될 뿐이다.
즉, 사람이 관념적으로 인식하는 거랑 컴퓨터가 인식하는 거랑은 차원이 다르다는 이야기.
그러면 저걸 어떻게 실제로 표현할 수 있을까?
여기서 오늘의 문제의 키 포인트가 하나 있다.
바로 아스키 코드(ASCII Code).
아스키 코드는 1963년 미국 ANSI에서 표준화한 정보교환용 7비트 부호체계를 말하는데 우리가 쓰는 Kotlin 역시 아스키 코드가 포함되어 있다.
참고로 아스키 코드 표는 다음과 같다.
여기서 우리가 사용할 부분은 바로 대문자 A~Z까지의 숫자 65~90, 그리고 소문자 a~z까지의 숫자 97~122 이다.
그래서 이걸 어떻게 써먹어야 하냐.
어떤 문자에 해당하는 숫자를 입력하면 그에 맞는 Char형을 출력한다.
예를 들어서 49를 입력하면 '1'을 출력하고, 82를 입력하면 'R'을 출력하는 식이다. 물론 그 반대의 경우도 가능하다.
그러면 이제 이걸 한 번 써보도록 하자.
우선 대문자.
if(ch.code in 65..90) {
if(ch.code + n in 65..90) {
answer += (ch.code + n).toChar()
}
else {
answer += (ch.code - 26 + n).toChar()
}
이건 만약 어떤 문자에 해당하는 코드 숫자에 n을 더했을 때 65~90 사이라면 그냥 n을 더하고, 90을 넘으면, 즉 Z를 넘어가면 26을 뺀 다음에 n을 더해서 대문자를 넘어가지 않게 해준다.
그리고 그렇게 나온 숫자에 해당하는 알파벳을 Char형으로 바꾸어서 표현한다.
if(ch.code in 97..122) {
if(ch.code + n in 97..122) {
answer += (ch.code + n).toChar()
}
else {
answer += (ch.code - 26 + n).toChar()
}
소문자도 대문자와 다르지 않다.
이제 이걸 종합하면 다음과 같이 나온다.
class Solution {
fun solution(s: String, n: Int): String {
var answer = ""
for(ch in s) {
if(ch.code in 65..90) {
if(ch.code + n in 65..90) {
answer += (ch.code + n).toChar()
} else {
answer += (ch.code - 26 + n).toChar()
}
}
else if(ch.code in 97..122) {
if(ch.code + n in 97..122) {
answer += (ch.code + n).toChar()
} else {
answer += (ch.code - 26 + n).toChar()
}
}
else {
answer += " "
continue
}
}
return answer
}
}
문자열 s에서 대문자이면 대문자 조건문, 소문자이면 소문자 조건문, 공백이면 한 칸 띄우기를 한 다음 반복하는 반복문이다.
2. registerForActivityResult
지난주에는 자기소개 앱 만들기 과제에서 필수적으로 넣어야 할 기능들을 구현하는 데까지 성공했다.
이번에는 추가적으로 넣으면 좋은 선택적 기능들을 구현해보도록 하겠다.
그 첫번째는 바로 이거다.
회원가입 페이지에서 입력한 아이디/비밀번호가 로그인 화면으로 돌아올 때 자동 입력되는 기능!
그리고 이에 대한 힌트로 registerForActivityResult에 대해서 알아보라고 적혀 있었다.
그러니까 registerForActivityResult를 공부하면 저 기능을 구현시킬 수 있다는 의미겠지?
그래서 오늘은 저거에 대해서 알아보기로 했다.
registerForActivityResult란?
registerForActivityResult는 ActivityResultContract와 ActivityResultCallback을 가져와서 다른 activity를 실행하는 데 사용할 ActivityResultLauncher를 반환하는 메소드… 라는데 ActivityResultContract는 뭐고, ActivityResultCallback은 또 뭔가?
- ActivityResultContract : 결과를 생성하는 데 필요한 입력 유형과 결과의 출력 유형을 정의
- ActivityResultCallback : ActivityResultContract에 정의된 출력 유형의 객체를 가져오는 onActivityResult() 메소드가 포함된 단일 메소드 인터페이스
…이렇게 봐서는 모르겠다.
다만, 저기서 유추 가능한 정보는 registerForActivityResult를 실행시키려면 ActivityResultContract와 ActivityResultCallback 이 두가지가 필요하다는 것.
조금 더 자세히 알아보자.
registerForActivityResult 사용법
private fun clickSignUp(){
with(binding){
btnSignup.setOnClickListener {
if(etSignupId.length() == 0 || etSignupName.length() == 0 || etSingupPassword.length() == 0){
Toast.makeText(this@SignUpActivity, "입력하지 않은 정보가 있습니다.", Toast.LENGTH_SHORT).show()
} else {
val intent = Intent(this@SignUpActivity, SignInActivity::class.java)
intent.putExtra("id", etSignupId.text.toString())
intent.putExtra("password", etSingupPassword.text.toString())
setResult(RESULT_OK, intent)
finish()
}
}
}
}
이 코드는 데이터를 보내는 회원가입 페이지 (SignUpActivity)에 들어갈 수 있는 코드다.
(물론 저렇게 넣었다는 건 아니다. 참고하기 위해서 다른 예시를 들고왔다.)
이런 식으로 데이터를 Extras에 보낸 뒤에 어떻게 하면 로그인 화면에 자동으로 입력될까?
private lateinit var resultLauncher: ActivityResultLauncher<Intent>
private fun setResultSignUp(){
resultLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()){ result ->
if (result.resultCode == Activity.RESULT_OK){
val id = result.data?.getStringExtra("id") ?: ""
val password = result.data?.getStringExtra("password")?:""
binding.etId.setText(id)
binding.etPassword.setText(password)
}
}
}
이것이 바로 ActivityResultCallback을 선언하는 코드다.
val id부터는 원래 Extras에 저장된 데이터를 불러오는 내용이니까 넘어가고 중요한 부분은 resultLauncher다.
여기서 registerForActivityResult 부분이 나오는데 잘 보면 () 안에 ActivityResultContracts와 StartActivityForResult()가 포함되어 있다.
이 때 StartActivityForResult()는 ActivityResultContracts의 객체를 담당하며, StartActivityForResult() 외에도 여러가지 객체를 불러와도 된다.
ActivityResultCallback 람다에서는 ActivityResult 객체가 파라미터로 떨어지고 여기서 intent와 result Code를 사용해서 원하는 데이터를 가져오면 된다.
private fun clickSignUp(){
binding.btnSignUp.setOnClickListener {
val intent = Intent(this, SignUpActivity::class.java)
resultLauncher.launch(intent)
}
}
그리고 resultLauncher.launch()를 통해 데이터를 받아올 activity를 실행한다.
그러면 이제 이걸 바탕으로 내일 자기소개 앱에 한 번 적용시켜보도록 하겠다.