Post

[ STUDY/Effective C++ ] 2022. 8. 17. 19:44

c++은 예외를 내보내는 소멸자를 좋아하지않는다.

당연하다. 소멸자가 그냥 조용히 소멸하는것이 아닌 예외까지 발생하면 프로그램의 불완전 종료 나 미정의 동작의 위험을 내포하고있기때문이다.

 

하지만 항사 우리가 원하는대로 코드를 짤 순 없다.

만약에 예외를 던지고 실패할 수 있는 코드를 소멸자에 넣어한다면 어떻게 해야할까

 

1. 프로그램 바로 끝내기

DBConn::~DBConn()
{
	try {db.close(); }
    catch (...) {
    	close 호출이 실패했다는 로그 출력;
        std::abort();
	}
}

abort를 호출해서 못 볼꼴을 미리 안보여준다.

 

 

2. 예외 삼켜버리기(무시하기)

DBConn::~DBConn()
{
	try {db.close(); }
    catch (...) {
    	close 호출이 실패했다는 로그 출력;
	}
}

발생한 예외를 그냥 무시하더라도 프로그램이 신뢰성 있게 지속될 경우에만 사용하자.

 

 

3. 사용자가 직접처리하기

void close()
{
	db.close();
    closed = true;
}

DBConn::~DBConn()
{
	if(!closed)
	try {db.close(); }
    catch (...) {
    	close 호출이 실패했다는 로그 출력;
        ...//실행끝내거나 예외무시
	}
}

사용자함수를 만들어 DBConnection이 닫혔는지 여부를 유지가능하며 사용자가 에러를 처리할 수 있는 기회를 가질 수 있다. 닫히지않았다면 DBConn의 소멸자에서 닫을 수도 있다. 

 

이렇게하면 데이터베이스 연결이 누출되지않으나, 소멸자에서 호출하는 close마저 실패한다면 다시 위의 1,2번 처럼 돌아올 수 밖에 없긴하다.

 

 

 

Post

[ STUDY/코딩문제 ] 2022. 8. 14. 23:34

행성 연결 성공


 

시간 제한 메모리 제한 제출 정답 맞힌 사람 정답 비율
1 초 256 MB 3807 1734 1236 42.591%

문제

홍익 제국의 중심은 행성 T이다. 제국의 황제 윤석이는 행성 T에서 제국을 효과적으로 통치하기 위해서, N개의 행성 간에 플로우를 설치하려고 한다.

두 행성 간에 플로우를 설치하면 제국의 함선과 무역선들은 한 행성에서 다른 행성으로 무시할 수 있을 만큼 짧은 시간만에 이동할 수 있다. 하지만, 치안을 유지하기 위해서 플로우 내에 제국군을 주둔시켜야 한다.

모든 행성 간에 플로우를 설치하고 플로우 내에 제국군을 주둔하면, 제국의 제정이 악화되기 때문에 황제 윤석이는 제국의 모든 행성을 연결하면서 플로우 관리 비용을 최소한으로 하려 한다.

N개의 행성은 정수 1,…,N으로 표시하고, 행성 i와 행성 j사이의 플로우 관리비용은 Cij이며, i = j인 경우 항상 0이다.

제국의 참모인 당신은 제국의 황제 윤석이를 도와 제국 내 모든 행성을 연결하고, 그 유지비용을 최소화하자. 이때 플로우의 설치비용은 무시하기로 한다.

입력

입력으로 첫 줄에 행성의 수 N (1 ≤ N ≤ 1000)이 주어진다.

두 번째 줄부터 N+1줄까지 각 행성간의 플로우 관리 비용이 N x N 행렬 (Cij), (1 ≤ i, j ≤ N, 1 ≤ Cij ≤ 100,000,000, Cij = Cji, Cii = 0) 로 주어진다.

출력

 

모든 행성을 연결했을 때, 최소 플로우의 관리비용을 출력한다.

 


풀이

#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;

int V, E;
vector<pair<long long, pair<int, int>>> edge;
int parents[1000];
int edgenum = 0;

int FindRoot(int x)
{
	if (x == parents[x])
		return x;
	return parents[x] = FindRoot(parents[x]);
}

void Merge(int x, int y)
{
	x = FindRoot(x);
	y = FindRoot(y);

	if (x == y)
		return;
	if (y > x)
		parents[y] = x;
	else
		parents[x] = y;
}





int main()
{
	ios::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);


	for (int i = 0; i < 1000; i++)
	{
		parents[i] = i;
	}

	int N;
	long long res = 0;
	cin >> N;

	long long input;
	for (int i = 0; i < N; i++)
	{
		for (int j = 0; j < N; j++) {
			cin >> input;
			if ((i < j) && (i != j)) {
				edge.push_back({ input,{i,j} });
			}
		}

	}


	sort(edge.begin(), edge.end());

	for (int i = 0; i < edge.size(); i++)
	{
		if (FindRoot(edge[i].second.first) == FindRoot(edge[i].second.second))
			continue;

		Merge(edge[i].second.first, edge[i].second.second);
		res += edge[i].first; 
		edgenum++;

		if (edgenum == N - 1)
			break;

	}
	cout << res<<'\n';
}

이 문제는 같은종류의 문제였던 최소스패닝트리의 전력난과 최소스패닝트리의 문제풀이만을 생각하고있다가 통수맞았습니다! 사실 통수가 아니라 제 지식과 응용의 문제이기도 하겠지만 이전까지 pair<int,pair<int,int>>를 잘 해오다가 이번 문제에서는 똑같이하면 안된다는것을 알았습니다.

Vector<pair<long long,pair<int,int>>>했을때 (좌) , pair<long long,pair<int,int>> 했을때(우)

위 사진은 각각 다르게 자료형을 가졌을때, sort하고 난 다음의 모습입니다.

vector<pair<long long,pair<int,int>>>로 하였을때는 sort가 cost의 오름차순으로 잘 정렬되어있지만, pair<long long,pair<int,int>> 를 했을 경우에는 중간부터 정렬이 어긋난것을 알 수가 있습니다.

 

이 원인은 알고보니 sort함수때문에 일어났는데요..제가 바보같이 pair<long long,pair<int,int>>를 했을 당시 sort를 (edge, edge+N)으로 두는 어마어마한 실수를 하였습니다. 분명 마지막 항목은 N이 아니고 그 배일텐데.. 제가  정말 앞에 푼 문제들만 생각하고 심각한 오류를 범했죠..

 

다행히 Vector<pair<long long,pair<int,int>>>를 했을때는 sort를 sort(edge.bigin(), edge.end())로 두었기에 제가 신경쓰지 않더라도 알아서 잘 정렬을 해주었습니다.

 

이 글을 쓰면서 다시 한번 쭉 검토해보니 통수가 아니라 정말 바보같은 실수네요! 오랜만에 문제를 풀어보았더니 이런 실수나 하고..부끄럽습니다! 열심히 이제부터 다시 공부해야겠네요 :D

 

끝만 잘 생각한다면 그냥 크루스칼 알고리즘 그대로 써도 될 정도의 최소스패닝트리 기본문제였습니다.

 

 

 

https://www.acmicpc.net/problem/16398

 

16398번: 행성 연결

홍익 제국의 중심은 행성 T이다. 제국의 황제 윤석이는 행성 T에서 제국을 효과적으로 통치하기 위해서, N개의 행성 간에 플로우를 설치하려고 한다. 두 행성 간에 플로우를 설치하면 제국의 함

www.acmicpc.net

 

Post

대학교 4학년 휴학중..

게임제작지원사업과 관련하여 제 게임을 지원을 받기위해 창업을 해야했습니다.

주변에 아는사람들도 없고 보험이라던가 국민연금이라던가 생각할게 많아 무서웠지만 어찌저찌 해결했고, 저 처럼 어려움을 겪고있는 사람들이 참고할 수 있도록 등록하는 방법에 대해서 적어보고자 합니다.

 

먼저 사업자등록을 하기위한 정보들중 기본정보를 제일 먼저 적게되는데요, 여기서 중요한것만 말씀드리겠습니다.

 

 

상호명 정하기

1. 상호명의 첫 시작은 무조건 한글로

사업자등록을 위해 제일 먼저 필요한 절차는 사업자 이름 정하기 입니다.

여기서 정말정말 중요하게 알아야할 것은

'첫글자는 무조건 한글이어야한다.' 입니다.

2. 중복되지않는 이름으로 정하기

사업자등록을 할때, 중복되지않는 상호명을 사용하여야합니다.

https://www.ftc.go.kr/

공정거래위원회 사이트에 가서 > 정보공개 > 통신판매사업자> 상호 검색 으로

원하는 이름을 검색하고 중복이 있는지 확인하시면됩니다.

 

 

사업장 소재지 정하기

아마 학생분들은 따로 작업실을 두지않는경우라면, 집에서 하실 경우가 많으실텐데 저도 마찬가지입니다.

집에서 작업하고 먹고 다 하기때문에 부모님과 함께사는 '본가'를 사업장으로 두었습니다.

사업장과 관련해서는 밑에 사업장정보입력에서 좀 더 자세하게 말씀드리겠습니다.

 

 

 

 

 

업종 선택하기

이제 본인이 사업자등록을 할려고 생각을 하게된 업종을 골라서 선택해야합니다.

사실 본인이 선택한 업종이 무엇인지 대충알더라도 코드는 정말...찾기 어려울 수 있습니다. 세부적으로 들어가면 엄청 다양하거든요..

위 사진 속 전체업종내려받기를 눌러 엑셀파일을 들어가

자신이 원하는 업종의 키워드가 들어가는 것을 찾으면 됩니다. Ctrl 키 + F 키 같이누르면 찾기 쉽습니다.

저 같은 경우에는 게임이 키워드이기에 '게임'으로 찾았고 모바일게임으로 주업종코드[722002]를 넣었습니다.

다만, 유료게임을 만들경우에는

응용소프트웨어 개발 및 공급업[722000] 을 부업종코드로 따로 넣을필요가있고

(구청에 통신판매업신고가 따로 필요)

게임 내에 광고를 넣을 경우에는

광고대행업[743002]을 부업종코드로 넣으셔야합니다.

부업종코드의 경우에는 추후에 정정이 될 수 있으니 너무 부담을 가지시진 않으셔도됩니다 :D

그리고 정 모를 경우에는 '126'으로 전화하셔서 물어보시면 정보를 얻거나 아니면 해당되는 담당자에게 따로 연결을 해주십니다!

 

 

사업장 정보입력

개업일자 본인이 원하는 날짜로 정하시면됩니다. 등록 이후날짜로 개업일자 정하셔도됩니다.

임대차내역 입력의 경우에

본가를 했다면, 집이 부모님명의더라도 본인소유라고 체크하시면됩니다.

대신, 나중에 등록할때 같이첨부하는 서류로 가족관계증명서주민등록등본을 첨부하시면됩니다.

그리고 자가면적은 집의 면적을 쓰는것이 아닌, 본인이 작업하는 공간에 대한 면적만 작성하시면 됩니다.

그래서 저는 작고 소중한 2평 제 방이 자가면적입니다 (๑•̀ㅂ•́)و✧

 

 

 

 

 

사업자 유형 선택

사실 이 사업자유형을 얘기하기위해서 블로그글을 썻다고 해도 과언이 아닙니다.

유형에는 일반/간이/면세 등등이 있는데 제가 선택한 업종인 모바일게임 개발및 배포는 '일반'에 속합니다.

여기서 대분류 '정보통신업'에 속하는 모든 업종들은 간이에 해당되지않습니다. 일반입니다.

저도 처음에는 잘 몰라서 매출이 얼마이상이 되지않고 1년에 신고해야할 서류같은걸 고려하여 '간이'를 선택하고 제출까지 하였으나 다음날 세무서에서 연락이 와서 설명을 듣고 담당자분께서 수정해주셔서 따로 제출하여주셨습니다.

 

사실 사업자유형까지 작성하셨으면 다 하셨습니다! :D!!

아마 '저장후다음'버튼을 누르면 서류같은것들을 첨부하실 수 있으실거고, 그 후 최종으로 제출이됩니다.

이렇게 접수완료가 되면 다음날이나 이틀뒤에 세무서에서 연락이오고 저처럼 정정할 부분들을 정정하거나 최종확인 후에 사업자등록이 완료됩니다.

 

 
 

짜잔! 다들 무사히 사업자등록하세요! o(〃^▽^〃)o

 

 

4대보험이나 국민연금관련 고민거리가 있을 경우

저는 대학생신분이기도하고 본가에서 부모님과 함께 지내다보니 보험관련이나 연금관련해서는 신경을 전혀 안쓰고살았습니다. 세금관련된것도 전혀 모르고 살았죠..

그러다가 사업자등록을 하게되면 그와 관련된 모든사항을 제가 해결해야한다는 말을 듣고 안그래도 어려운 사업자등록증! 더 어렵게 느껴졌습니다 .

하지만 소득이 없을경우에는 보험이라던가 연금 유예기간을 6개월신청할 수 있다고합니다.

그 동안에는 따로 서류를 내실 필요도, 세금,보험,연금 등 따로 신경 쓸 필요가없다고하니

만약 사업자등록 후에 우편으로 관련서류가 올 시에는 따로 전화를 하면되겠습니다 ! :D

Post

[ STUDY/유니티 ] 2022. 8. 2. 19:43

유니티 프로젝트에서 UI에 나타내는 Text중에 중간중간 변수의 값이 들어가야하는 상황이 나타났습니다.

하지만, 문자열을 쓰다가 중간에 다른 변수값을 string으로 변환해서 또 집어넣고, 또 다음문장이 들어왔다가 또! 다른 변수값을 string으로 변환해서 ..! 우와 완전 귀찮네요!

그리고 string에서 + 연산자를 통해 문자열을 합쳐줄때마다 새로운 인스턴스가 생성되어 결국 가비지가됩니다!

 

string 중간중간 변수의 값이 들어가야하는 상황이 발생했을때, 전체를 모두 문자열로 치환하고 사용한다면

1. 귀찮음

2. +연산자로 인한 가비지생성( 이는 StringBuilder로 해결가능)

 

그러던와중에 "문자열보간"이라는 기능을 찾았는데, 일단 보면 바로 이해가 됩니다

int charLevel;
int charMaxHP;

//안좋은 예
 Window.transform.GetChild(2).GetComponent<Text>().text  = "캐릭터 레벨: "+ charLevel.toString() +"\n 캐릭터 최대HP : "+ charMaxHP.toString();
 
 //문자열 보간
 Window.transform.GetChild(2).GetComponent<Text>().text  = $"캐릭터 레벨: {charLevel} \n 캐릭터 최대HP :  {charMaxHP}"

 

너무 간단해서 딱히 제가 적을것도 없지만, $ 라는 특수문자를 문자열앞에 세워두기만 하면 보간문자열기능을 바로 사용할 수 있습니다. 

 int apple=5,grape=6;
 //문자열 보간은 변수끼리 계산도 가능해요!
 Window.transform.GetChild(2).GetComponent<Text>().text  = $"사과랑 포도를 더하면: {apple + grape}"
 //11로 출력이됩니다 :D

 

참고로 같은 자료형끼리는 계산도 가능하니, 정말 편리합니다! :D 최고에요! XD

 

 

 

 

 

+) 여담이지만.. 저는 적용할려고 하였으나 따로 고려할 사항들이 생겨 못했습니다.. 그래도 엄청 유용해보이니 다들 개발 화이팅! 

▲ top