<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>gimmicks_.log</title>
        <link>https://velog.io/</link>
        <description>Done is better than perfect</description>
        <lastBuildDate>Mon, 09 Jan 2023 07:18:20 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>gimmicks_.log</title>
            <url>https://images.velog.io/images/gimmicks_/profile/b5acf73c-639f-497f-83cb-f9fb5499086f/74234778_2535420139867783_153934840524177408_n.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. gimmicks_.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/gimmicks_" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[2022.log()]]></title>
            <link>https://velog.io/@gimmicks_/2022.log</link>
            <guid>https://velog.io/@gimmicks_/2022.log</guid>
            <pubDate>Mon, 09 Jan 2023 07:18:20 GMT</pubDate>
            <description><![CDATA[<p>개발자가 되기로 결심하고 열심히 달려왔던 2022년이 지나갔다. </p>
<p>지난 1년을 회고하고 23년에 어떤 갓생을 보낼지 계획해보려고 한다.</p>
<hr>
<h2 id="2022-타임라인">2022 타임라인</h2>
<h3 id="차근차근-python-알고리즘-스터디">차근차근 python 알고리즘 스터디</h3>
<p>2월부터 7월까지 루트임팩트에서 진행한 파이썬 알고리즘 스터디에 지원해 활동했다. 사실상 개발 취준을 스터디로 시작하게 되었는데, 좋은 스터디 팀원들을 만나서 알고리즘 실력뿐만 아니라 개발자 취업시장의 전반적인 이야기를 듣고 어떻게 준비해야할 지 방향을 잡을 수 있었다.<a href="https://velog.io/@gimmicks_/algorithmstudy">스터디 회고</a></p>
<h3 id="nodejs-학원">Node.js 학원</h3>
<p>백엔드 개발자로 진로를 정한 후, 독학도 좋지만 조금 더 가까이서 코칭받을 수 있는 멘토와 동료 취준생 네트워킹의 필요성을 느껴서 국비학원을 알아보게 되었다. </p>
<p>일주일이 넘는 시간동안 국비학원을 찾아보고 면접을 보러다니면서 커리큘럼, 기관 후기, 거리 등을 고려해 Node.js 교육과정을 선택했고 3월부터 7월 말까지 학원에 다니게 되었다.</p>
<p>교육은 기대와 조금 <del>많이</del> 달랐다. 커리큘럼에 백엔드 이외의 부수적인 것들이 많이 없어서 선택한 교육과정이었는데 실제로는 커리큘럼에 적혀있지 않은 (앱인벤터, 파이썬 데이터 크롤링, 텐서플로... 등) 교육들이 긴 시간 이루어졌고, AWS나 GCP같은 배워보고 싶었던 과정은 아예 진행되지 않았다. </p>
<p>교육과정 이름에 적혀있는 Node.js는 실제로 2주정도 교육이 이루어졌다. 그 마저도 <a href="http://www.yes24.com/Product/Goods/62597864?pid=123487&amp;cosemkid=go15325014724202344&amp;gclid=Cj0KCQiA5NSdBhDfARIsALzs2EBhHiyZOEvpaCgc9-k9kbuakLDinfYcELVs8rh4ufczGmsG5-LA4cAaArRAEALw_wcB">Node.js교과서</a> 책을 그대로 따라가는 방식이어서, 서버관련 지식은 크게 배울 수 없었다.</p>
<p>하지만 정말 운이 좋게도 좋은 동료들을 만나 만족스러운 프로젝트를 완성시킬 수 있었고, 프로젝트 최우수상을 받을 수 있었다.
<img src="https://velog.velcdn.com/images/gimmicks_/post/c372d449-c64f-4e28-9916-a23010e5a7f1/image.jpeg" alt=""></p>
<p>뿐만 아니라 학원에서 만난 동료들과 주기적으로 만나 공부하고, 밥도 먹으면서 제일 큰 목표였던 취준생 네트워킹을 만든 것이 제일 큰 수확이었다!</p>
<h3 id="cs-공부">CS 공부</h3>
<p>새로운 지식들을 공부하면서 </p>
<ul>
<li>추상적으로 이게 이렇게 되는 건 알겠는데, <strong>더 자세하게 알면 좋지 않을까?</strong></li>
<li>당장 구현은 할 수 있겠는데, <strong>왜 이렇게 되는걸까?</strong></li>
</ul>
<p>라는 고민들을 자주 하게 되고, 학습할수록 지식 부채가 늘어가고 있다고 느끼게 되었다. </p>
<p>앞으로 개발하는 데 CS지식이 기초 체력이 되겠다고 판단했고, 마음이 맞는 국비교육때 만난 동료들을 모았다.
<img src="https://velog.velcdn.com/images/gimmicks_/post/7a05a2b3-66ed-43e6-8e77-d799ffceb3d7/image.png" alt=""></p>
<p>약 한 달동안 팀원들과 KOCW에서 유명한 이화여대 반효경 교수님의 <a href="http://www.kocw.net/home/cview.do?cid=3646706b4347ef09">운영체제</a>, 한양대 박석복 교수님의 <a href="http://www.kocw.net/home/cview.do?cid=6166c077e545b736">네트워크</a>를 수강했다. </p>
<p>사실 많이 지루하고 피곤했다. 하루 4시간 정도 계속 강의듣고 정리하고, 모르는 부분을 찾아보는 것이 쉽지만은 않았다. 하지만, 스터디 이후 새로운 기술을 공부할 때 아주 큰 도움이 되었다고 생각되는데,</p>
<ul>
<li>더 머릿속에 자세히 그려나가면서 로직을 설계할 수 있게 되었다. 머릿 속 설계도의 <strong>해상도</strong>를 높인 기분이다.</li>
<li>새로운 기술을 적용하고 공부하는 것에 대한 <strong>자신감</strong>이 늘게 되었다.</li>
<li>무섭게 느껴졌던 <strong>CS면접</strong>을 다소 쉽게 준비할 수 있게 되었다.</li>
</ul>
<p>특히 추후 프로젝트에서 s3, cloud front와 lambda를 도입해 이미지 다운로드 / 업로드 오버헤드를 줄이는 작업을 하게 되었는데, 이 때 공부했던 <strong>네트워크 지식</strong>이 크게 도움되었다.(추후 포스팅 예정)</p>
<p>새로 취준하려는 친구가 있으면 무조건 CS공부를 병행하라고 추천해주고 싶다. 앞으로 개발자로 끊임없이 공부하는 동안 CS공부를 놓지 말아야겠다고 생각하게 되었다.</p>
<h3 id="엘리스-sw트랙-3기-부트캠프"><a href="https://elice.training/track/sw">엘리스 SW트랙 3기 부트캠프</a></h3>
<p>Node.js 국비학원을 수료했지만, 백엔드 개발자로서 역량이 너무 부족하다고 생각했다. </p>
<p>더 전문적으로 배울 수 있는 부트캠프를 알아보게 되었고, 엘리스가 다음 장점을 갖고 있다고 생각되어 지원하게 되었다.</p>
<ol>
<li>교육이 온라인으로 이루어지고, 한 주에 할당된 학습량을 채우면 되기 때문에 부트캠프에 크게 얽매이지 않고 개인공부를 할 수 있다.</li>
<li>스터디를 권장하기 때문에 내가 필요한 공부를 같이 할 수 있는 동료를 쉽게 찾을 수 있다.</li>
<li><strong>팀 프로젝트시 팀별로 현업에서 일하는 FE/BE 코치님이 배정되어 매일 한 시간 오피스아워를 통해 자세한 코칭을 받을 수 있다.</strong></li>
</ol>
<p>사실 나는 한 사이클의 프로젝트를 겪었고, 동기부여가 잘 되어있다고 생각했기 때문에 위 장점들이 크게 느껴졌는데, 특히 3번 장점을 통해 혼자 개발하면서 느끼는 답답함과 의문점들을 해소할 수 있을 것이라 생각해 망설임 없이 지원했다.</p>
<p>엘리스에서 어떻게 공부했는지 자세하게 적진 않겠지만, 너무 좋은 경험을 많이 할 수 있었다. </p>
<p>확실히 체계적으로 관리받고 있다는 느낌을 받을 수 있었고, 커리큘럼이 프론트 위주로 되어있어서 큰 기대를 하지 않았는데, 중간중간 열린 백엔드 특강을 통해 계속 성장하고 있다는 느낌을 받을 수 있었다.</p>
<p>그리고 다양한 배경을 가진 사람들과 프로젝트, 스터디 등 네트워킹 할 수 있는 기회가 많았던 덕분에, 다양한 사람들을 만나고, 좋은 인연을 만들 수 있었다.</p>
<p>특히 2차 프로젝트는 PM역할을 맡아 지도, 사진 기반의 플랫폼을 웹페이지로 제작했는데, 우수상(3위)를 수상할 수 있었다...! 이 프로젝트에 관해서는 추후 포스팅 또는 포트폴리오에 더 자세히 적어보고자 한다.
<img src="https://velog.velcdn.com/images/gimmicks_/post/e64a97c7-a760-4403-8498-7bd0fc5e3655/image.jpg" alt=""></p>
<h3 id="정리">정리</h3>
<p>올해 3번의 프로젝트와 다양한 스터디들을 통해 다양한 네트워킹을 하면서 느낀 것은 <code>결국 남는건 사람</code>이다. </p>
<p>비전공자로 개발자가 되는게 조금은 외로운 길일 수도 있었지만, 감사하게도 좋은 동료들과 인연들을 많이 만난 덕분에 지치지 않고 꾸준히 공부할 수 있었다. 또 <code>일잘러</code>, <code>공잘러</code>, <code>열정러</code>들을 만나보면서 자극받아 항상 생각했던 것 보다 더욱 빠르게 성장할 수 있었다. </p>
<pre><code>이 글을 빌어 올해 저와 함께 공부하고 네트워킹 해주신 모든 분들께 감사함을 전합니다 😊</code></pre><p>프로젝트를 진행할 때 모든 문제를 기술로 해결하려고 하는 습관이 생겼다는 것을 중간에 깨닫게 되었다. 개발 공부에 몰입하다보니, 기획과 개발영역을 분리해버리고 생각했던 것이다. </p>
<p>앞으로 개발자로 일하게 될 때 이를 계속해서 주의해야겠다고 생각했다.</p>
<pre><code>Coder가 아닌 문제를 해결할 수 있는 Solver가 되자.</code></pre><hr>
<h2 id="2023-갓생살기">2023 갓생살기</h2>
<h3 id="취업">취업</h3>
<p>취업이라는 벽이 무섭게 느껴졌다. <code>가고싶은 곳에 취업하지 못하면 어떻게하지?</code> <code>면접관들 질문에 제대로 대답하지 못하면 어떻게하지?</code> 하는 두려움이 너무 컸기 때문이다.</p>
<p>나는 <code>0승 10패보다 0승 0패가 낫다</code>고 생각했던 것 같다. 패배가 무서워 이력서를 더 다듬고, 내 역량을 키우면서 취업의 벽을 곧바로 바라보지 못했다.
<img src="https://velog.velcdn.com/images/gimmicks_/post/cc59ef47-25b2-416b-8509-f78ba8eeb9c2/image.png" alt=""> </p>
<p>향로님 블로그 포스팅(<a href="https://jojoldu.tistory.com/684">링 위로 올라가기</a>)을 보며 올해는 그 마음을 고쳐야겠다 생각이 들었다. 나를 좀 더 믿고, 1월 중순부터 공격적으로 지원해보려고 한다.</p>
<pre><code>0승 0패보다 1승 100패가 낫다.</code></pre><h3 id="원티드-프리온보딩">원티드 프리온보딩</h3>
<p><a href="https://www.wanted.co.kr/events/pre_challenge_be_3">원티드 프리온보딩 챌린지 1월</a>에 지원했다.</p>
<p>관심있게 생각했던 함수지향 프로그래밍과 엘리스 2차프로젝트때 사용했던 Nest.js를 다루는 커리큘럼이 너무 마음에 들었다. 내일부터 시작하게 되는데 너무 기대된다.</p>
<h3 id="출첵스터디">출첵스터디</h3>
<p>작년 8월부터 집근처 공부할 수 있는 공간에서 오프라인 출석체크 스터디를 꾸준히 해왔는데, 취업과 여러 사정들로 팀원들이 나가게 되고 자바 스프링을 공부하시는 한분과 계속 스터디를 진행해왔다.</p>
<p>프로젝트도 끝이 났고, 새해를 맞아 출첵스터디를 인프런을 통해 2명 충원하게 되었다. 목표는 모두 취업하는 것이다. 꾸준하게 할 수 있는 원동력이 될 수 있었으면 좋겠다.</p>
<h3 id="cs-공부-1">CS 공부</h3>
<p><a href="https://www.youtube.com/@ChanSuShin">한국외대 신찬수 교수님</a>이 방학마다 오픈하시는 자료구조 수업에 수강신청했다.
<img src="https://velog.velcdn.com/images/gimmicks_/post/b726c1ec-dfd1-43a0-959e-f8eb11a985b3/image.png" alt=""></p>
<p>다양한 알고리즘으로 개발된 기술들을 공부하면서 자료구조 공부를 꼭 해야겠다고 생각하게 되었는데, 좋은 기회에 교수님께서 강의를 열어주셔서 최근에 신청하게 되었다. 2월까지 꼭 완강해보려고 한다.</p>
<hr>
<p>2022년은 감사할 일밖에 없었던 것 같다. 여러가지로 나에게 의미가 큰 해였다. 올해는 작년에 받았던 행운들을 주변사람들에게 나눠줄 수 있는 사람이 되고싶다 😀 </p>
<p>HAPPY NEW YEAR!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[SQL 기초 - 2]]></title>
            <link>https://velog.io/@gimmicks_/SQL-%EA%B8%B0%EC%B4%88-2</link>
            <guid>https://velog.io/@gimmicks_/SQL-%EA%B8%B0%EC%B4%88-2</guid>
            <pubDate>Tue, 24 May 2022 08:42:25 GMT</pubDate>
            <description><![CDATA[<pre><code class="language-sql">create table subject(
    -&gt; id int(11) not null auto_increment,
    -&gt; title varchar(30) not null,
    -&gt; description text,
    -&gt; created datetime not null,
    -&gt; author_id int(11) default null,
    -&gt; primary key(id));

desc subject;
+-------------+-------------+------+-----+---------+----------------+
| Field       | Type        | Null | Key | Default | Extra          |
+-------------+-------------+------+-----+---------+----------------+
| id          | int         | NO   | PRI | NULL    | auto_increment |
| title       | varchar(30) | NO   |     | NULL    |                |
| description | text        | YES  |     | NULL    |                |
| created     | datetime    | NO   |     | NULL    |                |
| author_id   | int         | YES  |     | NULL    |                |
+-------------+-------------+------+-----+---------+----------------+

create table author (
    -&gt; id int(11) not null auto_increment,
    -&gt; name varchar(20) not null,
    -&gt; profile varchar(200) default null,
    -&gt; primary key(id));

desc author;
+---------+--------------+------+-----+---------+----------------+
| Field   | Type         | Null | Key | Default | Extra          |
+---------+--------------+------+-----+---------+----------------+
| id      | int          | NO   | PRI | NULL    | auto_increment |
| name    | varchar(20)  | NO   |     | NULL    |                |
| profile | varchar(200) | YES  |     | NULL    |                |
+---------+--------------+------+-----+---------+----------------+

insert into author (id, name, profile) values(1, &#39;lee&#39;, &#39;developer&#39;);
insert into author (id, name, profile) values(2, &#39;kim&#39;, &#39;CEO&#39;);
insert into author (id, name, profile) values(3, &#39;park&#39;, &#39;Data scientist&#39;);

select * from author
+----+------+----------------+
| id | name | profile        |
+----+------+----------------+
|  1 | lee  | developer      |
|  2 | kim  | CEO            |
|  3 | park | Data scientist |
+----+------+----------------+

insert into subject(title, description, created, author_id) values(&#39;C#&#39;, &#39;C# is ...&#39;, NOW(), 1);
insert into subject(title, description, created, author_id) values(&#39;HTML5&#39;, &#39;HTML5 is ...&#39;, NOW(), 1);
insert into subject(title, description, created, author_id) values(&#39;JAVA&#39;, &#39;JAVA is ...&#39;, NOW(), 2);
insert into subject(title, description, created, author_id) values(&#39;CPlus&#39;, &#39;CPlus is ...&#39;, NOW(), 1);
insert into subject(title, description, created, author_id) values(&#39;MySQL&#39;, &#39;MySQL is ...&#39;, NOW(), 3);

select * from subject;
+----+-------+--------------+---------------------+-----------+
| id | title | description  | created             | author_id |
+----+-------+--------------+---------------------+-----------+
|  1 | C#    | C# is ...    | 2022-05-24 15:41:34 |         1 |
|  2 | HTML5 | HTML5 is ... | 2022-05-24 16:02:59 |         1 |
|  3 | JAVA  | JAVA is ...  | 2022-05-24 16:03:19 |         2 |
|  4 | CPlus | CPlus is ... | 2022-05-24 16:04:01 |         1 |
|  5 | MySQL | MySQL is ... | 2022-05-24 16:04:17 |         3 |
+----+-------+--------------+---------------------+-----------+</code></pre>
<p><code>subject</code> 와 <code>author</code> 은 분리되어 있지만, 실질적으로 <code>subject</code>테이블의 <code>author_id</code> 컬럼과  <code>author</code>테이블의 <code>id</code>컬럼으로 연결되어있다. 두 테이블을 두 컬럼을 통해 연결할 수 있다.</p>
<pre><code class="language-sql">select * from subject;
+----+-------+--------------+---------------------+-----------+
| id | title | description  | created             | author_id |
+----+-------+--------------+---------------------+-----------+
|  1 | C#    | C# is ...    | 2022-05-24 15:41:34 |         1 |
|  2 | HTML5 | HTML5 is ... | 2022-05-24 16:02:59 |         1 |
|  3 | JAVA  | JAVA is ...  | 2022-05-24 16:03:19 |         2 |
|  4 | CPlus | CPlus is ... | 2022-05-24 16:04:01 |         1 |
|  5 | MySQL | MySQL is ... | 2022-05-24 16:04:17 |         3 |
+----+-------+--------------+---------------------+-----------+

select * from author;
+----+------+----------------+
| id | name | profile        |
+----+------+----------------+
|  1 | lee  | developer      |
|  2 | kim  | CEO            |
|  3 | park | Data scientist |
+----+------+----------------+

select * from subject left join author on subject.author_id = author.id;
+----+-------+--------------+---------------------+-----------+------+------+----------------+
| id | title | description  | created             | author_id | id   | name | profile        |
+----+-------+--------------+---------------------+-----------+------+------+----------------+
|  1 | C#    | C# is ...    | 2022-05-24 15:41:34 |         1 |    1 | lee  | developer      |
|  2 | HTML5 | HTML5 is ... | 2022-05-24 16:02:59 |         1 |    1 | lee  | developer      |
|  3 | JAVA  | JAVA is ...  | 2022-05-24 16:03:19 |         2 |    2 | kim  | CEO            |
|  4 | CPlus | CPlus is ... | 2022-05-24 16:04:01 |         1 |    1 | lee  | developer      |
|  5 | MySQL | MySQL is ... | 2022-05-24 16:04:17 |         3 |    3 | park | Data scientist |
+----+-------+--------------+---------------------+-----------+------+------+----------------+</code></pre>
<p>중간의 <code>author_id</code>와 <code>id</code>컬럼을 제외하고 출력하고 싶어 다음과 같이 입력하면 에러가 난다.</p>
<pre><code class="language-sql">select id, title, description, created, name, profile from subject left join author on subject.author_id = author.id;</code></pre>
<p><code>subject</code>테이블과 <code>author</code> 테이블 모두 id라는 컬럼을 갖고있기 때문에 <strong><a href="https://en.wikipedia.org/wiki/Ambiguity_effect">모호성 에러</a></strong>가 발생하는 것이다. 이를 해결하기 위해 <code>id</code>컬럼을 더욱 자세히 적어줄 필요가 있다.</p>
<pre><code class="language-sql">select subject.id, title, description, created, name, profile from subject left join author on subject.author_id = author.id;
+----+-------+--------------+---------------------+------+----------------+
| id | title | description  | created             | name | profile        |
+----+-------+--------------+---------------------+------+----------------+
|  1 | C#    | C# is ...    | 2022-05-24 15:41:34 | lee  | developer      |
|  2 | HTML5 | HTML5 is ... | 2022-05-24 16:02:59 | lee  | developer      |
|  3 | JAVA  | JAVA is ...  | 2022-05-24 16:03:19 | kim  | CEO            |
|  4 | CPlus | CPlus is ... | 2022-05-24 16:04:01 | lee  | developer      |
|  5 | MySQL | MySQL is ... | 2022-05-24 16:04:17 | park | Data scientist |
+----+-------+--------------+---------------------+------+----------------+</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[MySQL 기초]]></title>
            <link>https://velog.io/@gimmicks_/sql</link>
            <guid>https://velog.io/@gimmicks_/sql</guid>
            <pubDate>Tue, 24 May 2022 06:03:32 GMT</pubDate>
            <description><![CDATA[<pre><code class="language-sql">// 서버 시작
mysql.server start

// 설정
mysql_secure_installation

// 접속
mysql -uroot -p

// 데이터베이스 생성
reate database node242 default character set utf8;

// 스키마 선택
use node242

// 테이블 추가
mysql&gt; create table topic(
    -&gt; id int(11) not null auto_increment, // auto_increment : 자동으로 증가
    -&gt; title varchar(100) not null,
    -&gt; description TEXT null,
    -&gt; created DATETIME not null,
    -&gt; author varchar(30) null,
    -&gt; profile varchar(100) null,
    -&gt; primary key(id))

// 테이블 목록
show tables

// 필드 출력
desc topic;

// 내용 추가(C)
insert into topic(title, description, created, author, profile) values(&#39;javascript&#39;,&#39;javascript is...&#39;, now(), &#39;KIS&#39;,&#39;developer&#39;);
insert into topic(title, description, created, author, profile) values(&#39;C++&#39;,&#39;C++ is...&#39;, now(), &#39;KIS&#39;,&#39;developer&#39;);
insert into topic(title, description, created, author, profile) values(&#39;Python&#39;,&#39;Python is...&#39;, now(), &#39;Lee&#39;,&#39;teacher&#39;);
insert into topic(title, description, created, author, profile) values(&#39;Nodejs&#39;,&#39;Nodejs is...&#39;, now(), &#39;Kim&#39;,&#39;developer&#39;);
insert into topic(title, description, created, author, profile) values(&#39;Mysql&#39;,&#39;Mysql is...&#39;, now(), &#39;Park&#39;,&#39;DBmanager&#39;);

// 내용 확인
select * from topic;

+----+------------+------------------+---------------------+--------+-----------+
| id | title      | description      | created             | author | profile   |
+----+------------+------------------+---------------------+--------+-----------+
|  1 | javascript | javascript is... | 2022-05-20 16:52:30 | KIS    | developer |
|  2 | C++        | C++ is...        | 2022-05-20 16:56:54 | KIS    | developer |
|  3 | Python     | Python is...     | 2022-05-20 16:57:39 | Lee    | teacher   |
|  4 | Nodejs     | Nodejs is...     | 2022-05-20 16:58:44 | Kim    | developer |
|  5 | Mysql      | Mysql is...      | 2022-05-20 16:59:32 | Park   | DBmanager |
+----+------------+------------------+---------------------+--------+-----------+

// 조건문
select * from topic where profile=&quot;developer&quot;;
+----+------------+------------------+---------------------+--------+-----------+
| id | title      | description      | created             | author | profile   |
+----+------------+------------------+---------------------+--------+-----------+
|  1 | javascript | javascript is... | 2022-05-20 16:52:30 | KIS    | developer |
|  2 | C++        | C++ is...        | 2022-05-20 16:56:54 | KIS    | developer |
|  4 | Nodejs     | Nodejs is...     | 2022-05-20 16:58:44 | Kim    | developer |
+----+------------+------------------+---------------------+--------+-----------+

// 정렬
// 내림차순 
select * from topic order by id desc
+----+------------+------------------+---------------------+--------+-----------+
| id | title      | description      | created             | author | profile   |
+----+------------+------------------+---------------------+--------+-----------+
|  5 | Mysql      | Mysql is...      | 2022-05-20 16:59:32 | Park   | DBmanager |
|  4 | Nodejs     | Nodejs is...     | 2022-05-20 16:58:44 | Kim    | developer |
|  3 | Python     | Python is...     | 2022-05-20 16:57:39 | Lee    | teacher   |
|  2 | C++        | C++ is...        | 2022-05-20 16:56:54 | KIS    | developer |
|  1 | javascript | javascript is... | 2022-05-20 16:52:30 | KIS    | developer |
+----+------------+------------------+---------------------+--------+-----------+

select * from topic order by title;
+----+------------+------------------+---------------------+--------+-----------+
| id | title      | description      | created             | author | profile   |
+----+------------+------------------+---------------------+--------+-----------+
|  2 | C++        | C++ is...        | 2022-05-20 16:56:54 | KIS    | developer |
|  1 | javascript | javascript is... | 2022-05-20 16:52:30 | KIS    | developer |
|  5 | Mysql      | Mysql is...      | 2022-05-20 16:59:32 | Park   | DBmanager |
|  4 | Nodejs     | Nodejs is...     | 2022-05-20 16:58:44 | Kim    | developer |
|  3 | Python     | Python is...     | 2022-05-20 16:57:39 | Lee    | teacher   |
+----+------------+------------------+---------------------+--------+-----------+

// 출력하는 데이터 제한
select * from topic order by id asc limit 2; // 2개만 보여주겠다
+----+------------+------------------+---------------------+--------+-----------+
| id | title      | description      | created             | author | profile   |
+----+------------+------------------+---------------------+--------+-----------+
|  1 | javascript | javascript is... | 2022-05-20 16:52:30 | KIS    | developer |
|  2 | C++        | C++ is...        | 2022-05-20 16:56:54 | KIS    | developer |
+----+------------+------------------+---------------------+--------+-----------+

// 수정 update
update topic set description =&#39;database is...&#39; where id=5;
+----+------------+------------------+---------------------+--------+-----------+
| id | title      | description      | created             | author | profile   |
+----+------------+------------------+---------------------+--------+-----------+
|  1 | javascript | javascript is... | 2022-05-20 16:52:30 | KIS    | developer |
|  2 | C++        | C++ is...        | 2022-05-20 16:56:54 | KIS    | developer |
|  3 | Python     | Python is...     | 2022-05-20 16:57:39 | Lee    | teacher   |
|  4 | Nodejs     | Nodejs is...     | 2022-05-20 16:58:44 | Kim    | developer |
|  5 | Mysql      | database is...   | 2022-05-20 16:59:32 | Park   | DBmanager |
+----+------------+------------------+---------------------+--------+-----------+

update topic set title =&#39;Database&#39; where id=5;
+----+------------+------------------+---------------------+--------+-----------+
| id | title      | description      | created             | author | profile   |
+----+------------+------------------+---------------------+--------+-----------+
|  1 | javascript | javascript is... | 2022-05-20 16:52:30 | KIS    | developer |
|  2 | C++        | C++ is...        | 2022-05-20 16:56:54 | KIS    | developer |
|  3 | Python     | Python is...     | 2022-05-20 16:57:39 | Lee    | teacher   |
|  4 | Nodejs     | Nodejs is...     | 2022-05-20 16:58:44 | Kim    | developer |
|  5 | Database   | database is...   | 2022-05-20 16:59:32 | Park   | DBmanager |
+----+------------+------------------+---------------------+--------+-----------+

//삭제 delete
delete from topic where id=5;
+----+------------+------------------+---------------------+--------+-----------+
| id | title      | description      | created             | author | profile   |
+----+------------+------------------+---------------------+--------+-----------+
|  1 | javascript | javascript is... | 2022-05-20 16:52:30 | KIS    | developer |
|  2 | C++        | C++ is...        | 2022-05-20 16:56:54 | KIS    | developer |
|  3 | Python     | Python is...     | 2022-05-20 16:57:39 | Lee    | teacher   |
|  4 | Nodejs     | Nodejs is...     | 2022-05-20 16:58:44 | Kim    | developer |
+----+------------+------------------+---------------------+--------+-----------+
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[JS - Spread 연산자]]></title>
            <link>https://velog.io/@gimmicks_/JS-Spread-%EC%97%B0%EC%82%B0%EC%9E%90</link>
            <guid>https://velog.io/@gimmicks_/JS-Spread-%EC%97%B0%EC%82%B0%EC%9E%90</guid>
            <pubDate>Sat, 21 May 2022 14:28:22 GMT</pubDate>
            <description><![CDATA[<h1 id="spread-연산자">Spread 연산자</h1>
<pre><code class="language-js">const cookie = {
  base: &#39;coockie&#39;,
  madIn: &#39;korea&#39;,
};
const chocochipCookie = {
  base: &#39;coockie&#39;,
  madIn: &#39;korea&#39;,
  toping: &#39;chocochip&#39;,
};
const blueberryCookie = {
  base: &#39;coockie&#39;,
  madIn: &#39;korea&#39;,
  toping: &#39;blueberry&#39;,
};
const strawberryCookie = {
  base: &#39;coockie&#39;,
  madIn: &#39;korea&#39;,
  toping: &#39;strawberry&#39;,
};</code></pre>
<p>다양한 종류의 쿠키 객체를 만들때 중복된 <code>key</code>값이 있을 경우 스프레드 연산자 <code>...</code>를 통해 간단하게 작성할 수 있다.</p>
<pre><code class="language-js">const cookie = {
  base: &#39;coockie&#39;,
  madIn: &#39;korea&#39;,
};
const chocochipCookie = {
  ...cookie,
  toping: &#39;chocochip&#39;,
};
const blueberryCookie = {
  ...cookie,
  toping: &#39;blueberry&#39;,
};
const strawberryCookie = {
  ...cookie,
  toping: &#39;strawberry&#39;,
};

console.log(chocochipCookie);
console.log(blueberryCookie);
console.log(strawberryCookie);</code></pre>
<pre><code>{ base: &#39;coockie&#39;, madIn: &#39;korea&#39;, toping: &#39;chocochip&#39; }
{ base: &#39;coockie&#39;, madIn: &#39;korea&#39;, toping: &#39;blueberry&#39; }
{ base: &#39;coockie&#39;, madIn: &#39;korea&#39;, toping: &#39;strawberry&#39; }</code></pre><p>이처럼 스프레드 연산자 <code>...</code>는 객체의 값을 새로운 객체에 펼쳐준다. 
<br></p>
<pre><code class="language-js">const noTopingCookies = [&#39;촉촉한쿠키&#39;, &#39;안촉촉한쿠키&#39;];
const topingCookies = [&#39;바나나쿠키&#39;, &#39;블루베리쿠키&#39;, &#39;딸기쿠키&#39;, &#39;초코칩쿠키&#39;];

const allCookies = [...noTopingCookies, ...topingCookies];
console.log(allCookies);</code></pre>
<pre><code>[ &#39;촉촉한쿠키&#39;, &#39;안촉촉한쿠키&#39;, &#39;바나나쿠키&#39;, &#39;블루베리쿠키&#39;, &#39;딸기쿠키&#39;, &#39;초코칩쿠키&#39; ]</code></pre><p>배열에서도 마찬가지로 스프레드 연산자를 사용할 수 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[JS - 비구조화 할당]]></title>
            <link>https://velog.io/@gimmicks_/JS-%EB%B9%84%EA%B5%AC%EC%A1%B0%ED%99%94-%ED%95%A0%EB%8B%B9</link>
            <guid>https://velog.io/@gimmicks_/JS-%EB%B9%84%EA%B5%AC%EC%A1%B0%ED%99%94-%ED%95%A0%EB%8B%B9</guid>
            <pubDate>Sat, 21 May 2022 14:17:17 GMT</pubDate>
            <description><![CDATA[<h1 id="비구조화-할당구조분해-할당">비구조화 할당(구조분해 할당)</h1>
<pre><code class="language-js">let arr = [&#39;one&#39;, &#39;two&#39;, &#39;three&#39;];

let one = arr[0];
let two = arr[1];
let three = arr[2];

console.log(one, two, three);</code></pre>
<pre><code>one two three</code></pre><pre><code class="language-js">let arr = [&#39;one&#39;, &#39;two&#39;, &#39;three&#39;];

let [one1, two1, three1] = arr;
console.log(one1, two1, three1);

// 배열읫 선언 분리 비구조화 할당 
let [one2, two2, three2] = [&#39;one&#39;, &#39;two&#39;, &#39;three&#39;];
console.log(one2, two2, three2);</code></pre>
<pre><code>one two three
one two three</code></pre><p>배열의 요소들을 하나 하나의 변수들로 할당할 경우 위와 같이 작성할 수 있지만, 비구조화 할당을 사용하면 더욱 간편하게 변수를 만들 수 있다.</p>
<pre><code class="language-js">let [one, two, three, four] = [&#39;one&#39;, &#39;two&#39;, &#39;three&#39;];
console.log(one, two, three, four);</code></pre>
<pre><code>one two three undefined</code></pre><p>배열의 요소보다 더 많은 변수를 할당받고 싶을 경우 마지막 변수에<code>undefined</code>가 할당된다. </p>
<pre><code class="language-js">let [one, two, three, four = &#39;four&#39;] = [&#39;one&#39;, &#39;two&#39;, &#39;three&#39;];
console.log(one, two, three, four);</code></pre>
<pre><code>one two three four</code></pre><p>변수의 기본값을 설정해줄 수 있다.</p>
<h1 id="활용">활용</h1>
<h2 id="스왑">스왑</h2>
<pre><code class="language-js">let a = 10;
let b = 20;
let tmp = 0;

tmp = a;
a = b;
b = tmp;
console.log(a, b);</code></pre>
<pre><code>20 10</code></pre><p>각각 변수의 값을 서로 바꾸기 위해서는 <code>tmp</code>변수를 만들어 보관했다가 옮기는 방식을 사용했다.</p>
<pre><code class="language-js">let a = 10;
let b = 20;

[a, b] = [b, a];
console.log(a, b);</code></pre>
<pre><code>20 10</code></pre><p>비구조화 할당을 이용해 간단하게 스왑기능을 구현할수 있다.</p>
<h2 id="객체-할당">객체 할당</h2>
<pre><code class="language-js">let object = { one: &#39;one&#39;, two: &#39;two&#39;, three: &#39;three&#39; };

let one = object.one;
let two = object.two;
let three = object.three;

console.log(one, two, three);</code></pre>
<pre><code>one two three</code></pre><p>객체의 값을 변수에 할당하는 것 또한 비구조화 할당을 활용할 수 있다.</p>
<pre><code class="language-js">let object = { one: &#39;one&#39;, two: &#39;two&#39;, three: &#39;three&#39;, name: &#39;홍길동&#39; };

let { name, one, two, three } = object;

console.log(one, two, three, name);</code></pre>
<pre><code>one two three 홍길동</code></pre><p>객체의 비구조화 할당은 인덱스나 순서가 아닌 <strong>키 값</strong>을 기준으로 할당받아햐 한다.</p>
<pre><code class="language-js">let object = { one: &#39;one&#39;, two: &#39;two&#39;, three: &#39;three&#39;, name: &#39;홍길동&#39; };

let { name: myName, one, two, three } = object;

console.log(one, two, three, myName);</code></pre>
<pre><code>one two three 홍길동</code></pre><p>변수의 이름을 다르게 할당할 수도 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[JS - 단락회로 평가(단축평가)]]></title>
            <link>https://velog.io/@gimmicks_/JS-%EB%8B%A8%EB%9D%BD%ED%9A%8C%EB%A1%9C-%ED%8F%89%EA%B0%80</link>
            <guid>https://velog.io/@gimmicks_/JS-%EB%8B%A8%EB%9D%BD%ED%9A%8C%EB%A1%9C-%ED%8F%89%EA%B0%80</guid>
            <pubDate>Sat, 21 May 2022 09:58:44 GMT</pubDate>
            <description><![CDATA[<h1 id="단락회로-평가단축평가">단락회로 평가(단축평가)</h1>
<blockquote>
<p>short-circuit evaluation</p>
</blockquote>
<pre><code class="language-js">console.log(false &amp;&amp; true);</code></pre>
<p><code>&amp;&amp;</code>연산자의 경우 둘 다 <code>true</code>일 경우 <code>true</code>를 반환하기 때문에 <strong>첫 번째 피연산자</strong>가 <code>false</code>일 경우 뒤의 피연산자는 굳이 볼 필요가 없어 연산을 끝내버리게 된다.</p>
<p><strong>이처럼 단락회로 평가는 표현식을 평가하는 도중에 평가 결과가 확정된 경우 나머지 평가 과정을 생략하는 것을 말한다.</strong></p>
<pre><code class="language-js">console.log(true || false);</code></pre>
<p><code>||</code>연산자도 마찬가지로 두 피연산자 중 하나만 <code>true</code>일 경우 <code>true</code>를 반환하기 때문에 뒤의 연산자는 볼 필요 없이 연산이 끝나버린다.</p>
<hr>
<p>** + 또한, 논리 연산자의 표현식의 결과는 <code>Boolean</code>값이 아닐 수도 있다.** </p>
<pre><code class="language-js">console.log(&#39;Cat&#39; &amp;&amp; &#39;Dog&#39;)
console.log(&#39;Cat&#39; || &#39;Dog&#39;)</code></pre>
<pre><code>Dog
Cat</code></pre><p>위 예제에서 <code>&#39;Dog&#39;</code> 와 <code>&#39;Cat&#39;</code>는  둘 다 <code>Truthy</code>한 값이다. 이 경우 <code>&amp;&amp;</code>연산자는 두번째 피연산자에서 평가 결과가 결정되므로 <code>Dog</code>를 반환하고, <code>||</code>연산자의 경우 첫번째 피연산자에서 평가 결과가 이미 결정되므로 <code>Cat</code>을 반환한다.</p>
<p>이런 단락회로 평가의 특성을 다양하게 활용할 수 있다.</p>
<h1 id="활용">활용</h1>
<h2 id="객체를-가리키기를-기대하는-변수가-null-또는-undefined가-아닌지-확인하고-프로퍼티를-참조할-때">객체를 가리키기를 기대하는 변수가 null 또는 undefined가 아닌지 확인하고 프로퍼티를 참조할 때</h2>
<pre><code class="language-js">const getName = (person) =&gt; {
  if (!person) {
    return &#39;객체가 아닙니다.&#39;;
  }
  return person.name;
};

let person;
const name = getName(person);
console.log(name);</code></pre>
<pre><code>객체가 아닙니다.</code></pre><p><code>Falsy</code> 속성을 이용해 예외를 만들어주는 예제를 사용했지만, 단락회로 평가를 사용해 코드를 더욱 간편하게 작성할 수 있다.</p>
<pre><code class="language-js">const getName = (person) =&gt; {
  const name = person &amp;&amp; person.name;
  return name || &#39;객체가 아닙니다.&#39;;
};

let person1 = { name: &#39;홍길동&#39; };
let person2 = null;

const name1 = getName(person1);
const name2 = getName(person2);

console.log(name1);
console.log(name2);
</code></pre>
<pre><code>홍길동
객체가 아닙니다.</code></pre><p><code>&amp;&amp;</code>연산에서 앞의 <code>person2</code> 의 값이 <code>Falsy</code>하기 때문에 코드가 끝나 두번째 피연산자인 <code>person.name</code>은 실행되지 않는다. 이런 속성을 이용하여 논리 연산자를 통해 간단하게 예외처리를 할 수 있다.</p>
<h2 id="함수-매개변수에-기본값을-설정할-때">함수 매개변수에 기본값을 설정할 때</h2>
<pre><code class="language-js">function getStringlength(str) {
  str = str || &#39;&#39;;
  return str.length;
}

console.log(getStringlength());
console.log(getStringlength(&#39;hi&#39;));</code></pre>
<pre><code>0
2</code></pre><p>함수를 호출할 때 인수를 전달하지 않으면 매개변수에는 <code>undefined</code>가 할당되어 위 함수의 경우 에러가 발생한다, 이 때 단락회로 평가를 사용해 매개변수의 기본값을 설정하면 에러를 방지할 수 있다.</p>
<pre><code class="language-js">function getStringlength(str = &#39;&#39;) {
  return str.length;
}</code></pre>
<p>번외 : ES6 매개변수의 기본값 설정</p>
<h2 id="다양한-유형의-값을-선택해서-리턴해야-할-때">다양한 유형의 값을 선택해서 리턴해야 할 때</h2>
<pre><code class="language-js">const getMeal = (mealType) =&gt; {
  if (mealType === &#39;한식&#39;) return &#39;불고기&#39;;
  if (mealType === &#39;양식&#39;) return &#39;파스타&#39;;
  if (mealType === &#39;중식&#39;) return &#39;멘보샤&#39;;
  if (mealType === &#39;일식&#39;) return &#39;초밥&#39;;
  return &#39;굶기&#39;;
};

const meal = {
  한식: &#39;불고기&#39;,
  중식: &#39;멘보샤&#39;,
  일식: &#39;초밥&#39;,
  양식: &#39;스테이크&#39;,
  인도식: &#39;카레&#39;,
};

const getMeal2 = (mealType) =&gt; {
  return meal[mealType] || &#39;굶기&#39;;
};

console.log(getMeal2(&#39;한식&#39;));
console.log(getMeal2(&#39;터키식&#39;));</code></pre>
<pre><code>불고기
굶기</code></pre><p>위의 예제처럼 다양한 값을 <code>getMeal()</code>함수처럼 <code>if</code>문을 통해 리턴할 경우 문법이 길어지고 수정이 힘들다. <code>meal</code> 객체를 생성 후 <code>getMeal2()</code>함수처럼 단락회로 평가의 특성을 활용할 경우 더욱 간결하고 수정에 용이하게 코드를 작성할 수 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[JS - 삼항 연산자]]></title>
            <link>https://velog.io/@gimmicks_/JS-%EC%82%BC%ED%95%AD-%EC%97%B0%EC%82%B0%EC%9E%90</link>
            <guid>https://velog.io/@gimmicks_/JS-%EC%82%BC%ED%95%AD-%EC%97%B0%EC%82%B0%EC%9E%90</guid>
            <pubDate>Sat, 21 May 2022 08:51:41 GMT</pubDate>
            <description><![CDATA[<h1 id="삼항-연산자">삼항 연산자</h1>
<pre><code class="language-js">조건문 ? 참일 때 실행 : 거짓일 때 실행</code></pre>
<p>삼항연산자는 조건문을 간단하게 작성할 때 사용하는 문법이다.</p>
<pre><code class="language-js">let a = 3;

if (a &gt;= 0) {
  console.log(&#39;양수&#39;);
} else {
  console.log(&#39;음수&#39;);
}</code></pre>
<pre><code>양수</code></pre><p>알고 싶은 수가 양수인지 음수인지를 판단하기 위해 <code>if</code>문을 활용했다. 위 코드를 삼항연산자를 사용할 경우 간단하게 표현할 수 있다.</p>
<pre><code class="language-js">let a = 3;

a &gt;= 0 ? console.log(&#39;양수&#39;) : console.log(&#39;음수&#39;);</code></pre>
<pre><code>양수</code></pre><h2 id="활용-1">활용 1</h2>
<pre><code class="language-js">let a = [];

const arrayStatus = a.length === 0 ? &#39;빈 배열&#39; : &#39;빈 배열이 아님&#39;;
console.log(arrayStatus);</code></pre>
<pre><code>빈 배열</code></pre><p>값을 <code>return</code>하도록 사용할 수 있다.</p>
<h2 id="활용-2">활용 2</h2>
<pre><code class="language-js">let a;
let b = [];

const result1 = a ? true : false;
const result2 = b ? true : false;

console.log(result1);
console.log(result2);</code></pre>
<pre><code>false
true</code></pre><p><a href="https://velog.io/@gimmicks_/JS-Truthy%EC%99%80-Falsy"><code>Truthy</code>와 <code>Falsy</code></a>를 활용해 사용할 수 있다.</p>
<h2 id="활용-3">활용 3</h2>
<pre><code class="language-js">/*
학점 계산 프로그램
90점 이삼 A+
50점 이삼 B+
둘다 아니면 F
*/
let score = 95; // A+
// let score = 70; // B+
// let score = 40; // F

score &gt;= 90 ? console.log(&#39;A+&#39;) : score &gt;= 50 ? console.log(&#39;B+&#39;) : console.log(&#39;F&#39;);</code></pre>
<pre><code></code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[JS - Truthy와 Falsy]]></title>
            <link>https://velog.io/@gimmicks_/JS-Truthy%EC%99%80-Falsy</link>
            <guid>https://velog.io/@gimmicks_/JS-Truthy%EC%99%80-Falsy</guid>
            <pubDate>Sat, 21 May 2022 08:34:51 GMT</pubDate>
            <description><![CDATA[<h1 id="truthy">Truthy</h1>
<p><code>Truthy</code>는 자바스크립트에서 <code>Boolean</code>을 기대하는 문맥에서 <strong>참</strong>으로 평가하는 값이다. - <a href="https://developer.mozilla.org/en-US/docs/Glossary/Truthy">참고</a></p>
<pre><code class="language-js">if (true)
if ({})
if ([])
if (42)
if (&quot;0&quot;)
if (&quot;false&quot;)
if (new Date())
if (-42)
if (12n)
if (3.14)
if (-3.14)
if (Infinity)
if (-Infinity)</code></pre>
<h1 id="falsy">Falsy</h1>
<p><code>Falsy</code>는 자바스크립트에서 <code>Boolean</code>을 기대하는 문맥에서 <strong>거짓</strong>으로 평가하는 값이다. - <a href="https://developer.mozilla.org/en-US/docs/Glossary/Falsy">참고</a></p>
<pre><code class="language-js">false, null, undefined, 0, -0, NaN, &quot;&quot;(빈문자열)</code></pre>
<h1 id="활용">활용</h1>
<pre><code class="language-js">const getName = (person) =&gt; {
  if (!person) {
    return &#39;객체가 아닙니다&#39;;
  }
  return person.name;
};

let person1 = null;
let person2 = { name: &#39;홍길동&#39; };

const name1 = getName(person1);
const name2 = getName(person2);

console.log(name1);
console.log(name2);</code></pre>
<pre><code>홍길동</code></pre><p><code>getName()</code>에 들어오는 매개변수가 <code>name</code>이라는 프로퍼티를 가지지 않거나, 아예 <code>null</code>이나 <code>undefined</code>같이 객체가 아닐경우 에 대해 <code>if (person === null || person === null)</code>과 같이 모든 경우에 대해 예외처리를 해주어야 한다. </p>
<p>이런 경우에 <code>Truthy</code>와 <code>Falsy</code>의 성질을 이용해서 예외처리를 해줄 수 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[JS - 배열 내장 함수]]></title>
            <link>https://velog.io/@gimmicks_/JS-%EB%B0%B0%EC%97%B4-%EB%82%B4%EC%9E%A5-%ED%95%A8%EC%88%98</link>
            <guid>https://velog.io/@gimmicks_/JS-%EB%B0%B0%EC%97%B4-%EB%82%B4%EC%9E%A5-%ED%95%A8%EC%88%98</guid>
            <pubDate>Sat, 21 May 2022 07:52:20 GMT</pubDate>
            <description><![CDATA[<h1 id="배열의-내장함수">배열의 내장함수</h1>
<h2 id="for문">for문</h2>
<pre><code class="language-js">const arr = [1, 2, 3, 4];
for (let i = 0; i &lt; arr.length; i++) {
  console.log(arr[i]);
}</code></pre>
<pre><code>1
2
3
4</code></pre><h2 id="foreach-메소드">forEach 메소드</h2>
<pre><code class="language-js">const arr = [1, 2, 3, 4];
arr.forEach((elm) =&gt; console.log(elm));</code></pre>
<pre><code>1
2
3
4</code></pre><p>배열의 하나 하나 요소를 콜백함수의 파라미터로 전달해준다.</p>
<p><code>forEach</code> 메소드를 활요해서 배열의 요소에 2배를 한 새로운 배열 만들기</p>
<pre><code class="language-js">const arr = [1, 2, 3, 4];
const newArr = [];

arr.forEach((elm) =&gt; newArr.push(elm * 2));
console.log(newArr);</code></pre>
<pre><code>[ 2, 4, 6, 8 ]</code></pre><h2 id="map-메소드">map 메소드</h2>
<pre><code class="language-js">const arr = [1, 2, 3, 4];
const newArr = arr.map((elm) =&gt; {
  return elm * 2;
});
console.log(newArr);</code></pre>
<pre><code>[ 2, 4, 6, 8 ]</code></pre><p><code>map</code> 메소드는 원본 배열의 모든 요소를 순회하면서 연산해 <code>return</code>된 값들을을 반환해 새로운 배열을 만들어준다.</p>
<h2 id="includes-메소드">includes 메소드</h2>
<pre><code class="language-js">const arr = [1, 2, 3, 4];
let number = 3;

arr.forEach((elm) =&gt; {
  if (elm === number) {
    console.log(true);
  }
});</code></pre>
<pre><code>true</code></pre><p><code>arr</code>배열 안에 <code>number</code>와 일치하는 값이 있는지 확인하는 프로그램, <code>include</code> 메소드를 이용하면 훨씬 간단하게 작성할 수 있다.</p>
<pre><code class="language-js">const arr = [1, 2, 3, 4];
let number = 3;

console.log(arr.includes(number));</code></pre>
<p>주어진 배열에서 전달받은 인자와 일치하는 값이 존재하는지 확인해주는 메소드이다. 타입까지 같은 값을 찾아주는 것을 유의하자 (<code>===</code>)</p>
<h2 id="indexof-메소드">indexOf 메소드</h2>
<pre><code class="language-js">const arr = [1, 2, 3, 4];
let number1 = 3;
let number2 = &#39;3&#39;;

console.log(arr.indexOf(number1));
console.log(arr.indexOf(number2));</code></pre>
<pre><code>2
-1</code></pre><p><code>indexOf</code>메소드는 주어진 배열에서 전달받은 인자와 일치하는 값이 있으면 인덱스를 찾아준다. 값이 배열에 존재하지 않을 경우 <code>-1</code>을 반환해준다.</p>
<h2 id="findindex-메소드">findIndex 메소드</h2>
<pre><code class="language-js">const arr = [
  { color: &#39;red&#39; },
  { color: &#39;blue&#39; },
  { color: &#39;black&#39; },
  { color: &#39;green&#39; }
];


console.log(
  arr.findIndex((elm) =&gt; {
    return elm.color === &#39;green&#39;;
  })
);</code></pre>
<pre><code>3</code></pre><p><code>findIndex</code>메소드는해당 콜백함수가 <code>true</code>인 <strong>첫번째 요소</strong>를 반환해준다. </p>
<h2 id="find-메소드">find 메소드</h2>
<pre><code class="language-js">const arr = [
  { color: &#39;red&#39; },
  { color: &#39;blue&#39; },
  { color: &#39;black&#39; },
  { color: &#39;green&#39; }
];

console.log(
  arr.find((elm) =&gt; {
    return elm.color === &#39;green&#39;;
  })
);</code></pre>
<pre><code>{ color: &#39;green&#39; }</code></pre><p><code>find</code>메소드는 <code>findIndex</code>와 비슷하지만, 해당 요소의 인덱스가 아닌 요소를 반환해준다.</p>
<h2 id="filter-메소드">filter 메소드</h2>
<pre><code class="language-js">const arr = [
  { num: 1, color: &#39;red&#39; },
  { num: 2, color: &#39;blue&#39; },
  { num: 3, color: &#39;black&#39; },
  { num: 4, color: &#39;green&#39; },
  { num: 5, color: &#39;blue&#39; },
];

console.log(arr.filter((elm) =&gt; elm.color === &#39;blue&#39;));</code></pre>
<pre><code>[ { num: 2, color: &#39;blue&#39; }, { num: 5, color: &#39;blue&#39; } ]</code></pre><p><code>filter</code>메소드는 전달한 콜백함수가 <code>true</code>를 반환하는 요소들을 <strong>배열로 반환</strong>하는 메소드이다.</p>
<h2 id="slice-메소드">slice 메소드</h2>
<pre><code class="language-js">const arr = [
  { num: 1, color: &#39;red&#39; },
  { num: 2, color: &#39;blue&#39; },
  { num: 3, color: &#39;black&#39; },
  { num: 4, color: &#39;green&#39; },
  { num: 5, color: &#39;blue&#39; },
];

console.log(arr.slice(0, 2));</code></pre>
<pre><code>[ { num: 1, color: &#39;red&#39; }, { num: 2, color: &#39;blue&#39; } ]</code></pre><p>배열을 잘라주는 메소드 <code>slice(a,b)</code>일경우 <code>a 인덱스</code>부터 <code>b 인덱스 - 1</code>까지의 요소들을 잘라서 반환해준다</p>
<h2 id="concat-메소드">concat 메소드</h2>
<pre><code class="language-js">const arr1 = [
  { num: 1, color: &#39;red&#39; },
  { num: 2, color: &#39;blue&#39; },
  { num: 3, color: &#39;black&#39; },
];

const arr2 = [
  { num: 4, color: &#39;green&#39; },
  { num: 5, color: &#39;blue&#39; },
];

console.log(arr1.concat(arr2));</code></pre>
<pre><code>[
  { num: 1, color: &#39;red&#39; },
  { num: 2, color: &#39;blue&#39; },
  { num: 3, color: &#39;black&#39; },
  { num: 4, color: &#39;green&#39; },
  { num: 5, color: &#39;blue&#39; }
]</code></pre><p>두 배열을 합쳐서 반환해주는 메소드</p>
<h2 id="sort메소드">sort메소드</h2>
<pre><code class="language-js">let chars = [&#39;나&#39;, &#39;다&#39;, &#39;가&#39;];

console.log(chars);
chars.sort();
console.log(chars);</code></pre>
<pre><code>[ &#39;나&#39;, &#39;다&#39;, &#39;가&#39; ]
[ &#39;가&#39;, &#39;나&#39;, &#39;다&#39; ]</code></pre><p>원본 배열을 정리하는 메소드</p>
<pre><code class="language-js">let numbers = [0, 1, 3, 2, 10, 30, 20];

console.log(numbers);
numbers.sort();
console.log(numbers);</code></pre>
<pre><code>[
   0,  1,  3, 2,
  10, 30, 20
]
[
   0, 1, 10, 2,
  20, 3, 30
]</code></pre><p>숫자를 정렬할 경우 문자를 기준으로 정렬(사전순)이 된다.</p>
<p>이런 경우를 위해 비교함수를 직접 만들어 정렬해줄 수 있다.</p>
<pre><code class="language-js">let numbers = [0, 1, 3, 2, 10, 30, 20];
const compare = (a, b) =&gt; {
  if (a &gt; b) {
    // 크다 - 뒤로 보냄
    return 1;
  }
  if (a &lt; b) {
    // 작다 - 앞으로 보냄
    return -1;
  }
  // 같다
  return 0;
};

console.log(numbers);
numbers.sort(compare);
console.log(numbers);</code></pre>
<pre><code>[
   0,  1,  3, 2,
  10, 30, 20
]
[
   0,  1,  2, 3,
  10, 20, 30
]</code></pre><h2 id="join-메소드">join 메소드</h2>
<pre><code class="language-js">const arr = [&#39;Hello&#39;, &#39;world&#39;, &#39;!&#39;];
console.log(arr.join(&#39; &#39;));</code></pre>
<pre><code>Hello world !</code></pre><p>배열의 모든 요소를 하나의 문자열로 합쳐주는 메소드. 매개변수를 넣지 않을 경우 <code>,</code>가 자동으로 넣어진다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[파이썬 지역변수와 전역변수]]></title>
            <link>https://velog.io/@gimmicks_/%ED%8C%8C%EC%9D%B4%EC%8D%AC-%EC%A7%80%EC%97%AD%EB%B3%80%EC%88%98%EC%99%80-%EC%A0%84%EC%97%AD%EB%B3%80%EC%88%98</link>
            <guid>https://velog.io/@gimmicks_/%ED%8C%8C%EC%9D%B4%EC%8D%AC-%EC%A7%80%EC%97%AD%EB%B3%80%EC%88%98%EC%99%80-%EC%A0%84%EC%97%AD%EB%B3%80%EC%88%98</guid>
            <pubDate>Wed, 04 May 2022 07:38:29 GMT</pubDate>
            <description><![CDATA[<h1 id="case1">Case1</h1>
<h2 id="case1-1">Case1-1</h2>
<pre><code class="language-py">def DFS1():
    print(&quot;In DFS1 :&quot;, cnt)

def DFS2():
    if cnt == 5:
        print(&quot;In DFS2 :&quot;, cnt)

cnt = 5
DFS1()
DFS2()
print(&quot;바깥 :&quot;, cnt)</code></pre>
<pre><code>In DFS1 : 5
In DFS2 : 5
바깥 : 5</code></pre><p>함수 안에서 변수가 호출되게 되면 컴퓨터는 <code>지역변수(스택 메모리)</code>를 먼저 찾고, 없으면 <code>전역변수(데이터 메모리)</code>를 찾게된다. <code>DFS1,2</code>함수에는 <code>cnt</code>변수가 선언되지 않았기 때문에 전역변수를 출력해주는 것을 확인할 수 있다.</p>
<h2 id="case1-2">Case1-2</h2>
<pre><code class="language-py">def DFS1():
    cnt = 3
    print(&quot;In DFS1 :&quot;, cnt)

def DFS2():
    if cnt == 5:
        print(&quot;In DFS2 :&quot;, cnt)

cnt = 5
DFS1()
DFS2()
print(&quot;바깥 :&quot;, cnt)</code></pre>
<pre><code>In DFS1 : 3
In DFS2 : 5
바깥 : 5</code></pre><p><code>DFS1()</code>함수에 <code>cnt</code>지역변수가 선언되어 스택메모리에 쌓이고 <code>cnt</code>변수를 출력했을 때 지역변수가 호출되어 3이 출력된다. <code>DFS1()</code>함수 호출이 종료되는 순간 스택 메모리에 저장된 지역변수 <code>cnt</code>는 삭제되고, <code>DFS2()</code> 에서는 전역변수 <code>cnt</code>가 출력된다.</p>
<h2 id="case1-3">Case1-3</h2>
<pre><code class="language-py">def DFS1():
    cnt = 3
    print(&quot;In DFS1 :&quot;, cnt)

def DFS2():  
    if cnt == 5: # &lt;&lt; the error occurs here
        cnt = cnt + 1
        print(&quot;In DFS2 :&quot;, cnt)

cnt = 5
DFS1()
DFS2()
print(&quot;바깥 :&quot;, cnt)</code></pre>
<pre><code>.
.
.
UnboundLocalError: local variable &#39;cnt&#39; referenced before assignment</code></pre><p><code>DFS2()</code>함수가 먼저 기계어로 번역될 때 함수 안의<code>cnt</code>가 지역변수로 먼저 번역이 된 후 <code>DFS2()</code>함수가 호출된다. 함수가 실행될 때 에러가 발생하는 라인에서 <code>cnt</code>는 지역변수를 참조해야 하지만, 선언된 지역변수<code>cnt</code>가 없기 때문에 오류를 출력하게 된다.</p>
<h2 id="case1-4">Case1-4</h2>
<pre><code class="language-py">def DFS1():
    cnt = 3
    print(&quot;In DFS1 :&quot;, cnt)

def DFS2():
    global cnt
    if cnt == 5:
        cnt = cnt + 1
        print(&quot;In DFS2 :&quot;, cnt)

cnt = 5
DFS1()
DFS2()
print(&quot;바깥 :&quot;, cnt)</code></pre>
<pre><code>In DFS1 : 3
In DFS2 : 6
바깥 : 6</code></pre><p>이를 해결하기 위해 전역변수를 함수 내에서 사용할 수 있도록 <code>global</code>을 이용한다. 이는 함수 내에서 해당 변수를 데이터 메모리 영역에 있는 전역변수의 메모리를 가르키겠다는 뜻으로, 함수내에서 해당 변수를 수정할 경우 전역변수가 수정됨을 인지해야 한다. </p>
<h1 id="case2추가-예제">Case2(추가 예제)</h1>
<h2 id="case2-1">Case2-1</h2>
<pre><code class="language-py">def DFS():
    a[0] = 7
    print(&quot;In DFS :&quot;, a)

a = [1, 2, 3]
DFS()
print(&quot;바깥 :&quot;, a)</code></pre>
<pre><code>In DFS : [7, 2, 3]
바깥 : [7, 2, 3]</code></pre><h2 id="case2-2">Case2-2</h2>
<pre><code class="language-py">def DFS():
    a = [7, 8] 
    print(&quot;In DFS :&quot;, a)

a = [1, 2, 3]
DFS()
print(&quot;바깥 :&quot;, a)</code></pre>
<pre><code>In DFS : [7, 8]
바깥 : [1, 2, 3]</code></pre><h2 id="case2-3">Case2-3</h2>
<pre><code class="language-py">def DFS():
    a = a + [4] # the error occurs here
    print(&quot;In DFS :&quot;, a)

a = [1, 2, 3]
DFS()
print(&quot;바깥 :&quot;, a)</code></pre>
<pre><code>.
.
.
UnboundLocalError: local variable &#39;a&#39; referenced before assignment</code></pre><h2 id="case2-4">Case2-4</h2>
<pre><code class="language-py">def DFS():
    global a
    a = a + [4] 
    print(&quot;In DFS :&quot;, a)

a = [1, 2, 3]
DFS()
print(&quot;바깥 :&quot;, a)</code></pre>
<pre><code>In DFS : [1, 2, 3, 4]
바깥 : [1, 2, 3, 4]</code></pre><p>출처 : 인프런 파이썬 알고리즘 강의  <a href="https://inf.run/MJQ5">https://inf.run/MJQ5</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[C_알고리즘 구현]]></title>
            <link>https://velog.io/@gimmicks_/calgorithm</link>
            <guid>https://velog.io/@gimmicks_/calgorithm</guid>
            <pubDate>Tue, 05 Apr 2022 04:33:23 GMT</pubDate>
            <description><![CDATA[<h1 id="linked-list">Linked list</h1>
<pre><code class="language-c">#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;string.h&gt;
#include &lt;stdbool.h&gt;
// #include &lt;conio.h&gt;

//노드 구조체
struct Node
{
    int value;
    struct Node *next;
};

struct Node *head;
// 연결리스트 초기화 - 머리 할당
void InitList()
{
    head = (struct Node *)malloc(sizeof(struct Node));
    head -&gt; next = NULL;
}

// Target 다음에 노드를 삽입
struct Node *InsertNode(struct Node *Target, struct Node *aNode)
{
    struct Node *New;

    New = (struct Node *)malloc(sizeof(struct Node));
    *New = *aNode;
    New -&gt; next = Target -&gt; next;
    Target -&gt; next = New;
    return New;
}

// Target 다음 노드를 삭제
bool DeleteNode(struct Node *Target)
{
    struct Node *Del;

    Del = Target -&gt; next;
    if (Del == NULL)
    {
        return 0;
    }
    Target -&gt; next = Del -&gt; next;
    free(Del);
    return 1;
}

void UnInitList()
{
    while (DeleteNode(head)) {;}

    free(head);
    head = NULL;
}

int main()
{
    int i;
    struct Node *Now, Temp;

    InitList();

    // 다섯 개의 노드 삽입
    Now = head;
    for (i = 1; i &lt;= 5; i++)
    {
        Temp.value = i;
        Now = InsertNode(Now, &amp;Temp);
    }

    // 두 번째 노드 삭제
    DeleteNode(head -&gt; next);

    // 순회하면서 출력
    for (Now = head -&gt; next; Now; Now = Now -&gt; next)
    {
        printf(&quot;%d\t&quot;, Now -&gt; value);
    }
    printf(&quot;\n&quot;);

    UnInitList();
}</code></pre>
<pre><code>1       3       4       5</code></pre><h1 id="stack">Stack</h1>
<pre><code class="language-c">#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;

int *Stack;
int Size;
int Top;

void InitStack(int aSize)
{
    Size = aSize;
    Stack = (int *)malloc(Size * sizeof(int));
    Top = -1;
}

void FreeStack()
{
    free(Stack);
}

int Push(int data)
{
    if (Top &lt; Size - 1)
    {
        Top++;
        Stack[Top] = data;
        return 1;
    }
    else
    {
        return 0;
    }
}

int Pop()
{
    if(Top &gt;= 0)
    {
        return Stack[Top--];
    }
    else
    {
        return -1;
    }
}

int main()
{
    InitStack(256);
    Push(7);
    Push(0);
    Push(6);
    Push(2);
    Push(9);
    printf(&quot;%d\n&quot;, Pop());
    printf(&quot;%d\n&quot;, Pop());
    printf(&quot;%d\n&quot;, Pop());
    printf(&quot;%d\n&quot;, Pop());
    printf(&quot;%d\n&quot;, Pop());
    FreeStack();
}</code></pre>
<pre><code>9
2
6
0
7</code></pre><h1 id="queue">Queue</h1>
<ul>
<li>head : 다음 삭제될 위치. 처리할 자료를 빼낸다.</li>
<li>tail : 다음 삽입될 위치. 새로 도착하는 자료가 쌓인다.<pre><code class="language-c">#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
</code></pre>
</li>
</ul>
<p>int *Queue;
int QSize;
int head, tail;</p>
<p>void InitQueue(int size)
{
    QSize = size;
    Queue = (int *)malloc(QSize * sizeof(int));
    head = tail = 0;
}</p>
<p>void FreeQueue()
{
    free(Queue);
}</p>
<p>int Enqueue(int data)
{
    if ((tail + 1) % QSize == head)
    {
        return 0;
    }</p>
<pre><code>Queue[tail] = data;
tail = (tail + 1) % QSize;
return 1;</code></pre><p>}</p>
<p>int Dequeue()
{
    int data;
    if (head == tail)
    {
        return -1;
    }
    data = Queue[head];
    head = (head + 1) % QSize;
    return data;
}</p>
<p>int main()
{
    int i;
    InitQueue(10);</p>
<pre><code>printf(&quot;빈 상태에서 삭제할 때 = %d\n&quot;, Dequeue());
for(i = 0; i &lt; 9; i++)
{
    Enqueue(i);
}

printf(&quot;가득찬 상태에서 삽입 = %s\n&quot;, Enqueue(100) ? &quot;성공&quot; : &quot;실패&quot;);
for(i = 0; i &lt; 9; i++)
{
    printf(&quot;%d &quot;, Dequeue());
}

FreeQueue();</code></pre><p>}</p>
<pre><code></code></pre><p>빈 상태에서 삭제할 때 = -1
가득찬 상태에서 삽입 = 실패
0 1 2 3 4 5 6 7 8
```</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[C++_OOP5]]></title>
            <link>https://velog.io/@gimmicks_/cpp5</link>
            <guid>https://velog.io/@gimmicks_/cpp5</guid>
            <pubDate>Mon, 04 Apr 2022 07:17:08 GMT</pubDate>
            <description><![CDATA[<h1 id="클래스의-동적-메모리-할당">클래스의 동적 메모리 할당</h1>
<h2 id="대입-연산자-오버로딩">대입 연산자 오버로딩</h2>
<p>기호가 같은 연산자를 여러 가지 기능을 가질 수 있도록 정의할 수 있다. 이를 <code>연산자 오버로딩</code>이라고 한다.</p>
<pre><code class="language-cpp">#include &lt;iostream&gt;
using namespace std;
class String
{
public:
    String(char ch, int nSize);
    ~String();
    void operator=(const String&amp; s);
    void SetData();

private:
    int nLength;
    char *pBuffer;
};

String::String(char ch, int nSize)
{
    nLength = nSize;
    pBuffer = new char[nLength + 1];
    memset(pBuffer, ch, nLength);
    pBuffer[nLength] = &#39;\0&#39;;
    cout &lt;&lt; &quot;pBuffer : &quot; &lt;&lt; pBuffer &lt;&lt; endl;
    cout &lt;&lt; &quot;nLength : &quot; &lt;&lt; nLength &lt;&lt; endl;
}

String::~String()
{
    delete[] pBuffer;
}

void String::operator=(const String&amp; s) // &amp; : CallbyReference하겠다!
{
    delete pBuffer;
    nLength = s.nLength;
    pBuffer = new char[nLength + 1];
    strcpy(pBuffer, s.pBuffer);
}

void String::SetData()
{
    cout &lt;&lt; &quot;pBuffer : &quot; &lt;&lt; this-&gt;pBuffer &lt;&lt; endl;
    cout &lt;&lt; &quot;nLength : &quot; &lt;&lt; this-&gt;nLength &lt;&lt; endl;
}

int main()
{
    String str1(&#39;A&#39;, 5);
    String str2(&#39;B&#39;, 5);
    str1 = str2;
}</code></pre>
<pre><code>pBuffer : AAAAA
nLength : 5
pBuffer : BBBBB
nLength : 5</code></pre><p><img src="https://media.vlpt.us/images/gimmicks_/post/048ef1ee-c9e1-4940-91cc-a651385e2df8/image.png" alt=""></p>
<pre><code class="language-cpp">str1 = str2;
str2.operator=(str1);</code></pre>
<p>두 문장 모두 같은 것이다. 위처럼 본다면 더 직관적으로 이해할 수 있다.</p>
<h3 id="객체의-자기-자신-대입-시에-대한-처리">객체의 자기 자신 대입 시에 대한 처리</h3>
<pre><code class="language-cpp">str1 = str1;</code></pre>
<p>자기 자신을 대입시 먼저 <code>str1</code>이 가르키는 메모리가 delete될것이고, 새로운 메모리 공간을 힙영역에 <code>nLength</code>길이만큼 할당한다. 문제는 <code>strcpy()</code>시에 <code>s.pBuffer</code>값을 가지고 올 수 없으므로 결국 복사는 실패하게 된다.</p>
<p><img src="https://media.vlpt.us/images/gimmicks_/post/eae12263-cb88-4ba8-ba68-8a75aee6619f/image.png" alt=""></p>
<pre><code class="language-cpp">void String::operator=(const String&amp; s)
{
    if(&amp;s == this)
        return;
    delete pBuffer;
    nLength = s.nLength;
    pBuffer = new char[nLength + 1];
    strcpy(pBuffer, s.pBuffer);
}</code></pre>
<p><code>operator=()</code>멤버함수에서 <strong>전달인자로 넘겨받은 클래스 객체</strong>와 <strong>현재 멤버함수의 소속</strong> 클래스가 같은지 검사해서 코드는 실행되지 않도록 <code>return</code> 처리하면 문제를 해결할 수 있다.</p>
<h2 id="복사-생성자">복사 생성자</h2>
<pre><code class="language-cpp">String str1(&#39;A&#39;,3);
String str2 = str1; // 복사 생성자1
String str2(str1); // 복사 생성자2</code></pre>
<p>객체 생성 시 초기화를 하되, 생성되는 객체를 다른 객체로 초기화 할 때 호출되는 생성자.</p>
<pre><code class="language-cpp">#include &lt;iostream&gt;
using namespace std;
class String
{
public:
    String(char ch, int nSize);
    ~String();
    String(const String&amp; s);
    void operator=(const String&amp; s);
    void SetData();

private:
    int nLength;
    char *pBuffer;
};

String::String(char ch, int nSize)
{
    nLength = nSize;
    pBuffer = new char[nLength + 1];
    memset(pBuffer, ch, nLength);
    pBuffer[nLength] = &#39;\0&#39;;
    // cout &lt;&lt; &quot;pBuffer : &quot; &lt;&lt; pBuffer &lt;&lt; endl;
    // cout &lt;&lt; &quot;nLength : &quot; &lt;&lt; nLength &lt;&lt; endl;
}

String::~String()
{
    delete[] pBuffer;
}

String::String(const String&amp; s)
{
    this-&gt;nLength = s.nLength;
    this-&gt;pBuffer = new char[this-&gt;nLength + 1];
    strcpy(this-&gt;pBuffer, s.pBuffer);
}

void String::operator=(const String&amp; s)
{
    if(&amp;s == this)
        return;
    delete pBuffer;
    this-&gt;nLength = s.nLength;
    this-&gt;pBuffer = new char[this-&gt;nLength + 1];
    strcpy(this-&gt;pBuffer, s.pBuffer);
}

void String::SetData()
{
    cout &lt;&lt; &quot;pBuffer : &quot; &lt;&lt; this-&gt;pBuffer &lt;&lt; endl;
    cout &lt;&lt; &quot;nLength : &quot; &lt;&lt; this-&gt;nLength &lt;&lt; endl;
}

int main()
{
    String str1(&#39;A&#39;, 5);
    String str2(str1);
    // String str2 = str1;  윗문장과 같음
    cout &lt;&lt; &quot;대입 후 str2&quot; &lt;&lt; endl;
    str2.SetData();
}</code></pre>
<pre><code>대입 후 str2
pBuffer : AAAAA
nLength : 5</code></pre><p><code>operator</code>에서는 <code>pBuffer</code>를 <code>delete</code>를 해주었지만, 복사생성자에서는 <code>delete</code>를 하지 않는다. 그 이유는 <code>operator</code>에서는 기존에 있던 데이터를 없애고 값을 받아야 했지만, 복사 생성자에서는 객체가 처음 생성되는 시점이기 때문에 <code>delete</code>할 필요가 없기 때문이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[모두의 알고리즘 with Python]]></title>
            <link>https://velog.io/@gimmicks_/%EB%AA%A8%EB%91%90%EC%9D%98-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-with-Python</link>
            <guid>https://velog.io/@gimmicks_/%EB%AA%A8%EB%91%90%EC%9D%98-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-with-Python</guid>
            <pubDate>Sat, 02 Apr 2022 23:41:02 GMT</pubDate>
            <description><![CDATA[<h1 id="첫째마당-알고리즘-기초">[첫째마당] 알고리즘 기초</h1>
<h2 id="1부터-n까지-연속된-숫자의-합을-구하는-알고리즘">1부터 n까지 연속된 숫자의 합을 구하는 알고리즘</h2>
<ol>
<li>첫 번째 방법<pre><code class="language-py">def sum_n(n):
 a = 0
 for i in range(1, n+1):
     a = a + i
 return a
</code></pre>
</li>
</ol>
<p>print(sum_n(10))
print(sum_n(100))</p>
<pre><code>    55
    5050

for문을 이용하여 a에 저장된 값을 하나씩 늘려가는 방법이다.

2. 두 번째 방법
```py
def sum_n(n):
    return n * (n + 1) // 2

print(sum_n(10))
print(sum_n(100))</code></pre><pre><code>55
5050</code></pre><p>등차수열의 합을 구하는 공식인<br>$$\displaystyle\sum_{k=0}^{n}{k}=$$ $$n(n+ 1)\over 2$$ 을 이용하여 간단하게 작성할 수 있다. 
<br> 첫 번째 방법은 입력값 $$n$$이 커질수록 덧셈을 많이 반복하지만, 두 번째 방법은 $$n$$값의 크기와 관계없이 연산을 한번씩만 하면 답을 얻을 수 있기 때문에 더욱 좋은 방법이다. 
<br> 이렇게 주어진 문제를 푸는 여러 가지 방법 중 어떤 방법이 더 좋은 것인지 판단할 때 필요한 것이 <strong>&#39;알고리즘 분석&#39;</strong> 이다</p>
<h3 id="계산-복잡도">계산 복잡도</h3>
<p>어떤 알고리즘이 문제를 풀기 위해 해야 하는 계산이 얼마나 복잡한지 나타낸 정도를 <strong>&#39;계산 복잡도(complexity)&#39;</strong> 라고 한다. 계산 복잡도를 표현하는 방법에는 여러가지가 있는데, 그 중 대문자 O표기법을 많이 사용한다(빅 오 표기법)</p>
<p>첫 번째 알고리즘은 입력크기 $$n$$에 대해 사칙연산을 n번 해야한다. 이 때 이 알고리즘의 계산 복잡도를 $$O(n)$$이라고 표현한다. 필요한 계산 횟수가 입력 크기에 <strong>&#39;정비례&#39;</strong> 할 때 $$O(n)$$이라고 표현한다.</p>
<p>두 번째 알고리즘은 입력 크기 n과 무관하게 사칙연산을 세 번해야 한다. 이 때 알고리즘의 계산 복잡도는 $$O(1)$$로 표현한다.</p>
<ul>
<li>$$O(n)$$ : 필요한 계산 횟수가 입력 크기 $$n$$과 비례할 때</li>
<li>$$O(1)$$ : 필요한 계산 횟수가 입력 크기 $$n$$과 무관할 때</li>
</ul>
<h2 id="최댓값을-찾는-알고리즘">최댓값을 찾는 알고리즘</h2>
<pre><code class="language-py">def find_max(a):
    max_v = a[0]
    for i in range(1,len(a)):
        if a[i] &gt; max_v:
            max_v = a[i]
    return max_v</code></pre>
<p>리스트의 첫 번째 값을 저장해놓고, 다음 값을 첫 번째 값과 비교해 크다면 max_v에 할당하여 최댓값을 찾는 알고리즘이다.</p>
<p>이 알고리즘 또한 입력 크기가 $$n$$일 때 계산은 정비례관계에 있기 때문에, 계산복잡도를 $$O(n)$$으로 표현할 수 있다.</p>
<h2 id="최댓값의-위치를-구하는-알고리즘">최댓값의 위치를 구하는 알고리즘</h2>
<pre><code class="language-py">def find_max_idx(a):
    max_idx = 0
    for i in range(1,len(a)):
        if a[i] &gt; a[max_idx]:
            max_idx = i
    return max_idx</code></pre>
<h2 id="동명이인을-찾는-알고리즘">동명이인을 찾는 알고리즘</h2>
<pre><code class="language-py">name = [&quot;Tom&quot;, &quot;Jerry&quot;, &quot;Mike&quot;, &quot;Tom&quot;]

def find_same_name(a):
    n = len(a)
    result = set()
    for i in range(0, n - 1): #마지막은 비교할 필요가 없음
        for j in range(i + 1, n):  
            if a[i]==a[j]:
                result.add(a[i])
    return result</code></pre>
<p>n번째 이름을 마지막까지 같은지 차례차례 비교하고, 같은 이름이 있다면 result 집합에 추가한다. 마지막은 비교하지 않아도 되기 따문에, 두 번째 for문의 범위는 range(i+1, n)이 된다.</p>
<p>이 경우 계산복잡도는, 입력크기(이름 숫자) $$n$$에 대해 
$$0+1+2+...(n-1)$$번이다, 이를 등차수열의 합으로 계산하면 
$${1\over2}n^2+{1\over2}n$$번이 된다. 결국 $$n$$의 제곱에 비례해서 계산시간이 변하는 것이 핵심이기 때문에, 계산복잡도를 $$O(n^2)$$으로 표현할 수 있다.</p>
<h2 id="연습문제">연습문제</h2>
<pre><code class="language-py">#1부터 n까지 연속한 숫자의 제곱의 합을 구하는 프로그램
def pow_sum1(n):
    a = 0
    for i in range(1, n+1):
        a = a + i ** 2
    return a

def pow_sum2(n):
    return n * (n + 1) * (2 * n + 1) // 6</code></pre>
<pre><code class="language-py">#숫자 n개를 리스트로 입력받아 최솟값을 구하는 프로그램
lst = list(map(int, input().split()))

deffind_min(a):
    min_v = a[0]
    for i in range(1,len(a)):
        if a[i] &lt; min_v:
            min_v = a[i]
    return min_v

print(find_min(lst))</code></pre>
<pre><code class="language-py">#n명 중 두 명을 뽑아 짝을 지을 수 있는 모든 조합을 출력하는 프로그램
lst = [&quot;Tom&quot;, &quot;Jerry&quot;, &quot;Mike&quot;]

def pair_name(a):
    n = len(a)
    for i in range(0, n - 1):
        for j in range(i + 1, n):
            print(a[i], &quot;-&quot;, a[j])

print(pair_name(lst))</code></pre>
<h1 id="둘째마당-재귀-호출">[둘째마당] 재귀 호출</h1>
<h2 id="팩토리얼을-구하는-알고리즘">팩토리얼을 구하는 알고리즘</h2>
<pre><code class="language-py">def fact_1(n):
    f = 1
    for i in range(1, n + 1):
        f = f * i
    return f</code></pre>
<pre><code class="language-py">def fact_2(n):
    if n &lt;=1 :
        return 1
    return n * fact_2(n - 1)</code></pre>
<p>fact_2 함수는 $$n!=n*(n-1)!$$ 의 성질을 이용하여 작성한 재귀호출 코드이다.  반복문을 이용한 알고리즘과 재귀 호출을 이용한 알고리즘의 계산복잡도는 모두 $O(n)$이다.</p>
<h2 id="최대공약수-알고리즘">최대공약수 알고리즘</h2>
<pre><code class="language-py">def gcd_1(a, b):
    i = min(a, b)
    while True:
        if a % i == 0 and b % i == 0:
            return i
        i = i - 1</code></pre>
<pre><code class="language-py">def gcd_2(a,b):
    if b == 0:
        return a
    return gcd_2(b, a 5 b)</code></pre>
<p>gcd_1 코드는 두 수 중 더 작은 값을 놓고 1씩 줄여가며 공통된 약수인지 비교해보는 코드이다. gcd_2 코드는 유클리드 알고리즘을 이용한 코드인데, 수학자 유클리드가 생각해낸 최대공약수의 성질에 따라 작성한 코드이다.</p>
<blockquote>
<p>a와 b의 최대공약수는 &#39;b&#39;와 &#39;a를 b로 나눈 나머지&#39;의 최대공약수와 같다. $$gcd(a,b)=gcd(b,a%b)$$</p>
</blockquote>
<h2 id="하노이의-탑-옮기기">하노이의 탑 옮기기</h2>
<p>원반이 n개인 하노이의 탑 옮기기 (출발점 from, 도착점 to, 보조 aux)</p>
<pre><code class="language-py"># 하노이이의 탑 알고리즘
def hanoi(n, from_pos, to_pos, aux_pos):
    if n == 1:
        print(from_pos, &quot;-&gt;&quot;, to_pos)
        return

    hanoi(n - 1, from_pos, aux_pos, to_pos) # 원반 n-1개를 2번 기둥으로 이동
    print(from_pos, &quot;-&gt;&quot;, to_pos) # 가장 큰 원반을 3번 기둥으로 이동
    hanoi(n - 1, aux_pos, to_pos, from_pos) # 2번 기둥에 있는 n-1개 원반을 3번 기둥으로 이동
</code></pre>
<ol>
<li>원반이 한개면 그냥 옮기면 끝(종료조건)</li>
<li>1번 기둥에있는 n-1개를 2번 기둥으로 옮기기</li>
<li>1번 기둥에 있는 가장 큰 원반을 3번으로 옮기기</li>
<li>2번 기둥에 있는 n-1개 원반을 다시 3번 기둥으로 옮기기</li>
</ol>
<p>탑의 층수가 높을수록 원반을 더 많이 움직여야 한다. $n$층의 탑을 옮기려면 원반을 모두 $$2^n-1$$번 옮겨야 하는 것을 알 수 있으므로, 계산복잡도를 $O(2^n)$으로 나타낼 수 있다.</p>
<h2 id="연습문제-1">연습문제</h2>
<pre><code class="language-py"># 1부터 n까지의 합 구하기(재귀 호출)
def Q4_1(n):
    if n &lt;=1 :
        return 1
    return n + Q4_1(n-1)

# 숫자 n개 중에서 최댓값 찾기
def Q4_2(a):
    n = len(a)
    if n &lt;= 1:
        return a[0]
    max_tmp = Q4_2(a[0:n-1])
    if max_tmp &gt; a[n-1]:
        return max_tmp
    else:
        return a[n-1]

# 피보나치 수열
def Q5_1(n):
    if n &lt;= 1:
        return  n
    return Q5_1(n-1) + Q5_1(n-2)</code></pre>
<h1 id="셋째마당-탐색과-정렬">[셋째마당] 탐색과 정렬</h1>
<h2 id="순차-탐색-알고리즘">순차 탐색 알고리즘</h2>
<pre><code class="language-py">def serch_list(a,x);
    n = len(a)
    for i in range(0, n):
        if x == a[i]:
            return i
    return -1</code></pre>
<p>주어진 리스트에서 특정값의 위치를 찾아 돌려주는 알고리즘</p>
<h2 id="선택정렬">선택정렬</h2>
<pre><code class="language-py">#1
def find_min_idx(a):
    n = len(a)
    min_idx = 0
    for i in range(1, n):
        if a[i] &lt; a[min_idx]:
            min_idx = i
    return min_idx

def sel_sort(a):
    result = []
    while a:
        min_idx = find_min_idx(a)
        value = a.pop(min_idx)
        result.append(value)
    return result

#2
def sel_sort(a):
    n = len(a)
    for i in range(0, n - 1):
        min_idx = i
        for j in range(i+1, n):
            if a[j] &lt; a[min_idx]:
                min_idx = j
        a[i], a[min_idx] = a[min_idx], a[i]

</code></pre>
<p>선택정렬은 리스트의 최솟값을 하나씩 빼서 새로운 리스트에 넣어 정렬하는 방법이다. 계산복잡도 : $O(n^2)$</p>
<h2 id="삽입정렬">삽입정렬</h2>
<pre><code class="language-py">#1
def find_ins_idx(r, v):
    for i in range(0, len(r)):
        if v &lt; r[i]:
            return i
    return len(r) # 찾아서 없으면 맨 뒤

def ins_sort(a):
    result = []
    while a:
        value = a.pop(0) # 리스트에서 한개 꺼내서 
        ins_idx = find_ins_idx(result, value) # 값이 들어갈 위치를 찾아
        result.insert(ins_idx, value) # 찾은 위치에 삽입 
    return result

#2
def ins_sort(a):
    n = len(a)
    for i in range(1, n):
        key = a[i]
        j = i - 1
        while j &gt;= 0 and a[j] &gt; key:
            a[j + 1] = a[j]
            j -= 1
        a[j + 1] = key</code></pre>
<p>삽입 정렬은 값을 하나 꺼내 새로운 리스트의 적당한 위치를 찾아 삽입해 정렬하는 방법이다. 계산복잡도 : $O(n^2)$</p>
<h2 id="병합정렬">병합정렬</h2>
<pre><code class="language-py">#1
def merge_sort(a):
    n = len(a)
    if n &lt;= 1: # 종료 조건
        return a

    mid = n // 2
    g1 = merge_sort(a[:mid])
    g2 = merge_sort(a[mid:])

    result = []
    while g1 and g2:
        if g1[0] &lt; g2[0]:
            result.append(g1.pop(0))
        else :
            result.append(g2.pop(0))

    while g1:
        result.append(g1.pop(0))
    while g2:
        result.append(g2.pop(0))</code></pre>
<p>병합정렬은 리스트를 절반으로 나눈 다음, 서로 첫 번째 값들을 비교하며 재귀 호출로 풀어가는 방식이다. 계산복잡도 : $O(n*logn)$</p>
<h2 id="퀵정렬">퀵정렬</h2>
<pre><code class="language-py">def quick_sort(a):
    n = len(a)
    if n &lt;= 1:
        return a
    pivot = a[-1] # 기준값
    g1 = []
    g2 = []

    for i in range(0, n -1): # 마지막 값은 기준값
        if a[i] &lt; pivot:
            g1.append(a[i]) # 크면 g1
        else:
            g2.append(a[i]) # 작으면 g2
    return quick_sort(g1) + pivot + quick_sort(g2)</code></pre>
<p>퀵정렬은 기준값(pivot)을 정한 뒤, 그 값보다 큰 그룹과 작은 그룹을 나누어가며 재귀호출로 풀어가는 방식이다.</p>
<p>퀵 정렬의 경우, 기준값을 잘 못잡는 경우(가장 크거나 작은 값을 기준값으로 잡는 경우) 선택정렬이나 삽입정렬처럼 계산복잡도가 $O(n^2)$이 되어버리지만, 평균적일 때는 $O(n*logn)$이다. </p>
<h2 id="이분탐색">이분탐색</h2>
<pre><code class="language-py">def binary_serch(a, x):
    start = 0
    end = len(a) - 1

    while start &lt;= end:
        mid = (start + end) // 2
        if x == a[mid]:
            return mid
        elif x &gt; a[mid]:
            start = mid + 1
        else:
            end = mid - 1
    return -1</code></pre>
<p>이분탐색이란 <strong>정렬된</strong> 리스트에서 특정값을 찾아 위치를 찾는 문제에서 리스트의 중간값과 특정값을 비교해보며 탐색하는 알고리즘이다.
계산복잡도 : $O(logn)$</p>
<h2 id="연습문제-2">연습문제</h2>
<pre><code class="language-py"># 7_1
def serch_list_2(a,x):
    n = len(a)
    ans = []
    for i in range(0, n):
        if x == a[i]:
            ans.append(i)

    if ans != []:
        return ans
    else:
        return -1

# 7_3
def serch_student(s_no, s_name, num):
    for i in range(0, len(s_no)) :
        if num == s_no[i]:
            return s_name[i]
    return &quot;?&quot;

# 11_1 거품정렬
def bubble_sort(a):
    n = len(a)
    while True:
        changed = False
        for i in range(0, n - 1):
            if a[i] &gt; a[i + 1]:
                print(a)
                a[i], a[i + 1] = a[i + 1], a[i]
                changed = True
        if changed == False:
            return

# 12_1 재귀 호출을 이용한 이분탐색
def binary_serch_2(a, x, start, end):
    if start &gt; end:
        return -1
    mid = (start + end) // 2
    if x == a[mid]:
        return mid
    elif x &gt; a[mid]:
        return binary_serch_2(a, x, mid + 1, end)
    else :
        return binary_serch_2(a, x, start, mid - 1)
    return -1</code></pre>
<h1 id="넷째마당-자료구조">[넷째마당] 자료구조</h1>
<h2 id="큐queue와-스택stack">큐(queue)와 스택(stack)</h2>
<p>큐와 스택은 컴퓨터 과학에서 다루는 여러 가지 자료 중 가장 기본것인 것으로, 자료를 넣는 동작과 빼는 동작을 할 수 있으며, 자료가 일렬로 보관된다는 공통점이 있지만, 자료를 넣고 뺄 때 동작하는 방식이 서로 다르다.</p>
<p>큐(queue)는 줄서기에 비유할 수 있다. 택시를 타기 위해 줄을 서는 과정에서, 택시가 도착하면 가장 먼저 줄을 선 사람이 가장 먼저 택시를 타게 되는 것처럼 큐도 같은 특징을 가지고 있다. <strong>First In First Out</strong>
큐에 자료를 한 개 집어넣는 동작을 인큐(enqueue), 꺼내는 동작을 디큐(dequeue)라고 표현한다.</p>
<p>스택(stack)은 접시 쌓기에 비유할 수 있다. 다 먹은 접시를 쌓을 때 접시를 차곡차곡 위로 쌓아 올리고, 설거지 하기위해 접시를 꺼낼 때도 가장 위에 있는 접시부터 꺼내는 것처럼, 스택은 가장 마지막에 들어간 자료를 가장 먼저 꺼내는 특징을 가지고 있다. <strong>Last In First Out</strong></p>
<h2 id="회문-찾기-알고리즘">회문 찾기 알고리즘</h2>
<p>순서대로 읽어도 거꾸로 읽어도 그 내용이 같은 낱말을 회문(palindrome)이라고 한다. 어떤 문장이 주어졌을 때, 이 문장이 회문인지 아닌지 찾는 알고리즘을 작성한다. </p>
<pre><code class="language-py">def palindrome(s):
    qu = []
    st = []
    for x in s:
        if x.isalpha():
            qu.append(x.lower())
            st.append(x.lower())

    while qu:
        qu.pop(0) != st.pop
        return False

    return True
</code></pre>
<h2 id="딕셔너리를-이용한-동명이인-찾기-알고리즘2">딕셔너리를 이용한 동명이인 찾기 알고리즘2</h2>
<pre><code class="language-py">def find_same_name(a):
    name_dict = {}
    for name in a:
        if name in name_dict:
            name_dict[name] += 1
        else:
            name_dict = 1

    result = set()
    for name in name_dict:
        if name_dict[name] &gt;= 2:
            result.add(name)

    return result</code></pre>
<p>문제3 에서 리스트를 이용해 작성했던 알고리즘은 모든 사람을 서로 비교하여 같은 이름이 있는지 찾아내는 방식으로, 사람수가 n명일 때 계산 복잡도는 $O(n^2)$이었지만, 딕셔너리를 이용해 알고리즘을 작성했을 땐 $O(n)$의 시간복잡도를 가지는 것을 알 수 있다.</p>
<h2 id="친구의-친구-찾기그래프">친구의 친구 찾기(그래프)</h2>
<p>친구관계를 이용하여 직접 아는 친구들과 그 친구들의 친구들, 직간접적으로 아는 모든 사람들을 출력하는 프로그램을 작성하려 한다. 친구 관계 문제를 풀기 위해 꼭지점들과 꼭지점 사이를 연결한 선의 집합을 이용한 그래프를 이용해 친구관계를 선으로 표현할 수 있다.</p>
<h3 id="친구관계">친구관계</h3>
<pre><code>1. Summer와 John은 친구 관계 입니다.
2. Summer와 Justin은 친구 관계 입니다.
3. Summer와 Mike는 친구 관계 입니다.
4. Justion과 May는 친구 관계 입니다.
5. May와 Kim은 친구 관계 입니다.
6. John과 Justin은 친구 관계 입니다.
7. Justin과 Mike는 친구 관계 입니다.
8. Tom과 Jerry는 친구 관계 입니다.</code></pre><h3 id="그래프-표현">그래프 표현</h3>
<p><img src="https://media.vlpt.us/images/gimmicks_/post/54dae135-b031-43b6-9a5c-1655d9111908/image.png" alt="">
(출처 : <a href="https://stricky.tistory.com/196">https://stricky.tistory.com/196</a>)</p>
<h3 id="친구-정보-프로그램">친구 정보 프로그램</h3>
<pre><code class="language-py">fr_info = {
    &#39;Summer&#39; : [&#39;John&#39;, &#39;Justin&#39;, &#39;Mike&#39;],
    &#39;John&#39; : [&#39;Summer&#39;, &#39;Justin&#39;],
    &#39;Justin&#39; : [&#39;John&#39;, &#39;Summer&#39;, &#39;Mike&#39;, &#39;May&#39;],
    &#39;Mike&#39; : [&#39;Summer&#39;, &#39;Justin&#39;],
    &#39;May&#39; : [&#39;Justin&#39;, &#39;Kim&#39;],
    &#39;Kim&#39; : [&#39;May&#39;],
    &#39;Tom&#39; : [&#39;Jerry&#39;],
    &#39;Jerry&#39; : [&#39;Tom&#39;]    
}</code></pre>
<h3 id="모든-친구를-찾는-알고리즘">모든 친구를 찾는 알고리즘</h3>
<pre><code class="language-py">def all_friends(g, start):
    qu = []
    done = set()

    qu.append(start)
    done.add(start)

    while qu:
        p = qu.pop(0)
        print(p)
        for x in g[p]:
            if x not in done:
                qu.append(x)
                done.add(x)</code></pre>
<p>처리할 사람을 저장할 큐<code>qu</code>를 만들고, 큐에 이미 추가한 사람을 저장할 집합<code>done</code>을 만들어 큐에사람이 남아 있다면 큐에서 처리할 사람을 꺼내 출력한 후, 큐에 추가된 적이 없는 사람을 골라 집합에 추가하는 과정을 반복하는 방식으로 코드를 구현할 수 있다.</p>
<h2 id="친밀도-계산-알고리즘">친밀도 계산 알고리즘</h2>
<p>A와 B가 친구이고, B와 C가 친구라고 가정할 때, A-B(1), B-c(1)의 친밀도를 가진다. A와 C는 B를 통해 친구의 친구가 되었으므로 A를 기준으로 C의 친밀도는 2라는 것을 알 수 있다. 이 성질을 이용해 친구들을 큐에 넣을 때 친밀도를 증가시키면서 친밀도 계산 알고리즘을 구현할 수 있다.</p>
<pre><code class="language-py">def print_all_friends(g, start): 
    qu = [] 
    done = set()

    qu.append((start, 0)) 
    done.add(start)
    while qu:
        (p, d) = qu.pop(0)
        print(p, d) 
        for x in g[p]:
            if x not in done: 
                qu.append((x, d + 1))
                done.add(x)</code></pre>
<h2 id="연습문제-3">연습문제</h2>
<pre><code class="language-py"># 13_1
def solution(s):
    s = s.upper()
    size = len(s)

    if s == s[::-1]:
        return True
    else:
        return False

# 14_1
def solution(info, num):
    if num in info:
        return info
    else:
        return &quot;?&quot;

# 15_1
def sulution(g, start):
    qu = []
    done = set()

    qu.append(start)
    done.add(start)

    while qu:
        p = qu.pop(0)
        print(p)
        for x in g[p]:
            if x not in done:
                qu.append(x)
                done.add(x)</code></pre>
<h1 id="다섯째마당-응용문제">[다섯째마당] 응용문제</h1>
<h2 id="미로-찾기-알고리즘">미로 찾기 알고리즘</h2>
<p>미로의 형태와 출발점과 도착점이 주어졌을 때, 최단 경로를 찾는 것을 컴퓨터로 통해 구현하려면 어떻게 해야할까?
이때 필요한 것이 <code>모델링</code>이다. 모델링이란 주어진 문제를 정형화라거나 단순화해서 수학이나 프로그램으로 설명할 수 있도록 다시 표현하는 것을 말한다. </p>
<h3 id="모델링">모델링</h3>
<p>미로 정보를 그래프로 나타내고, 이를 딕셔너리로 바꾸면 미로문제를 <code>모델링</code>할 수 있다.
<img src="https://media.vlpt.us/images/gimmicks_/post/58de3247-10bf-441c-882a-7789f8f5eebf/image.png" alt="">
<img src="https://media.vlpt.us/images/gimmicks_/post/e29c8314-e061-4ea4-90b5-8651fc20534b/image.png" alt=""></p>
<pre><code class="language-py">maze = { 
        &#39;a&#39; : [&#39;e&#39;], 
        &#39;b&#39; : [&#39;c&#39;,&#39;f&#39;], 
        &#39;c&#39; : [&#39;b&#39;,&#39;d&#39;], 
        &#39;d&#39; : [&#39;c&#39;], 
        &#39;e&#39; : [&#39;a&#39;,&#39;i&#39;], 
        &#39;f&#39; : [&#39;b&#39;,&#39;g&#39;,&#39;j&#39;], 
        &#39;g&#39; : [&#39;f&#39;,&#39;h&#39;], 
        &#39;h&#39; : [&#39;g&#39;,&#39;l&#39;], 
        &#39;i&#39; : [&#39;e&#39;,&#39;m&#39;], 
        &#39;j&#39; : [&#39;f&#39;,&#39;k&#39;,&#39;n&#39;], 
        &#39;k&#39; : [&#39;j&#39;,&#39;o&#39;], 
        &#39;l&#39; : [&#39;h&#39;,&#39;p&#39;], 
        &#39;m&#39; : [&#39;i&#39;,&#39;n&#39;], 
        &#39;n&#39; : [&#39;m&#39;,&#39;j&#39;], 
        &#39;o&#39; : [&#39;k&#39;], 
        &#39;p&#39; : [&#39;l&#39;] 
        }
</code></pre>
<h3 id="미로찾기-알고리즘">미로찾기 알고리즘</h3>
<pre><code class="language-py">def solve_maze(g, start, end):
    qu = []
    done = set()

    qu.append(start)
    done.add(start)

    while qu:
        p = qu.pop(0)
        v = p[-1]

        if v == end:
            return p

        for x in g[v]:
            if x not in done:
                qu.append(p + x)
                done.add(x)

    return &quot;?&quot;</code></pre>
<h2 id="가짜동전-찾기-알고리즘">가짜동전 찾기 알고리즘</h2>
<p>겉보기에는 같은 동전 n개에서 싸고 가벼운 재료로 만들어진 가짜동전을 양팔저울을 이용해 찾아내는 알고리즘</p>
<h3 id="저울질에-해당하는-기능-구현">저울질에 해당하는 기능 구현</h3>
<p>a부터 b까지 동전을 저울의 왼쪽, c에서 d까지 동전을 저울의 오른쪽에 올려 저울질하는 함수이다. 왼쪽이 가볍다면 왼쪽에 양팔저울이 있다는 것이고 -1을 리턴하고, 오른쪽에 있으면 1을 리턴한다. 양쪽 무게가 같다면 어느 쪽에도 가짜 동전이 없는 것이고 결과값을 0을 리턴하는데, 이는 저울에 올리지 않은 동전 중에 가짜 동전이 있다는 것이다.</p>
<pre><code class="language-py">def weigh(a, b, c, d):
    fake = 29 # 가짜동전의 위치, 알고리즘은 weigh함수를 이용해 값을 맞춰야한다.

    if a &lt;= fake and fake &lt;= b:
        return -1

    if c &lt;= fake and fake &lt;= d:
        return 1

    return 0</code></pre>
<h3 id="동전-찾기">동전 찾기</h3>
<p>모든 동전을 하나씩 올려놓고 비교할 수 있지만, 이분 탐색을 활용해 반씩 그룹을 나누어 비교하면 더욱 효율적으로 알고리즘을 작성할 수 있다.</p>
<pre><code class="language-py">def find_fakecoin(left, right):
    # 종료 조건 : 가짜 동전이 있을 범위 안에 동전이 한 개일때
    if left == right:
        return left

    half = (right - left + 1) // 2
    g1_left = left
    g1_right = left + half - 1
    g2_left = left + half
    g2_right = g2_left + half - 1

    result = weigh(g1_left, g1_right, g2_left, g2_right)
    if result == -1: # 그룹 1이 가벼움
        return find_fakecoin(g1_left, g1_right)
    elif result == 1: # 그룹 2가 가벼움
        return find_fakecoin(g2_left, g2_right)
    else: 
        return right </code></pre>
<h3 id="알고리즘-분석">알고리즘 분석</h3>
<p>동전을 하나씩 비교할 경우 계산복잡도는 $O(n)$이지만, 동전을 절반씩 나누어 후보를 좁히며 비교하면 $O(logn)$ 으로 더욱 효율적으로 구현할 수 있다. 리스트 탐색에서의 이분탐색과 가짜동전문제는 겉으로 볼 때 다른문제로 보이지만, 잘 생각해보면 비슷한 문제임을 알 수 있다.</p>
<h2 id="최대-수익-알고리즘">최대 수익 알고리즘</h2>
<p>어떤 주식에 대해 특정 기간동안 가격 변화가 주어졌을 때, 그 주식 한 주를 한 번 사고 팔아 얻을 수 있는 최대 수익계산 알고리즘</p>
<h3 id="알고리즘">알고리즘</h3>
<p>가능한 모든 경우를 비교하면 직관적이지만, 불필요한 비교를 너무 많이해 비교횟수가 커지게 된다.
주식을 사는 날이 아닌 파는 날을 중심으로 이전 날들의 주가 중 최솟값을 알면 최대 수익을 쉽게 계산할 수 있다.</p>
<pre><code class="language-py">def max_profit(prices):
    n = len(prices)
    max_profit = 0         
    min_price = prices[0]  # 첫째 날의 주가를 주가의 최솟값으로 기억

    for i in range(1, n): 
        # 지금까지의 최솟값에 주식을 사서 i날에 팔 때의 수익
        profit = prices[i] - min_price
        if profit &gt; max_profit:    
            max_profit = profit

        if prices[i] &lt; min_price:  
            min_price = prices[i]

    return max_profit</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[차근차근 Python 알고리즘 스터디 회고]]></title>
            <link>https://velog.io/@gimmicks_/algorithmstudy</link>
            <guid>https://velog.io/@gimmicks_/algorithmstudy</guid>
            <pubDate>Sat, 02 Apr 2022 23:39:00 GMT</pubDate>
            <description><![CDATA[<h1 id="스터디-회고">스터디 회고</h1>
<p>루트임팩트에서 진행한 <a href="https://impact.career/career/1412">차근차근 python 알고리즘 스터디</a>에 참여했다. 8주간 진행한 스터디의 회고록을 남겨보고자 한다.</p>
<hr>
<h2 id="스터디를-시작한-이유">스터디를 시작한 이유</h2>
<p>개발 직군으로 진로를 선택하고, 취업에 있어서 코딩테스트가 필수적이라는 것을 알게 되었다. 대학에서 연구할 때 파이썬을 다뤄본 경험이 있고 파이썬이 초보자가 코테에서 비교적 유리하게 시작할 수 있다는 것을 알게 되어, 파이썬으로 코테를 준비하고자 결심했다.</p>
<p>매일 개발직군에 대한 유튜브를 찾아보고 검색해서인지, 페이스북과 인스타에 뜨는 모든 광고가 코딩관련 기관, 학원으로 바뀌었다. 무심코 넘기던 중, 임팩트 캠퍼스의 스터디 모집광고(?)를 마주치게 되었고, 무조건 신청해야겠다고 생각되어 지원했다.
<img src="https://media.vlpt.us/images/gimmicks_/post/ce0ce5ff-7e1c-448b-bbf6-d78edcbd483a/image.png" alt=""></p>
<h2 id="시작할-때-목표">시작할 때 목표</h2>
<p><img src="https://media.vlpt.us/images/gimmicks_/post/b3092d42-6e85-4a31-aa21-dc06ee0a3178/image.png" alt="">
스터디를 시작하기 전까지 진로에 대한 고민으로 많이 방황했고 너무 불규칙적인 생활을 했기 때문에, 스터디를 계기삼아 이를 극복하는 것을 목표로 세웠던 기억이 난다. </p>
<h2 id="스터디-진행">스터디 진행</h2>
<p>스터디는 인프런 <a href="https://www.inflearn.com/course/%ED%8C%8C%EC%9D%B4%EC%8D%AC-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EB%AC%B8%EC%A0%9C%ED%92%80%EC%9D%B4-%EC%BD%94%EB%94%A9%ED%85%8C%EC%8A%A4%ED%8A%B8/dashboard">파이썬 알고리즘 문제풀이</a> 강의와 <a href="http://www.yes24.com/Product/Goods/40443936">모두의 알고리즘 with 파이썬</a> 책을 계획한 분량만큼 학습한 뒤, 일요일에 비대면으로 만나 공유하고, 모각코-코드리뷰 및 한 주를 회고하는 방식으로 진행됐다. </p>
<p>스터디 공지 및 활동기록은 슬랙과 노션을 사용했다.</p>
<h2 id="반성">반성</h2>
<p><code>정말 꾸준히 했는가?</code> 라고 질문한다면 쉽게 답하지 못할 것 같다. 바쁜 일들을 핑계로 알고리즘 공부를 우선순위에서 밀어버리는 일들이 많았던 것 같다. 특히 3월부터는 9 to 6 학원에 다니게 되면서 더 어수선해지고 스터디를 챙기지 못하게 되었다  <del>핑계</del>. </p>
<p>강의는 뒤로 갈수록 점점 어려워지고, 한 문제에 할애해야 하는 시간도 길어지면서 집중도도 떨어지다 보니 스터디 후반에 공부에 많이 소홀해졌다.</p>
<h2 id="그래서-무엇을-얻었는가">그래서 무엇을 얻었는가</h2>
<p>얻은 것들을 하나하나 나열하기엔 너무 많은 것 같다. </p>
<p>먼저 학습적인 면에서는 알고리즘의 전체적인 부분을 크게 훑은 것이 가장 크다고 생각된다. 특히 알고리즘을 처음 접했을 때 막연해보이고 겁부터 났었는데 <del>사실 지금도</del> , <a href="http://www.yes24.com/Product/Goods/40443936">모두의 알고리즘 with 파이썬</a> 교재에서 너무 쉽고 간단하게 설명되어 있어서 가벼운 마음으로 접근할 수 있었던 것 같다.</p>
<p>또한 vscode 개발 환경을 셋업하고, 슬랙, 노션, 벨로그 등 다양한 툴들을 이용하면서 앞으로 공부하면서 어떻게 기록하고, 협업할지 감을 잡았다. </p>
<p>그리고 무엇보다, 개발자가 되는 여정의 망망대해에 배를 타고 올랐다는 것이 가장 큰 수확이다. <code>시작이 가장 어렵다.</code> 내가 방황하며 가장 크게 깨달은 문장이다. 같이 공부하는 스터디원들이 있어서 더욱 수월하게 시작할 수 있었고 꾸준히 할 수 있었다. </p>
<h2 id="앞으로-계획">앞으로 계획</h2>
<p>먼저 다 끝내지 못한 강의들을 부지런히 마무리 해야한다. 4월 안에 끝내는 것을 목표로 강의를 듣고, 프로그래머스 필수 문제와 <a href="https://cafe.naver.com/startdevelopercareer">판교가는길</a> 카페의 알고리즘 추천 50문을 학원 끝날 때(~8월)까지 풀어볼 예정이다. </p>
<h2 id="8주의-여정을-마치며">8주의 여정을 마치며</h2>
<p>스터디원들에게 너무 고맙다. 비록 스터디가 거의 다 끝나갈 때가 되어서야 말문이 트이고(?) 친해졌지만, 좋은 네트워크를 만든 것 같아서 너무 좋다. 특히 스터디원 중 두 분은 스터디 기간동안 취업을 하셨고, 스터디원들에게 적극적으로 도움을 주려고 해주셔서 너무 감사하다.</p>
<p>그리고 8주동안 고생해주신 리더님도 너무 감사하다. 팀원들이 스터디에 잘 참여할 수 있도록 계속 리마인드 해주시고 공지해주셔서 정말 매끄럽게 스터디가 진행될 수 있도록 계속 소통해주셨다. </p>
<p>스터디원들 모두 각자 이루고자 하는 목표들 이뤘으면 좋겠고, 취업 후에도 같은 직군에서 일하는 동료로써 좋은 네트워크 활동이 이루어졌으면 좋겠다!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[C++_OOP4]]></title>
            <link>https://velog.io/@gimmicks_/cpp4</link>
            <guid>https://velog.io/@gimmicks_/cpp4</guid>
            <pubDate>Fri, 01 Apr 2022 08:52:15 GMT</pubDate>
            <description><![CDATA[<h1 id="클래스의-특징과-객체-활용">클래스의 특징과 객체 활용</h1>
<h2 id="const">const</h2>
<h3 id="const-멤버함수">const 멤버함수</h3>
<p>const 사용 목적은 객체의 멤버변수를 변경시킬 수 없도록 하기 위함이다.
const 멤버함수는 객체의 멤버변수를 변경할 수 없는 읽지 전용함수로, const로 지정되지 않은 다른 함수도 호출할 수 없다.</p>
<pre><code class="language-cpp">    int GetX() const
    {
        return this-&gt;x;
    }</code></pre>
<h3 id="const-객체">const 객체</h3>
<p>객체를 상수로 취급하여 초기화된 데이터 외에 다른 데이터로 변경 불가능하게 만든다.</p>
<pre><code class="language-cpp">int main()
{
    const MousePoint pt1(10, 20);
    MousePoint pt2(100, 200);

    pt1 = pt2;
}</code></pre>
<p>pt1은 상수화 되었기 때문에 수정할 수 없다.</p>
<h2 id="static">static</h2>
<p>전역변수는 현재 클래스뿐 아니라 다른 클래스에서도 접근 가능해 객체지향 철학에 위배된다. static변수는 전역변수와 같은 성질의 멤버 함수이되, 외부 클래스에서는 접근할 수 없는 변수이다.</p>
<h3 id="static-멤버변수">static 멤버변수</h3>
<p>메모리 구조상 전역변수와 같은 공간인 데이터영역에 메모리가 할당. 전역변수와 비슷한 성질을 가지면서도 클래스에 국한되어 사용된다는 차이가 있다.</p>
<p>static으로 선언하면 클래스에 대한 객체가 생성되어도, 단 하나의 변수만 메모리에 할당된다. static변수가 private속성을 갖는다면 같은 클래스의 멤버함수에서만 접근 가능하고 클래스 외부함수에서는 접근이 불가능하다.</p>
<p>전역변수와 같이 프로그램 시작 시 한번만 초기화한다. 또한 접근지정자는 초기화 과정에 전혀 영향을 주지 않으므로, private속성의 static 멤버변수일지라도 클래스 외부에서 초기화 가능하다.</p>
<p>소속클래스명 <code>::</code>영역결정 연산자 표시해줌으로써 static멤버변수의 소속을 지정해준다</p>
<pre><code class="language-cpp">double Deposit::dInterestRate = 0.05;</code></pre>
<pre><code class="language-cpp">#include &lt;iostream&gt;
using namespace std;

class Deposit
{
public:
    Deposit() // 디폴트 생성자
    {
    }

    Deposit(char *name, double balance) // 생성자(오버로딩)
    {
        strName = name;
        dBalance = balance;
    }

    void BankBalnce()
    {
        dBalance = dBalance + (dBalance * dInterestRate);
    }

    static void SetInterestRate(double dNewRate)
    {
        dInterestRate = dNewRate;
    }

private:
    char *strName;
    double dBalance;
    static double dInterestRate;
};

double Deposit::dInterestRate = 0.05;

int main()
{
    Deposit custom1;
    Deposit custom2;

    Deposit::SetInterestRate(0.03);
}</code></pre>
<h3 id="static-멤버함수">static 멤버함수</h3>
<p>static 멤버변수의 값을 변경하기 위해 static 멤버 함수를 사용한다.</p>
<p>private 속성의 static 멤버변수 <code>dInterestRate</code>에 접근하기 위해서 사용한다.</p>
<pre><code class="language-cpp">#include &lt;iostream&gt;
using namespace std;

class Deposit
{
public:
    Deposit() // 디폴트 생성자
    {
    }

    Deposit(char *name, double balance) // 생성자(오버로딩)
    {
        strName = name;
        dBalance = balance;
    }

    void BankBalnce()
    {
        dBalance = dBalance + (dBalance * dInterestRate);
    }

    static void SetInterestRate(double dNewRate)
    {
        dInterestRate = dNewRate;
    }

    static double GetInterestRate()
    {
        return dInterestRate;
    }

private:
    char *strName;
    double dBalance;
    static double dInterestRate;
};

double Deposit::dInterestRate = 0.05;

int main()
{
    cout &lt;&lt; &quot;변경 전 이자율 : &quot; &lt;&lt; Deposit::GetInterestRate() &lt;&lt; endl;
    Deposit::SetInterestRate(0.03); // 이자율 변경
    cout &lt;&lt; &quot;변경된 이자율 : &quot; &lt;&lt; Deposit::GetInterestRate() &lt;&lt; endl;
}</code></pre>
<pre><code>현재 이자율 : 0.05
변경된 이자율 : 0.03</code></pre><p>static 멤버함수는 특정 객체에 영향을 미치지 않으므로 <code>this포인터</code>를 사용하지 못한다. 
또한 static 멤버함수 내에서 일반 멤버함수를 호출하지 못하는데, 일반 멤버함수는 객체를 통해서 관리되는 함수이기 때문이다. </p>
<h4 id="객체-상태-정보-관리">객체 상태 정보 관리</h4>
<p>static 멤버를 사용하여 객체의 상태 정보 관리에 사용 가능하다.</p>
<pre><code class="language-cpp">#include &lt;iostream&gt;
using namespace std;

class Deposit
{
public:
    Deposit() // 디폴트 생성자
    {
        nCount++;
        cout &lt;&lt; &quot;객체 개수(생성) : &quot; &lt;&lt; nCount &lt;&lt; endl;
    }
    ~Deposit()
    {
        nCount--;
        cout &lt;&lt; &quot;객체 개수(소멸) : &quot; &lt;&lt; nCount &lt;&lt; endl;
    }

    Deposit(char *name, double balance) // 생성자(오버로딩)
    {
        strName = name;
        dBalance = balance;
    }

    void BankBalnce()
    {
        dBalance = dBalance + (dBalance * dInterestRate);
    }

    static void SetInterestRate(double dNewRate)
    {
        dInterestRate = dNewRate;
    }

    static double GetInterestRate()
    {
        return dInterestRate;
    }

private:
    char *strName;
    double dBalance;
    static double dInterestRate;
    static int nCount;
};

double Deposit::dInterestRate = 0.05;
int Deposit::nCount = 0;

int main()
{
    Deposit custom1;
    Deposit custom2;
    Deposit custom3;
    Deposit custom4;
}</code></pre>
<pre><code>객체 개수(생성) : 1
객체 개수(생성) : 2
객체 개수(생성) : 3
객체 개수(생성) : 4
객체 개수(소멸) : 3
객체 개수(소멸) : 2
객체 개수(소멸) : 1
객체 개수(소멸) : 0</code></pre><h2 id="프렌드friend">프렌드(Friend)</h2>
<p>클래스의 멤버변수 접근 지정자는 private으로 외부로부터 접근을 차단한다. 오직 멤버함수를 통해서만 멤버변수에 접근이 가능한데, 이 규칙을 깨는 변칙적인 기능이 프렌드이다.(나에게 접근을 허용하겠다)  </p>
<h1 id="클래스의-동적-메모리-할당">클래스의 동적 메모리 할당</h1>
<h2 id="newdelete">new/delete</h2>
<h3 id="동적-메모리의-필요성">동적 메모리의 필요성</h3>
<p>동적메모리는 실행시간에 할당되어 사용되는 메모리 블록을 말한다.(힙)
&lt;-&gt;정적 메모리(스택)</p>
<p>동적 메모리는 프로그램 작성 시 얼마만큼의 메모리가 필요한지 알지 못하는 경우에 사용된다. 객체지향 언어에서는 동적 메모리 생성시 <code>new</code>, 소멸시 <code>delete</code>(C++) 연산자를 사용한다.</p>
<pre><code class="language-cpp">#include &lt;iostream&gt;
using namespace std;

int main()
{
    int *pBuffer;
    int nLength;
    cout &lt;&lt; &quot;힙 영역에 할당할 메모리 수 :&quot;;
    cin &gt;&gt; nLength;

    pBuffer = new int[nLength];

    for (int i = 0; i &lt; nLength; i++)
        pBuffer[i] = i + 1;
    for (int i = 0; i &lt; nLength; i++)
        cout &lt;&lt; pBuffer[i] &lt;&lt; &quot; &quot;;

    cout &lt;&lt; endl;
    delete[] pBuffer;
}</code></pre>
<pre><code>힙 영역에 할당할 메모리 수 : 15
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 </code></pre><p><img src="https://media.vlpt.us/images/gimmicks_/post/55770dbd-85f4-43d5-8585-bc1f67a67a67/image.png" alt=""></p>
<h3 id="힙-영역에-객체-생성">힙 영역에 객체 생성</h3>
<p><code>new</code>연산자를 통해 클래스 타입의 메모리를 생성 후 선언한 객체 포인터 변수에 생성 메모리 주소를 넘겨준다</p>
<pre><code class="language-cpp">int main()
{
    MousePoint *pt;
    pt = new MousePoint(10, 20);

    cout &lt;&lt; &quot;x좌표 : &quot; &lt;&lt; pt-&gt;GetX() &lt;&lt; endl;
    cout &lt;&lt; &quot;y좌표 : &quot; &lt;&lt; pt-&gt;GetY() &lt;&lt; endl;

    delete pt;
}</code></pre>
<pre><code>x좌표 : 10
y좌표 : 20</code></pre><p><img src="https://media.vlpt.us/images/gimmicks_/post/82850676-9ca0-478c-baf8-683c900a4156/image.png" alt=""></p>
<h2 id="객체-포인터-배열">객체 포인터 배열</h2>
<p>여러 개의 객체를 관리하는 방법으로 배열을 선언하여 사용할 수 있는데, 이를 객체 포인터 배열이라고 한다.</p>
<pre><code class="language-cpp">int main()
{
    MousePoint *pArr[3]; //1
    pArr[0] = new MousePoint(10, 20);
    pArr[1] = new MousePoint(100, 200);
    pArr[2] = new MousePoint(1000, 2000);

    for (int i = 0; i &lt; 3; i++)
        cout &lt;&lt; pArr[i]-&gt;GetX() &lt;&lt; &quot;, &quot; &lt;&lt; pArr[i]-&gt;GetY() &lt;&lt; endl;

    for (int i = 0; i &lt; 3; i++)
        delete pArr[i]; //1

    MousePoint* mp = new MousePoint[3]; //2
    delete[] mp; //2
}
</code></pre>
<pre><code>10, 20
100, 200
1000, 2000</code></pre><p>//1 객체를 delete
//2 배열을 delete</p>
<h2 id="포인터-멤버변수를-갖는-클래스">포인터 멤버변수를 갖는 클래스</h2>
<h3 id="클래스-내의-동적-메모리-할당">클래스 내의 동적 메모리 할당</h3>
<pre><code class="language-cpp">#include &lt;iostream&gt;
using namespace std;
class String
{
public:
    String(char ch, int nSize);
    ~String();

private:
    int nLength;
    char *pBuffer;
};

String::String(char ch, int nSize)
{
    nLength = nSize;
    pBuffer = new char[nLength + 1];
    memset(pBuffer, ch, nLength);
    pBuffer[nLength] = &#39;\0&#39;;
    cout &lt;&lt; &quot;pBuffer : &quot; &lt;&lt; pBuffer &lt;&lt; endl;
    cout &lt;&lt; &quot;nLength : &quot; &lt;&lt; nLength &lt;&lt; endl;
}
String::~String()
{
    delete[] pBuffer;
}
int main()
{
    String str(&#39;A&#39;, 5);
}</code></pre>
<pre><code>pBuffer : AAAAA
nLength : 5</code></pre><h3 id="객체끼리의-대입">객체끼리의 대입</h3>
<pre><code class="language-cpp">int main()
{
    String str1(&#39;A&#39;, 3);
    String str2(&#39;B&#39;, 5);
    str1 = str2;
}</code></pre>
<p>객체끼리의 대입할 때 객체끼리의 대입은 멤버 대 멤버의 복사가 일어난다.</p>
<pre><code class="language-cpp">str2.nLength = str1.nLength;
str2.pBuffer = str1.pBuffer;</code></pre>
<ul>
<li><p>대입 이전
<img src="https://media.vlpt.us/images/gimmicks_/post/e27115bf-ee2a-45df-addd-ef30c3fd0007/image.png" alt=""></p>
</li>
<li><p>대입 이후
<img src="https://media.vlpt.us/images/gimmicks_/post/8f0b8933-f5db-44ce-89b9-27ea26a8585c/image.png" alt=""></p>
</li>
</ul>
<p>같은 주소값을 갖는 것은 문제되지 않지만, 객체가 소멸할 때 stack메모리 중 str2객체가 먼저 소멸하는데, 소멸할 때 소멸자를 호출하면 str2의 pBuffer멤버변수가 가리키고 있는 힙 영역을 <code>delete</code>하게 된다. <strong>시스템으로 다시 반납</strong></p>
<p>str1도 같은 메모리를 가르키고 있으므로 str1 객체 소멸시 pBuffer가 가리키는 메모리 영역을 다시 <code>delete</code>하려 하는데, 이 메모리는 이미 비워지고 시스템에 반납되어 런타임에서 접근하지 못해 오류가 발생한다.</p>
<p>이 문제를 해결하기 위해 <code>대입 연산자 오버로딩(Assignment Operator Overloading)</code>이라는 방법을 사용한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[C++_OOP3]]></title>
            <link>https://velog.io/@gimmicks_/cpp3</link>
            <guid>https://velog.io/@gimmicks_/cpp3</guid>
            <pubDate>Thu, 31 Mar 2022 12:57:26 GMT</pubDate>
            <description><![CDATA[<h2 id="객체-포인터">객체 포인터</h2>
<p>객체의 주소값을 저장하기 위한 변수로, 객체를 간접 참조하기 위해 사용한다.</p>
<pre><code class="language-cpp">#include &lt;iostream&gt;
using namespace std;

// 클래스 정의
class MousePoint
{
    private : // 외부에서 접근하지 못하게 함
        int x, y;

    public :
        void SetXY(int nX, int nY);
        MousePoint(); // 디폴트 생성자
        MousePoint(int nX, int nY); // 생성자
        ~MousePoint(); // 소멸자

        // private한 x,y값을 출력
        int GetX(){return x;}
        int GetY(){return y;}
};

// 멤버함수 구현
void MousePoint::SetXY(int nX, int nY)
{
    x = nX;
    y = nY;
    cout &lt;&lt; &quot;x = &quot; &lt;&lt; x &lt;&lt; endl;
    cout &lt;&lt; &quot;y = &quot; &lt;&lt; y &lt;&lt; endl;
}

MousePoint::MousePoint() // 디폴트 생성자
{
    cout &lt;&lt; &quot;생성자 호출&quot; &lt;&lt; endl;
    x = 10;
    y = 20;
}

MousePoint::MousePoint(int nX, int nY) // 생성자
{
    x = nX;
    y = nY;
}

MousePoint::~MousePoint() // 소멸자
{
    cout &lt;&lt; &quot;소멸자 호출&quot; &lt;&lt; endl;
}

// 객체 생성
int main()
{
    MousePoint pt(10,20);
    MousePoint *pObj;
    pObj = &amp;pt;
    cout &lt;&lt; pt.GetX() &lt;&lt; endl;
    cout &lt;&lt; pt.GetY() &lt;&lt; endl;
    cout &lt;&lt; pObj-&gt;GetX() &lt;&lt; endl;
    cout &lt;&lt; pObj-&gt;GetY() &lt;&lt; endl;
}</code></pre>
<pre><code>10
20
10
20
소멸자 호출</code></pre><p><code>-&gt;</code> : 간접 참조 연산자. </p>
<h2 id="this-포인터">this 포인터</h2>
<p>객체가 함수를 호출할때는 어떤 객체가 호출한지 알 수 있지만, 함수 입장에서는 누가 나를 호출한지 모른다. 누가 나를 호출했는지 알아야 할 상황에 <code>this</code>포인터를 사용한다.</p>
<pre><code class="language-cpp">// 1
void MousePoint::SetXY(int nX, int nY)
{
    x = nX;
    y = nY;
}

// 2
void MousePoint::SetXY(int X, int Y)
{
    this -&gt; x = x;
    this -&gt; y = y;
}</code></pre>
<h2 id="전달인자가-객체인-함수">전달인자가 객체인 함수</h2>
<p>값 전달 방식(복사)과 레퍼런스 전달 방식(주소값)이 있다.</p>
<h3 id="값-전달-방식call-by-value">값 전달 방식(Call by value)</h3>
<p>기본 자료형을 값 전달 방식으로 사용한 것처럼, 객체도 값 전달 방식으로 전달이 가능하다. 실 매개변수와 형식 매개변수의 메모리 관리가 별도로 이루어진다.</p>
<pre><code class="language-cpp">#include &lt;iostream&gt;
using namespace std;

// 클래스 정의
class MousePoint
{
    private : // 외부에서 접근하지 못하게 함
        int x, y;

    public :
        void SetXY(int nX, int nY);
        MousePoint(); // 디폴트 생성자
        MousePoint(int nX, int nY); // 생성자
        ~MousePoint(); // 소멸자

        // private한 x,y값을 출력
        int GetX()
        {
            return this -&gt; x;
        }
        int GetY()
        {
            return this -&gt; y;
        }
};

// 멤버함수 구현
void MousePoint::SetXY(int nX, int nY)
{
    x = nX;
    y = nY;
}

MousePoint::MousePoint() // 디폴트 생성자
{
    cout &lt;&lt; &quot;생성자 호출&quot; &lt;&lt; endl;
    x = 10;
    y = 20;
}

MousePoint::MousePoint(int nX, int nY) // 생성자
{
    x = nX;
    y = nY;
}

MousePoint::~MousePoint() // 소멸자
{
    // cout &lt;&lt; &quot;소멸자 호출&quot; &lt;&lt; endl;
}

void SetRect(MousePoint pt1, MousePoint pt2) // call by value
{
    cout &lt;&lt; &quot;pt1.GetX : &quot; &lt;&lt; pt1.GetX() &lt;&lt; endl;
    cout &lt;&lt; &quot;pt1.GetX : &quot; &lt;&lt; pt1.GetY() &lt;&lt; endl;
    pt1.SetXY(1000, 2000);
    cout &lt;&lt; &quot;pt1.GetX : &quot; &lt;&lt; pt1.GetX() &lt;&lt; endl;
    cout &lt;&lt; &quot;pt1.GetX : &quot; &lt;&lt; pt1.GetY() &lt;&lt; endl;
}

void CopyObject(MousePoint pt1, MousePoint pt2)
{
    pt1 = pt2;
    cout &lt;&lt;&quot;pt1.GetX() : &quot; &lt;&lt; pt1.GetX() &lt;&lt; endl;
    cout &lt;&lt;&quot;pt1.GetY() : &quot; &lt;&lt; pt1.GetY() &lt;&lt; endl;
}

// 객체 생성
int main()
{
    MousePoint mp1(10, 20);
    MousePoint mp2(100, 200);
    cout &lt;&lt;&quot;mp1.GetX() : &quot; &lt;&lt; mp1.GetX() &lt;&lt; endl;
    cout &lt;&lt;&quot;mp1.GetY() : &quot; &lt;&lt; mp1.GetY() &lt;&lt; endl;
    CopyObject(mp1, mp2);
    cout &lt;&lt;&quot;mp1.GetX() : &quot; &lt;&lt; mp1.GetX() &lt;&lt; endl;
    cout &lt;&lt;&quot;mp1.GetY() : &quot; &lt;&lt; mp1.GetY() &lt;&lt; endl;
}</code></pre>
<pre><code>mp1.GetX() : 10
mp1.GetY() : 20
pt1.GetX() : 100
pt1.GetY() : 200
mp1.GetX() : 10
mp1.GetY() : 20</code></pre><h3 id="레퍼런스-방식call-by-reference">레퍼런스 방식(Call by reference)</h3>
<p><code>&amp;</code>표시를 통해 실매개변수의 별칭을 형식 매개변수에 부여해서 같은 메모리를 사용하게한다.</p>
<p>객채의 결과값을 반환하려면 반환하려는 값의 타입과 함수의 반환 타입을 일치시켜주면 된다. 함수 결과 반환 시 결과값을 저장하기 위한 별도의 메모리가 할당된다. (= 반환값은 call by value)</p>
<pre><code class="language-cpp">---중복코드---
void CopyObject(MousePoint &amp;pt1, MousePoint &amp;pt2)
{
    pt1 = pt2;
    cout &lt;&lt; &quot;pt1.GetX() : &quot; &lt;&lt; pt1.GetX() &lt;&lt; endl;
    cout &lt;&lt; &quot;pt1.GetY() : &quot; &lt;&lt; pt1.GetY() &lt;&lt; endl;
}

// 객체 생성
int main()
{
    MousePoint mp1(10, 20);
    MousePoint mp2(100, 200);
    cout &lt;&lt; &quot;mp1.GetX() : &quot; &lt;&lt; mp1.GetX() &lt;&lt; endl;
    cout &lt;&lt; &quot;mp1.GetY() : &quot; &lt;&lt; mp1.GetY() &lt;&lt; endl;
    CopyObject(mp1, mp2);
    cout &lt;&lt; &quot;mp1.GetX() : &quot; &lt;&lt; mp1.GetX() &lt;&lt; endl;
    cout &lt;&lt; &quot;mp1.GetY() : &quot; &lt;&lt; mp1.GetY() &lt;&lt; endl;
}</code></pre>
<pre><code>mp1.GetX() : 10
mp1.GetY() : 20
pt1.GetX() : 100
pt1.GetY() : 200
mp1.GetX() : 100
mp1.GetY() : 200</code></pre><p>함수의 반환값을 레퍼런스 형식으로 처리하면 함수의 결과값을 저장하기 위한 메모리를 따로 할당할 필요가 없다. (= 반환값까지 call by reference)</p>
<blockquote>
<p>mp1 = &amp;pt1 = CopyObject()  모두 같은 메모리</p>
</blockquote>
<pre><code class="language-cpp">MousePoint&amp; CopyObject(MousePoint &amp;pt1, MousePoint &amp;pt2)
{
    pt1 = pt2;
    cout &lt;&lt; &quot;pt1.GetX() : &quot; &lt;&lt; pt1.GetX() &lt;&lt; endl;
    cout &lt;&lt; &quot;pt1.GetY() : &quot; &lt;&lt; pt1.GetY() &lt;&lt; endl;
    return pt1;
}

// 객체 생성
int main()
{
    MousePoint mp1(10, 20);
    MousePoint mp2(100, 200);
    cout &lt;&lt; &quot;mp1.GetX() : &quot; &lt;&lt; mp1.GetX() &lt;&lt; endl;
    cout &lt;&lt; &quot;mp1.GetY() : &quot; &lt;&lt; mp1.GetY() &lt;&lt; endl;
    MousePoint ap1 = CopyObject(mp1, mp2);
    cout &lt;&lt; &quot;mp1.GetX() : &quot; &lt;&lt; mp1.GetX() &lt;&lt; endl;
    cout &lt;&lt; &quot;mp1.GetY() : &quot; &lt;&lt; mp1.GetY() &lt;&lt; endl;
    cout &lt;&lt; &quot;ap1.GetX() : &quot; &lt;&lt; ap1.GetX() &lt;&lt; endl;
    cout &lt;&lt; &quot;ap1.GetY() : &quot; &lt;&lt; ap1.GetY() &lt;&lt; endl;
}
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[C++_OOP2]]></title>
            <link>https://velog.io/@gimmicks_/cpp2</link>
            <guid>https://velog.io/@gimmicks_/cpp2</guid>
            <pubDate>Thu, 31 Mar 2022 12:56:44 GMT</pubDate>
            <description><![CDATA[<h1 id="hello-c-입출력">Hello C++ 입출력</h1>
<h2 id="출력cout">출력(cout)</h2>
<pre><code class="language-cpp">#include &lt;iostream&gt;
// io : input, output
// 입출력을 흘러가게 하는 역할을 하는 라이브러리

int main()
{
    std::cout &lt;&lt; &quot;Hello C++&quot; &lt;&lt; std::endl;
    // std::cout 객체 : c++에서 화면에 출력시 사용하는 출력 객체
    // std라는 이름 공간에 존재하는 cout 객체를 사용하겠다는 의미
    return 0;
}</code></pre>
<pre><code>Hello C++</code></pre><p><code>::</code> : 스코프 연산자, 영역 결정 연산자</p>
<pre><code class="language-cpp">#include &lt;iostream&gt;

int main()
{
    int a = 10;
    float b = 3.14f;
    char c = &#39;A&#39;;

    std::cout &lt;&lt; a &lt;&lt; std::endl;
    std::cout &lt;&lt; b &lt;&lt; std::endl;
    std::cout &lt;&lt; c &lt;&lt; std::endl;
    return 0;
}</code></pre>
<pre><code>10
3.14
A</code></pre><pre><code class="language-cpp">#include &lt;iostream&gt;

using namespace std;
int main()
{
    int a = 10;
    float b = 3.14f;
    char c = &#39;A&#39;;

    cout &lt;&lt; a &lt;&lt; endl;
    cout &lt;&lt; b &lt;&lt; endl;
    cout &lt;&lt; c &lt;&lt; endl;

    return 0;
}</code></pre>
<p><code>using namespace std;</code>를 통해 간단하게 작성할 수 있다.</p>
<h2 id="이름-공간namespace">이름 공간(namespace)</h2>
<p>특정 공간에 이름을 지정해 준다는 의미이다. </p>
<pre><code class="language-cpp">#include &lt;iostream&gt;

namespace A
{
    void func(void)
    {
        std::cout &lt;&lt; &quot;A학급 주성&quot; &lt;&lt; std::endl;
    }
}

namespace B
{
    void func(void)
    {
        std::cout &lt;&lt; &quot;B학급 주성&quot; &lt;&lt; std::endl;
    }
}

int main()
{
    A::func();
    return 0;
}</code></pre>
<pre><code>A학급 주성</code></pre><h2 id="입력cin">입력(cin)</h2>
<pre><code class="language-cpp">#include &lt;iostream&gt;

using namespace std;
int main()
{
    int a;
    float b;
    char c;

    cin &gt;&gt; a;
    cout &lt;&lt; &quot;정수값 출력 : &quot; &lt;&lt; a &lt;&lt; endl;
    cin &gt;&gt; b;
    cout &lt;&lt; &quot;정수값 출력 : &quot; &lt;&lt; b &lt;&lt; endl;
    cin &gt;&gt; c;
    cout &lt;&lt; &quot;문자열 출력 : &quot; &lt;&lt; c &lt;&lt; endl;

    return 0;
}</code></pre>
<pre><code>1
정수값 출력 : 1
1.4
정수값 출력 : 1.4
a
문자열 출력 : a</code></pre><h1 id="c에서의-새로운-규칙">C++에서의 새로운 규칙</h1>
<h2 id="변수-선언">변수 선언</h2>
<p>C에서는 변수들을 먼저 선언해주고 코드를 작성해야 했지만, C++에서는 중간에서도 변수를 선언할 수 있다.</p>
<h2 id="매개변수-기본값-설정">매개변수 기본값 설정</h2>
<ul>
<li>선언부<pre><code class="language-cpp">void func(int a = 10, int b = 20);</code></pre>
</li>
<li>호출부1 <pre><code class="language-cpp">func(100, 200); // 전달인자의 값은 각각 100과 200</code></pre>
</li>
<li>호출부2 <pre><code class="language-cpp">func(50); // 전달인자의 값은 50, 20
func(); // 전달인자의 값은 10, 20</code></pre>
매개변수 기본값을 설정할 경우, 호출부에서 매개변수를 생략하더라도 기본값이 설정되게 된다.</li>
</ul>
<pre><code class="language-cpp">#include &lt;iostream&gt;
using namespace std;

void func(int a = 10, int b = 20);

int main()
{
    func(); // 전달인자x
    func(100);
    func(100, 200);
    return 0;
}

void func(int a, int b)
{
    cout &lt;&lt; &quot;두 전달인자 출력: &quot; &lt;&lt; a &lt;&lt; &quot; &quot; &lt;&lt; b &lt;&lt; endl;
}</code></pre>
<pre><code>두 전달인자 출력: 10 20
두 전달인자 출력: 100 20
두 전달인자 출력: 100 200</code></pre><h2 id="전역변수와-지역변수">전역변수와 지역변수</h2>
<p>C언어에서는 전역변수와 지역변수의 이름이 같을 시 지역변수가 전역변수보다 우선권을 가진다.</p>
<pre><code class="language-c">#include &lt;stdio.h&gt;

int nTemp = 10;
int main()

{
    {
        int nTemp = 20;
        printf(&quot;nTemp의 값은 : %d이다.\n&quot;, nTemp);
    }
    printf(&quot;nTemp의 값은 : %d이다.\n&quot;, nTemp);
}</code></pre>
<pre><code>nTemp의 값은 : 20이다.
nTemp의 값은 : 10이다.</code></pre><p>C++ 언어에서는 전역변수와 지역변수 존재시 영역 결정 연산자<code>::</code>을 통해 지역 내에서 전역변수를 출력할 수 있다.</p>
<pre><code class="language-cpp">#include &lt;iostream&gt;
using namespace std;
int nTemp = 10;

int main()
{
    {
        int nTemp = 20;
        cout &lt;&lt; &quot;nTemp = &quot; &lt;&lt; nTemp &lt;&lt; endl; 
        cout &lt;&lt; &quot;::nTemp = &quot; &lt;&lt; ::nTemp &lt;&lt; endl; 
    }
    cout &lt;&lt; &quot;nTemp = &quot; &lt;&lt; nTemp &lt;&lt; endl; 
}</code></pre>
<pre><code>nTemp = 20
::nTemp = 10
nTemp = 10</code></pre><h2 id="인라인-함수">인라인 함수</h2>
<p>코드 라인 자체가 호출부 안에 포함된다는 의미, <code>#define</code> 매크로의 단점을 보완하고, 일반 함수 호출의 부하를 덜어준다. 최근에는 컴파일러 성능이 좋아 인라인 함수를 붙여주지 않아도 컴파일러가 필요한 기능에 인라인 함수로 동작하게 만들어준다.</p>
<h2 id="오버로딩">오버로딩</h2>
<p>C에서의 두 숫자의 합을 반환하는 함수의 경우, 입력값이 정수, 실수, 문자값을 매개변수로 사용하는 함수 모두 따로 선언해줘야 했다.</p>
<pre><code class="language-c">#include &lt;stdio.h&gt;

int AddI(int a, int b);
double AddD(double a, double b);
char AddC(char a, char b);

int main()
{
    int i;
    double d;
    char c;

    i = AddI(10, 20);
    d = AddD(3.14, 1.59);
    c = AddC(&#39;A&#39;, 1);    
    printf(&quot;정수값 출력 : %d\n&quot;, i);
    printf(&quot;실수값 출력 : %f\n&quot;, d);
    printf(&quot;문자값 출력 : %c\n&quot;, c);
}

int AddI(int a, int b)
{
    return a + b;
}
double AddD(double a, double b)
{
    return a + b;
}
char AddC(char a, char b)
{
    return a + b;
}</code></pre>
<pre><code>정수값 출력 : 30
실수값 출력 : 4.730000
문자값 출력 : B</code></pre><p>C++에서는 오버로딩이 가능해 같은 이름으로 함수를 만들 수 있다.</p>
<pre><code class="language-cpp">#include &lt;iostream&gt;

using namespace std;

int Add(int a, int b);
double Add(double a, double b);
char Add(char a, char b);

int main()
{
    int i;
    double d;
    char c;

    i = Add(10, 20);
    d = Add(3.14, 1.59);
    c = Add(&#39;A&#39;, char(1));    
    printf(&quot;정수값 출력 : %d\n&quot;, i);
    printf(&quot;실수값 출력 : %f\n&quot;, d);
    printf(&quot;문자값 출력 : %c\n&quot;, c);
}

int Add(int a, int b)
{
    return a + b;
}
double Add(double a, double b)
{
    return a + b;
}
char Add(char a, char b)
{
    return a + b;
}</code></pre>
<pre><code>정수값 출력 : 30
실수값 출력 : 4.730000
문자값 출력 : B</code></pre><p>템플릿코드를 사용할 경우 더 간단하게 만들 수 있다. 보통 프레임워크 개발자나 엔진 개발자들이 이용한다.</p>
<pre><code class="language-cpp">#include &lt;iostream&gt;

using namespace std;

template &lt;class T&gt; T Add(T a, T b);

int main()
{
    int i;
    double d;
    char c;

    i = Add(10, 20);
    d = Add(3.14, 1.59);
    c = Add(&#39;A&#39;, char(1));    
    printf(&quot;정수값 출력 : %d\n&quot;, i);
    printf(&quot;실수값 출력 : %f\n&quot;, d);
    printf(&quot;문자값 출력 : %c\n&quot;, c);
}

template &lt;class T&gt; T Add(T a, T b)
{
    return a + b;
}</code></pre>
<h1 id="클래스class">클래스(Class)</h1>
<p>사용자가 정의한 추상적인 데이터형(Abstract Data Type)</p>
<p>클래스는 C언어의 구조체와 비슷한 형태이며, 멤버 변수와 멤버 함수로 구성된다.</p>
<pre><code class="language-cpp">class 클래스 이름
{
    접근 지정자:
        데이터형 멤버변수;
    접근 지정자:
        데이터형 멤버함수;
}</code></pre>
<h2 id="접근-지정자">접근 지정자</h2>
<p>클래스는 멤버 선언 시 접근 권한을 설정한다.
<code>private</code> : 접근 불가
<code>public</code> : 접근 가능
<code>protected</code> : 자식은 접근 가능하지만, 외부에서는 접근 불가능</p>
<h2 id="멤버함수-접근">멤버함수 접근</h2>
<pre><code class="language-cpp">#include &lt;iostream&gt;
using namespace std;

// 클래스 정의
class MousePoint
{
    private : // 외부에서 접근하지 못하게 함
        int x, y;

    public :
        void SetXY(int nX, int nY);
};

// 멤버함수 구현
void MousePoint::SetXY(int nX, int nY)
{
    x = nX;
    y = nY;
    cout &lt;&lt; &quot;x = &quot; &lt;&lt; x &lt;&lt; endl;
    cout &lt;&lt; &quot;y = &quot; &lt;&lt; y &lt;&lt; endl;
}

// 객체 생성
int main()
{
    MousePoint point; // 객체
    point.SetXY(10, 20);
}</code></pre>
<pre><code>x = 10
y = 20</code></pre><p><code>MousePoint</code> 클래스에서 멤버변수 <code>x, y</code>는 <code>private</code>로 막혀있기 때문에, 객체에서 변수에 접근하기 위해서 멤버함수 <code>SetXY</code>를 통해야한다.</p>
<h2 id="생성자와-소멸자">생성자와 소멸자</h2>
<h3 id="생성자constructor">생성자(constructor)</h3>
<h4 id="초기화">초기화</h4>
<p>초기화란 기본 데이터를 선언과 동시에 초기값을 대입하는 것이다.</p>
<pre><code class="language-cpp">int a = 5;
float b = 10.5;
int c[5] = {1, 2, 3, 4, 5};</code></pre>
<p>변수 선언 후에 값의 할당이 이루어지는 경우 초기화라고 하지 않는다</p>
<pre><code class="language-cpp">int a;
a = 5;</code></pre>
<h4 id="생성자의-필요-이유">생성자의 필요 이유</h4>
<p>클래스 생성 시 매번 반복되는 초기화 멤버 함수를 만들어야 한다. 객체 생성 시 자동으로 초기화해주는 초기화 전용함수가 있는데, 이 함수를 <code>생성자(constructor)</code>라고한다.</p>
<h4 id="생성자의-특징">생성자의 특징</h4>
<ul>
<li>생성자의 이름은 클래스의 이름과 동일</li>
<li>생성자 타입 지정하지 않음</li>
<li>생성자의 호출은 객체 선언 시 자동으로 호출. 인위적 호출 안됨</li>
<li>반환값을 지정하지 않음</li>
<li>디폴트 생성자가 존재</li>
</ul>
<p>생성자도 오버로딩이 가능하다는 것을 기억하자.</p>
<h3 id="소멸자destructor">소멸자(destructor)</h3>
<p>객체가 소멸할 때 자동 호출되는 소멸자가 존재한다.</p>
<h4 id="소멸자의-특징">소멸자의 특징</h4>
<ul>
<li>소멸자도 클래스의 이름을 그대로 사용한다. 맨 앞에 틸트<code>~</code>기호 표기</li>
<li>소멸자의 타입 지정 안함</li>
<li>객체 소멸 시 자동 호출. 인위적 호출 금지</li>
<li>반환값을 지정하지 않음</li>
<li>전달인자 지정 안함</li>
<li>소멸자는 생성자처럼 오버로딩 안됨</li>
</ul>
<pre><code class="language-cpp">#include &lt;iostream&gt;
using namespace std;

// 클래스 정의
class MousePoint
{
    private : // 외부에서 접근하지 못하게 함
        int x, y;

    public :
        void SetXY(int nX, int nY);
        MousePoint(); // 디폴트 생성자
        MousePoint(int nX, int nY); // 생성자
        ~MousePoint(); // 소멸자
};

void MousePoint::SetXY(int nX, int nY) // 멤버함수
{
    x = nX;
    y = nY;
    cout &lt;&lt; &quot;x = &quot; &lt;&lt; x &lt;&lt; endl;
    cout &lt;&lt; &quot;y = &quot; &lt;&lt; y &lt;&lt; endl;
}

MousePoint::MousePoint() // 디폴트 생성자
{
    cout &lt;&lt; &quot;생성자 호출&quot; &lt;&lt; endl;
    x = 10;
    y = 20;
    cout &lt;&lt; &quot;x = &quot; &lt;&lt; x &lt;&lt; endl;
    cout &lt;&lt; &quot;y = &quot; &lt;&lt; y &lt;&lt; endl;
}

MousePoint::MousePoint(int nX, int nY) // 생성자
{
    x = nX;
    y = nY;
    cout &lt;&lt; &quot;x = &quot; &lt;&lt; x &lt;&lt; endl;
    cout &lt;&lt; &quot;y = &quot; &lt;&lt; y &lt;&lt; endl;
}

MousePoint::~MousePoint() // 소멸자
{
    cout &lt;&lt; &quot;소멸자 호출&quot; &lt;&lt; endl;
}

// 객체 생성
int main()
{
    MousePoint point; // 객체
}</code></pre>
<pre><code>생성자 호출
x = 10
y = 20
소멸자 호출</code></pre><p>생성자는 오버로딩이 가능하다.</p>
<h1 id="클래스의-특징과-객체-활용">클래스의 특징과 객체 활용</h1>
<h2 id="객체-배열">객체 배열</h2>
<p>다수의 변수 사용시 배열을 선언한 것처럼 객체 또한 배열로 선언이 가능한데, 이를 <code>객체 배열</code>이라고 한다.</p>
<pre><code class="language-cpp">#include &lt;iostream&gt;
using namespace std;

// 클래스 정의
class MousePoint
{
    private : // 외부에서 접근하지 못하게 함
        int x, y;

    public :
        void SetXY(int nX, int nY);
        MousePoint(); // 디폴트 생성자
        MousePoint(int nX, int nY); // 생성자
        ~MousePoint(); // 소멸자

        // private한 x,y값을 출력
        int GetX(){return x;}
        int GetY(){return y;}
};

// 멤버함수 구현
void MousePoint::SetXY(int nX, int nY)
{
    x = nX;
    y = nY;
    cout &lt;&lt; &quot;x = &quot; &lt;&lt; x &lt;&lt; endl;
    cout &lt;&lt; &quot;y = &quot; &lt;&lt; y &lt;&lt; endl;
}

MousePoint::MousePoint() // 디폴트 생성자
{
    cout &lt;&lt; &quot;생성자 호출&quot; &lt;&lt; endl;
    x = 10;
    y = 20;
    // cout &lt;&lt; &quot;x = &quot; &lt;&lt; x &lt;&lt; endl;
    // cout &lt;&lt; &quot;y = &quot; &lt;&lt; y &lt;&lt; endl;
}

MousePoint::MousePoint(int nX, int nY) // 생성자
{
    x = nX;
    y = nY;
    // cout &lt;&lt; &quot;x = &quot; &lt;&lt; x &lt;&lt; endl;
    // cout &lt;&lt; &quot;y = &quot; &lt;&lt; y &lt;&lt; endl;
}

MousePoint::~MousePoint() // 소멸자
{
    cout &lt;&lt; &quot;소멸자 호출&quot; &lt;&lt; endl;
}

// 객체 생성
int main()
{
    MousePoint pt[3] = {MousePoint(10, 20), MousePoint(30, 40), MousePoint(50, 60)};
    // pt[0].x = 10, pt[0].y = 20  ....

    for (int i = 0; i &lt; 3; i++)
    {
        cout &lt;&lt; pt[i].GetX() &lt;&lt; endl;
        cout &lt;&lt; pt[i].GetY() &lt;&lt; endl &lt;&lt; endl;
    }
}</code></pre>
<pre><code>10
20

30
40

50
60

소멸자 호출
소멸자 호출
소멸자 호출</code></pre><h2 id="객체-포인터">객체 포인터</h2>
<p>객체의 주소값을 저장하기 위한 변수로, 객체를 간접 참조하기 위해 사용한다.</p>
<pre><code class="language-cpp">MousePoint *pObj;
MousePoint pt(10,20)
pObj = &amp;pt;</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[C++_OOP1]]></title>
            <link>https://velog.io/@gimmicks_/Cpp1</link>
            <guid>https://velog.io/@gimmicks_/Cpp1</guid>
            <pubDate>Thu, 31 Mar 2022 12:53:56 GMT</pubDate>
            <description><![CDATA[<h1 id="객체지향-프로그래밍">객체지향 프로그래밍</h1>
<p><code>Object Oriented Programming</code></p>
<h2 id="구조적-프로그래밍과-객체지향-프로그래밍">구조적 프로그래밍과 객체지향 프로그래밍</h2>
<p>구조적 프로그래밍방식은 순차적, 하향식 및 폭포수 방식이라고도 하며, 기능적인 기본단위는 함수이다.</p>
<p>객체지향 프로그래밍의 기능 단위는 객체이며, 사용자의 요청에 의해 처리되는 구조이다.</p>
<h2 id="추상화abstraction">추상화(Abstraction)</h2>
<p>&lt;-&gt; 구체화</p>
<p><code>개</code>라는 본질과 삽살개, 진돗개, 치와와같은 구체적인 개들의 관계. 코드의 유연성과 효율성을 위해 공통점들을 뽑아 추상화한다. </p>
<h2 id="캡슐화encapsulation">캡슐화(Encapsulation)</h2>
<p>데이터 은닉. 외부에서 내부를 볼 수 없게 한다는 의미이다. 외부로부터 데이터를 조작할 인터페이스가 필요하다.</p>
<blockquote>
<p>클래스 = 데이터 + 메소드(멤버 함수)</p>
</blockquote>
<h2 id="다형성polymorphism">다형성(Polymorphism)</h2>
<p>함수의 이름이 같더라도 전달 인자 타입, 개수 등에 따라 구분, 오버로딩(Overloading)과 오버라이딩(Overriding)기법이 있다.</p>
<h3 id="오버로딩overloading">오버로딩(Overloading)</h3>
<p>사전적 의미는 <code>과적하다</code>, <code>적재하다</code>라는 의미이다. 겉모습은 똑같지만 내용이 다른 경우이며, 이름이 같은 함수일지라도 전달인자 타입이나 개수가 다른경우를 말한다.</p>
<pre><code class="language-cpp">int Plus(int a, int b)
{
    return a + b;
}

char Plus(char a, char b)
{
    return a + b;
}

double Plus(double a, double b)
{
    return a + b;
}</code></pre>
<h3 id="오버라이딩overriding">오버라이딩(Overriding)</h3>
<p><code>올라타다</code>, <code>엎어친다</code>라는 의미로, 무언가에 올라타서 기존의 것을 덮어버린다는 개념이다. 상속의 개념이 기반되어야한다.</p>
<p>상속받은 것들 중, 필요한 기능을 재정의(덮어쓰기)하는 개념이다.</p>
<h2 id="상속성inheritance">상속성(Inheritance)</h2>
<p>이미 완성된 기능에 새로운 기능을 더해 새로운 객체를 만들 때, 모든 기능을 입력할 필요 없이 완성된 기능을 상속받아 사용할 수 있다. </p>
<pre><code class="language-cpp">접근 지정자   클래스이름 : 부모 클래스
{
    //멤버 목록
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[C언어_12]]></title>
            <link>https://velog.io/@gimmicks_/c12</link>
            <guid>https://velog.io/@gimmicks_/c12</guid>
            <pubDate>Thu, 31 Mar 2022 12:49:37 GMT</pubDate>
            <description><![CDATA[<h2 id="파일분할">파일분할</h2>
<p>코드의 양과 라인이 많아지면 하나의 파일에서 관리하기 힘들어 진다. 효율성을 높이기 위해 파일을 나누어 관리한다.</p>
<p>작게는 기능 단위, 크게는 모듈단위로 나누는데, 객체지향에서는 클래스 단위로 나눈다.</p>
<h4 id="헤더파일의-사용법">헤더파일의 사용법</h4>
<ul>
<li><code>#include &lt;헤더 파일 이름&gt;</code> : 헤더 파일을 컴파일러에서 설정한 경로에서 찾는다</li>
<li><code>#include &quot;헤더 파일 이름&quot;</code> : 현재 작업경로에서 찾고, 없는 경우 컴파일러 설정 경로에서 찾는다.</li>
<li><code>#include &quot;c:\&quot;</code> : 절대경로</li>
</ul>
<pre><code class="language-c">//main.c
#include &lt;stdio.h&gt;
#include &quot;add.h&quot;

int Add(int a, int b);

int main(void)
{
    int result;
    result = Add(2, 3);
    printf(&quot;두 수의 합 : %d\n&quot;, result);
    return 0;
}

//add.h (같은 경로 내)
int Add(int a, int b)
{
    return a+b;
}</code></pre>
<pre><code>두 수의 합 : 5</code></pre><h4 id="헤더파일-사용상-특징-및-규칙">헤더파일 사용상 특징 및 규칙</h4>
<ul>
<li>표준 헤더파일 &quot;stdio.h&quot;와 사용자 정의 파일 &quot;stdio.h&quot;을 정의했다면, 사용자 정의파일만 적용된다.</li>
<li>헤더파일 선언 시 대소문자 구분하지 않는다.</li>
<li>경로 구분 시 <code>/</code>을 사용한다.</li>
<li>가급적 절대 경로를 사용하지 않는다.</li>
</ul>
<h4 id="헤더파일과-프로토타입">헤더파일과 프로토타입</h4>
<pre><code class="language-c">// main.c
#include &lt;stdio.h&gt;
#include &quot;header.h&quot;

int main(void)
{
    int result;
    result = Add(2, 3);
    printf(&quot;두 수의 합 : %d\n&quot;, result);
    return 0;
}

int Add(int a, int b)
{
    return a+b;
}

//header.h
#pragma once

extern int Add(int a, int b);</code></pre>
<p>함수의 프로토타입을 보통 헤더파일에 저장하여 사용한다.</p>
<h2 id="조건부-컴파일">조건부 컴파일</h2>
<p>조건에 따라 컴파일을 할 것인지 말 것인지 결정하는 것으로, 소스코드 내에서 특정 영역을 지정하여 컴파일 유무를 결정한다.</p>
<pre><code class="language-c">#include &lt;stdio.h&gt;
#define DEBUG 1 // DEBUG가 정의되어 있다.(true)

int main(void)
{
#if DEBUG
    printf(&quot;디버그 모드로 동작합니다.\n&quot;);
#else
    printf(&quot;릴리즈 모드로 동작합니다.\n&quot;);
#endif
    return 0;
}</code></pre>
<p><code>DEBUG</code>가 정의되어있기 때문에, <code>#if DEBUG</code> 이하문이 작동하고, <code>#else</code> 이하문은 작동하지 않는다.</p>
<h2 id="내장-매크로">내장 매크로</h2>
<ul>
<li>_<em>DATE_</em> : 현재 날짜</li>
<li>_<em>TIME_</em> : 현재 시간</li>
<li>_<em>LINE_</em> : 라인 번호</li>
<li>_<em>FILE_</em> : 파일의 이름</li>
</ul>
<p>내장 매크로는 코드 디버깅에 유용하다</p>
<pre><code class="language-c">#include &lt;stdio.h&gt;

int main(void)
{
    printf(&quot;현재 날짜는 %s입니다.\n&quot;, __DATE__);
    printf(&quot;현재 시간은 %s입니다.\n&quot;, __TIME__);
    printf(&quot;소스 파일은 %s입니다.\n&quot;, __FILE__);
    printf(&quot;현재 라인번호는 %d입니다.\n&quot;, __LINE__);
}</code></pre>
<pre><code>현재 날짜는 Mar 29 2022입니다.
현재 시간은 12:00:24입니다.
소스 파일은 main.c입니다.
현재 라인번호는 26입니다.</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[C언어_11]]></title>
            <link>https://velog.io/@gimmicks_/c11</link>
            <guid>https://velog.io/@gimmicks_/c11</guid>
            <pubDate>Thu, 31 Mar 2022 12:47:54 GMT</pubDate>
            <description><![CDATA[<h1 id="구조체">구조체</h1>
<p>구조체란 하나 이상의 서로 다른 종류의 변수들을 묶어서 새로운 자료형을 정의하는 것이다.</p>
<pre><code class="language-c">struct student
{
    char name[10];
    int age;
    int height;
};</code></pre>
<ul>
<li>student : 구조체 이름</li>
<li>name, age, height : 구조체 멤버</li>
</ul>
<pre><code class="language-c">[구조체 변수명].[구조체 멤버]
st1.name</code></pre>
<p>멤버에 접근시 <code>.</code>을 사용하는데, 이를 직접접근이라고 한다.</p>
<pre><code class="language-c">#include &lt;stdio.h&gt;
#include &lt;string.h&gt;

struct student
{
    char name[10];
    int age;
    int height;
}st1;

int main(void)
{
    strcpy(st1.name, &quot;James&quot;);
    st1.age = 25;
    st1.height = 178;
    printf(&quot;이름 = %s, 나이 = %d, 키 = %d\n&quot;, st1.name, st1.age, st1.height);
    return 0;
}</code></pre>
<pre><code>이름 = James, 나이 = 25, 키 = 178</code></pre><h1 id="전처리기">전처리기</h1>
<p>소스파일 -(전처리)&gt; 전처리파일 -(컴파일)&gt; 목적파일 -(링크)&gt; 실행파일</p>
<p><code>#</code>이 붙은 전처리문은 컴파일러에서 처리하지 않고, 전처리기에서 처리된다.</p>
<p>전처리기 지시자의 종류</p>
<ul>
<li>헤더파일 선언 : <code>#include</code></li>
<li>매크로 정의 : <code>#define</code></li>
<li>조건부 컴파일 : <code>#ifdef</code></li>
</ul>
<h2 id="매크로">매크로</h2>
<p><code>#define</code> 전처리기 지시자를 사용하여 매크로를 사용</p>
<pre><code class="language-c">#include &lt;stdio.h&gt;
#define PI 3.14

int main(void)
{
    double area;
    double radius;
    fputs(&quot;반지름을 입력하시오 :&quot;, stdout);
    scanf(&quot;%lf&quot;, &amp;radius);
    area = radius * radius * PI;
    printf(&quot;원의 넓이는 %lf입니다.\n&quot;, area);
    return 0;
}</code></pre>
<pre><code>반지름을 입력하시오 :30
원의 넓이는 2826.000000입니다.</code></pre><h3 id="선언-시-유의사항">선언 시 유의사항</h3>
<ul>
<li>이름 중간에 공백 불가</li>
<li>이름 시작 시 숫자 불가</li>
<li>이름 변수와 구분하기 위해 대문자 사용</li>
</ul>
<p>매크로 상수를 배열 선언 시 배열의 길이로 사용할 수 있다.</p>
<pre><code class="language-c">#include &lt;stdio.h&gt;
#define SIZE 5

int main(void)
{
    char str[SIZE] = &quot;LOVE&quot;;
    int i;
    for(i = 0; i &lt; SIZE; i++)
    {
        printf(&quot;배열의 요소 %d은 %c\n&quot;,i , str[i]);
    }
    return 0;
}</code></pre>
<pre><code>배열의 요소 0는 L
배열의 요소 1는 O
배열의 요소 2는 V
배열의 요소 3는 E
배열의 요소 4는 </code></pre><h3 id="매크로의-중첩-선언">매크로의 중첩 선언</h3>
<p>이미 선언한 매크로를 또 다른 매크로에서 사용할 수 있다.</p>
<pre><code class="language-c">#include &lt;stdio.h&gt;
#define A 5
#define B A + 10

int main()
{
    printf(&quot;A = %d\n&quot;, A);
    printf(&quot;B = %d\n&quot;, B);
    printf(&quot;B * 2 = %d\n&quot;, B * 2);
    return 0;
}</code></pre>
<pre><code>A = 5
B = 15
B * 2 = 25</code></pre><p>생각대로라면 <code>B * 2</code>가 30이 나와야 하지만, 컴파일러는 단순치환 하여 <code>A + 10 * 2</code>로 인식하기 때문에, 25가 나온다. 이를 방지하기 위해 괄호를 사용한다.</p>
<pre><code class="language-c">#include &lt;stdio.h&gt;
#define A 5
#define B (A + 10)

int main()
{
    printf(&quot;A = %d\n&quot;, A);
    printf(&quot;B = %d\n&quot;, B);
    printf(&quot;B * 2 = %d\n&quot;, B * 2);
    return 0;
}</code></pre>
<pre><code>A = 5
B = 15
B * 2 = 30</code></pre><h3 id="매크로함수">매크로함수</h3>
<p>자료형에 독립적이고 함수의 경우처럼 루틴을 호출하는 것이 아닌 단순 치환하는 것이므로 더욱 빠르지만, 복잡해지는 경우 쓰지 않는 것이 좋다.</p>
]]></description>
        </item>
    </channel>
</rss>