배열과 문자열

배열과 문자열

1. 배열 기초

배열은 같은 타입의 여러 값을 연속된 메모리에 저장합니다.

배열 선언과 초기화

#include <iostream>

int main() {
    // 크기 지정
    int arr1[5];  // 초기화되지 않음 (쓰레기값)

    // 초기화 목록
    int arr2[5] = {1, 2, 3, 4, 5};

    // 부분 초기화 (나머지는 0)
    int arr3[5] = {1, 2};  // {1, 2, 0, 0, 0}

    // 전체 0으로 초기화
    int arr4[5] = {};  // {0, 0, 0, 0, 0}

    // 크기 자동 결정
    int arr5[] = {1, 2, 3};  // 크기 3

    // 출력
    for (int i = 0; i < 5; i++) {
        std::cout << arr2[i] << " ";
    }
    std::cout << std::endl;

    return 0;
}

배열 접근

#include <iostream>

int main() {
    int arr[5] = {10, 20, 30, 40, 50};

    // 읽기
    std::cout << "첫 번째: " << arr[0] << std::endl;  // 10
    std::cout << "세 번째: " << arr[2] << std::endl;  // 30

    // 쓰기
    arr[1] = 200;
    std::cout << "수정 후: " << arr[1] << std::endl;  // 200

    // 범위 기반 for
    for (int num : arr) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    return 0;
}

배열 크기

#include <iostream>

int main() {
    int arr[5] = {1, 2, 3, 4, 5};

    // sizeof로 크기 계산
    int size = sizeof(arr) / sizeof(arr[0]);
    std::cout << "배열 크기: " << size << std::endl;  // 5

    // C++17: std::size
    // #include <iterator>
    // std::cout << std::size(arr) << std::endl;

    return 0;
}

2. 다차원 배열

2차원 배열

#include <iostream>

int main() {
    // 3행 4열
    int matrix[3][4] = {
        {1, 2, 3, 4},
        {5, 6, 7, 8},
        {9, 10, 11, 12}
    };

    // 접근
    std::cout << "matrix[1][2] = " << matrix[1][2] << std::endl;  // 7

    // 전체 출력
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 4; j++) {
            std::cout << matrix[i][j] << "\t";
        }
        std::cout << std::endl;
    }

    return 0;
}

3차원 배열

#include <iostream>

int main() {
    int cube[2][3][4] = {
        {
            {1, 2, 3, 4},
            {5, 6, 7, 8},
            {9, 10, 11, 12}
        },
        {
            {13, 14, 15, 16},
            {17, 18, 19, 20},
            {21, 22, 23, 24}
        }
    };

    std::cout << "cube[1][2][3] = " << cube[1][2][3] << std::endl;  // 24

    return 0;
}

3. std::array (C++11)

크기가 고정된 안전한 배열입니다.

#include <iostream>
#include <array>

int main() {
    std::array<int, 5> arr = {1, 2, 3, 4, 5};

    // 크기
    std::cout << "크기: " << arr.size() << std::endl;

    // 접근
    std::cout << "첫 번째: " << arr[0] << std::endl;
    std::cout << "마지막: " << arr.back() << std::endl;

    // 범위 검사 접근
    std::cout << "arr.at(2): " << arr.at(2) << std::endl;
    // arr.at(10);  // 예외 발생!

    // 범위 기반 for
    for (int num : arr) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    // 채우기
    arr.fill(0);

    return 0;
}

배열 vs std::array

특징 C 배열 std::array
크기 확인 sizeof 계산 .size()
범위 검사 없음 .at()
복사 불가 가능
함수 전달 포인터로 변환 값/참조 전달 가능

4. C 스타일 문자열

문자 배열로 문자열을 표현합니다.

#include <iostream>
#include <cstring>  // strlen, strcpy 등

int main() {
    // 문자열 리터럴
    char str1[] = "Hello";  // {'H', 'e', 'l', 'l', 'o', '\0'}
    char str2[10] = "World";

    // 길이
    std::cout << "길이: " << strlen(str1) << std::endl;  // 5

    // 출력
    std::cout << str1 << std::endl;

    // 문자별 접근
    for (int i = 0; str1[i] != '\0'; i++) {
        std::cout << str1[i] << " ";
    }
    std::cout << std::endl;

    return 0;
}

C 문자열 함수

#include <iostream>
#include <cstring>

int main() {
    char str1[20] = "Hello";
    char str2[20] = "World";
    char dest[40];

    // 복사
    strcpy(dest, str1);
    std::cout << "strcpy: " << dest << std::endl;  // Hello

    // 연결
    strcat(dest, " ");
    strcat(dest, str2);
    std::cout << "strcat: " << dest << std::endl;  // Hello World

    // 비교
    if (strcmp(str1, str2) < 0) {
        std::cout << str1 << " < " << str2 << std::endl;
    }

    // 찾기
    char* pos = strstr(dest, "World");
    if (pos != nullptr) {
        std::cout << "찾음: " << pos << std::endl;  // World
    }

    return 0;
}

5. std::string

C++의 문자열 클래스입니다.

기본 사용

#include <iostream>
#include <string>

int main() {
    // 생성
    std::string s1 = "Hello";
    std::string s2("World");
    std::string s3(5, 'x');  // "xxxxx"

    // 출력
    std::cout << s1 << " " << s2 << std::endl;

    // 길이
    std::cout << "길이: " << s1.length() << std::endl;  // 5
    std::cout << "크기: " << s1.size() << std::endl;    // 5 (동일)

    // 빈 문자열 체크
    std::string empty;
    std::cout << "비어있음: " << empty.empty() << std::endl;  // true

    return 0;
}

문자열 연산

#include <iostream>
#include <string>

int main() {
    std::string s1 = "Hello";
    std::string s2 = "World";

    // 연결
    std::string s3 = s1 + " " + s2;
    std::cout << s3 << std::endl;  // Hello World

    // += 연산
    s1 += "!";
    std::cout << s1 << std::endl;  // Hello!

    // append
    s1.append(" C++");
    std::cout << s1 << std::endl;  // Hello! C++

    // 비교
    if (s1 == "Hello! C++") {
        std::cout << "같음" << std::endl;
    }

    if (s1 < s2) {  // 사전순 비교
        std::cout << s1 << " < " << s2 << std::endl;
    }

    return 0;
}

문자열 접근

#include <iostream>
#include <string>

int main() {
    std::string str = "Hello";

    // 인덱스 접근
    std::cout << "첫 문자: " << str[0] << std::endl;  // H
    std::cout << "마지막: " << str.back() << std::endl;  // o

    // 범위 검사 접근
    std::cout << "at(1): " << str.at(1) << std::endl;  // e

    // 수정
    str[0] = 'h';
    std::cout << str << std::endl;  // hello

    // 범위 기반 for
    for (char c : str) {
        std::cout << c << " ";
    }
    std::cout << std::endl;

    return 0;
}

부분 문자열

#include <iostream>
#include <string>

int main() {
    std::string str = "Hello, World!";

    // 부분 문자열 추출
    std::string sub = str.substr(7, 5);  // 위치 7부터 5글자
    std::cout << sub << std::endl;  // World

    // 위치부터 끝까지
    std::string rest = str.substr(7);
    std::cout << rest << std::endl;  // World!

    return 0;
}

검색

#include <iostream>
#include <string>

int main() {
    std::string str = "Hello, World!";

    // 찾기
    size_t pos = str.find("World");
    if (pos != std::string::npos) {
        std::cout << "위치: " << pos << std::endl;  // 7
    }

    // 문자 찾기
    pos = str.find('o');
    std::cout << "첫 번째 o: " << pos << std::endl;  // 4

    // 뒤에서 찾기
    pos = str.rfind('o');
    std::cout << "마지막 o: " << pos << std::endl;  // 8

    // 못 찾은 경우
    pos = str.find("xyz");
    if (pos == std::string::npos) {
        std::cout << "찾지 못함" << std::endl;
    }

    return 0;
}

수정

#include <iostream>
#include <string>

int main() {
    std::string str = "Hello, World!";

    // 삽입
    str.insert(7, "Beautiful ");
    std::cout << str << std::endl;  // Hello, Beautiful World!

    // 삭제
    str.erase(7, 10);  // 위치 7부터 10글자 삭제
    std::cout << str << std::endl;  // Hello, World!

    // 교체
    str.replace(7, 5, "C++");  // World를 C++로
    std::cout << str << std::endl;  // Hello, C++!

    // 지우기
    str.clear();
    std::cout << "비어있음: " << str.empty() << std::endl;

    return 0;
}

6. 문자열 변환

숫자 ↔ 문자열

#include <iostream>
#include <string>

int main() {
    // 숫자 → 문자열
    int num = 42;
    std::string str1 = std::to_string(num);
    std::cout << "to_string: " << str1 << std::endl;

    double pi = 3.14159;
    std::string str2 = std::to_string(pi);
    std::cout << "to_string: " << str2 << std::endl;

    // 문자열 → 숫자
    std::string s1 = "123";
    int n1 = std::stoi(s1);
    std::cout << "stoi: " << n1 << std::endl;

    std::string s2 = "3.14";
    double d1 = std::stod(s2);
    std::cout << "stod: " << d1 << std::endl;

    // 다른 변환 함수
    // std::stol - long
    // std::stoll - long long
    // std::stof - float

    return 0;
}

문자 변환

#include <iostream>
#include <cctype>
#include <string>

int main() {
    char c = 'a';

    // 대소문자 변환
    std::cout << "대문자: " << (char)std::toupper(c) << std::endl;  // A

    c = 'Z';
    std::cout << "소문자: " << (char)std::tolower(c) << std::endl;  // z

    // 문자 검사
    std::cout << std::boolalpha;
    std::cout << "isalpha('A'): " << (bool)std::isalpha('A') << std::endl;  // true
    std::cout << "isdigit('5'): " << (bool)std::isdigit('5') << std::endl;  // true
    std::cout << "isspace(' '): " << (bool)std::isspace(' ') << std::endl;  // true

    // 문자열 전체 대문자로
    std::string str = "Hello World";
    for (char& c : str) {
        c = std::toupper(c);
    }
    std::cout << str << std::endl;  // HELLO WORLD

    return 0;
}

7. 문자열 입력

#include <iostream>
#include <string>

int main() {
    std::string word;
    std::string line;

    // 단어 입력 (공백 전까지)
    std::cout << "단어 입력: ";
    std::cin >> word;
    std::cout << "입력: " << word << std::endl;

    // 버퍼 비우기
    std::cin.ignore();

    // 줄 전체 입력
    std::cout << "문장 입력: ";
    std::getline(std::cin, line);
    std::cout << "입력: " << line << std::endl;

    return 0;
}

8. 문자열 분리

#include <iostream>
#include <string>
#include <sstream>
#include <vector>

int main() {
    std::string str = "apple,banana,cherry,date";

    // stringstream 사용
    std::stringstream ss(str);
    std::string token;
    std::vector<std::string> tokens;

    while (std::getline(ss, token, ',')) {
        tokens.push_back(token);
    }

    for (const auto& t : tokens) {
        std::cout << t << std::endl;
    }

    return 0;
}

9. string_view (C++17)

문자열을 복사 없이 참조합니다.

#include <iostream>
#include <string>
#include <string_view>

void print(std::string_view sv) {
    std::cout << sv << std::endl;
}

int main() {
    std::string str = "Hello, World!";
    const char* cstr = "C-style string";

    // 다양한 문자열 타입을 받을 수 있음
    print(str);
    print(cstr);
    print("Literal");

    // 부분 문자열도 복사 없이
    std::string_view sv = str;
    std::cout << sv.substr(0, 5) << std::endl;  // Hello

    return 0;
}

10. 실습 예제

문자열 뒤집기

#include <iostream>
#include <string>
#include <algorithm>

int main() {
    std::string str = "Hello";

    // 방법 1: reverse 함수
    std::reverse(str.begin(), str.end());
    std::cout << str << std::endl;  // olleH

    // 방법 2: 직접 구현
    str = "World";
    int len = str.length();
    for (int i = 0; i < len / 2; i++) {
        std::swap(str[i], str[len - 1 - i]);
    }
    std::cout << str << std::endl;  // dlroW

    return 0;
}

팰린드롬 검사

#include <iostream>
#include <string>
#include <algorithm>

bool isPalindrome(const std::string& str) {
    std::string reversed = str;
    std::reverse(reversed.begin(), reversed.end());
    return str == reversed;
}

int main() {
    std::cout << std::boolalpha;
    std::cout << isPalindrome("radar") << std::endl;  // true
    std::cout << isPalindrome("hello") << std::endl;  // false
    return 0;
}

단어 개수 세기

#include <iostream>
#include <string>
#include <sstream>

int countWords(const std::string& str) {
    std::stringstream ss(str);
    std::string word;
    int count = 0;

    while (ss >> word) {
        count++;
    }

    return count;
}

int main() {
    std::string text = "Hello World this is C++";
    std::cout << "단어 수: " << countWords(text) << std::endl;  // 5
    return 0;
}

11. 요약

종류 특징
C 배열 T[] 고정 크기, 경계 검사 없음
std::array<T, N> 고정 크기, 안전함
C 문자열 char[] null 종료, 수동 관리
std::string 동적 크기, 자동 관리
std::string_view 읽기 전용 참조
std::string 메서드 설명
length(), size() 길이
empty() 비어있는지
substr(pos, len) 부분 문자열
find(str) 검색
replace(pos, len, str) 교체
insert(pos, str) 삽입
erase(pos, len) 삭제

다음 단계

06_Pointers_and_References.md에서 포인터와 참조를 배워봅시다!

to navigate between lessons