배열, 문자열1

이정현
∙∙조회 2

20261001 배열, 문자열1

배열(2차원배열)

행과 열로 이루어진 배열. 표 모양의 데이터라고 보면된다. 2차원 배열은 대괄호 안에 쉼표를 넣어 선언하고, [행, 열]로 칸을 지정한다.

csharp
// 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]}");

css
출력 결과

int[2, 3]
          [,0]     [,1]     [,2]
        ┌────────┬────────┬────────┐
  [0,]  │   1    │   2    │   3    │
        ├────────┼────────┼────────┤
  [1,]  │   4    │   5    │   6    │
        └────────┴────────┴────────┘

GetLength

Length는 2차원 배열에서 전체 칸 수를 돌려준다. 행 수와 열 수는 각각 구해야 한다.

csharp
//행 수와 열 수를 각각 구해오는 예시
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차원 배열도 순회 할 수 있다. 다만 행 구분 없이 모든칸을 순서대로 순환한다.

csharp
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차원 배열은 모든 행의 열 개수가 같아야 한다. 그래서 행마다 개수가 다른 데이터에는 가변배열을 사용한다. [][]이런식으로 쓴다. [,]와는 다르다.
csharp
//가변 배열 예시
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

같은 문장이라도 소스코드에 적는 방법은 여러가지이다.

표기이름이스케이프 해석값 삽입
"..."일반 문자열OX
@"..."축차 문자열XX
$"..."보간 문자열OO
$@"..."축차 + 보간XO

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진수 네 자리로 문자를 지정

축차 문자열

문자열의 앞에 @를 붙이면 이스케이프 시퀀스를 해석하지 않고 적힌 그대로 다룸. 백슬래시가 많은 경로에서 편함.

csharp
// 위와 아래가 같은 결과가 나옴
string path1 = "C:\\Users\\Player\\Documents\\save.dat";
string path2 = @"C:\Users\Player\Documents\save.dat";

줄바꿈도 적힌대로 유지됨

csharp
string help = @"사용법
  move  이동
  hit   공격
  quit  종료";

큰따옴표는 2개씩 적어주어야 한다.

csharp
string quoted = @"그가 ""안녕""이라고 말함";
string wrongWay = @"백슬래시 방식: \""안녕\""";

보간 문자열

값을 문장에 끼워넣을 때 사용

csharp
using System;

string name = "홍길동";
int level = 15;

Console.WriteLine("이름: " + name + ", 레벨: " + level);      // 이어 붙이기
Console.WriteLine($"이름: {name}, 레벨: {level}");            // 보간

중괄호 안에는 식, 조건 연산자 모두 넣을 수 있다. 중괄호 자체를 출력하기 위해선 큰따옴표처럼 중괄호를 두번 연속으로 적어주어야 한다.

csharp
using System;

int hp = 15;

Console.WriteLine($"중괄호: {{{hp}}}");
Console.WriteLine($"빈 중괄호: {{}}");
Console.WriteLine($"코드 모양: if (hp > 0) {{ ... }}");

자리폭 맞추기

값 뒤에 폭을 적으면 자리 폭을 맞출 수 있다.({값, 폭}) 단 값이 폭보다 길면 폭을 무시하고 모두 출력된다.(잘리지 않음)

표기뜻
{값,10}폭10, 오른쪽정렬(앞에 10만큼 공백)
{값,-10}폭10, 왼쪽정렬(뒤에 10만큼 공백)
{값}값의 길이만큼만
  • 주의사항: 폭은 글자 수로 셈. 한글은 콘솔에서 두칸을 차지하지만 글자 수로는 1이므로, 한글과 영문을 같은 열에 섞으면 화면에서는 열이 어긋나 보임.
csharp
이렇게 영문과 한글을 섞어서 작성하면
Console.WriteLine($"{"Sword",-10}{1200,8}");
Console.WriteLine($"{"검",-10}{1200,8}");

출력할 때 아래처럼 보이게 된다.
Sword         1200
검             1200

구분선 만들기

같은 문자로 폭만큼 채우려면new string(문자, 개수)를 쓰면 된다.

csharp
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.57
    F0, F2소수 자릿수 지정(구분 없음)1235, 1234.57
    P0, P1백분율(100을 곱하고 %)123457%, 123456.8%
    D5정수를 자릿수만큼 0으로 채움정수에만
    X, X416진수정수에만
    C통화지역 설정을 따름
  • 정수 서식

  • 백분율

  • 폭과 서식을 함께 쓰기

  • 지역 설정에 따라 달라지는 서식

  • 반올림 유효하지 않은 서식문자는 무시된다.

축차와 보간을 함께 쓰기

$@표기

csharp
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}을 적고 값은 뒤에 순서대로 나열한다.

csharp
using System;

Console.WriteLine("이름: {0}, 레벨: {1}", "홍길동", 15);

  • 주의사항: 없는 번호를 적으면 실행 중 오류가 발생한다.
csharp
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형을 반환한다.

csharp
string text = "Hello";
char first = text[0]; // <- char 반환

  • index를 사용하여 접근시 범위를 벗어나면 실행 중 오류가 발생한다.
  • string은 인덱스로는 읽기만 가능하고 쓰기는 안된다.(컴파일 오류)
  • 한글자만 바꾸고 싶은 경우 새 문자열을 만들어야 한다.
csharp

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를 다루는 메서드로 글자를 바꿔서 이어 붙일 수 있음

csharp
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은 앞뒤 공백을 제거함

csharp
using System;

string text = "   Hello, World!   ";

Console.WriteLine($"원본      [{text}]");
Console.WriteLine($"Trim      [{text.Trim()}]");
Console.WriteLine($"TrimStart [{text.TrimStart()}]");
Console.WriteLine($"TrimEnd   [{text.TrimEnd()}]");

특정 문자를 지정해 깎을 수도 있음

csharp
using System;

string wrapped = "***중요***";
string path = "///home///";

Console.WriteLine(wrapped.Trim('*'));
Console.WriteLine(path.Trim('/'));
Console.WriteLine("xxyyHELLOyyxx".Trim('x', 'y'));

PadLeft와 PadRight

원하는 길이가 되도록 채워넣은 결과 문자열을 반환한다.

  • 자리 폭 지정처럼 출력 모양만 정하는 것과 다르다.
csharp
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을 반환하므로 인덱스로 바로 사용하기 전에 확인을 해야함.

csharp
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와 짝을지어 쓰면 구분자 앞뒤를 나눌 수 있음.
csharp
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)}");

결과는 아래와 같이 나온다.

makefile
폴더: D:\Projects\MyGame
파일: player.png
이름: player
확장자: png

Replace

찾은 것을 모두 바꿈. 하나만 바꾸는 것이 아니라 전부 바꿈. 원본은 그대로임. 결과값을 쓰려면 따로 받아 두어야 함.

  • 주의: 전부 바뀌기 때문에 잘못다루면 엉뚱한 값이 변경된다.

Remove와 Insert

Remove와 Insert의 첫 인수는 시작 인덱스임. Remove의 두 번째 인수는 지울 코드 단위의 개수이며, Insert의 두 번째 인수는 끼워 넣을 문자열임.