TIL(52)

이채원·2026년 9월 3일

TIL

목록 보기
53/77

오늘의 할일
1. 코드카타 정리
2. 세션 정리


코드카타 정리

네오와 프로도가 숫자놀이를 하고 있습니다. 네오가 프로도에게 숫자를 건넬 때 일부 자릿수를 영단어로 바꾼 카드를 건네주면 프로도는 원래 숫자를 찾는 게임입니다.

다음은 숫자의 일부 자릿수를 영단어로 바꾸는 예시입니다.

1478 → "one4seveneight"
234567 → "23four5six7"
10203 → "1zerotwozero3"
이렇게 숫자의 일부 자릿수가 영단어로 바뀌어졌거나, 혹은 바뀌지 않고 그대로인 문자열 s가 매개변수로 주어집니다. s가 의미하는 원래 숫자를 return 하도록 solution 함수를 완성해주세요.

참고로 각 숫자에 대응되는 영단어는 다음 표와 같습니다.

숫자 영단어
0 zero
1 one
2 two
3 three
4 four
5 five
6 six
7 seven
8 eight
9 nine

#include <string>
#include <vector>

using namespace std;

int solution(string s) {
    int answer = 0;
    string answer_str = ""; // 최종 숫자를 문자열 형태로 이어 붙일 변수
    string temp = "";       // 알파벳을 하나씩 모아서 단어를 만들 변수
    // 문자열 한 글자씩 확인
    for (int i = 0; i < s.length(); i++) {
        
        // 만약 지금 읽은 글자가 숫자라면
        if (s[i] >= '0' && s[i] <= '9') {
            answer_str += s[i];
        } 
        // 숫자가 아니라 알파벳이라면
        else {
            temp += s[i];
            
            // temp에 모인 알파벳이 숫자 단어가 되었는지 확인
            if (temp == "zero") { answer_str += "0"; temp = ""; }
            else if (temp == "one") { answer_str += "1"; temp = ""; }
            else if (temp == "two") { answer_str += "2"; temp = ""; }
            else if (temp == "three") { answer_str += "3"; temp = ""; }
            else if (temp == "four") { answer_str += "4"; temp = ""; }
            else if (temp == "five") { answer_str += "5"; temp = ""; }
            else if (temp == "six") { answer_str += "6"; temp = ""; }
            else if (temp == "seven") { answer_str += "7"; temp = ""; }
            else if (temp == "eight") { answer_str += "8"; temp = ""; }
            else if (temp == "nine") { answer_str += "9"; temp = ""; }
        }
    }

    // 완성된 문자열을 정수로 바꾸고 answer로 
    answer = stoi(answer_str); 

    return answer; 
}

AI가 작성한 코드

#include <string>
#include <vector>

using namespace std;

int solution(string s) {
    // 숫자의 인덱스(0~9)와 영단어가 정확히 일치하도록 배열을 준비합니다.
    vector<string> words = {
        "zero", "one", "two", "three", "four", 
        "five", "six", "seven", "eight", "nine"
    };

    // 0부터 9까지 10개의 영단어를 순서대로 검사합니다.
    for (int i = 0; i < 10; i++) {
        size_t pos = 0; // 문자열을 찾기 시작할 위치
        
        // s 문자열 안에서 현재 영단어(words[i])가 더 이상 안 나올 때까지 반복해서 찾습니다.
        while ((pos = s.find(words[i], pos)) != string::npos) {
            // 영단어를 찾았다면, 그 위치(pos)부터 영단어 길이만큼을 숫자(i)로 바꿔치기합니다.
            s.replace(pos, words[i].length(), to_string(i));
            
            // 바꾼 숫자 바로 다음 칸부터 다시 탐색을 이어나갑니다.
            pos += 1; 
        }
    }

    return stoi(s);
}
  1. s.find(찾을 글자, 시작 위치):
    문자열 안에서 특정 단어가 어디 있는지 인덱스 찾아내는 함수. 만약 끝까지 없다면 C++에서 "못 찾았다"는 뜻으로 쓰이는 string::npos를 리턴

  2. s.replace(시작 위치, 지울 길이, 새 글자):
    지정한 위치부터 글자를 싹 지우고, 그 자리에 새로운 글자를 끼워 넣습니다. ("zero"가 있던 자리를 지우고 "0"을 넣는 역할)

  3. to_string(숫자):
    숫자 i를 문자열 "i"로 변환. replace 함수는 문자열만 끼워 넣을 수 있기 때문에 정수인 i를 문자로 바꿔주는 것


스타터응용반 세션 : 3회차 정리

1. 컴포넌트 시스템, 루트 컴포넌트 (Component & Root Component)

  • UPrimitiveComponent의 구성 요소: Location(위치), Rotation(회전), Scale(크기), Attachment, 렌더링, Collision(충돌), Geometry를 포함
  • Scene Component와 루트 컴포넌트: Actor에 Scene Component가 여러 개 있을 경우, 그중 하나를 Actor의 루트 컴포넌트로 사용 가능
  • Transform 관리 방식: 루트 컴포넌트가 Actor 전체 Transform의 기준이 됨. 언리얼의 Actor는 Transform 값을 직접 보관하지 않고, 루트 컴포넌트의 Transform을 Actor의 Transform으로 사용

2. 컴포넌트 어태치먼트 (Attachment)

  • Attachment 주요 메서드: 공식 문서에 따르면 생성자에서는 SetupAttachment, 플레이 도중 즉시 어태치먼트를 변경할 때는 AttachToComponent를 주요 방법으로 사용
  • 상속과 어태치먼트의 차이: Attachment는 C++의 '상속'과 완전히 다른 개념!!!
  • C++ 상속 구조: UStaticMeshComponent -> UPrimitiveComponent -> USceneComponent
  • Component Attachment: Root -> Mesh 등의 부착 관계 (별개의 개념)
  • SetupAttachment()는 부모와 자식 간의 공간 관계를 만들어 주는 기능

3. 이동 컴포넌트 종류 (Movement Components)

  • UCharacterMovementComponent
  • UProjectileMovementComponent
  • URotatingMovementComponent
  • UInterpToMovementComponent

4. IWYU 헤더 관리 방식 (Include What You Use)

  • 기본 원칙: 언리얼 엔진은 IWYU 방식의 헤더 관리를 사용, 각 파일에서 실제로 필요한 헤더만 포함해서 사용
  • 의존성 분리: 헤더와 구현 파일의 의존성을 분리하면 불필요한 헤더 포함을 줄일 수 있음. 특히 .h 파일은 다른 여러 .cpp 파일에서 다시 포함될 수 있으므로, 불필요한 헤더를 계속 추가하면 컴파일 의존성이 커짐
  • 헤더 vs 구현 파일: 헤더 파일에는 선언에 필요한 내용만 두고, 실제 함수 구현에서만 필요한 헤더는 가능한 .cpp에 두는 것이 좋음
  • 전방 선언 활용:
  • 포인터나 레퍼런스 형태로 타입 이름만 필요한 경우에는 상황에 따라 전방 선언을 사용해서 헤더 의존성을 더 줄일 수 있음
  • 반면, 상속을 받거나 해당 타입의 멤버 함수에 접근하는 등 완전한 클래스 정의가 필요한 곳에서는 헤더 포함

5. 카메라와 스프링 암 (SpringArm & Camera Component)

  • SpringArm (스프링 암): 자식 컴포넌트를 일정 거리만큼 떨어뜨려 유지하고, 충돌이 발생하면 길이를 줄였다가 충돌이 사라지면 다시 원래 거리로 돌아가는 Camera Boom 용도로 사용
  • CameraComponent: 실제 카메라의 위치와 회전뿐만 아니라 FOV, Projection Type, Post Process 등 담당

6. 포인터 시스템 (Raw Pointer vs TObjectPtr vs Smart Pointers)

  • Raw Pointer: C++ 언어에서 일반적인 포인터(UCameraComponent* 등)
  • 특징: UObject가 Garbage Collection 대상인지, 객체가 살아있는지, 참조 대상이 제거되었는지, Replication 대상인지를 자동으로 추적하지 못함. (예: T* Weapon = new Weapon[2])
  • 사용처: 함수의 지역 변수, 함수의 파라미터, 짧은 시간 동안 사용하는 참조, UPROPERTY 멤버가 아닌 임시 참조.
  • TObjectPtr: 언리얼에서 UObject 계열 객체를 참조하기 위해 제공하는 오브젝트 포인터 타입. 이름에 Ptr이 들어가 스마트 포인터로 오해할 수 있으나 목적이 다름!!!
  • 공식 문서에서는 Raw Pointer 대신 TObjectPtr을 사용하도록 안내
  • 지원 기능: UPROPERTY 지원, Garbage Collection 참조 추적, Replication
  • TSharedPtr / TUniquePtr: 일반적인 C++ 객체 수명 관리에서 사용하는 스마트 포인터 (TObjectPtr과 구분됨)

7. 회전, 방향, 그리고 행렬 (Rotators, Vectors & Rotation Matrix)

  • 회전 공부의 3대 요소: 1) 회전값, 2) 방향값, 3) 실제로 회전시키는 것을 구분
  • 회전값: FRotator
  • 방향: FVector
  • 실제 회전: SetActorRotation() 같은 함수 사용
  • 언리얼 엔진의 기본 방향 벡터:
  • X축 = 앞 (ForwardVector: (1, 0, 0))
  • Y축 = 오른쪽 (RightVector: (0, 1, 0))
  • Z축 = 위 (UpVector: (0, 0, 1))
  • FRotator 구성:
  • FRotator(Pitch, Yaw, Roll) 형태로 회전값을 저장
  • Pitch (Y축 회전), Yaw (Z축 회전), Roll (X축 회전).
  • 캐릭터가 지면에서 방향을 돌 때 가장 많이 사용하는 것은 Yaw. (예: FRotator Rotation(0.0f, 90.0f, 0.0f), SetActorRotation(FRotator(0,0,0));)
  • Local과 World (회전 행렬 / FRotationMatrix) (비행기 떠올리기)
  • FRotationMatrix: 어떤 회전을 기준으로 했을 때 앞, 오른쪽, 위가 어디인지 알려주는 도구(회전 행렬, 방향표)
  • 수학적으로는 Matrix이지만, 쉽게 말해 회전된 방향표!!
  • 예를 들어 FRotationMatrix(FRotator(0.0f, 90.0f, 0.0f))는 Yaw가 90도 들어간 상태를 기준으로 앞, 오른쪽, 위가 어디인지 계산할 수 있는 방향표를 만드는 것
profile
초보 개발자

0개의 댓글