728x90
반응형

전체 글 326

[Ubuntu 20.04] 비디오 드라이버 설치하기

1. 그래픽카드 정보 확인 $ubuntu-drivers devices 2. 그래픽카드 설치 자동으로 설치 $sudo ubuntu-drivers autoinstall 수동으로 설치 $sudo apt install nvidia-driver-450 설치가 끝나면 리부팅해준다. 3. 설치 후 확인 $nvidia-smi 자세한 내용은 아래 블로그를 참고하세요. [Ubuntu 20.04 LTS]Nvidia드라이버 설치하기 그래픽카드 정보 및 드라이버 확인하기 아래 3가지 명령어중 1가지만 터미널에 입력 후 엔터를 눌러줍니다. 그래픽카드 및 설치 가능한 드라이버 확인 ubuntu-drivers devices 현재 사용중인 그래픽카 pstudio411.tistory.com

운영체제/Ubuntu 2021.04.22

[MFC] Control 깜빡임 방지 코드

MFC에서 Control을 Update 하다 보면 깜빡임이 발생한다. 그럴 경우에 Update를 하고자 하는 기능 사이에 다음 함수를 추가하면 깜빡임을 해결할 수 있다. LockWindowUpdate(); - Control Update 중지 UnlockWindowUpdate(); - Contorl Update 중지 해제 아래와 같이 대량의 업데이트가 필요할 경우 깜빡임을 제거할 수 있다. LockWindowUpdate(); for (unsigned int row = 0; row < mcData.size(); row++) { InsertItem(row, CString(mcData[row].machID), 0); SetItemText(row, 1, CString(mcData[row].submachID)); ..

[MySQL] Cursor

MySQL은 Stored Procedure의 내부에 Cursor를 사용할 수 있다. Cursor는 일반 프로그래밍 언어의 파일 처리와 방법이 비슷하기 때문에 행의 집합을 다루기에 편리한 기능을 많이 제공해 준다. 1. Cursor의 처리 순서 Curosr는 일반적으로 아래와 같은 순서를 통해서 처리된다. Cursor를 하나씩 이해하기보다는 우선 간단한 예제로 Cursor의 동작을 이해하는 것이 빠르다. DELIMITER $$ CREATE PROCEDURE SP_check_integrity_submach() BEGIN DECLARE endOfRow BOOLEAN DEFAULT FALSE; -- 행의 끝 여부 (Default : FALSE) -- CURSOR에 사용할 변수 DECLARE sqlmachID V..

DB/MySQL 2021.04.20

[MySQL] 중복 제거문 DISTINCT, GROUP BY

SELECT 문을 실행하다 보면 여러 개의 같은 데이터를 반환하게 된다. 이때 중복된 데이터를 제거하고 싶다면 DISTINCT나 GROUP BY를 사용하면 된다. 예를 들어 아래와 같은 TABLE이 있다고 가정하자. machID가 01인 Machine을 불러오는 Query를 작성해 보자. SELECT FIELD명 FROM TABLE명 WHERE machID='01'; Query를 전송하면 다음과 같은 결과를 나타나는데, 이때 '01'이라는 값이 중복되어 호출된다. 이러한 중복을 제거하기 위해서 사용하는 SQL 명령어가 DISTINCT, GROUP BY이다. e.g) DISTINCT문 SELECT DISTINCT FIELD명 FROM TABLE명 WHERE machID='01'; e.g) GROUP BY문..

DB/MySQL 2021.04.20

[C++] 3점을 지나는 외접원의 중심점 구하기

3점을 지나는 원은 통상 삼각형의 외접원(CircumCircle)이라고변의 중심에서 내린 수선이 만나는 지점이다. 이때 넓이는 헤론(Heron)의 공식에 의해서 가 된다. 물론, 가정이 있다. 헤론의 공식으로 넓이를 구하면 사인(Sin) 법칙의 응용으로 외접원의 반지름을 구할 수 있다. 그렇다고 원의 중심을 구할 수 있는 것은 아니다. 결국 원의 중심을 구하기 위해서는 각 변의 중심을 잇는 수선을 구해서 교차점을 구해야 한다. // 외접원의 중심 구하기 double d, d2, yi; Point2D[] CenPoint = new Point2D[2]; for (int i = 0; i < 2; i++) CenPoint[i] = new Point2D(); // 각 변의 중심점 구하기 CenPoint[0].x ..

코드/C++ 2021.04.20

컨스트럭터 내에서 할당 대신 초기화를 사용하라

한 번 설정하고, 여러 곳에서 활용하자. 컨스트럭터 내에서 멤버 변수의 설정을 위한 할당 대신 초기화를 사용하면 불필요한 런터임 작업과 타이핑을 줄일 수 있다. 컨스트럭터는 내부적으로 초기화 코드를 만들어낸다. 다음 코드를 보자. class A { string s1_, s2_; public: A() { s1_ = "Hello,"; s2_ = "World"; } }; 실제로는 여러분이 다음과 같이 작성한 것처럼 컨스트럭터의 코드가 만들어진다. A() : s1_(), s2_() { s1_ = "Hello,"; s2_ = "World"; } 즉 직접 초기화하지 않은 개체는 표준 컨스트럭터를 통해 자동으로 초기화되고, 할당 연산자를 통해 할당된다는 것이다. 주요한 개체의 할당 연산자는 이미 만들어진 개체를 다룬..

최소화된 클래스를 사용하라

나누고 정복하라. 작은 클래스가 만들기도 쉽고, 얻기도 쉬울 뿐만 아니라 테스트하고 사용하기도 쉬우며, 다양한 상황에서 활용하기에도 편리하다. 다양한 기능을 가진 클래스 대신 간단한 개념을 담은 작은 클래스를 만들어 활용하자. 하나의 클래스에서 복잡하고 완전한 기능을 제공하는 방식은 분명 매력적인 것이 사실이지만, 작은 클래스를 사용하는 것이 대부분의 시스템에 있어 보다 효율적인 이유가 여러 가지 있다. 최소화된 클래스는 각각 하나의 명확한 개념만을 포함하므로, 여러 개의 분리된 개념을 포함하는 클래스와는 달리 서로 간의 구분이 쉽다는 장점이 있다. 작은 클래스는 보다 이해하기 쉽고, 사용하기 쉬우며 재활용하기도 쉽다. 작은 클래스는 분산과 배치에도 유리하다. 많은 기능이 집적된 클래스의 경우 별도의 덩..

내부의 것은 너무 노출시키지 말라.

클래스가 관리하는 내부 테이터에 대한 핸들을 리턴하여 클라이언트가 개체의 상태를 좌우하게끔 만드는 것은 좋지 않다. 다음 코드를 보자. class Socket { public: ................. int GetHandle() const { return handle_; } // 이렇게 해서는 안된다. private: int handle_; }; 데이터를 숨기는 것은 강력한 추상화와 모듈화의 도구이다. 하지만 데이터를 숨겨놓고 그 제어권을 내주는 것은 스스로를 파괴하는 행동이며, 마치 대문을 잠가놓고 열쇠를 꽂아두는 것과 같다. 그 이유는 다음과 같다. 클라이언트가 기능을 제어할 두 가지 방법을 가지게 된다 클래스의 추상체(Socket)를 이용하거나, 클래스가 의존하고 있는 임플리먼테이션을 제어..

만들고 있는 클래스가 무엇인지 확실히 하라

클래스는 종류에 따라 그 쓰임이 다르며, 적용되는 규칙 또한 다르다. 먼저 값 클래스(std::pair, std::vector)는 다음과 같은 특징이 있다. 값을 중심으로 한 공용 디스트럭터, 복사 컨스트럭터, 할당이 존재한다. 가상 함수가 없다. 기반 클래스가 아닌 구체적인 클래스로 사용된다. 다른 클래스의 직접적인 멤머로서 또는 스택 내에서 인스턴스가 만들어진다. 기반 클래스(base calss)는 클래스 계층을 이루는 단위로, 다음과 같은 특징이 있다. 공용(public)이면서 가상(virtual)이거나 보호된(protected)이면서 가상이 아닌 디스트럭터, 비 공용 복사 컨스트럭터, 할당 연사자 등이 있다. 가상 함수를 통해 인터페이스를 구성한다. 인스턴스는 힙에서 동적으로 만들어지거나 스마트 ..

간접적인 타입 변환을 피하기 위해 오버로딩을 활용하라

간접적인 타입 변환은 코딩의 편리함에는 도움을 줄는지 몰라도 임시 개체가 만들어진다는 점에서 그다지 효율적이지는 못하다. 이러한 추가적인 개체의 생성을 피하고 최적화를 이루기 위해서는 변환이 일어나지 않는 범위 내에서 일반적인 인자 타입을 사용한 오버로딩 함수를 사용하면 된다. 사무실에서 일하던 중 종이가 다 떨어졌다면 어떻게 할 것인가? 복사를 담당하는 동료에게 가서 몇 장을 얻어오면 잠시나마 문제는 해결될 것이지만 그렇게 오래 가지는 못할 것이다. 간접 변환이 하는 일이 바로 이것이다. 임시적인 개체를 만들어 잠지 문제를 해결하는 것을 말한다. class string { string(const char* text); // 간접 변환을 가능하도록 함 }; bool operator==(const stri..

표준적인 형식의 산술 및 할당 연산자를 사용하라

a+b가 있다면 a+=b도 같은 의미인 것이 좋다. 즉 두 대상 사이에 이루어지는 산술 연산자의 경우 같은 효과를 가지는 할당 연산자도 제공해야만 중복을 피하고 효율을 극대화할 수 있다. 일반적으로 바이너리 연산자 @가 있다면 a@=b나 a=a@b와 같은 할당 연산 버전도 준비하고, 같은 의미를 가지게끔 해주는 것이 좋다. 이를 위해서는 다음과 같이 @ 연산을 @= 방식으로 만들면 된다. T& T::operator@=(const T&) { // .... 구현 내용 ... return *this; } T operator@(const T& lhs, const T& rhs) { T temp(lhs); return temp @=rhs; } 두 함수의 기능은 같다고 볼 수 있다. 할당 형식은 실제 작업을 수행하고..

값, (스마트) 포인터, 참조 중 적절한 방식으로 인자를 얻어라

인자가 입력, 출력, 입력/출력 중 어떤 것인지, 그리고 값, 참조 인자 중 어떤 것인지 적절히 선택하라. 인자에 대한 값, 참조, 포인터를 적절히 선택하는 것은 안전과 효율성을 높이는 좋은 습관이다. 비록 효율성이 가장 중요한 부분은 아니지만 다른 부분에 악영향을 미치지 않는 한 효율적인 코드를 작성하는 것이 좋을 것이다. 입력의 용도로만 사용되는 인자의 경우는 포인트와 참조에 대해 const 속성을 부여하는 것이 좋다. 값에 의한 복사(point, complex)가 용이한 기본 타입(char, float)과 값 개체를 사용하는 것이 좋다. 다른 사용자가 정의한 타입을 받아들일 때에는 const로의 참조 방식을 사용하자. 함수에서 인자의 복사가 이루어지는 경우에는 참조보다는 값에 의한 전달을 사용하자...

헤더 파일은 충분히 완성된 형태로 만들어라.

각 헤더 파일이 자체적으로 완성도가 있게끔 작성하라. 헤더의 내용과 관련이 있는 다른 헤더는 첨가시켜 주어야 한다. 만약 어떤 헤더 파일이 다른 헤더 파일을 포함시켜야만 작동할 수 있도록 만들어진다면 그만큼 그 헤더 파일의 완성도는 떨어지게 되고, 그 헤더 파일의 사용자는 활용에 어려움을 겪게 될 것이다. 헤더는 스스로 충분히 자급자족할 수 있는 형태로 완성도 있게 만들어야 한다는 것이다. 즉, 빌드 내에서 각 헤더는 분리시켜 컴파일하고, 각각 오류나 경고가 없게 만들어야 한다. 템플릿과 연결되었을 때의 미묘한 이슈들을 짚고 넘어가자. 예 1 : 의존 이름. 템플릿은 정의되는 시점에 컴파일되는 것이 일반적이지만, 의존 이름이나 타입이 아직 그 시점까지 컴파일되지 않았을 경우는 예외이다. template ..

정의의 의존성과 순환 의존성을 최소화하라

지나치게 의존적인 것은 좋지 않다. 정의 내용을 #include 하여 의존하게 되는 상황을 줄여야 한다. 상호 의존적인 것도 피해야 한다. 순환 의존성은 두 모듈이 직/간접적으로 서로에게 의존하고 있을 때 발명하는데, 모듈은 기능이 응집된 단위이기 때문에 서로 의존하는 모듈은 진정한 개별 모듈이라 볼 수 없으며, 오히려 하나의 커다란 모듈로 보는 것이 옳다. 즉, 순환 의존성은 모듈의 장점에 위배되는 것으로, 큰 프로젝트에서 피해야 할 부분이다. 타입의 정의가 절실히 필요한 경우가 아니라면 일방적으로 방향으로의 선언을 사용하는 것이 좋다. 클래스 C의 완전한 정의가 필요한 두 가지 경우를 보자. C 개체의 크기를 알아야 할 경우 e.g. 스택에 C를 할당할 때나 다른 타입과 직접적으로 연결된 멤버로 사용..

너무 긴 함수와 많은 중첩 구조는 피하라

짧은 것이 긴 것보다 낫고, 평면적이 것이 깊은 것보다 낫다. 모든 함수는 그 이름에 맞는 적절한 하나의 역할을 가져야 한다. 여러 개의 작은 요소들이 합쳐서 하나의 긴 함수로 만드는 것은 결코 좋은 방법이 아니다. 너무 긴 라인으로 구성된 함수와 블록(if, for, while, try 등)이 중첩된 구조는 함수의 이해를 힘들게 하고, 관리를 힘들게 하는 주범이다. 블록을 중첩해서 사용하면 그만큼 코드를 읽는 사람의 입장에서 이해가 힘든 것이 당연하다. 블록을 읽어 내려가다가 내부에 다른 블록이 등장하면 지금까지 읽었던 내용을 기억해 둔 상태에서 새로운 블록의 내용을 모두 파악하고, 다시 기억해둔 내용을 꺼내어 조합해야 하기 때문이다. 가능하면 함수의 최대 길이를 제한하는 습관을 가지고, 다음과 같은 ..

변수는 항상 초기화하여 사용하라.

깔끔한 상태에서 시작하라. 초기화되지 않은 변수는 C와 C++에서 있어 버그의 온상이므로, 상상 변수 사용 전에 깨끗한 메모리 상태를 만들어야 한다. 순차적 언어인 파스칼, C, 포트란, 코볼 등을 사용할 때는 변수를 사용하는 코드와 정의하는 코드가 분리되고, 사용되기 직전에 값을 할당하지만, 이러한 방식은 절대 권장되지 않는 형태이다. 초기화 되지 않은 변수에 대한 일반적인 오해 중 하나는 그로 인해 프로그램의 실행이 방해받을 것이라는 점이다. 하지만 이러한 프로그램들은 몇 년간 별다른 문제없이 실행될 수 잇다. 다만 이후에 다른 문맥에서의 호출, 재 컴파일 등 프로그램의 다른 부분에 생긴 변화로 인해 간헐적인 프로그램 중단이 발생할 수 있다. 표준 초기값이나 ? 를 사용하는 경우.. // 권장되지 않..

가능하면 로컬 변수를 선언하여 사용하라

사용 범위가 넓은 함수는 가능하면 최소화하라. 변수는 하나의 상태이고, 가능하면 최소의 상태를 다루는 것이 편하다. 변수의 수명은 최소한 짧게 유지하도록 하자. 필요 이상으로 수명이 길게 정해진 변수는 다음과 같은 단점을 가지고 있다. 프로그램의 이해와 관리가 힘들다 예를 들어 현재 드라이브만이 바뀌었을 때 모듈 경로 문자열도 업데이트되어야 하는가? 문맥상의 의미를 파악하기 힘들다 대부분의 영역에서 유효한 범위인 네임스페이스 수준의 변수가 최악의 경우이다. 값이 초기화되기 쉽다 적절한 초기화 없이 변수를 선언해서는 안 된다. 초기화되지 않은 변수는 C와 C++ 프로그램에서 버그를 발생키는 큰 원인이며, 컴파일러에 의해 언제나 감지될 수 있으므로 주의를 기울여야 한다. 변수를 가능하면 로컬 범위로 정의하고..

728x90
반응형