반응형

윈도우에서 UTF-8 with BOM 파일을 찾아 모두   UTF-8 without BOM 형식으로 변환하기.

아래에서 첫 번째에 최상위 경로를 주고 powershell에서 실행하면 일괄로 변경한다. 

 

$targetFolder = "data"  # 변환할 최상위 폴더 경로

# UTF-8 BOM 3바이트 시퀀스
$utf8BOM = [byte[]](0xEF,0xBB,0xBF)

# 대상 폴더 내 모든 파일 재귀 탐색
Get-ChildItem -Path $targetFolder -File -Recurse | ForEach-Object {
    $file = $_.FullName

    # 파일을 바이트 단위로 읽기
    $bytes = [System.IO.File]::ReadAllBytes($file)

    # BOM 존재 여부 체크
    if ($bytes.Length -ge 3 -and $bytes[0] -eq $utf8BOM[0] -and $bytes[1] -eq $utf8BOM[1] -and $bytes[2] -eq $utf8BOM[2]) {
        Write-Host "BOM 발견 및 제거 중: $file"

        # BOM 제거한 바이트 배열 생성
        $bytesWithoutBOM = $bytes[3..($bytes.Length - 1)]

        # BOM 제거된 바이트를 임시 파일에 기록
        $tempFile = [System.IO.Path]::GetTempFileName()
        [System.IO.File]::WriteAllBytes($tempFile, $bytesWithoutBOM)

        # 임시 파일을 원본 파일로 덮어쓰기
        Move-Item -Path $tempFile -Destination $file -Force
    }
    else {
        Write-Host "BOM 없음: $file"
    }
}

 

이 시스템에서 스크립트를 실행할 수 없으므로 ~~~파일을 로드할 수 없습니다. 라고 에러가 나면.

관리자 모드 powershell에서

Set-ExecutionPolicy RemoteSigned

 

 

반응형

std::optional이 필요한가요?

C++에서는 전통적으로 "값이 없음을 나타내는" 방법이 마땅치 않았어요.

  • 포인터일 경우는 nullptr로 표현할 수 있었지만,
  • 값 타입(int, double, struct 등)에서는 특별한 값을 정하거나 별도 플래그를 둬야 했죠.

이런 문제를 해결하기 위해 optional이 등장했어요.

std::optional 이란?

std::optional<T>는 T 타입의 값을 가질 수도 있고, 안 가질 수도 있는 컨테이너입니다.

#include <optional>

std::optional<int> maybeGetValue(bool condition) {
    if (condition)
        return 42;
    else
        return std::nullopt;  // 아무 값도 없음
}

 


 주요 특징 정리

기능설명
std::optional<T> T 타입의 optional 객체 생성
std::nullopt 값이 없음을 표현하는 상수
.has_value() or if (opt) 값이 있는지 확인
.value() 값을 가져옴 (값이 없으면 예외 발생)
.value_or(default) 값이 있으면 그 값, 없으면 기본값 반환
*opt or opt.value() 값에 접근 (값이 있어야 안전함)

사용 예제

#include <iostream>
#include <optional>
#include <string>

std::optional<std::string> findNameById(int id) {
    if (id == 1)
        return "Alice";
    else
        return std::nullopt;
}

int main() {
    auto name = findNameById(2);

    if (name.has_value()) {
        std::cout << "이름: " << *name << "\n";
    } else {
        std::cout << "이름을 찾을 수 없습니다.\n";
    }

    return 0;
}

언제 쓰면 좋을까?

  • 함수에서 값을 반환할 수도, 안 할 수도 있는 경우 (null 대신)
  • 포인터를 쓰지 않고도 값 없음(null) 상태 표현 가능
  • std::optional<T>는 T가 복사/이동 가능한 타입일 때 사용 가능

C++에서 Optional은 어떤 점이 좋을까?

  • 명시적이고 타입 안정성 있음 (null pointer 같은 오류 줄임)
  • 함수 인터페이스가 더 직관적이고 안전해짐
  • null 체크나 특별한 에러코드를 리턴하는 방식보다 표현력이 풍부함

'Develop > C&CPP' 카테고리의 다른 글

[cpp] thread  (0) 2025.04.20
[cpp] atomic  (0) 2025.04.20
[cpp] mutex, lock  (0) 2025.04.20
[cpp] cpp17에서 달라진 점  (0) 2025.04.20
[cpp] cpp14에서 추가된 것  (0) 2025.04.20
반응형

std::thread 사용법 정리 (C++17 기준)

1. 기본 개념

  • C++11부터 도입된 std::thread는 병렬 실행을 위한 클래스입니다.
  • 쓰레드를 생성하면 자동으로 시작되며, 작업이 끝날 때까지 join() 또는 detach() 호출로 관리해야 합니다.

2. 기본 예제

#include <iostream>
#include <thread>

void say_hello() {
    std::cout << "Hello from thread!" << std::endl;
}

int main() {
    std::thread t(say_hello); // 쓰레드 시작
    t.join();                 // 메인 쓰레드가 t를 기다림
}
  • join()이 없으면 프로그램이 끝나기 전에 쓰레드가 종료되지 않을 수 있어 런타임 오류 발생.

3. 인자 전달

void print_sum(int a, int b) {
    std::cout << a + b << std::endl;
}

int main() {
    std::thread t(print_sum, 3, 4);
    t.join();
}
  • 값은 복사되어 전달됩니다.
  • 참조를 넘기려면 std::ref() 사용
void modify(int& x) {
    x += 10;
}

int main() {
    int value = 5;
    std::thread t(modify, std::ref(value));
    t.join();
    std::cout << value << std::endl; // 15
}

4. 람다 함수 사용

std::thread t([](){
    std::cout << "Running in a lambda thread!" << std::endl;
});
t.join();

5. 멤버 함수 호출

class Worker {
public:
    void run() {
        std::cout << "Worker running!" << std::endl;
    }
};

int main() {
    Worker w;
    std::thread t(&Worker::run, &w); // 객체 포인터 전달
    t.join();
}

6. join() vs detach()

  • join(): 쓰레드가 끝날 때까지 기다림
  • detach(): 쓰레드를 백그라운드에서 실행시키고 제어를 넘김
std::thread t([]() {
    std::this_thread::sleep_for(std::chrono::seconds(1));
    std::cout << "Detached thread done" << std::endl;
});
t.detach(); // join하지 않아도 됨

주의: detach한 쓰레드는 더 이상 제어할 수 없으며, 메인 함수가 먼저 종료되면 문제가 생길 수 있음.


7. 쓰레드 ID 확인

 
std::cout << std::this_thread::get_id() << std::endl;

8. 쓰레드 관련 함수들

  • std::this_thread::sleep_for(duration): 일정 시간 동안 sleep
  • std::this_thread::yield(): 다른 쓰레드에게 CPU 양보
  • std::thread::hardware_concurrency(): 시스템의 논리 코어 수 반환

9. 예외 처리

std::thread 자체는 예외를 전달하지 않기 때문에, 예외는 쓰레드 내부에서 처리해야 합니다.

std::thread t([]() {
    try {
        throw std::runtime_error("error!");
    } catch (const std::exception& e) {
        std::cout << "Caught exception: " << e.what() << std::endl;
    }
});
t.join();

10. C++17에서 유용한 추가 기능

  • std::scoped_lock을 쓰레드와 뮤텍스에 함께 사용 가능
  • std::shared_mutex (읽기/쓰기 락)과 함께 사용 시 성능 최적화 가능
  • 쓰레드 안전한 std::atomic 변수와 병행 사용

 

std::shared_mutex란?

  • 동시에 여러 개의 쓰레드가 읽을 수 있도록 허용하지만,
  • 쓰기(수정) 시에는 단 하나의 쓰레드만 접근 가능하게 만드는 락입니다.

읽기: 병렬 허용
쓰기: 단독만 허용

예: std::mutex와 std::shared_mutex의 차이

일반 std::mutex 사용 시

cpp
std::mutex mtx; void read() {
std::lock_guard<std::mutex> lock(mtx); // 읽기 작업
}

읽기조차 직렬화됨 (읽기끼리도 동시에 접근 불가)


std::shared_mutex 사용 시

#include <shared_mutex>

std::shared_mutex shared_mtx;

void read() {
    std::shared_lock<std::shared_mutex> lock(shared_mtx); // 여러 쓰레드 동시에 가능
    // 읽기 작업
}

void write() {
    std::unique_lock<std::shared_mutex> lock(shared_mtx); // 단독 접근
    // 쓰기 작업
}

여러 쓰레드가 동시에 읽기 가능
쓰기 쓰레드는 단독 접근만 허용 (읽기 중인 쓰레드가 끝날 때까지 대기)

성능 최적화의 이유

쓰기보다 읽기가 많은 상황 (예: 캐시, 설정 조회 등)에서는:

  • std::mutex: 모든 작업이 직렬 → 비효율적
  • std::shared_mutex: 읽기 병렬화 가능 → 성능 향상
#include <iostream>
#include <thread>
#include <shared_mutex>
#include <vector>

std::shared_mutex shared_mtx;
int shared_data = 0;

void reader(int id) {
    std::shared_lock<std::shared_mutex> lock(shared_mtx);
    std::cout << "Reader " << id << " read value: " << shared_data << std::endl;
}

void writer(int value) {
    std::unique_lock<std::shared_mutex> lock(shared_mtx);
    shared_data = value;
    std::cout << "Writer wrote value: " << value << std::endl;
}

int main() {
    std::vector<std::thread> threads;

    // 읽기 쓰레드 여러 개
    for (int i = 0; i < 5; ++i)
        threads.emplace_back(reader, i);

    // 쓰기 쓰레드 하나
    threads.emplace_back(writer, 100);

    for (auto& t : threads) t.join();
}

'Develop > C&CPP' 카테고리의 다른 글

[cpp] optional  (0) 2025.04.25
[cpp] atomic  (0) 2025.04.20
[cpp] mutex, lock  (0) 2025.04.20
[cpp] cpp17에서 달라진 점  (0) 2025.04.20
[cpp] cpp14에서 추가된 것  (0) 2025.04.20

+ Recent posts