본문 바로가기

Unity 개발 공부

[내배캠 사전캠프] 6일차 C# 난수생성,문자열처리,out,ref,is,as (25.03.28)

랜덤 숫자 생성(Random)

 

Random rnd = new Random();

int number = rnd.Next(); // 0 이상 Int32.MaxValue 미만의 정수

int numberInRnage = rnd.Next(1,11); // 1이상 11미만의 정수 1~10

double doubleVal = rnd.NextDouble();// 0.0이상 1.0미만의 실수

 

예시)

Random rnd = new Random();

for(int i = 0; i < 5 ; i++)

{

Console.WriteLine(rnd.Next(1,101));

}

// 1~100 사이 랜덤 숫자를 5번 반복해서 내놓는다.

 

사용상황

주사위굴리기

임의 샘플 데이터 생성

보안이 필요없는 난수 

등에 쓰인다.

 

축약으로

var rnd = new Random ();

으로도 쓰이지만, 처음엔 타입 명시를 권장한다.

 

문자열 처리(String) 에 대하여

주요속성

Length : 문자열 길이 반환 // 예시  "abc".Length // 3

Chars[index] : 특정 위치 문자 반환 (인덱스 0부터)  // 예시 "abc"[1] // 'b'

 

 

 

자주쓰는 메서드

메서드                                             반환형        설명                                                   예시

Substring(startIndex) string startIndex부터 끝까지 "Hello".Substring(2) // "llo"
Substring(start, length) string 부분 문자열 "Hello".Substring(1,3) // "ell"
IndexOf(string) int 첫 등장 인덱스, 없으면 -1 "apple".IndexOf("p") // 1
Contains(string) bool 부분 문자열 포함 여부 "apple".Contains("pl") // true
Replace(old, new) string 문자/문자열 치환 "hi".Replace("h","b") // "bi"
Split(char[]) string[] 구분자로 분리 "a,b,c".Split(',') // ["a","b","c"]
Trim() string 양 끝 공백 제거 " hi ".Trim() // "hi"
ToUpper()/ToLower() string 대/소문자 변환  
StartsWith(string) bool 문자열 시작 검사 "test".StartsWith("te") // true
EndsWith(string) bool 문자열 끝 검사  

예시 추가)
Equal 사용하기 , == 사용하기

string str1 = "Hello";
string str2 = "World";
bool isEqual = str1 == str2; // false
bool isEqualMethod = str1.Equals(str2); // false

Substring(start, length) 사용하기

string message = "Hello, World!";
string hello = message.Substring(0, 5); // "Hello"

Split(char[]) 사용하기

string[] parts = "a,b,c".Split(',');
foreach (string part in parts)
{
    Console.WriteLine(part);
}

// 하면 

a

b

c

다른 방법으로는,

string[] parts = "a,b,c".Split(',');
Console.WriteLine(string.Join(", ", parts));

 

// 하면

a, b, c

여기서 Split 메서드는 특정 구분자를 기준으로 잘라서 여러개의 작은 문자열로 나누는 기능이다.

반환 타입이 

string[ ] 인걸 보면, -문자열이 여러개 들어있는 배열임을 알 수 있다.

배열 자체를 콘솔에 직접쓰면 타입 이름만 나온다(System.String[ ]) 가 출력된다.

구분할 구분자가 없으면,

string text = "abcdef";
string[] parts = text.Split(','); 
Console.WriteLine(parts.Length);        // 1
Console.WriteLine(parts[0]);            // "abcdef"

배열 하나에 전체 문자열이 담긴다.

그리고 배열이기때문에 특정 인덱스의 문자를 출력할게 아니라면,

string fruits = "apple,banana,grape";
string[] parts = fruits.Split(','); // ',' 기준으로 분리

// 배열 출력
for(int i = 0; i < parts.Length; i++)
{
    Console.WriteLine($"parts[{i}] = {parts[i]}");
}

혹은

string text = "a,b,c,d,e";
string[] textArray = text.Split(',');

foreach (string item in textArray)
{
    Console.WriteLine(item);
            
}

이런식으로 쓸 수 있다.

 

 

포맷팅

문자열 보간

int age =25;

string msg = $"I am {age} years old.";

 

String.Format

string fmt = string.Format("I am {0} years old.", age);

 

혹은 변수가 두개 선언된 예시

 

string name = "John";
int age = 30;
string message = String.Format("Name: {0}, Age: {1}", name, age); // "Name: John, Age: 30"

조금 해석해보자면,

string name = "John";    // 변수 선언
int age = 30;

string result = String.Format(
    "Name: {0}, Age: {1}",  // formatString (첫 번째 인수)
    name,                   // {0} 에 대응하는 두 번째 인수
    age                     // {1} 에 대응하는 세 번째 인수
);

 

플레이스홀더        인수                                                                  위치값

{0} 2번째 인수 name ("John")
{1} 3번째 인수 age (30)

 

 

  • 메서드 호출 구문: Method(arg1, arg2, arg3, ...)
  • String.Format(formatString, arg0, arg1, ...) 에서 formatString 도 하나의 인수이고, {0}, {1} 은 뒤따르는 인수들의 순서(index)를 가리키는 자리 표시자 입니다.
  • 문법 형태 {n}을 플레이스 홀더라 부르며, 문자열 서식(foramt string) 안에서 나중에 채워질 자리표시자 역할을 하는 문법이다. 여기서 n은 0부터 시작하는 정수이며 String.Format 호출시 전달된 인수 순서를 가리킨다.

 string.Format("Hello, {0}! You are {1} years old.", name, age);

플레이스홀더      가리키는 인수값                                                 예시

{0} 첫 번째 인수 name → "John"
{1} 두 번째 인수 age → 30

 

추가예시)

 

Console.WriteLine(String.Format("{0} + {0} = {1}", "Hi", "HiHi"));
// 출력: Hi + Hi = HiHi

 

문자열합치기

+ 연산자나 String.Concat 메서드를 사용하여 문자열을 합칠 수 있습니다.

string str1 = "Hello";
string str2 = "World";
string message = str1 + ", " + str2 + "!"; // "Hello, World!"

 

문자배열변환

 

string message = "Hello";
char[] chars = message.ToCharArray(); // { 'H', 'e', 'l', 'l', 'o' }
string newMessage = new string(chars); // "Hello"

 

out과 ref 처리

 

우선 값 전달(By Value) 라는 개념을 한번 짚고 넘어간다.

-값전달변수의 값을 복사해서 메서드로 넘겨주는 방식이다.

-메서드에서 매개변수원본 변수의 복사본이기 때문에, 메서드 내부에서 값을 변경하더라도 원본 변수는 변경되지 않는다.

 

예시)

void Increment(int x)
{
    x += 1; // 복사본 x를 1 증가시킴
}

int a = 5;
Increment(a); // a의 값은 여전히 5
Console.WriteLine(a); // 출력: 5

 

메서드에서는 x의 복사본만 수정되고, 원본변수 a는 변경되지않는다.

 

void 메서드에서 값 내보내는 방법은 있다. 값을 반환하지는 않는다.

-출력하거나(Console.WriteLine) 참조형 객체를 수정하는 방식으로 값을 외부에 전달 가능하다.

-값을 반환하지않고 단순히 값을 수정하거나 출력하는 형태로도 결과를 내보낸다.

예시)

void PrintIncrement(int x)
{
    Console.WriteLine(x + 1); // 계산된 값을 출력만 함
}

int a = 5;
PrintIncrement(a);  // 출력: 6
Console.WriteLine(a);  // 출력: 5 (원본은 변경되지 않음)

 

혹은 참조형 객체를 이용,

예시)

class MyData
{
    public int Value;
}

void IncrementValue(MyData data)
{
    data.Value += 1; // 참조형 객체의 값을 수정
}

MyData obj = new MyData { Value = 5 };
IncrementValue(obj);  // obj.Value가 1 증가
Console.WriteLine(obj.Value);  // 출력: 6

여기서 참조형 객체는 메서드 내부에서 수정되므로 메서드 외부에서도 변경된 값을 확인할 수 있다.

 

혹은 아싸리 그냥 반환하게 써내려간다.

int Increment(int x)
{
    return x + 1;  // 값을 반환
}

int a = 5;
int b = Increment(a);  // 반환된 값을 b에 할당
Console.WriteLine(b);   // 출력: 6

참조전달( By Reference)

참조전달변수의 주소(참조)를 메서드로 넘겨주는 방식이다.

메서드 내부에서 참조를 통해 원본 변수를 직접 수정할 수 있다.

void IncrementRef( ref int x)

{

x += 1; // 원본 x 값을 수정

}

 

int a = 5;

IncrementRef( ref a) ; // a 값이 1 증가

Console.WriteLine( a ) ; // 출력 : 6

ref 키워드는 a 변수의 참조를 넘겨주기 때문에 메서드 내부에서 원본 변수 a를 수정 가능하다.

 

Out의 기본 개념

out은 메서드가 값을 반환하는 것이 아니라,

메서드가 값을 할당해야 할때 사용되며, 달리말하면 반드시 메서드 내에서 값을 할당하게 되며 이를 외부로 전달하는 방식이다.

외부에서 초기값을 제공할 필요가 없다. 오히려 메서드 내부에서 값을 계산하고 할당 후,

외부에서는 그 값을 받아서 사용하게 된다. 
기존의 매개변수를 사용한 일반 메서드는 값을 읽기만하고, 메서드 내부에서 그 값을 수정해도 원본 값에 영향이 없었다.

값을 반환할때, 메서드 내에서 결과를 계산해서 반환 하는 형식일 뿐이다.

 

반환(Return) 복습 : 메서드에서 값을 외부로 돌려주는것

반환은 메서드가 내부에서 계산한 결과를 외부로 전달하는 과정을 뜻함.

메서드가 끝날때 return 키워드를 사용하여 값을 반환하면 그 값은 메서드가 호출된 곳으로 돌려보내진다.

 

public int Add(int a, int b) // int는 반환값 타입, Add는 메서드 이름

{

return a + b; // a+b 한 값을 반환하겠음

}

 

public class Program

{

public static void Main()

{

int result = Add(5,10); // Add 메서드를 호출하고 그 결과값을 'result'에 저장하겠다는 뜻.

Console.WriteLine(result); // 출력: 15

}

}

 

Add 메서드는 두개의 매개변수(a, b) 를 받아 그 값을 더한 결과를 반환한다.

메서드 내에서 return a+ b; 로 결과값을 반환하며, 이 결과값을 외부에서 받아 result라는 변수에 할당 한다.

result = Add(5,10);반환된 값result 변수할당 하는 구문이다.

 

할당(Assign)복습: 값을 변수에 저장하는 것

할당은 값을 변수에 저장하는 과정이다. 이 값은 변수에 들어가게 되며, 그 이후에 값을 사용하거나 수정할 수 있다.

= 연산자를 사용하여 변수에 값을 할당한다.

 

int result = 5;

result = result +10; 

Console.WriteLine(result);

라면

result =5; 는 5라는 값을 result 라는 변수에 할당한것

result = result +10; 은 result 변수에 기존값(5)에 10을 더한 값을 다시 result에 할당한것

 

반환가 할당은 함께 자주 사용된다. 메서드가 값을 반환하고, 그 값을 다른 변수에 할당하여 사용한다.

public int Add(int a, int b)
{
    return a + b;  // a와 b를 더한 값을 반환
}

public class Program
{
    public static void Main()
    {
        int sum = Add(5, 10);  // Add 메서드를 호출하고 그 값을 'sum'에 할당, 잘보면 int a =5; int b= 10; 으로 초기화
        Console.WriteLine(sum);  // 출력: 15
    }
}

초기화(Initialization)복습 :변수에 처음으로 값을 할당하는 과정
초기화된 값
이란, 그 변수가 처음으로 값을 가지는 순간을 의미, 변수는 초기화된 값을 가지고 메모리에서 특정한 역할을 하게된다.
int sum = Add(5,10); 에서 5와 10은 Add 메서드를 호출할때 넘겨주는 인수(arguments) 이다.
Add 메서드 내부에서는 이 인수들이 매개변수 a와 b에 초기화되어 사용된다.

 

초기화 예시 1: 메서드 외부에서 값 할당.
int a = 5;

int b =10;

이러면, 변수 a와 b가 초기화된 값을 가지며, 그 값은 메서드가 실행되기 전에 할당된다.

 

초기화 예시 2: 메서드 내부에서 값 할당.

public int Add (int a, int b)

{

return a + b; // a와 b는 메서드 호출 시 초기화됨

}

Add(5,10)을 호출하면서, 메서드 Add의 매개변수 a와 b에 5와 10이 초기화 된다.

매개변수는 메서드 내보에서만 사용될 값이다.

따라서, Add 메서드 내부에서 a와b는 호출시 전달된 값 5와 10으로 초기화된다.

초기화와 값 할당예시:

 

int a;        // 변수 a 선언 (초기화되지 않음)
a = 5;        // 값 할당 (초기화 후 값 할당)

int b = 10;   // 변수 b 초기화 (초기화와 할당이 동시에 일어남)
b = 20;       // 값 할당 (초기화된 b에 새로운 값 할당)

 

정리하자면, 

초기화변수처음값을 할당

값 할당이미 초기화된 변수에 값을 새로 할당

따라서,

메서드 호출시 인수를 전달하면, 그 값들이 메서드의 매개변수초기화

 

다시 돌아가서 

 

Out 예제를 보자

public bool TryAdd(int a, int b, out int result)  // 'out' 사용
{
    result = a + b;  // 메서드 내에서 값을 할당
    return true;  // 성공
}

public class Program
{
    public static void Main()
    {
        int result;
        bool success = TryAdd(5, 10, out result);  // result는 메서드 내에서 할당됨
        Console.WriteLine($"Success: {success}, Result: {result}");  // 출력: Success: True, Result: 15
    }
}

여기서 result = a+ b; 는 메서드 내부에서 값을 할당했다.

out 매개변수호출할때 초기화 할 필요가없다. 메서드 내부에서 값이 할당 되어 결과를 외부로 전달한다. 

 

핵심 차이점:

  • 일반 매개변수메서드 호출 시 초기화된 값을 전달하고, 메서드 내에서 그 값을 수정하지 않으며 반환하는 방식입니다.
  • out 매개변수메서드가 값을 할당해야 하며, 호출 시 초기화할 필요가 없고, 메서드 내부에서 할당한 값을 외부로 전달하는 방식입니다.

1. Out을 가장 많이 사용하는 예시는 값 변환 작업이다. 

 

public bool TryParseInt(string input, out int result)
{
    if (int.TryParse(input, out result))  // TryParse는 out을 사용하여 값 할당
    {
        return true;  // 변환 성공
    }
    else
    {
        result = 0;  // 실패 시 기본값 할당
        return false; // 변환 실패
    }
}

// 사용 예시
string input = "123";
int number;
bool success = TryParseInt(input, out number);
Console.WriteLine($"Success: {success}, Number: {number}");  // 출력: Success: True, Number: 123

input = "abc";
success = TryParseInt(input, out number);
Console.WriteLine($"Success: {success}, Number: {number}");  // 출력: Success: False, Number: 0

 

혹은 

2. 다수의 값을 반환할때도 유용하다

public void CalculateValues(int input, out int result1, out int result2)
{
    result1 = input * 2;  // 계산 결과 할당
    result2 = input + 10; // 계산 결과 할당
}

// 사용 예시
int result1, result2;
CalculateValues(5, out result1, out result2);
Console.WriteLine($"Result1: {result1}, Result2: {result2}");  // 출력: Result1: 10, Result2: 15

 

3. out을 사용하여 상태업데이트에도 가능하다.

public void UpdateHealth(int currentHealth, int damage, out int newHealth)
{
    newHealth = currentHealth - damage;  // 새로운 체력 계산 후 할당
}

// 사용 예시
int currentHealth = 100;
int damage = 30;
int newHealth;
UpdateHealth(currentHealth, damage, out newHealth);
Console.WriteLine($"New Health: {newHealth}");  // 출력: New Health: 70

 

-> 참고로 위의 예시들은 축약이며, 작동되도록 실제로 코드로 쓰면

public class Character
{
    public static void UpdateHealth(int currentHealth, int damage, out int newHealth)
    {
        newHealth = currentHealth - damage;
    }
}

public class Program
{
    public static void Main()
    {
        int currentHealth = 100;
        int damage = 30;
        int newHealth;
        Character.UpdateHealth(currentHealth, damage, out newHealth);  // static 메서드 호출
        Console.WriteLine($"New Health: {newHealth}");  // 출력: New Health: 70
    }
}

와 같이 표기한다. 객체 없이 메서드 호출은 안된다. 그러려면 static으로 메서드를 정의해야한다. (위의 예시는 그리했다)
객체를 포함하는 식은 

public class Character
{
    public void UpdateHealth(int currentHealth, int damage, out int newHealth)
    {
        newHealth = currentHealth - damage;  // 체력 계산 후 할당
    }
}

public class Program
{
    public static void Main()
    {
        // 객체 생성
        Character player = new Character();

        int currentHealth = 100;
        int damage = 30;
        int newHealth;

        // 객체를 통해 메서드 호출
        player.UpdateHealth(currentHealth, damage, out newHealth);

        Console.WriteLine($"New Health: {newHealth}");  // 출력: New Health: 70
    }
}

이다.

 

....

 

마지막으로 

is와 as 에 대해서 알아보자

C#에서 isas 키워드는 객체의 타입을 확인하고 변환하는 데 사용됩니다. 두 키워드는 타입 검사 및 변환을 더 간단하고 안전하게 수행할 수 있도록 도와줍니다.
is (타입 확인)
사용 예: 객체가 특정 타입인지 확인할 때 사용합니다.
특징:
결과는 true 또는 false로 반환됩니다.
타입이 일치하면 true, 그렇지 않으면 false를 반환합니다.
예제 코드:

 

object obj = "Hello, World!";
if (obj is string)
{
    Console.WriteLine("obj is a string");
}
else
{
    Console.WriteLine("obj is not a string");
}

 
as (타입 변환)
사용 예: 객체를 특정 타입으로 안전하게 변환할 때 사용합니다.
특징:
타입 변환이 성공하면 변환된 객체를 반환합니다.
실패하면 null을 반환합니다.
예제 코드:

 

object obj = "Hello, World!";
string str = obj as string;
if (str != null)
{
    Console.WriteLine("Conversion successful: " + str);
}
else
{
    Console.WriteLine("Conversion failed");
}

 
차이점:
is는 객체가 특정 타입인지 확인하는 데 사용됩니다.
as는 객체를 특정 타입으로 변환하는 데 사용되며, 변환에 실패하면 null을 반환합니다.