본문 바로가기
Computer Algorithms

[바킹독 실전 알고리즘 0x02] 기초 코드 작성 요령 II

by Hangii 2023. 1. 28.

STL과 함수 인자

void func(int a){
	a=5;
}
int main(void){
	int t=0;
    func(t);
    cout << t;
}
  • int를 함수 인자로 보내면 값이 복사되어 전달된다. 따라서 func내에서 값을 바꾸더라도 main의 변수 t에는 아무런 영향을 주지 않는다.
void func(int arr[]){
	arr[0] = 10;
}
int main(void){
	int arr[3] = {1,2,3};
    func(arr);
    cout << arr[0];
}
  • 배열을 함수 인자로 보내면 배열의 주소가 전달된다. 따라서 func함수 내에서 arr[0] 값이 바뀌면 원본의 값도 자연스럽게 바뀐다.
struc pt{
	int x,y;
};
void func(pt a){
	a.x = 10;
}
int main(void){
	pt tmp = {0,0};
    func(tmp);
    cout << tmp.x;
}
  • 구조체도 int와 비슷하게 값이 다 복사되어 전달되기 때문에 func함수에서 값을 바꿔도 원본에는 영향을 주지 않는다.

 

참조자

두 변수에 저장된 값을 서로 바꾸는 swap함수를 떠올려보자. swap함수의 매개변수로 그냥 int를 전달한다면 값은 바뀌지 않을 것이다. 함수에는 복사된 값이 전달될 것이고, 이 값들을 아무리 서로 바꾼다 한들 원본에는 영향을 주지 않기 때문이다. 그래서 C언어에서는 다음과 같이 매개변수로 포인터를 전달한다. 

void swap(int* a, int* b){
    int tmp = *a;
    *a = *b;
    *b = tmp;
}

C++에서는 참조자를 사용해서 이 문제를 해결할수도 있다. int 뒤에 &를 붙인 형태를 매개변수로 전달하면 int reference, 즉 참조자가 전달된다. 참조자를 사용하면 함수 내에서는 매개변수들을 모두 int를 사용하듯이(포인터를 사용하지 않고) swap해도 원본 값이 바뀌게 된다. 참조자를 사용하면 참조 정보의 주소 부분만 전달된다.

void swap2(int& a, int& b){
    int tmp = a;
    a = b;
    b = tmp;
}

 

STL

C++에서 제공하는 라이브러리. STL도 구조체와 비슷하게 함수의 매개변수로 전달할 때 복사본을 만들어서 전달하는 특성을 가진다. 따라서 STL을 매개변수로 보내는 코드에서는 이 복사본을 만드는 시간복잡도가 소요된다. 이런 비효율성을 해결하고 싶다면 참조자를 사용하면 된다. 참조자는 참조하는 정보의 주소 부분만 매개변수로 전달하기 때문이다.

 

표준 입출력

입력과 출력을 할 때, C에서는 scanf/printf를 사용하고 C++에서는 cin/cout을 사용한다. 이들 기능의 차이는 거의 없다. 

scanf나 cin을 사용해 공백이 포함된 문자열을 입력받으려고 하면 공백 전까지만 입력이 되는 문제가 발생한다. 이는 getline을 사용해서 해결할 수 있다. 대신 getline은 C++ string일때만 사용 가능함에 주의해야 한다.

string s;
getline(cin, s);
cout << s;

scanf/printf와 달리, cin/cout은 입출력으로 인한 시간 초과를 막기 위해 ios::sync_with_stdio(0), cin.tie(0) 이 두 명령어를 실행해야 한다. 이 명령어들을 작성하지 않으면 입출력량이 많을 때 시간 초과가 발생할 수 있다.

 

sync_with_stdio(0)는 C stream과 C++ stream의 동기화를 끊는 코드이므로, 이 코드를 쓴 후부터는 scanf/printf를 사용해서는 안된다. 참고로 VS2017/2019에서는 stream이 무조건 동기화되도록 설정되어있어서 이 코드가 안먹힐 것이다.

 

cin.tie(0)는 여러 번의 입출력 명령이 반복되는 경우에 cin 명령을 실행하기 전에 cout 버퍼를 비우지 않는 코드이다. 온라인 코드 채점 사이트에서는 console에 출력된 값만 보고 결과를 판단하기 때문에 이 기능을 꺼두는 것이 효율적이다.

 

endl은 개행문자("\n")를 출력하고 출력 버퍼를 비우라는 명령인데, 절대 쓰지 않는 것이 좋다. 어차피 온라인 저지 프로그램은 프로그램이 종료되는 시점의 출력을 보고 채점을 하는 것이기 때문에, 코드 중간에 버퍼를 지우는 명령을 할 필요가 없다. 줄바꿈이 필요하다면 그냥 개행문자를 사용하는 것이 훨씬 낫다.

 

코드 작성 팁:

디버거는 굳이 사용하지 않아도 된다!

 

댓글