개인 프로젝트/개인학습

C# 프로그래밍 기초

Young_A 2025. 7. 1. 10:45

목차

    팀원들 기다리거나, 애매하게 남은 시간을 활용하기 위해 예전에 구매해놓고 완강하지 못한 강의를 동시에 진행하려고 한다.

    https://www.udemy.com/course/the-complete-c-sharp-developer-course/?couponCode=24T4MT300625G1

    다음주부터 2주간 C# 기초, 심화를 진행하니 그 동안 진행하면 끝낼 수 있지 않을까 한다.

     

    영어로 된 강좌를 한국어로 recap하면 좋을 것 같아서 시간이 조금 걸리더라도 진행해보려고 한다.

    TIL에 C# recap까지 올리게 되면 정리가 잘 안될 것 같아서 따로 글을 쓰고 링크를 넣는 식으로 하려고 한다. 

     

    ++

    내일배움 스파르타에서 제공하는 C# 강의도 들으면서, 디테일을 추가하거나 했다.


    컴파일러

    작성한 소스 코드를 기계가 이해할 수 있는 코드로 변환하는 프로그램. 여러 단계를 걸쳐 이루어진다.

    단순한 번역만 하는 도구가 아니라, 코드의 구조와 의미를 이해하고 최적화하며, 실행 가능한 형태로 만드는 복잡한 과정을 수행한다.

    컴파일러의 작동 원리를 이해하면 디버깅 능력과 코드 작성 시의 설계력 향상에 도움이 된다.

    1. Lexical Analysis (어휘분석)
      • 소스 코드를 문자 단위로 잃어 의미 있는 단어(토큰)로 나눈다.
      • 예: 변수명, 숫자, 기호 등을 구분
    2. Syntax Analysis (구문 분석)
      • 어휘 분석 결과를 기반으로 토큰들의 구조를 분석한다.
      • 문장이 문법에 맞는지 확인하고, 구문 트리(Syntax Tree)를 생성한다.
    3. Semantic Analysis (의미 분석)
      • 문장이 의미적으로도 올바른지 확인한다. (예: 정수형 변수에 문자열을 대입하는 등의 오류 탐지)
      • 변수의 선언 여부, 타입 일치 여부 등을 검사하고, 주석이 달린 트리(Annotated Syntax Tree)를 생성한다.
    4. Intermediate Code Generation (중간 코드 생성)
      • 소스 코드를 중간 표현(Intermediate Representation)으로 변환한다.
      • 고급 언어와 저급 언어의 중간 형태로, 기계어로 바꾸기 쉽게 만든다.
    5. Code Optimization (코드 최적화)
      • 불필요한 코드를 제거하거나 실행 순서를 조정해 프로그램의 성능을 개선한다.
      • 실행 시간과 메모리 사용을 최소화하는 데 목적이 있다.
    6. Code Generation (기계어 생성)
      • 최적화된 중간 코드를 실제 타겟 머신이 실행할 수 있는 기계어로 변환한다.
      • 이 과정에서 재배치 가능한 기계어 코드가 생성된다.
    7. Symbol Table (심볼 테이블)
      • 컴파일 과정 전반에서 사용되는 변수명, 타입, 범위 등의 정보를 저장하고 관리하는 구조.
      • 빠른 식별자 검색과 스코프 관리를 가능하게 한다.

    .Net Core

    크로스 플랫폼을 지원하는 오픈소스 .NET 프레임워크의 재구현 버전

    기존의 .Net Framework를 대체하기 보다는 대안으로 제공되며, Windows 없이도 C# 개발이 가능하다.

    특징

    • Windows, Linux, macOS 모두에서 실행 가능.
    • ASP.NET MVC, Web API, 콘솔 앱, 라이브러리, 단위 테스트 프로젝트 지원
    • WinForms, UWP는 기본 미지원 (대신 일부 오픈소스 대안 존재)
    • .NET Standard 1.6 이상을 타겟팅하면 UWP에서도 라이브러리 사용 가능

    즉, Linux/macOS에서도 C#을 개발하거나, 기존 .NET 앱을 리눅스 서버에서 실행하는 등

    플랫폼에 구애받지 않고 한 번 작성한 C# 코드를 어디서나 구현할 수 있게 하는 유연한 개발 환경을 제공한다.


    변수

    int x = 1;	//정수형
    float f = 5.5f;	//소수점 포함 숫자, 접미사 f 필요
    double d = 9.8;	//더 정밀한 실수형, 접미사 d (생략가능)
    decimal m = 100.25m;	//고정 소숫점 숫자, 접미사 m 필요
    string  name = "Jon";	//문자열
    char letter = 'a';	//문자형
    bool isTrue = true;	//참/거짓
    
    //문자열 연결(Concatenation): 문자열과 변수를 +로 연결한다.
    Console.WriteLine("Double is " + d);	//Double is 9.8
    
    //변수 선언과 동시에 값 할당
    int price1 = 200;
    //변수 선언만
    int price2;
    //변수 값 할당
    price2 = 100;
    //변수끼리 대입 가능
    int sum = price1 + price2;
    //변수 여러개 선언 가능
    int num1, num2, num3;
    //변수 여러개 연쇄 할당으로 초기화
    num1 = num2 = num3 = 10;
    //변수 여러개 선언 및 각각 초기화
    int num4 = 10, num5 = 10, num6 = 10;
    //(주의) 아래의 경우는 마지막만 초기화됨.
    int num7, num8, num9 = 10;

     

    타입 메모리 크기 범위
    char 2 유니코드 문자
    string   유니코드 문자열
    bool 1 true 또는 false

    정수형 및 실수형 변수는 따로 정리.


    리터럴 (Literal)

    리터럴 (literal)은 프로그램 소스 코드에 직접 작성된 고정된 값을 의미하며, 컴파일 시 상수로 처리된다.

    변수나 상수에 할당되거나 연산에 사용되며, 리터럴을 사용하는 것은 일종의 하드코딩을 하는 것이다.


    형 변환 (Casting & Type Conversion)

    타입이 다르면 직접 대입 불가 하며, 변환 함수 사용이 필요하다.

    //숫자를 문자열로 변환하기
    int serialNo = 100;
    string accountNo = serialNo.ToString();	//"100"
    
    //정수 -> 실수: 자동 변환 가능
    float anyNo = serialNo;	//OK
    
    //실수 -> 정수: 명시적 변환 필요
    float anyNo2 = 3.9f;
    int serialNo2 = Convert.ToInt32(anyNo2);	//4 (반올림)
    //Convert.ToInt32()는 반올림해서 변환된다.
    
    //문자열 -> 정수
    string str = "123";
    int number = int.Parse(str);	//123 (소숫점이 있었으면 에러 발생)

    Var 키워드

    타입을 명시하지 않고 변수 선언을 할 수 있는 키워드.

    컴파일 시점에 자동으로 타입이 추론 된다.

    var name = "Jon Snow";	//string
    var age = 30;	//int
    var pi = 3.14;	//double
    var price = 99.9m;	//decimal
    var flag = true;	//bool

     

    단, 초기화 없이 선언이 불가능하고, 한 번 타입이 정해지면 다른 타입으로 변경할 수 없다.

     

    복잡한 타입을 간결하게 표현하거나, 반복문 LINQ 결과 등을 처리할 때, 명확한 초기화 값이 있을 때만 사용이 권장된다.

    코드의 간결성을 높이지만, 가독성과 명확성 유지가 중요하므로 타입이 명확하지 않거나 초기화 없이 선언하려면 명시적 타입 사용이 더 적절하다.


    기본 정수형 데이터 타입

    타입 메모리 크기 값의 범위 부호 (음수 저장 가능 여부)
    sbyte 1 byte -128 ~ 127 O
    byte 1 byte 0 ~ 255
    short 2 byte -32,768 ~ 32,767 O
    ushort 2 byte 0 ~ 65,535 X
    int 4 byte -2,147,483,648 ~ 2,147,483,647 O
    uint 4 byte 0 ~ 4,294,967,295 X
    long 8 byte -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807 O
    ulong 8 byte 0 ~ 18,446,744,073,709,551,615 X

     

    MaxValue, MinValue 활용 가능하다

    Console.WriteLine(int.MaxValue);   // 2147483647
    Console.WriteLine(uint.MinValue);  // 0

     

    타입 범위를 벗어난 값을 넣으면 컴파일/런타임 에러가 발생한다.

     

    원시 타입 (Primitive Type)은 컴퓨터 프로그래밍에서 가장 기본이 되는 데이터 타입을 의미한다.

    원시 타입은 int, float, double, char 등이 있다. (string, decimal 등은 아니다.)

    Console.WriteLine(typeof(int).IsPrimitive);   // true
    Console.WriteLine(typeof(string).IsPrimitive); // false

     

    타입 메타데이터(Type Metadata)는 프로그램 실행 중에 타입(자료형)에 대한 정보를 코드로 확인할 수 있는 기능을 말한다.

    Console.WriteLine(typeof(int).IsValueType);  // true //값이 직접 저장되는 타입이다.
    Console.WriteLine(typeof(string).IsClass);   // true //참조 타입(클래스)이다.
    Console.WriteLine(typeof(int).IsClass);      // false
    Console.WriteLine(typeof(int).IsSealed);     // true //상속이 불가능한 타입인지 여부

    실수형 데이터 타입

    타입 메모리 크기 소수점 이하 정확도(자리수) 특징
    float 4 bytes 약 7자리 빠르지만 정확도 낮음
    double 8 bytes 약 15 ~ 16자리 float보다 더 정밀함
    decimal 16 bytes 약 28 ~ 29자리 가장 정밀하지만 느림, 메모리 많이 사용
    float f_no = 1f / 3f;	//접미사 f
    double d_no = 1d / 3d;	//접미사 d (생략가능)
    decimal m_no = 1m / 3m;	//접미사 m
    
    Console.WriteLine("Float no. is {0}", f_no);    // 약 7자리 소수점까지
    Console.WriteLine("Double no. is {0}", d_no);   // 약 15~16자리 소수점까지
    Console.WriteLine("Decimal no. is {0}", m_no);  // 약 28~29자리 소수점까지

    DateTime 클래스

    날짜와 시간을 저장하고 다양한 방식으로 출력 및 계산할 수 있는 클래스이다.

    DateTime myDate = new DateTime();
    Console.WriteLine(myDate);  // 0001-01-01 00:00:00 (기본값)
    
    //특정 날짜 지정 가능(년, 월, 일)
    myDate = new DateTime(2020, 5, 10);
    
    //현재 날짜/시간 가져오기
    DateTime today = DateTime.Today;  // 오늘 날짜, 시간은 00:00:00
    DateTime now = DateTime.Now;      // 현재 날짜와 시간
    
    //날짜/시간 포맷 변환
    Console.WriteLine(now.ToShortDateString());  // 출력 예시: 2025-07-02
    Console.WriteLine(now.ToShortTimeString());  // 출력 예시: 10:32
    Console.WriteLine(now.ToLongDateString());   // 출력 예시: Wednesday, July 02, 2025
    
    //날짜/시간 계산
    now.AddDays(10);    // 10일 더하기
    now.AddYears(2);    // 2년 더하기
    now.AddHours(-6);   // 6시간 빼기
    
    //커스텀 포맷 사용법
    string formatted = string.Format("Date is {0:yyyy-MM-dd}", myDate);
    Console.WriteLine(formatted);

     

    주요 포맷 패턴

    패턴 의미 패턴 의미 패턴 의미
    yyyy 연도 (4자리) MM 월 2자리, 01~12 dd 일 2자리
    - MMM 월 약어 (Jan) ddd 요일 약어(Mon)
    MMMM 월 전체 이름(July) dddd 요일 전체 이름
    HH 시 (24시간 형식) mm ss
    tt AM/PM 표시 -

    C#에서의 에러 종류 3가지

    1. Syntax Error (문법 오류)
      • 코드 문법을 위반했을 때 발생
      • 컴파일 타임에 발견 (IDE에서 빨간 줄 표시)
      • 해결: 문법 수정
    2. Run-Time Error (실행 오류, 예외 Exception)
      • 문법은 맞지만 실행 중에 발생하는 오류
      • 대표적인 경우: 0으로 나누기, 없는 파일 열기, null 참조 접근 등
      • 해결: 예외 처리 (try-catch)하거나 조건문으로 방지
    3. Logical Error (논리 오류)
      • 문법도 맞고 실행도 되지만, 결과가 의도와 다름
      • 프로그래머의 논리적 실수로 잘못된 계산이나 조건 등 발생
      • 해결: 디버깅, 출력문 활용해 로직 점검
    //Syntax Error
    int a = 10  // 세미콜론(;) 누락 → 문법 오류
    string name = 123;  // 타입 불일치 → 문법 오류
    
    //Run-Time Error
    int a = 0;
    int b = 1;
    int c = b / a;  // 실행 중 0으로 나누기 → 예외 발생
    
    //Logical Error
    int total = 10;
    int count = 3;
    int average = total * count;  // 논리적 실수: 곱셈 대신 나눗셈이어야 함

    C#의 대표적인 네이밍 규칙 (Code Convention)

    스타일 예시 사용처 및 특징
    camelCase myVariableName 변수명, 매개변수명 등에 사용.
    첫 글자 소문자, 단어 시작은 대문자
    PascalCase MyClassName 클래스, 메소드, 속성 등에 사용.
    모든 단어의 첫 글자 대문자.
    snake_case my_variable_name 일부 언어나 데이터베이스에서 사용.
    C#에서는 거의 사용하지 않음
    kebab-case my-variable-name C#에서는 사용 불가.
    하이픈(-)은 연산자로 간주됨.

     

    좋은 네이밍을 위한 일반 규칙

    • 일관성 유지: 프로젝트 내에서는 하나의 스타일을 정하고 끝까지 유지
    • 가독성 우선: 의미있는 전체 단어 사용 (good) getProductCode / (not good) getProCod
    • 자연스러운 영어 어순 유지: (good) horizontalAlignment/ (not good) alignmentHorizontal
    • 예약어 피하기: DateTime, string 등 C# 내장 타입이거나 키워드와 겹치지 않도록 주의
    • 숫자와 특수기호 지양: 숫자나 기호는 되도록 사용하지 않음. (good) valueOne, dataSet/ (not good) value1, dataSet

    문화권에 따른 네이밍 방식 (주관적의견)

    영어권 개발자들과 한국어권 개발자들의 네이밍 방식이 다른 것 같다.

    당연히 영어권 개발자들이 자연스럽게 영단어 조합을 사용해야한다는 느낌이 강하다. 가독성과 협업을 우선 시 하기 때문에 네이밍에 충분한 시간을 투자하고, 코드 자체를 문서가 될 수 있도록 노력하는 편인 것 같다.

    한국어권 개발자들은 영어 실력과 개발 실력 둘 모두를 계발하는 과정에서 빠른 개발과 기능을 우선하게 되어 변수명보다는 작동을 우선 시 하기 위해 축약어나 숫자 표기를 혼용하는 느낌이 강하다.

     

    Microsoft C# 코딩 규칙 확인해보면 좋다.


    사용자 입력 받기 Console.ReadLine()

    Console.ReadLine()은 사용자의 입력을 문자열(string)으로 반환한다.

    반환값을 받을 변수는 반드시 string 타입이어야한다.

    Console.WriteLine("What is your name?");
    string name = Console.ReadLine();
    
    //활용
    Console.WriteLine("Welcome {0}", name);               // 방식 1: 보간
    Console.WriteLine("Welcome " + name + ", Welcome back"); // 방식 2: 연결

    기본 산술 연산자

    연산자 의미 예시 결과
    + 덧셈 x + y 8
    - 뺄셈 x - y 4
    * 곱셈 x * y 12
    / 나눗셈 x / y 3
    & 나머지 x % y 0

     

    문자열 결합과 산술 연산의 차이

    int x = 6;
    int y = 2;
    
    Console.WriteLine("Result: " + x + y);      // 출력: Result: 62 (문자열 결합됨)
    Console.WriteLine("Result: " + (x + y));    // 출력: Result: 8 (정상적인 수치 연산)

    복합 대입 연산자

    연산자 예시 설명
    += x += y; x = x + y;
    -= x -= y; x = x - y;
    *= x *= y; x = x * y;
    /= x /= y; x = x / y;
    %= x %= y; x = x % y;

    증감 연산자

    연산자 설명
    ++ 1증가
    -- 1감소
    int num = 10;
    Console.Writeline(num++); //10 출력 이후 num = 11이 됨
    Console.Writeline(++num); //num = 12가 된 후 12 출력

    연산자 우선 순위

    우선순위 연산자 종류 예시 설명
    1 괄호 (a + b) 괄호, 가장 먼저 계산
    2 단항 연산자 ++a, --a, -a, +a, !a 변수 하나에 작용하는 연산자
    3 산술 연산자 +, - , *, /, % 기본적인 수학 연산자 (곱하기, 나누지, 나머지 우선)
    4 시프트 연산자 <<, >> 비트 단위 이동
    5 관계 연산자 <, >, <=, >=, ==, != 비교 결과를 반환
    6 논리 연산자 &&, || 조건 결합하여 참/거짓을 반환
    7 할당 연산자 =, +=, -=, *=, /=, %= 대입 (가장 마지막에 실행)

    if 조건문

    if는 조건이 true일 경우에만 중괄호 안 코드를 실행한다.

    if (조건) //true, false 값이 들어가도록 비교 연산자를 주로 사용한다.
    {
        // 조건이 참일 때 실행되는 코드
    }

    비교 연산자

    비교 연산자 의미
    == 같다
    != 다르다
    > 크다
    < 작다
    >= 크거나 작다
    <= 작거나 같다
    //예시
    int x = 5;
    int y = 7;
    
    if (x > y)
    {
        Console.WriteLine("x는 y보다 큽니다.");
    }
    else if (x < y)
    {
        Console.WriteLine("x는 y보다 작습니다.");
    }
    else
    {
        Console.WriteLine("x와 y는 같습니다.");
    }

     


    switch 문

    switch 문은 하나의 변수 값에 따라 여러 분기 중 하나를 선택해 실행할 때 사용한다.

    if-else if-else 구조보다 가독성이 좋고 간결한 구조로 비교 대상이 정해진 값 중 하나일 때 유용하다.

    각 case의 끝에는 반드시 break; 를 써야 다음 분기 실행을 막을 수 있다.

    switch (변수)
    {
        case 값1:
            // 변수 값이 값1일 때 실행
            break;
        case 값2:
            // 변수 값이 값2일 때 실행
            break;
        default:
            // 어떤 case에도 해당하지 않을 때 실행
            break;
    }

     

    case 값은 상수(Constant)여야 하며, 변수나 연산식 사용은 불가능하다.


    논리 연산자 (Logical Operators)

    연산자 기호 설명
    AND && 두 조건 모두 true일 때 true
    OR || 둘 중 하나가 true일 때 true
    NOT ! 조건을 부정(반전)

     

    논리 연산자 진리표

    X Y X&&Y X||Y !X
    true true true true false
    true false false true false
    false true false true true
    false false false false true
    //예제
    bool isUserNameValid = true;  
    bool isEmailValid = false;    
    bool isPasswordValid = true;  
    
    if ((isUserNameValid || isEmailValid) && isPasswordValid)
    {
        Console.WriteLine("로그인 성공");
    }
    else
    {
        Console.WriteLine("로그인 실패");
    }

    비트 연산자

    비트 연산자는 데이터의 비트 (bit) 단위로 연산을 수행하는 연산자이다.

    연산자 설명
    & (AND) 두 비트 값이 모두 1일 때 1을 반환
    | (OR) 두 비트 값 중 하나라도 1일 때 1을 반환
    ^ (XOR) 두 비트 값이 서로 다를 때 1을 반환
    ~ (NOT)  두 비트 값의 보수 (complement)를 반환
    << (왼쪽 시프트) 비트를 왼쪽으로 이동
    >> (오른쪽 시프트) 비트를 오른쪽으로 이동
    int a = 0b1100; // 12 (2진수)
    int b = 0b1010; // 10 (2진수)
    
    int and = a & b; // 0b1000 (8)
    int or = a | b; // 0b1110 (14)
    int xor = a ^ b; // 0b0110 (6)
    
    int c = 0b1011; // 11 (2진수)
    int leftShift = c << 2; // 0b101100 (44)
    int rightShift = c >> 1; // 0b0101 (5)
    
    int d = 0b1100; // 12 (2진수)
    int bit3 = (d >> 2) & 0b1; // 0b0011 & 0b1 = 0b11 & 0b1 = 0b1 (1) (3번째 비트)
    d |= 0b1000; // 0b1100 | 0b1000 = 0b1100 (12)

    3항 연산자

    3항 연산자는 if 문의 간단한 형태로, 조건식의 결과에 따라 두 값을 선택하는 연산자이다.

    (조건식) ? 참일 경우 값 : 거짓일 경우 값;

    int currentExp = 1200;
    int requiredExp = 2000;
    string result = (currentExp >= requiredExp) ? "레벨업 가능" : "레벨업 불가능";	//"레벨업 불가능"

    TryParse

    TryParse는 사용자가 입력한 문자열을 숫자로 변환할때, 잘못된 입력이 들어오는 것을 방지한다.

    Convert.ToInt32()나 int.Parse()는 예외(Exception)을 발생시켜 프로그램이 중단되는 것을 방지하기 위해 TryParse를 사용한다.

    int number;
    bool isParsed = int.TryParse(userInput, out number);

     

    이 경우 Parse하는 데 성공한다면, true를 반환하므로 isParsed는 ture가 된다.

    성공했을 경우에는 number에 변환된 int 값이 대입된다.

    실패했을 경우에는 isParsed는 false, number는 0이 된다.


    const (상수)

    프로그램에서 절대로 변하지 않아야 하는 값을 선언할 때 const 키워드를 이용하여 상수(Constant)로 선언한다.

    컴파일 타임에 값이 결정되어야 하며, 한 번 정의하면 절대 변경할 수 없다.

    따라서 선언과 동시에 반드시 초기화해야한다.

    const double Gravity = 9.81;
    const double Pi = 3.14159;

    Command Prompt 설정

    콘솔 창의 제목 표시줄을 우클릭하여 Command Prompt를 커스터마이징(글꼴, 배경색, 글자색, 창 크기 등) 할 수 있다.

    개인적으로는 기본이 익숙해서... 그냥 이용한다.

    또한, C# 코드 안에서도 콘솔 색상을 바꿀 수 있다.

    Console.BackgroundColor = ConsoleColor.White;
    Console.ForegroundColor = ConsoleColor.Black;
    Console.WriteLine("하얀색!");
    Console.ReadLine();
    Console.BackgroundColor = ConsoleColor.Red;
    Console.ForegroundColor = ConsoleColor.White;
    Console.WriteLine("주의!");


    문자열 조작 (String Manipulation)

    문자열(string)은 문자들의 연속된 집합으로 0부터 시작하는 인덱스로 각 문자를 접근할 수 있다.

    공백 제거: Trim()

    앞 뒤 공백을 제거한다. (가운데 공백은 제거되지 않음)

    string input = "   hello   ";
    string cleaned = input.Trim(); // "hello"

    대소문자 변환: ToUpper(), ToLower()

    string name = "john doe";
    string upper = name.ToUpper(); // "JOHN DOE"
    string lower = name.ToLower(); // "john doe"

    문자열 길이 확인: Length

    string name = "  Alice  ";
    Console.WriteLine(name.Length);           // 9 //공백 포함 길이
    Console.WriteLine(name.Trim().Length);    // 5 //공백 제거 후 길이

    문자열 대체: Replace()

    string text = "hello";
    string updated = text.Replace("e", "a"); // "hallo"

    문자열 전체에서 해당 문자를 찾아 모두 바꿔준다.

    처음 등장 위치 확인: IndexOf()

    특정 문자나 문자열이 처음으로 등장하는 인덱스를 반환한다.

    해당 문자가 없으면 -1을 반환한다.

    string title = "Game of Thrones";
    int index = title.IndexOf("o"); // 결과: 6 (첫 번째 'o')

    마지막 등장 위치 확인: LastIndexOf()

    특정 문자나 문자열이 마지막으로 등장하는 인덱스를 반환한다.

    해당 문자가 없으면 -1을 반환한다.

    string title = "Game of Thrones";
    int lastIndex = title.LastIndexOf("o"); // 결과: 11 (마지막 'o')

    문자열 일부 추출: Substring()

    string s = "Game of Thrones";
    string part = s.Substring(5);       // 결과: "of Thrones" (5번째 인덱스부터 끝까지)
    string part2 = s.Substring(5, 2);   // 결과: "of" (5번째 인덱스부터 2글자)

    유효하지 않은 인덱스나 범위를 지정하면 ArgumentOutOfRangeException 발생.

    문자 제거: Remove()

    string s = "Game of Thrones";
    string removed = s.Remove(5);     // 결과: "Game " (5번째 인덱스부터 이후 모두 제거)
    string removed2 = s.Remove(5, 3); // 결과: "Game Thrones" (5번째부터 3글자 제거)

    Insert()

    문자열의 특정 위치에 다른 문자열을 삽입한다.

    string s = "Game of Thrones";
    string inserted = s.Insert(5, "the "); // 결과: "Game the of Thrones"

    Split()

    string s = "Game of Thrones";
    string[] words = s.Split(' ');	// {"Game", "of", "Thrones" }

    문자열 비교

    //str1 문자열과 str2 문자열을 비교한 후, isEqual 변수에 그 결과를 저장
    string str1 = "Hello";
    string str2 = "World";
    bool isEqual = str1 == str2; 
    
    //str1 문자열과 str2 문자열을 대소 비교
    string str1 = "Apple";
    string str2 = "Banana";
    int compare = string.Compare(str1, str2);
    //str1 < str2: 음수, str1 == str2: 0, str1 > str2: 양수

     


    이스케이프 시퀀스 (Escape Sequences)

    문자열을 " "(큰따옴표)로 감싸는데, 문자열 안에 큰 따옴표를 직접 쓰면 오류가 발생한다. (문자열 구분자로 인식)

    이를 해결하지 위해 백슬래시(\)를 사용한다.

    string text = "John said, "Hello!"";  // 오류 발생
    string text = "John said, \"Hello!\"";
    이스케이프 시퀀스 의미
    \' 작은 따옴표 (') 삽입
    \" 큰 따옴표 (") 삽입
    \\ 백슬래시 (\) 삽입
    \n 새 줄 (줄바꿈)
    \t 탭 (tab) 공간 삽입
    \r 캐리지 리턴 (줄의 시작으로 이동 이전 내용 덮어쓰기)
    \a 경고음 (Alert sound)
    \b 백 스페이스 삽입

     

    \r은 \n과 함께 사용해야 줄바꿈을 표현할 수 있다.

    string s1 = ("\\r사용 이전\r\\r사용 이후");
    string s2 = ("\\r\\n사용 이전\r\n\\r\\n사용 이후");
    Console.WriteLine(s1);
    Console.WriteLine("----");
    Console.WriteLine(s2);


    문자열 연결

    기본 문자열 연결 (Concatenation)

    + 연산자로 문자열과 변수를 연결한다. 단순하고 직관적이지만, 복잡한 문자열에는 가독성이 떨어질 수도 있다.

    string name = Console.ReadLine();	//younga 입력
    Console.WriteLine("Welcome back, " + name);	//Welcome back, younga

    문자열 포맷 (Placeholders)

    string.Format 혹은 Console.WriteLine에서 {0} {1} 등의 플레이스 홀더를 사용한다.

    string name = Console.ReadLine();	//younga 입력
    int age = 1;
    Console.WriteLine("Name: {0}, Age: {1}", name, age); //Name: younga, Age: 1

    문자열 보간 (String Interpolation)

    $ 기호를 문자열 앞에 붙이고, {변수명}을 직접 넣는다. *C# 6.0 이상에서 지원한다.

    string name = Console.ReadLine();	//younga 입력
    Console.WriteLine($"Welcome back, {name}");	//Welcome back, younga

    for 반복문

    초기식, 조건식, 증감식을 통해 반복을 제어하며, 반복 횟수가 명확할 때 사용한다.

    for (int i = 0; i < 10; i++)
    {
        Console.WriteLine(i);
    }

    while 반복문

    조건문이 참인 동안 계속 실행되며, 반복 횟수가 명확하지 않을 때 사용한다.

    int i = 0;
    while (i < 10)
    {
        Console.WriteLine(i);
        i++;
    }

    do-while 반복문

    조건 검사 전에 한 번은 무조건 실행되어 최소 1회 실행이 보장된다.

    int num;
    do
    {
        num = int.Parse(Console.ReadLine());
    } while (num != 0);

    foreach 반복문

    배열이나 컬렉션을 순회할 때 사용된다.

    인덱스를 직접 다루지 않는다.

    string[] items = { "검", "방패", "물약" };
    foreach (string item in items)
    {
        Console.WriteLine(item);
    }

    중첩 반복문

    반복문 안에 또 다른 반복문을 포함하여 이차원 구조나 다중 반복 작업에 사용된다.

    //구구단 출력 예제
    for (int i = 2; i <= 9; i++)
    {
        for (int j = 1; j <= 9; j++)
        {
            Console.WriteLine(i + " x " + j + " = " + (i * j));
        }
    }

    break, continue

    break은 반복문을 즉시 종료한다.

    continue는 현재 반복을 건너뛰고 다음 반복으로 진행한다.

    for (int i = 1; i <= 10; i++)
    {
        if (i % 3 == 0)
        {
            continue;	//3의 배수는 건너뛴다.
        }
    
        Console.WriteLine(i);
    
        if (i == 7)
        {
            break;	//7까지만 반복된다.
        }
    }

    배열

    같은 자료형의 데이터를 연속적으로 저장하는 자료 구조이다.

    인덱스를 통해 각 요소에 접근할 수 있다.

    1차원 배열

    단일 인덱스로 요소에 접근하는 가장 기본적인 배열 구조.

    int[] numbers = { 1, 2, 3 };
    Console.WriteLine(numbers[0]);

    2차원 배열

    행과 열의 구조를 가지며, 표 형태의 데이터를 표현할 수 있다.

    int[,] grid = { { 1, 2 }, { 3, 4 } };
    Console.WriteLine(grid[0, 1]);

    컬렉션

    자료를 저장하고 관리하는 가변 크기의 구조이다.

    System.Collections.Generic 네임스페이스를 사용한다.

    List

    순차적으로 데이터를 저장하며, 크기가 유동적인 배열 형태의 컬렉션이다.

    List<int> numbers = new List<int> { 1, 2, 3 };

    Dictionary

    키-값 쌍으로 데이터를 저장하며, 키는 중복될 수 없다.

    Dictionary<string, int> scores = new Dictionary<string, int>();
    scores.Add("Alice", 100);

    Stack

    후입선출(LIFO) 구조. 나중에 넣은 데이터가 먼저 나간다.

    Stack<int> stack = new Stack<int>();
    stack.Push(1);

    Queue

    선입선출(FIFO) 구조. 먼저 넣은 데이터가 먼저 나간다.

    Queue<int> queue = new Queue<int>();
    queue.Enqueue(1);

    HashSet

    중복 없는 데이터를 저장하는 집합 구조. 순서를 보장하지 않는다.

    HashSet<int> set = new HashSet<int>();
    set.Add(1);

    배열과 리스트 (비교)

    배열과 리스트는 모두 데이터를 연속적으로 저장하지만, 크기 변경 가능 여부와 기능성에서 중요한 차이가 있다.

     

    크기 변경 가능 여부

    • 배열: 생성 시 크기가 고정되며 이후 변경 불가능
    • 리스트: 요소 추가/삭제에 따라 자동으로 크기 조절이 되는 구조.

    리스트는 내부적으로 배열을 기반으로 동작하지만, 용량을 초과하면 더 큰 배열을 새로 만들고 기존 데이터를 복사하여 확장한다.

    이 구조를 동적 배열(Dynamic Array)라고 하며, 유연한 대신에 확장 시 순간적인 성능 저하가 발생할 가능성이 있다.

    List<int> list = new List<int> { 1, 2, 3 };
    list.Add(4); // 내부 배열을 초과하면 더 큰 배열로 복사됨

    메모리 사용 방식

    • 배열: 고정된 메모리 공간을 사용하며, 예측 가능한 성능을 제공
    • 리스트: 메모리 공간이 부족할 경우 더 큰 배열을 새로 할당하고 복사.
      • 일시적으로 메모리 사용량 증가할 수 있으나, 대부분의 일반적인 사용에서는 문제 없음.

    기능적 차이

    • 배열: 인덱스를 통한 단순한 접근에 적합
    • 리스트: Add, Remove, Insert, Contains 등의 내장 기능 제공으로 유연한 데이터 조작이 가능함.
    list.Remove(2); // 값 2 제거
    list.Insert(1, 99); // 인덱스 1에 99 삽입

    성능 고려

    • 배열: 구조가 단순해 루프 처리 등에서 빠르고 안정적인 성능
    • 리스트: 동적 확장과 기능성으로 편리하지만 반복 중 빈번한 추가/삭제 작업은 성능 저하의 원인이 됨.
    for (int i = 0; i < 1000; i++)
    {
        list.Add(i); // 반복문 내부의 추가는 배열 복사를 유발할 수 있음
    }

    사용처 예시

    사용 상황 자료 구조
    크기 변경이 없고 반복 위주 처리 배열
    데이터 수가 유동적이고 조작이 잦은 경우 리스트
    실시간 성능이 중요한 게임 루프 배열
    필터링, 정렬 등 유연한 데이터 처리 리스트

     

    '개인 프로젝트 > 개인학습' 카테고리의 다른 글

    유니티 입문 (2D) - TopDown  (0) 2025.07.23
    유니티 입문 (3D) - The Stack  (0) 2025.07.22
    유니티 입문 (2D) - Flappy Plane  (0) 2025.07.21
    알고리즘  (0) 2025.07.08
    C# 객체 지향 프로그래밍  (0) 2025.07.06