C#과 유니티5-1

망고·2024년 1월 26일

C#과 유니티

목록 보기
9/10
post-thumbnail

[C#과 유니티, 실전 게임으로 제대로 시작하기]섹션5. 스터디

문자열 다루기

문자열 함수

  • Length()
    문자열의 길이를 반환한다.
void Start(){
	string str1 = "Hello";
    Debug.Log(str1.Length); //str1의 길이인 5가 반환된다.
}
  • IndexOf()
    인수가 몇 번째 글자인지 반환한다. 문자열에 인수가 없으면 -1을 반환한다.
void Start(){
	string str1 = "Hello";
    Debug.Log(str1.IndexOf("e")); //0번째 H부터 시작하여 "e"인수는 1번째 순서에 있기에 1을 반환한다. 
}
  • Replace()
    특정 문자열을 치환한다.
void Start(){
	string str1 = "Hello";
    Debug.Log(str1.Replace("el", "55"); //el부분을 55로 치환해주어 H55lo가 출력된다.
}
  • Split()
    특정 문자를 기준으로 문자열을 나누어 배열로 반환한다.
void Start(){
	string str1 = "abcdef";
    string[] arr = str1.Split('c'); //c를 기준으로 문자열을 나눈다.
    Debug.Lof(arr.Length); //c를 기준으로 2개의 배열이 나왔기에 2가 출력된다.
    Debug.Log(arr[0]); //ab가 arr[0]에 담긴다. 
    Debug.Log(arr[1]); //def가 arr[1]에 담긴다.
}

예시>

void Start(){
	string str1 = "철수, 철불, 철목, 철석";
    string[] arr = str1.Split(',');
    foreach (string name in arr){ //arr배열을 하나씩 name 변수에 담는다.
    	Debug.Log(name); //철수 철불 철목 철석 이 따로 출력된다.
    }
}
  • SubString()
    문자열을 부분적으로 잘라서 반환한다.
void Start(){
	string str1 = "tomato";
    Debug.Log(str1.SubString(2)); //인수의 숫자부터 시작하여 출력해준다. 즉, 2번째에 엤는 m부터 끝까지 출력한다. mato
    Debug.Log(str1.SubString(1,3)); //1부터 3개의 문자를 출력한다. oma
    Debug.Log(str1.SubString(str1.indexOf("o"),3); //o부터 3개의 문자를 반환하기에 oma가 출력된다.
}
  • string.Format()
void Start(){
// int num = 43*72;
// string str1 = "43 * 72 = num"; //str1에 들어간 num은 문자열로 취급하기 때문에 int로 선언한 num이 대입되지 않는다. 이러한 문제를 해결하기 위해 string.Format()을 사용한다.
	string newStr = string.Format("43 * 72 = {0}", 43 * 72); //43*72의 값이 {0}인덱스에 들어가 3096이 출력된다.
}

예시>

void Start(){
	for(int i = 2; i < 10 ; i++){
    	for(int j = 1 < 10 ; j++){
        	Debug.Log(string.Format("{0} * {1} = {2}", i, j, i*j)); //구구단이 출력된다.
        }
     }
}

string 형변환

int num = 1; 
/*string str1 = (string)num; //int는 값형이고, string은 참조형이기에 형변환을 하지 못한다.*/
string str1 = num.Tostring(); //num의 값을 string으로 변환하여 str1에 담간다. str1은 문자열"1"이 된다.
int num2 = int.Parse(str1); //문자열인 "1"을 1로 반환하여 num2에 담긴다.
int num3 = float.Parse(str1); //float형으로 반환하여 1.0f가 num3에 담긴다.

Static

객체와 상관없이 타입에 종속적인 멤버로 선언된다.

void Start(){
	ExampleClass ex1 = new ExampleClass();
    ExampleClass ex2 = new ExampleClass();
    
    ex1.number = 1;
    ex2.number = 2;
    
    Debug.Log(ex1.number); //1이 출력된다.
    Debug.Log(ex2.number); //2가 출력된다.
    
}

class ExampleClass{
	public int number;
}

이 코드에서 public int number을 static으로 전환하면 ex1.number와 ex2.number에서 오류가 발생한다. ex1.number와 ex2.number 둘 다 ex1,ex2의 객체에 종속했지만 number을 static으로 전환하면 객체와 상관없이 ExampleClass에 종속된다.

void Start(){
    ExampleClass.number = 1;
    ExampleClass.number = 2;
    
    Debug.Log(ExampleClass.number); //2가 출력된다.
    
}

class ExampleClass{
	public static int number;
}

예시>

void Start(){

	Member chulsoo = new Member(17,"chulsoo");
	Member jisoo = new Member(18,"jisoo");
	Debug.Log(Member.numberOfMembers); //2가 출력된다.
}

class Member{
	public int age;
    public string name;
    public static int numberOfMembers; //멤버의 총 숫자
    
    public Member(int age, string name){
    	this.age=age;
    	this.name=name;
    	numberOfMembers++; //생성자가 실행될 때 마다 값이 1씩 증가한다.
    }
}

컬렉션

using System.Collections를 활용하여 배열의 비효율성을 보완하기위한 타입들이 존재한다.

  • ArrayList
    중간에 있는 요소를 제거하기 편하다.
void Start(){
	ArrayList myAr = new ArrayList();
    myAr.Add(1); //{1}
    myAr.Add(36); //{1, 36}
    myAr.Add("Hello"); //{1, 36, "Hello"}
    Debug.Log(myAr.Count); //Count를 활용하여 myAr에 몇 개의 요소가 있는지 확인할 수 있다. 3이 출력된다.
    myAr.Remove(36); //{1, "Hello"}
    myAr.RemoveAt(1); //1번째 요소인 Hello가 제거된다. {1}
}
  • Hashtable
    key와 value를 사용하여 저장한다. key의 값은 숫자나 문자 등 제한받지 않는다.
void Start(){
	Hashtable myHT = new Hastable();
    myHT.Add("첫 번째",1234); //"첫 번째"가 key값이고, 1234가 value값이다. "첫 번째"인덱스에 1234가 저장된다.
    myHT.add(3,"안녕"); //3인덱스에 "안녕"이 저장된다.
    myHT.Remove(3); //key가 3인 공간이 제가된다.   
}
  • Queue
    Firts In First Out(FIFO)의 구조를 가진다.
void Start(){
	Queue myQueue = new Queue;
    myQueue.Enqueue(3); //Enqueue를 활용하여 인수를 추가한다. {3}
    myQueue.Enqueue(6); //{3, 6}
    myQueue.Enqueue(9); //{3, 6, 9}
    
    myQueue.Dequeue(); //Dequeue를 활용하려 인수를 제거한다. 첫 번째로 저장되었던 3이 제거된다. {6, 9}
    myQueue.Dequeue(); //{9}
    myQueue.Dequeue(); //{}
    
}
  • Stack
    Last In First Out(LIFO)의 구조를 가진다.
void Start(){
	Stack myStack = new Stack();
    myStack.Push(3); //Push를 활용하여 인수를 추가한다. {3}
    myStack.Push(6); //{3, 6}
    myStack.Push(9); //{3, 6, 9}
    
    myStack.Pop(); //Pop을 활용하여 인수를 제거한다. 마지막으로 추가된던 인수가 먼저 나간다. {3, 6}
    myStack.Pop(); //{3}
    myStack.Pop(); //{}

}
  • Peek
void Start(){
	Queue myQueue = new Queue;
    myQueue.Enqueue(3); 
    myQueue.Enqueue(6); 
    myQueue.Enqueue(9); 
    
    myQueue.Peek(); //인수가 제거되지 않고 첫 번째 인수인 3이 출력된다.
    myQueue.Peek(); //똑같이 3이 출력된다.
	
}

Object 타입과 박싱/언박싱

object : 모든 자료형을 담을 수 있다.

object number = 1;
object str = "asdf"; //어떤 자료형이든 담을 수 있다.

int num = 1;
object a = num; //암시적 형변환 ->박싱

object b = 5;
int num2 = (int)b; //명시적 형변환 ->언박싱

Object의 문제점

박싱과 언박싱을 수행하는 데 많은 계산 과정이 필요하다. 값 형식이 박싱되면 완전히 새로운 개체가 생성되어야 한다. 이 작업은 단순 참조 할당보다 20배나 오래 걸린다.(20배 성능이 저하된다.) 언박싱 시 캐스팅 프로세스는 할당의 4배에 달하는 시간이 소요된다.

System.Collections 네임스페이스프 클래스는 구체적 형식의 개체(int, float...)가 아니라 object 형식의 개체로 요소를 저장한다. 가능하면 System.Collections.Generic네임스페이스 또는 System.Collections.Concurrent네임스페이스의 제너릭 컬렉션을 사용한다.
C# Boxing 및 Unboxing

제네릭

void Start(){
	DataClass_int dc1 = new DataClass_int();
    dc1.data = 1;
    dc1.GetData();
    
    DataClass_char dc2 = new DataClass_char();
    dc2.data = "hello";
    dc2.GetData();
    
}

class DataClass_int{
	public int data;
    
    public int GetData(){
    	return data;
    }
}

class DataClass_char{
	public char data;
    
    public char GetData(){
    	return data;
    }
}

-> 클래스를 정의할 때 미리 타입을 정했기 때문에 나중에 타입과 관련하여 수정하기 번거러움이 있다.

제네릭 : 타입을 미리 정의하지 않고 타입을 사용할 때 정의한다.
형식 매개변수 (T) : 미리 타입을 정의하지 않고 임의로 T라 타입을 정의한다.

void Start(){
	DataClass<int> dc1 = new DataClass<int>;
    dc1.data = 1;
    dc1.GetData();
    
    DataClass<char> dc2 = new DataClass<char>;
    dc2.data = "hello";
    dc2.GetData();
}

class DataClass<T>{
	public T data;
    
    public T GetData{
    	return data;
    }
}

DataClass를 제네릭으로 선언하여 DataClass를 사용할 때 타입을 정의할 수 있도록 한다.

이와같은 방법으로 이전에 GetComponent<>를 사용한 적이 있다.

제네릭 컬렉션

CollectionGeneric
ArrayListList<>
HastableDictionary<>
QueueQueue<>
StackStack<>
  • List<>
void Start(){
	List<int> myList = new List<int>();
	myList.Add(1); //{1}
    myList.Add(2); //{1, 2}
    Debug.Log(myList[0]); //1이 출력된다.
    //myList.Add("Hello"); -> List타입이 int이기에 오류가 난다.
    myList.Remove(2); //{1}
}
  • Dictionary<>
void Start(){
	Dictionary<string, int> myDict = new Dictionary<string, int>();
    myDict.Add("첫 번째",1234);
    myDict.Add("두 번째",4567);
    myDict.Remove("두 번째");
    Debug.Log(myDict["첫 번째"]); //1234가 출력된다.
}
  • Queue<>
void Start(){
	Queue<float> myQueue = new Queue<float>();
    myQueue.Enqueue(3.0f); //{3.0}
    myQueue.Enqueue(6.0f); //{3.0, 6.0}
    Debug.Log(myQueue.Peek()); //3.0f가 출력된다.
    myQueye.Dequeue(); //{6.0}
}
  • Stack<>
void Start(){
	Stack<char> myStack = new Stack<char>();
    myStack.Push('a'); //{a}
    myStack.Push('b'); //{a, b}
    Debug.Log(myStack.Peek()); //b가 출력된다.
    myStack.Pop(); //{a}	
}

0개의 댓글