👾 내일배움캠프/🎮 TIL & WIL
내일배움캠프 6일차 TIL - C# 기초 문법 (1)
리리핸
2023. 8. 14. 22:19
[공부 내용]
* 기억해야 할 부분 또는 헷갈리는 내용 위주로
프로그래밍 기본 요소
(1) Escape Sequence
이스케이프 시퀀스 | 설명 |
\' 또는 \" | 문자열 내에 따옴표 삽입 |
\\ | 문자열 내 역슬래시 삽입: 파일 경로 등의 표기에 필요한 경우 많음 |
\n | 줄바꿈 |
\r | 현재 줄 맨 앞으로 이동 |
\t | 탭 삽입 |
\b | 백스페이스 삽입 |
- 다른 프로그래밍 언어들과 거의 비슷한 것 같다.
- \r, \t, \b는 모두 활성 위치(커서)를 옮겨가도록 한다. 그 후에 덮어쓰기 되는 것
- \b 백스페이스 삽입 같은 경우에도 커서를 한 칸 뒤로 옮기기 때문에 백스페이스 역할을 하는 것
(2) 주석
- 작성하는 습관이 들지 않아 주석을 정말 안 쓰는데 (심지어 코드도 나만 알아볼 수 있는 최악의 상황), 앞으로 협업이 많아질 것을 생각하면 필요한 정보들을 표시하는 습관을 들여야겠다.
- 물론 주석 의존 금지 (주석 대신 누구나 알아볼 수 있는 직관적인 코드를 쓰는 습관 들이기, 주석은 코드 대체 불가)
- 필요한 경우에만 사용하기 (불필요한 주석은 코드 읽기를 방해)
변수와 자료형
(1) 자료형의 세분화
- 메모리의 효율적인 사용
- ex) sbyte는 음수값 포함하기 때문에 양수를 쓸 때 사용하면 음수 부분을 버리는 비효율적인 활용이 됨
- 정확한 데이터 표현
- 데이터가 int의 표현 범주를 넘어설 때는 더 큰 long이나 ulong 등을 쓰도록
- float과 double의 차이도 마찬가지 --> 서로 다른 범위의 값을 표현할 수 있음
- 타입 안전성
- 해당 자료형이 가질 수 있는 값의 범위를 통해 코드를 제한
(2) 변수 선언과 초기화
- 기본적인 변수 선언: 자료형 변수이름;
- 한 번에 여러 개의 변수 선언 가능: int num1, num2, num3;
- 변수 초기화: 변수에 값을 저장 (변수이름 = 값;)
- 한 번에 여러 개 초기화
- Int num1, num2, num3 = 10; (x) // 이 경우 num 3만 초기화 됨
- num1 = num2 = num3 = 10; // 이런 식으로 오른쪽에서부터 할당 가능
(3) *** 변수명 ***
- 규칙
- 식별자: 변수, 메서드, 클래스, 인터페이스 등의 이미 이름. 키워드(이미 예약된 이름)를 쓸 수 없다.
- 첫 문자는 알파벳 or 언더스코어(_)
- 두 번째부터는 숫자도 가능 (알파벳, 숫자, 언더스코어만 가능)
- 대소문자 구분
- 명확한 이름 사용하기 (식별자 명으로 x, a, b와 같은 무의미한 이름은 지양하기 / 어떤 용도로 쓰였는지 이해하기 쉬운 이름)
- 코드 컨벤션 (관습적으로 쓰이는 규칙)
- PascalCase: 클래스, 매서드, 프로퍼티
- camelCase: 변수, 매개변수, 로컬변수
- 대문자: ID, HTTP, FTP 등 예외
- 관련 없는 코드 사이에서 빈 줄 하나 추가
- 메서드, 클래스 등의 블록 사이에는 두 줄 추가
(4) 형변환
- 형변환: 데이터의 타입을 바꾸는 것
- 명시적 형변환: 직접 바꾸는 것
- ex) int num; --> string age = num.ToString();
- (int / int)는 나머지를 버리고 int로 반환하기 때문에 평균값 등을 구할 때는 둘 중 하나를 부동소수점형(float 또는 double)의 형태로 명시적으로 변환시켜야 함
- 암시적 형변환: 직접 변환하지 않아도 계산 중에 자동적으로 형태를 변환하여 인식되는 것
- 작은 데이터타입에서 더 큰 데이터타입으로 대입하는 경우 발생
- byte --> int
- 리터럴 값이 대입되는 경우
- float result = 1; (1은 int 형태이지만 컴파일러가 float으로 판별)
- 정수형과 부동소수점형 간의 연산 --> 부동소수점형으로
- 작은 데이터타입에서 더 큰 데이터타입으로 대입하는 경우 발생
- var 키워드: 초기값에 따라 자료형이 컴파일러에 의해 자동으로 결정됨
- 변수를 선언하는 시점에서 변수의 자료형을 정확히 알 수 없는 경우에 유용하게 사용할 수 있다.
- ex) var num = 20; --> int 자료형으로 결정
연산자와 문자열 처리
(1) 연산자
- 산술연산자 : + - / * %
- 관계연산자 : ==, !=, >, <, >=, <=
- 논리연산자 : &&, ||, !
- 증감연산자 : ++ (1 증가), -- (1 감소)
- 전위 vs 후위에 따라 실행이 달라진다.
- 코드는 왼쪽에서부터 오른쪽으로 읽히며 실행된다. ++x (전위)의 경우 증감연산자에 의해 더하는 행위를 할 준비가 완료된 상태에서 x라는 변수를 만나기 때문에 바로 연산자 발동한다. 그러나 x++ (후위)의 경우 x를 이미 처리했는데 ++가 뒤에 나오기 때문에 뒤에 붙은 모든 작업이 끝난 후에 값이 더해진다.
(2) 비트연산자
연산자 | 설명 |
& (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; // 0 (3번째 비트)
d |= 0b1000; // 0b1100 | 0b1000 = 0b1100 (12)
- 도대체 어떤 경우에 쓰이는 친구인지 궁금해서 찾아보았는데, 아직 내가 쓸 단계는 아닌 것 같다.
- https://velog.io/@jdja2004/%EB%B9%84%ED%8A%B8-%EC%97%B0%EC%82%B0%EC%9E%90-bitwise-operator
비트 연산자 (bitwise operator)
비트 연산이란? 비트 연산은 비트 단위로 수행되는 연산이다. 기본 자료형 char, int와 같은 바이트 단위보다 더 작은 비트 단위를 다룬다. 정수형 변수 또는 정수형 값을 이루는 모든 비트들에 대
velog.io
(3) 문자열
- 생성: string str1 = new string(‘I’, 5); // str1 == “iiiii” 같은 문자를 지정된 횟수만큼 반복해서 만듦
- 연결: 더하기
- 분할: Split() - 띄어쓰기(공백) 또는 입력값을 기준으로 나누어 배열 형태로 저장
- 검색
- string str = “Hello, World!”;
- int index = str.IndexOf(“World!); // index == 7
- 대체:
- string newStr = str.Replace(“World”, “Universe”); // newStr == “Hello, Universe!”
- 문자열의 대소비교: 사전식 비교. 사전에 뒤에 나올수록 높은 값 (문자열 길이 상관 x)
- string apple = "apple";
- apple > "ant" // false
- 포맷팅
- 문자열 형식화 (위) vs 문자열 보간 (아래) --- 편한 방법 골라 쓰기
string name = "John";
int age = 30;
string message = string.Format("My name is {0} and I'm {1} years old.", name, age);
string name = "John";
int age = 30;
string message = $"My name is {name} and I'm {age} years old.";
조건문과 반복문
*코드의 흐름을 제어하므로 제어문에 해당
(1) 조건문
- 조건문 종류: if / else / else if / 중첩조건문 / switch / 3항연산자
- 3항연산자
- (조건식) ? 참일 경우 값 : 거짓일 경우 값;
- string result = (currentExp >= requiredExp) ? "레벨업 가능" : "레벨업 불가능"; // (조건식)의 결과에 따라 다른 값이 할당 되는 사례
- Switch문은 break만나기 전까지 쭈욱 읽기 때문에, case를 이어서 쓰면 동일한 실행을 둘 이상의 케이스에서 진행할 수 있음
switch (변수나 식)
{
case 값1:
// 값1이 나온 경우 실행되는 코드
break;
case 값2:
// 값2가 나온 경우 실행되는 코드
break;
// ...
default:
// 모든 case문에 해당하지 않는 경우 실행되는 코드
break;
}
- case를 인덱스로 생각하면 좋을 듯. 해당되는 인덱스로 바로 찾아 가는 느낌. case를 찾아갔는데 다음 case까지 break가 없으면 다음 break가 나올 때까지의 내용을 다 실행함.
- 따라서 case 값1: 부분에 break가 없으면 값 1에 해당하는 경우이더라도 (값 1이 나온 경우 실행되는 코드)와 (값 2가 나온 경우 실행되는 코드)가 모두 실행됨.
(2) 반복문
- for문 : 초기식, 조건식, 증감식을 사용하여 반복문을 작성
- 명확한 회차, 명확한 데이터가 주어질 때 사용
- n번 반복하기
- while :
- 변화되는 조건 속에서 ~가 될 때까지
- 조건이 강조
- do while
- while문과 비슷하지만 조건식을 검사하기 전에 먼저 코드 블록을 한 번 실행한다는 점!
- foreach문 : // 직접 써본 적 없으니 활용해보기
- 배열이나 컬렉션의 요소를 하나씩 꺼내서 활용 (해당 자료 구조의 길이 만큼 반복)
foreach (자료형 변수 in 배열 또는 컬렉션)
{
// 배열 또는 컬렉션의 모든 요소에 대해 반복적으로 실행되는 코드
}
배열과 컬렉션
(1) 배열
- 동일한 자료형의 값들이 연속적으로 저장되는 구조
- 인덱스를 통해 요소 접근
// 배열 선언
데이터_유형[] 배열_이름;
// 배열 초기화
배열_이름 = new 데이터_유형[크기];
// 배열을 한 줄로 선언 및 초기화
데이터_유형[] 배열_이름 = new 데이터_유형[크기];
// 배열 요소에 접근
배열_이름[인덱스] = 값;
값 = 배열_이름[인덱스];
- 다차원 배열
- 여러 배열을 묶어서 행과 열로 구성된 표와 같아 보이는 배열
- 맵 만들 때 활용
(2) 컬렉션
- 자료를 모아 놓은 데이터 구조
- 배열과 다르게 크기가 가변적
- 사용하려면 System.Collections.Generic 네임스페이스 추가 필요
- List
- Length 쓸 수 없음. 대신 Count()를 씀
List<int> numbers = new List<int>(); // 빈 리스트 생성
numbers.Add(1); // 리스트에 데이터 추가
numbers.Add(2);
numbers.Add(3);
numbers.Remove(2); // 리스트에서 데이터 삭제
foreach(int number in numbers) // 리스트 데이터 출력
{
Console.WriteLine(number);
}
- Dictionary
- 키와 값으로 구성
using System.Collections.Generic;
Dictionary<string, int> scores = new Dictionary<string, int>(); // 빈 딕셔너리 생성
scores.Add("Alice", 100); // 딕셔너리에 데이터 추가
scores.Add("Bob", 80);
scores.Add("Charlie", 90);
scores.Remove("Bob"); // 딕셔너리에서 데이터 삭제
foreach(KeyValuePair<string, int> pair in scores) // 딕셔너리 데이터 출력
{
Console.WriteLine(pair.Key + ": " + pair.Value);
}
- Stack / Queue
- Stack은 후입선출(LIFO) 구조를 가진 자료 구조
- Stack<int> stack1 = new Stack<int>();
- int value = stack1.Pop(); // value = 3 (마지막에 추가된 요소)
- Queue는 선입선출(FIFO) 구조를 가진 자료 구조
- Queue<int> queue1 = new Queue<int>();
- int value = queue1.Dequeue(); // value = 1 (가장 먼저 추가된 요소)
- Stack은 후입선출(LIFO) 구조를 가진 자료 구조
- HashSet
- HashSet은 중복되지 않은 요소들로 이루어진 집합
- 중복 제거 등에 활용하기 좋을 듯?
(3) 배열과 리스트
- 배열의 정해진 크기 때문에 리스트를 더 편하게 생각하고 무분별하게 리스트를 사용하는 경우가 많다고 함.
- 리스트는 크기가 가변적인 대신 메모리 사용량, 데이터 접근 시간 증가
- 배열이 가진 기능들을 활용하지 못하므로 코드 복잡도 증가
- 필요에 따라 잘 선택해서 사용할 필요
메서드
(1) 메서드
- 독립적인 기능 단위의 코드블록
- 코드의 재사용성과 모듈화를 위해 사용, 필요할 때 호출하여 실행
[접근 제한자] [리턴 타입] [메서드 이름]([매개변수])
{
// 메서드 실행 코드
}
- 구조와 문법
- 접근제한자 : 메서드에 접근할 수 있는 범위.
- public: 어디에서나
- private: 같은 클래스 내에서만
- protected: 상속받은 자식의 클래스에서만
- 리턴 타입
- 반환값이 있을 경우 : 반환값의 데이터 타입으로 설정
- 반환값이 없을 경우 : void
- 메서드 이름 : PascalCase로 쓰도록
- 접근제한자 : 메서드에 접근할 수 있는 범위.
(2) 메서드 오버로딩
- 이름의 메서드를 다양한 매개변수 목록으로 다중 정의
- 매개변수의 개수, 타입, 순서가 다를 경우 활용
- 호출하는 입장에서는 고려할 부분이 없다. 호출 시 입력되는 매개변수에만 영향을 받아 알아서 적절한 함수를 선택함
(3) 재귀 함수
- 예시로 보는 게 가장 좋을 듯
void CountDown(int n)
{
if (n <= 0)
{
Console.WriteLine("Done");
}
else
{
Console.WriteLine(n);
CountDown(n - 1); // 자기 자신을 호출
}
}
// 메서드 호출
CountDown(5);
- 함수 내에서 함수가 반복적으로 호출됨
- 이전 프로젝트에서도 카운트다운에 활용할 수 있었을 것 같다
[기록]
잘한 점 :
- 딱히 없는 것 같다... 어떡하지...
어려웠던 점 :
- 집중하기...
되돌아보기 :
- 오늘의 몰입도 : 50점
- 여행 피로 + 어느 정도 아는 내용 --> 집중 정말 안 됨..
- 그래도 꾸역꾸역 2주차까지는 들었으니까 절반은 주기
- 스스로 찾아보기: 20점
- 별로 한 게 없다..
내일 목표
- C#문법종합반 3주차까지 듣기
- Invoke, Coroutine 등 시간 관련된 공부
- 생명 주기 공부
- 피로 회복 잘 하고 공부 패턴 돌려놓기..