본문 바로가기
알고리즘

알고리즘을 위한 C++ 시작하기

by ash9river 2024. 4. 9.

기존 C에서 C++로 바꾸면서 printf나 scanf 같은 C형식의 입출력 혹은 헤더 배제

#include <iostream>
int main(){
  int a;
  cin>>a;
  cout<<a;
  return 0;
}

또한 자료구조를 이용할 시, 직접 구현보다는 동적 할당이 편리한 C++의 STL 사용

vector,pair,tuple,stack,queue 등이 있다.


그 이외의 기본적인 것들은 C와 다를 것이 없으나 빠른 입출력은 이하의 코드를 이욯한다.

    cin.tie(0);
    ios_base::sync_with_stdio(0);

cin.tie(NULL)은 cin과 cout의 묶음을 푼다.

기본적으로 cin으로 읽을 때는 출력 버퍼를 비우기 때문에 입력과 출력을 여러 번 번갈아서 반복해야 하는 경우에는 위 코드가 필수적이다.


ios_base::sync_with_stdio(false)는 C와 C++의 버퍼를 분리한다.

이것을 사용하면 cin/cout이 더 이상 stdin/stdout과 맞춰 줄 필요가 없으므로 속도가 빨라진다.


단, 버퍼가 분리되었으므로 cin과 scanf, gets, getchar 등을 같이 혼용하면 안되고, cout과 printf, puts, putchar 등을 같이 사용하면 안된다.

또한, 출력시 endl 대신에 '\n'을 사용하는 것이 더 빠르다.

endl 사용시 출력 버퍼를 비워내기 때문에 특정 코테에서 특정 테스트 케이스를 만족하여 부분 점수를 받는 목적 이외에는 사용하지 않는 편이 좋다.

그 이외의 C++헤더나 STL의 사용법은 코딩해나가면서 배우는 것이 편하다.
특히, 배열의 원소들을 정렬할 시, 그냥 C++의 sort() 함수 사용
cin과 getline을 혼용시, cin은 개행 문자를 남겨두기 때문에, 입력버퍼를 비워줘야 한다.

  int a;
  string str;
  cin>>a;
  cin.ignore();
  getline(cin,str);

입력 버퍼를 비우기 위해 cin.ignore() 함수 활용한다.


EOF처리는 엄청 쉽다.

  string a;
  while(true){
    cin>>a;
    if(cin.eof()) break;
  }

또는

    string a;
    while(cin>>a){
        // 활용 코드가 들어갑니다
    }

getline 함수 활용시

  string str;
  while(getline(cin,str)){
    cout<<str;
  }

변수 선언
  • 지역변수는 스택 영역에 생성되고, 전역변수는 데이터 영역에 생성되기 때문에 데이터가 많은 경우 함수의 매개 변수로 전달시 실패할 수도 있음.(stack memory 초과)
  • 알고리즘 문제 풀이할 때, 대부분의 경우 전역변수에 두는 편이 더 나음.(데이터 접근 및 변경에 용이하고, 스택영역에서 배열 생성의 메모리 제한을 감안하지 않아도 됨)

배열 초기화

1. memset으로 초기화

#include <cstirng>
#include <vector>
int main(){
    int arr[10];
    bool std::vector<int> v(10);
    memset(arr,0,sizeof(arr));
    memset(v,false,sizeof(v));
}

cstring 헤더에 있는 memset 함수로 초기화 1바이트 단위로 값을 세팅하기 때문에 0이나 -1 또는, char 타입이 아닌 값으로 초기화할 시 오류 발생.


2. fill로 초기화

#include <algorithm>
#include <vector>
int main(){
    int arr1[10];
    std::fill(&arr1[0],&arr1[10],98);
    int arr2[10][10];
    std::fill(&arr2[0][0],&arr2[9][10],98);
    int arr3[10][10][10];
    std::fill(&arr3[0][0][0],&arr3[9][9][10],98);
    std::vector<int> v1(10);
    std::fill(v1.begin(),v1.end(),77);
    std::vector<std::vector<int>> v2(10,std::vector<int>(10));
    std::fill(v2.begin(),v2.end(),std::vector<int>(v2[0].size(),77));
}

절대값 함수

절대값 함수 헤더에 따른 차이

std::abs()

  • 변수가 int형으로 프로모션할 수 없는 형태이면 오류 발생.

#include <algorithm>

  • int 타입의 정수 절대값 함수(abs)의 오버로딩

#include <cmath>

  • float, double 타입의 실수 절대값 함수(abs)의 오버로딩

부동 소수점 출력

cout << fixed << setprecision(n): 소수점 아래 n자리까지 반올림하여 출력하는 방식(#include <iomanip> 필요함)

const double dNum = 1234.56789;

// 1
cout << dNum << endl;

// 2
cout.precision(5);
cout << dNum << endl;

// 3
cout << fixed;
cout.precision(6);
cout << dNum << endl;

// 4
cout.unsetf(ios::fixed);
cout << dNum << endl;

// 5
cout.setf(ios::fixed);
cout.precision(5);
cout << dNum << endl;

[출력 결과]

1234.57
1234.6
1234.567890
1234.57
1234.56789
1. 아무런 설정 없이 출력했을 때, 전체 자릿수가 6으로 고정되는 것을 알 수 있다.
C++ 역시 출력할 때 자동으로 반올림되는 것을 알 수 있다.

2. 자릿수를 조정하는 함수이다.
precision(5) = 전체 자릿수를 5로 조절했기 때문에 1234.6이 출력된 것을 알 수 있다.

3. "cout << fixed"라는 표현은 소숫점 아래 값을 고정하는 표현이다.
즉, cout << fixed 이후에 precision(6)을 입력하면 소숫점 아래를 6으로 고정한다.

4, 5.
"cout << fixed"라는 표현은 cout.setf(ios::fixed); 로 사용할 수도 있다.
setf와 반대되는 표현이 unsetf이다. (설정 해제)
3번에서 소수점 아래 자릿수를 6으로 고정했고, 4번에서 이 설정을 해제하고, 5번에서 소수점 아래 자릿수를 5로 고정했다.

부동 소수점 출처