VS Code에서는 Ctrl + Shift + F 였던 걸로 기억하는데, 역시 IDE마다 다르다. 혹시 안 먹히면 정렬 하고싶은 부분 선택 혹은 전체 선택을 하고 눌러보자.
for (int i = 2; i <= 9; i++)
{
for (int j = 1; j <= 9; j++)
{
Console.WriteLine(i + " x " + j + " = " + (i * j));
}
Console.WriteLine();
}
지금 코드는 이렇게 생겼다.
for (int i = 1; i <= 9; i++)
{
for (int j = 2; j <= 9; j++)
{
Console.Write(j + " x " + i + " = " + (j * i) + "\t");
}
Console.WriteLine();
}
이렇게 고쳐주면 된다.
기존 구구단이 앞이 고정, 뒤가 움직이는 식이었는데, 우리 생각대로 가로로 찍히게 하려면 가로로 2x1, 3x1, 4x1이 찍히면 되는 식이었다.
뒤가 고정, 앞이 움직여야 하니 앞이 j, 뒤가 i이고 j는 2부터 시작, i는 1부터 시작인 것으로 뒤집어 주었다.
for(;;)
이렇게 쓰면 while(true) 처럼 무한루프에 빠진다.
그냥 new Random()은 지정 시드 없이 초기화. (new Random(Int32)로 쓸 수도 있음.) Random().Next(n, m) 라고 쓰면 지정된 범위 내 임의의 정수 반환. (n이상 m미만)
int[] scores = new int[5];
for (int i = 0; i < scores.Length; i++)
{
Console.Write("학생 " + (i + 1) + "의 성적을 입력하세요. ");
scores[i] = int.Parse(Console.ReadLine());
}
int sum = 0;
for (int i = 0; i < scores.Length; i++) { sum += scores[i]; }
double average = (double)sum / scores.Length;
Console.WriteLine("성적의 평균은 " + average + "점 입니다.");
여기서 (double)sum / scores.Length; 를 하지 않으면 int / int 타입이라서 average를 double로 선언해도 소용이 없다. 그래서 타입 캐스팅을 해주는 것.

namespace ConsoleApp4
{
internal class Program
{
void PrintLine()
{
for (int i = 0; i< 10; i++)
{
Console.WriteLine("=");
}
}
public static void Main(string[] args)
{
Console.WriteLine("Hello, World!");
PrintLine();
}
}
}
PrintLine() 함수는 정확히는 internal class인 Program 밑에 있는 메서드라서 Program.PrintLine() 으로 호출되어야 한다. 그런데 Main함수에 붙은 static은 인스턴스 (Program)를 생성하지 않고 그냥 실행시켜서, 이 PrintLine()이 어떤 클래스의 PrintLine()인지 알 수 없게 된다. 그래서 실행할 수 없는 것.
-> 이건 Program.PrintLine() 이라고 써도 안 된다. 방법은 PrintLine()에다가 static을 붙이면 된다. (Main에서 static을 떼면 빌드 오류가 나기 때문)
static 필드: 클래스에서 딱 하나만 생기고 공유되는 변수
static 메서드: 인스턴스 없이 불러올 수 있는 메서드
non static이면 Program pr = new Program() 이런 식으로 반드시 생성자를 써서, pr.PrintLine() 이런 식으로 호출해줘야 한다.

이렇게 해주면 빨간 줄이 사라진다.
F10을 누르면 콜스택이 메서드를 파고들지 않고 넘어가버린다. 메서드를 파고들고 싶다면 F11을 누르자.
오버로딩: 같은 이름, 다른 동작

이걸 잘 모르겠으면 늘 쓰던 Console.WriteLine() 을 입력해보면 오버로딩 18개를 볼 수 있다.

구조체는 값 형식(Value type) - 어딘가에 할당하거나 대입할 때 순전히 전부 복사가 일어난다. 클래스와 대조되는 성질.
구조체는 struct 키워드를 사용해서 만든다. 필드와 메서드로 이루어져 있다.
구조체도 클래스 비슷하게 구조체이름.필드 또는 구조체이름.메서드 식으로 접근한다.
JAVA의 length나 Javascript의 length를 생각하고 아무 생각없이 이차원배열 map의 map.Length를 for문의 인덱스에 걸어 썼던 나는 틱택토가 박살나는 광경을 보았다.

엙? 찍어본 콘솔에는 map.Length()가 25가 찍히는 것을 보았다. 5*5로 전체 길이를 리턴하고 있었다. 다섯 줄이 있으니까 5가 나올거라는 예상은 잘못 되었다.
이 틱택토 맵의 경우 5개짜리가 5줄이니 뭘 써도 상관 없었다. map.GetLength(0) 으로 i값의 한계를 고치니 터지지 않고 무사히 돌아갔다.
int[,] map = new int[5, 5]
{
{ 1,0,1,1,0},
{ 1,1,0,1,0},
{ 0,1,1,1,0},
{ 1,1,0,1,1},
{ 0,1,1,1,0}
};
for (int i = 0; i < map.GetLength(0); i++)
{
for (int j = 0; j < map.GetLength(0); j++)
{
if (map[i, j] == 1)
{
Console.Write("■");
}
else
{
Console.Write("□");
}
}
Console.WriteLine();
}

-> 아니면 이 문제를 해결하려면 가변배열로 선언하면 된다. C#도 JAVA처럼 int[][] 방식으로 이차원배열을 선언할 수 있는데, 이 방식이 가변배열이다.
이건 아주 옛날에 항해99에서 자바스프링을 공부할 때 영준님이 설명해주신 객체지향과 클래스 강의가 기억나는 내용이다. 골자는 대충 이렇다.
설계도(클래스)를 숨길 순 없다. 그래서 대신 필드랑 메서드를 숨기는거다.
그래서 JAVA의 기본 접근제어자(생략)는 package-private인데, C#은 그냥 private으로 되어 있는 것 같다.

환장하겠네. 참고 블로그를 보면 일반적으로는 4개를 쓰는 것 같다. private, internal, protected, public.