잡다로그

[C++/코테] 기초 코드 작성 요령 (2) 본문

Algorithm

[C++/코테] 기초 코드 작성 요령 (2)

날으는다람쥐 2023. 11. 6. 16:33

C++ 복습을 위해 기초 문법을 일부분 기록한 글입니다. 

STL과 함수 인자

C++에서는 함수 인자에 값을 보내면 복사본을 전달한다. 그렇기 때문에 함수에서의 동작이 원본 변수에 적용되지 않게 되는데, 그러한 원리를 값에 의한 호출이라고 한다.

값에 의한 호출 (Call by value)

#include <iostream>
using namespace std;

void func(int a)
{
    a = 5;
}

int main(void)
{
    int t = 0;
    func(t);
    cout << t;	// 출력 결과 0
}

참조에 의한 호출 (Call by reference)

#include <iostream>
using namespace std;

void func(int &a)
{
    a = 5;
}

int main(void)
{
    int t = 0;
    func(t);
    cout << t;	// 출력 결과 5
}

 

값에 의해 호출할 경우 함수로 전달된 변수의 복사본이 함수에 전달된다. 따라서 함수 내부에서 값을 변경하더라도 전달한 변수(t)에는 영향을 주지 않는다. 기본적인 전달 방식이다.

그러나 참조에 의한 호출을 할 경우 함수 내에서 변수 값을 변경하면, 원본 변수 (t)에도 영향을 주게 된다. 

 

포인터와 배열

  • & 연산자는 주소를 의미한다.
  • * 는 포인터 변수를 의미한다.
  • 포인터 변수 + 1 은 포인터 변수의 크기만큼 더해진다. 즉, 다음 변수를 가리키게 된다.
  • 배열 변수 arr 이 있을 때, 이는 &arr[0] 과 동일하다.
#include <iostream>
using namespace std;

void func(int arr[])
{
    arr[0] = 10;
}

int main(void)
{
    int arr[3] = {1, 2, 3}'
    func(arr);
    cout << arr[0];
}

arr을 인자로 넘긴다는 것은 arr의 주소를 넘겨주는 것과 같기 때문에, func에서 배열의 원소를 바뀌면 원본 배열도 바뀌게 된다.

참조자 (Reference)

// 복사된 a와 복사된 b를 바꾸는 것은 무의미하다.
void swap1(int a, int b){
    int tmp = a;
    a = b;
    b = tmp;
}

// 참조를 통해 두 변수의 값을 바꿀 수 있다.
void swap2(int* a, int* b){
    int tmp = *a;
    *a = *b;
    *b = tmp;
}

// 또는 참조자(&)를 이용한다.
void swap3(int& a, int& b){
    int tmp = a;
    a = b;
    b = tmp;
}

swap3를 호출하는 방식은 글 상단의 참조에 의한 호출을 참고하자.

STL (Standard Template Library)

vector

  • 배열과 비슷한 기능을 구현한다.
  • #include <vector> 에 선언되어 있다.
  • 가변 배열로, 일반 배열과 다르게 크기를 늘렸다 줄였다 할 수 있다.
bool cmp1(vector<int> v1, vector<int> v2, int idx){
    return v1[idx] > v2[idx];
}

vector의 길이가 n일 때, 이 예제의 시간 복잡도는 $O(N)$ 이다. 인자를 함수로 넘겨줄 때 복사본을 전달하게 되는데, 그 때 벡터의 각 인수를 복사하는 데에 필요한 시간이 $O(N)$ 기 때문이다.

bool cmp2(vector<int>& v1, vector<int>& v2, int idx){
    return v1[idx] > v2[idx];
}

이 예제의 시간 복잡도는 $O(1)$이 된다. 함수 인자로 벡터의 주소만 전달하기 때문이다.

표준입출력

문자열

  • char은 1byte의 아스키 코드를 저장하는 자료형이다.
  • chat*은 문자열을 나타내는 포인터 변수로, 문자열 시작 주소를 가리킨다.
  • char[]은 문자열을 나타내는 배열로, 문자열 하나하나 수정이 가능하다. 꼭 크기를 명시해서 선언해야 한다.
  • string은 STL에 정의된 문자열 클래스이다.

 

  • char arr[] = "Hello, world!"; 의 길이는 14로, 문자열의 끝을 알리는 null 문자(\0)까지 포함한다.
  • STL에서 제공하는 String 클래스를 사용하면, 문자열 끝에 null 문자가 들어가지 않고, 문자열 길이를 동적으로 변경 가능하다.
  • String 클래스는 cin, cout으로 입출력이 가능하고 getline 함수도 이용할 수 있다. C의 scanf와 printf는 사용할 수 없다.

 

공백을 포함하는 문자열 입력받기

char a[10];
scanf("%[^\n]", a);			// 줄바꿈이 나오기 전까지 입력을 받겠다는 것을 명시

#include <string>
string s;
getline(cin, s);
cout << s;

 

입출력 주의사항1

cin/cout을 사용하려면, 입출력으로 인한 시간 초과를 막기 위해 아래 두 명령어를 실행해야 한다.

ios::sync_with_stdio(0)

C stream과 C++ stream을 동시에 사용할 수 있도록 동기화되어 있는 것을 끊는 명령어. 시간을 절약할 수 있다. 동기화를 끊으면 printf와 cout을 동시에 사용할 수 없다.

cin.tie(0)

키보드로 받은 입력은 출력 buffer에 임시로 저장된 후 buffer가 비워지면서 화면(콘솔)에 보여지게 되는 원리이다. 

buffer의 존재 때문에 출력 순서가 꼬일 수 있다. 그래서 cin 명령어를 수행하기 전에 cout 버퍼를 비워서 출력할 것을 먼저 출력하고 새로 입력을 받는다.

그러나 코테에서 채점 사이트는 출력만 채점하여 출력 순서의 영향이 없다. 그래서 cin 명령어를 수행하기 전에 cout 버퍼를 비우지 않도록 하는 코드이다.

 

입출력 주의사항2

edl 사용하지 않기.

  • 개행문자를 사용하고 출력버퍼를 비우라는 명령어.
  • 줄바꿈이 필요하면 endl이 아닌 개행문자를 출력하기

 

⭐ 코딩테스트는 개발이 아니다.

⭐ 친절한 클린 코드, 누가봐도 이해되는 변수(자료형)을 사용하는 것이 아니라 문제해결을 위한 코딩을 하면 된다. 예를 들어 공백을 포함하여 배열의 원소를 출력해야 할 때, 맨 마지막이 공백으로 끝나서 '1 2 3 4 '와 같이 출력되어 상관없다.

 

#include <iostream>
using namespace std;

int main(void)
{
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    int n, x;
    cin >> n >> x;

    int *a = new int[n];
    for (int i = 0; i < n; i++) // 배열 입력받기
        cin >> a[i];

    // 출력
    for (int i = 0; i < n; i++)
    {
        if (a[i] < x)
            cout << a[i] << ' ';
    }

    delete[] a; // 변수 해제
}

이렇게 한 눈에 이해 가능한 코드보다

#include <bits/stdc++.h>
using namespace std;

int main(void)
{
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    int n, x, t;
    cin >> n >> x;
    while (n--)
    {
        cin >> t;
        if (t < x)
            cout << t << ' ';
    }
}

 

이렇게 불필요한 라인을 전부 줄인 코드가 유리하다.


내용 출처:

https://youtu.be/6lhVHP8bkPA?si=Pnh4RfbtOEndFFd2

https://youtu.be/voct7BVMqdA?si=qxvXAGYMz13S5P6r

Comments