배열, 문자열1
20261001 배열, 문자열1
배열(2차원배열)
행과 열로 이루어진 배열. 표 모양의 데이터라고 보면된다.
2차원 배열은 대괄호 안에 쉼표를 넣어 선언하고, [행, 열]로 칸을 지정한다.
// 2차원배열 선언 예시
using System;
int[,] matrix = new int[2, 3]; // 2행 3열
matrix[0, 0] = 1;
matrix[0, 1] = 2;
matrix[0, 2] = 3;
matrix[1, 0] = 4;
matrix[1, 1] = 5;
matrix[1, 2] = 6;
Console.WriteLine($"0행 1열: {matrix[0, 1]}");
Console.WriteLine($"1행 2열: {matrix[1, 2]}");
출력 결과
int[2, 3]
[,0] [,1] [,2]
┌────────┬────────┬────────┐
[0,] │ 1 │ 2 │ 3 │
├────────┼────────┼────────┤
[1,] │ 4 │ 5 │ 6 │
└────────┴────────┴────────┘
GetLength
Length는 2차원 배열에서 전체 칸 수를 돌려준다. 행 수와 열 수는 각각 구해야 한다.
//행 수와 열 수를 각각 구해오는 예시
using System;
int[,] scores =
{
{ 90, 85, 77 },
{ 60, 72, 88 }
};
Console.WriteLine($"전체 칸 수: {scores.Length}");
Console.WriteLine($"행 수: {scores.GetLength(0)}");
Console.WriteLine($"열 수: {scores.GetLength(1)}");
입력하는 변수는 각 배열의 순서로 만약 3차원 배열일 경우
[0,1,2] 각 자릿수의 크기를 구해온다고 상각 하면 된다.
각 항목을 랭크라고 부른다.
2차원 배열에서의 foreach
foreach로 2차원 배열도 순회 할 수 있다. 다만 행 구분 없이 모든칸을 순서대로 순환한다.
using System;
int[,] scores =
{
{ 90, 85, 77 },
{ 60, 72, 88 }
};
foreach (int score in scores)
{
Console.Write($"{score} ");
}
Console.WriteLine();
위 예시를 실행하면 90 85 77 60 72 88 이와 같이 출력된다.
가변 배열
행마다 길이가 다른 배열.
- 2차원 배열은 모든 행의 열 개수가 같아야 한다.
그래서 행마다 개수가 다른 데이터에는 가변배열을 사용한다.
[][]이런식으로 쓴다.[,]와는 다르다.
//가변 배열 예시
using System;
int[][] jagged = new int[3][]; // 행 3개짜리 틀
jagged[0] = new int[] { 1, 2, 3, 4, 5 };
jagged[1] = new int[] { 6, 7 };
jagged[2] = new int[] { 8, 9, 10 };
for (int i = 0; i < jagged.Length; i++)
{
Console.Write($"{i} 행 ({jagged[i].Length} 칸): ");
for (int j = 0; j < jagged[i].Length; j++)
{
Console.Write($"{jagged[i][j]} ");
}
Console.WriteLine();
}
2차원 배열 처럼 가변 배열도 foreach문을 사용할 수 있다.
문자열1
같은 문장이라도 소스코드에 적는 방법은 여러가지이다.
| 표기 | 이름 | 이스케이프 해석 | 값 삽입 |
|---|---|---|---|
"..." | 일반 문자열 | O | X |
@"..." | 축차 문자열 | X | X |
$"..." | 보간 문자열 | O | O |
$@"..." | 축차 + 보간 | X | O |
flowchart TD A[문자열을 적어야 함] --> B{백슬래시가 많은가} B -->|예| C{값을 끼워야 하는가} B -->|아니오| D{값을 끼워야 하는가} C -->|예| E["$@"...""] C -->|아니오| F["@"...""] D -->|예| G["$"...""] D -->|아니오| H[""...""]
이스케이프시퀀스 표
| 시퀀스 | 뜻 | 쓰는 자리 |
|---|---|---|
\n | 줄바꿈 | 한 문자열 안에서 줄을 나눌 때 |
\t | 탭 | 칸을 맞춰 늘어놓을 때 |
\\ | 백슬래시 자체 | 파일 경로, 정규 표현식 |
\" | 큰따옴표 자체 | 문자열 안의 인용 |
\' | 작은따옴표 자체 | char리터럴에서 |
\r | 캐리지 리턴 | 커서를 줄의 맨 앞으로 되돌림(되돌린 후 입력되는 값은 덮어써짐) |
\0 | 널문자 | 값이 0인 문자이며 빈 문자열과 다름 |
\a | 경고음 | 콘솔에서 소리를 냄 |
\b | 백스페이스 | 한 칸 되돌림 |
\uXXXX | 유니코드 문자 | 16진수 네 자리로 문자를 지정 |
축차 문자열
문자열의 앞에 @를 붙이면 이스케이프 시퀀스를 해석하지 않고 적힌 그대로 다룸.
백슬래시가 많은 경로에서 편함.
// 위와 아래가 같은 결과가 나옴
string path1 = "C:\\Users\\Player\\Documents\\save.dat";
string path2 = @"C:\Users\Player\Documents\save.dat";
줄바꿈도 적힌대로 유지됨
string help = @"사용법
move 이동
hit 공격
quit 종료";
큰따옴표는 2개씩 적어주어야 한다.
string quoted = @"그가 ""안녕""이라고 말함";
string wrongWay = @"백슬래시 방식: \""안녕\""";
보간 문자열
값을 문장에 끼워넣을 때 사용
using System;
string name = "홍길동";
int level = 15;
Console.WriteLine("이름: " + name + ", 레벨: " + level); // 이어 붙이기
Console.WriteLine($"이름: {name}, 레벨: {level}"); // 보간
중괄호 안에는 식, 조건 연산자 모두 넣을 수 있다. 중괄호 자체를 출력하기 위해선 큰따옴표처럼 중괄호를 두번 연속으로 적어주어야 한다.
using System;
int hp = 15;
Console.WriteLine($"중괄호: {{{hp}}}");
Console.WriteLine($"빈 중괄호: {{}}");
Console.WriteLine($"코드 모양: if (hp > 0) {{ ... }}");
자리폭 맞추기
값 뒤에 폭을 적으면 자리 폭을 맞출 수 있다.({값, 폭})
단 값이 폭보다 길면 폭을 무시하고 모두 출력된다.(잘리지 않음)
| 표기 | 뜻 |
|---|---|
{값,10} | 폭10, 오른쪽정렬(앞에 10만큼 공백) |
{값,-10} | 폭10, 왼쪽정렬(뒤에 10만큼 공백) |
{값} | 값의 길이만큼만 |
- 주의사항: 폭은 글자 수로 셈. 한글은 콘솔에서 두칸을 차지하지만 글자 수로는 1이므로, 한글과 영문을 같은 열에 섞으면 화면에서는 열이 어긋나 보임.
이렇게 영문과 한글을 섞어서 작성하면
Console.WriteLine($"{"Sword",-10}{1200,8}");
Console.WriteLine($"{"검",-10}{1200,8}");
출력할 때 아래처럼 보이게 된다.
Sword 1200
검 1200
구분선 만들기
같은 문자로 폭만큼 채우려면new string(문자, 개수)를 쓰면 된다.
using System;
Console.WriteLine(new string('=', 30));
Console.WriteLine($"{"결과",-10}{"값",10}");
Console.WriteLine(new string('-', 30));
Console.WriteLine($"{"합계",-10}{432,10}");
Console.WriteLine($"{"평균",-10}{86.4,10}");
Console.WriteLine(new string('=', 30));
서식 지정
-
값 서식: 중괄호 안에
값:서식형태로 적으면 정해진 모양으로 바꿔서 표기한다. 폭과 함께 쓸 때는값,폭:서식순서다.서식 뜻 예( 1234.5679)N0, N2천 단위 구분, 소수 자릿수 지정 1,235,1,234.57F0, F2소수 자릿수 지정(구분 없음) 1235,1234.57P0, P1백분율(100을 곱하고 %) 123457%,123456.8%D5정수를 자릿수만큼 0으로 채움 정수에만 X, X416진수 정수에만 C통화 지역 설정을 따름 -
정수 서식
-
백분율
-
폭과 서식을 함께 쓰기
-
지역 설정에 따라 달라지는 서식
-
반올림 유효하지 않은 서식문자는 무시된다.
축차와 보간을 함께 쓰기
$@표기
using System;
string userName = "Player";
string fileName = "slot1.dat";
string savePath = $@"C:\Users\{userName}\Documents\MyGame\{fileName}";
Console.WriteLine(savePath);
String.Format
{0}표기: 보간 문자열이 생기기 전에 사용하던 자리 표시자다.
문자열에 {0}, {1}을 적고 값은 뒤에 순서대로 나열한다.
using System;
Console.WriteLine("이름: {0}, 레벨: {1}", "홍길동", 15);
- 주의사항: 없는 번호를 적으면 실행 중 오류가 발생한다.
using System;
Console.WriteLine("{0} {1}", "하나"); // 1번 값이 없음
문자열2
이미 있는 문자열을 조사하고 가공하기 위한 string의 메서드들.
| 하는 일 | 수단 |
|---|---|
| 문자 하나씩 보기 | Length, [인덱스], foreach |
| 모양 다듬기 | ToUpper, ToLower, Trim, PadLeft |
| 찾기 | IndexOf, LastIndexOf, Contains, StartWith, EndsWith |
| 비교하기 | ==, Equals, Compare |
| 잘라내고 바꾸기 | Substring, Replace, Remove, Insert |
| 나누고 합치기 | Split, Join, Concat, ToCharArray |
| 검사하기 | IsNullOrEmpty, IsNullOrWhiteSpace |
| 반복해서 이어 붙이기 | StringBuilder |
참고: 문자열을 바꾸는 메서드는 원본을 바꾸지 않고 새 문자열을 돌려줌
문자 하나씩 다루기
문자열을 인덱스로 접근해서 데이터를 받아오면 char형을 반환한다.
string text = "Hello";
char first = text[0]; // <- char 반환
- index를 사용하여 접근시 범위를 벗어나면 실행 중 오류가 발생한다.
- string은 인덱스로는 읽기만 가능하고 쓰기는 안된다.(컴파일 오류)
- 한글자만 바꾸고 싶은 경우 새 문자열을 만들어야 한다.
string text = "Hello";
string changed = "J" + text.Substring(1);
foreach로 글자를 순회
문자열은 글자를 차례로 꺼낼 수 있으므로 foreach가 그대로 통한다.
char 판별 메서드
char에는 글자가 어떤 종류인지 알려주는 메서드가 있음. 문자열을 한글자씩 훑어 분류할 떄 사용.
| 메서드 | 참인 경우 |
|---|---|
char.IsLetter(c) | 글자(한글, 영문 모두) |
char.IsDigit(c) | 숫자 0~9 |
char.IsLetterOrDigit(c) | 글자 또는 숫자 |
char.IsWhiteSpace(c) | 공백, 탭, 줄바꿈 |
char.IsUpper(c), char.IsLower(c) | 대문자, 소문자 |
char.IsPunctuation(c) | 마침표, 쉼표 같은 문장 부호 |
글자를 바꿔 새 문자열 만들기
char를 다루는 메서드로 글자를 바꿔서 이어 붙일 수 있음
using System;
string text = "Hello World";
string swapped = "";
foreach (char c in text)
{
if (char.IsUpper(c))
{
swapped += char.ToLower(c);
}
else if (char.IsLower(c))
{
swapped += char.ToUpper(c);
}
else
{
swapped += c;
}
}
Console.WriteLine($"원본: {text}");
Console.WriteLine($"뒤바꿈: {swapped}");
Trim으로 공백 제거
사용자가 입력한 값에는 앞뒤 공백이 섞이기 쉬움. Trim은 앞뒤 공백을 제거함
using System;
string text = " Hello, World! ";
Console.WriteLine($"원본 [{text}]");
Console.WriteLine($"Trim [{text.Trim()}]");
Console.WriteLine($"TrimStart [{text.TrimStart()}]");
Console.WriteLine($"TrimEnd [{text.TrimEnd()}]");
특정 문자를 지정해 깎을 수도 있음
using System;
string wrapped = "***중요***";
string path = "///home///";
Console.WriteLine(wrapped.Trim('*'));
Console.WriteLine(path.Trim('/'));
Console.WriteLine("xxyyHELLOyyxx".Trim('x', 'y'));
PadLeft와 PadRight
원하는 길이가 되도록 채워넣은 결과 문자열을 반환한다.
- 자리 폭 지정처럼 출력 모양만 정하는 것과 다르다.
using System;
string label = "42";
Console.WriteLine($"[{label.PadLeft(8)}]");
Console.WriteLine($"[{label.PadRight(8)}]");
Console.WriteLine($"[{label.PadLeft(8, '0')}]");
Console.WriteLine($"[{label.PadRight(8, '.')}]");
Console.WriteLine($"길이: {label.PadLeft(8).Length}");
IsNullOrEmpty와 IsNullOrWhiteSpace
IsNullOrEmpty: 값이 없거나 "". IsNullOrWhiteSpace: 값이 없거나 "" 또는 공백만 있는지도 확인.
찾기
IndexOf와 LastIndexOf
문자나 문자열이 몇 번째 자리에 있는지 알려줌. 없으면 -1을 돌려줌
없을 때 -1을 반환하므로 인덱스로 바로 사용하기 전에 확인을 해야함.
using System;
string text = "Hello, World!";
Console.WriteLine($"첫 'o': {text.IndexOf('o')}");
Console.WriteLine($"마지막 'o': {text.LastIndexOf('o')}");
Console.WriteLine($"\"World\": {text.IndexOf("World")}");
Console.WriteLine($"없는 것: {text.IndexOf('z')}");
Contains, StartsWith, EndsWith
index위치가 아니라 있는지 없는지만 필요하면 Contains가 뜻이 분명함
비교
==
문자열 끼리는 ==로 내용을 비교함. 대소문자를 가린다.
Equals로 대소문자 무시
대소문자를 무시하고 비교하려면 Equals에 비교식을 함께 넘김.
ToLower로 맞추는 것과 결과는 비슷하지만 새 문자열을 만들지 않음.
Compare로 순서 비교
같은지 다른지가 아니라 어느 것이 앞인지 알아야 할 때 사용함. 결과의 부호로 판단함.
- 주의: 부호만 정해져 있고 숫자의 크기는 정해져 있지 않음.
잘라내기와 바꾸기
Substring
시작위치부터 끝까지, 또는 시작 위치부터 몇 글자를 뗴어낼 수 있다.
- 주의: 범위를 넘기면 실행중 오류가 남 indexOf와 짝을지어 쓰면 구분자 앞뒤를 나눌 수 있음.
using System;
string path = @"D:\Projects\MyGame\player.png";
int lastSlash = path.LastIndexOf('\\');
int lastDot = path.LastIndexOf('.');
Console.WriteLine($"폴더: {path.Substring(0, lastSlash)}");
Console.WriteLine($"파일: {path.Substring(lastSlash + 1)}");
Console.WriteLine($"이름: {path.Substring(lastSlash + 1, lastDot - lastSlash - 1)}");
Console.WriteLine($"확장자: {path.Substring(lastDot + 1)}");
결과는 아래와 같이 나온다.
폴더: D:\Projects\MyGame
파일: player.png
이름: player
확장자: png
Replace
찾은 것을 모두 바꿈. 하나만 바꾸는 것이 아니라 전부 바꿈. 원본은 그대로임. 결과값을 쓰려면 따로 받아 두어야 함.
- 주의: 전부 바뀌기 때문에 잘못다루면 엉뚱한 값이 변경된다.
Remove와 Insert
Remove와 Insert의 첫 인수는 시작 인덱스임. Remove의 두 번째 인수는 지울 코드 단위의 개수이며, Insert의 두 번째 인수는 끼워 넣을 문자열임.



