<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>no_lunch.log</title>
        <link>https://velog.io/</link>
        <description>런치는 점심</description>
        <lastBuildDate>Mon, 13 Nov 2023 19:17:23 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>no_lunch.log</title>
            <url>https://velog.velcdn.com/images/no_lunch/profile/1a79b827-9431-4d85-bc7f-1040e624dd4b/image.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. no_lunch.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/no_lunch" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[1010]]></title>
            <link>https://velog.io/@no_lunch/1010</link>
            <guid>https://velog.io/@no_lunch/1010</guid>
            <pubDate>Mon, 13 Nov 2023 19:17:23 GMT</pubDate>
            <description><![CDATA[<p>&lt; 오전 &gt;</p>
<p>TCP / IP Socket Programming</p>
<p>./hello_server 9190
./hello_client 127.0.0.1 9190</p>
<p>---- 파일 디스크립터 설명</p>
<p>---- 포트 번호 
&lt; 오후 &gt;</p>
<p>SAMBA 서버 구축 </p>
<p>$ sudo apt-get install samba samba-common-bin</p>
<p>$ sudo smbpasswd -a pi  // (pi) 유저의 패스워드 설정</p>
<p>$ vim /etc/samba/smb.conf // vim 에 아래 추가</p>
<p>[aaa]
  comment = pi share folder
  path = /home/aaa/shareSamba
  valid users = aaa
  browseable = yes
  guest ok = no
  read only = no
  create mask = 0777</p>
<p>$ sudo /etc/init.d/samba-ad-dc // 삼바 재실행
        혹은
$ sudo service smbd stop // start 혹은 restart</p>
<p>후에 윈도우 탐색기에서 \169.254.42.230 접속 ( Username / Password 입력)</p>
<hr>
<p>TCP/IP Socket 프로그래밍 </p>
<ul>
<li>bind </li>
<li>OSI 7 계층 , TCP/IP Protocol</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[1005]]></title>
            <link>https://velog.io/@no_lunch/1005</link>
            <guid>https://velog.io/@no_lunch/1005</guid>
            <pubDate>Mon, 13 Nov 2023 19:17:13 GMT</pubDate>
            <description><![CDATA[<p>&lt;오전&gt;
Git 예제
Linux에 대한 설명 </p>
<p>&lt;오후&gt;
gpio - v
gpio readall</p>
<p>WiringPi를 이용해 구현해보는 Raspberry Pi 예제</p>
<p>LED, 스위치</p>
<p>PINMAP
SW 1 | GP4
SW 2 | GP17
SW 3 | GP27
SW 4 | GP22</p>
<p>LED 1| GP23
LED 2| GP24
LED 3| GP25
LED 4| GP1    </p>
<p>PIR  | GP7</p>
<p>PIEZO| GP12</p>
<p>-- 라즈베리 파이 인터럽트 처리 
<a href="https://blog.naver.com/simjk98/222175571376">https://blog.naver.com/simjk98/222175571376</a></p>
<p>#include &lt;wiringPi.h&gt;
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;</p>
<p>#define LED_PIN 4 </p>
<p>int main(void) {
    if (wiringPiSetup() == -1) {
        printf(&quot;WiringPi 초기화 실패!\n&quot;);
        return 1;
    }</p>
<pre><code>pinMode(LED_PIN, OUTPUT);
for (int i=0; i &lt; 5; i++){
    digitalWrite(LED_PIN, HIGH);
    printf(&quot;LED 켜짐\n&quot;);
    delay(1000); 

    digitalWrite(LED_PIN, LOW);
    printf(&quot;LED 꺼짐\n&quot;);
    delay(1000); 
}

return 0;</code></pre><p>}</p>
<hr>
<p>#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;wiringPi.h&gt;</p>
<p>//gpio 사용
#define LED_PIN 23
#define BUTTON_PIN 4
#define delay_val 300</p>
<p>int main(void){
    if (wiringPiSetupGpio() == -1) {
        printf(&quot;GPIO 초기화 실패!\n&quot;);
        return 1;
    }</p>
<pre><code>pinMode(BUTTON_PIN, INPUT);
pinMode(LED_PIN, OUTPUT);

while(1){
    if(digitalRead(BUTTON_PIN) == HIGH){
        digitalWrite(LED_PIN, HIGH);
        printf(&quot;Button Pushed..! -&gt; LED ON\n&quot;);
        delay(delay_val); 
    } 
    else {
        digitalWrite(LED_PIN, LOW);
        printf(&quot;LED OFF\n&quot;);
        delay(delay_val); 
    }
}

return 0;</code></pre><p>}</p>
<p>//ISR(Interrupt Service Routine) 구현
int led1_flag = 0;
void sw1_isr(void){
    if(led1_flag == 0){
        digitalWrite(LED_PIN,HIGH);
        led1_flag=1;
    } else {
        digitalWrite(LED_PIN,LOW);
        led1_flag=0;
    }
    prtintf(&quot;SW1 pushed..!!&quot;);
}</p>
<hr>
<pre><code class="language-c">#include &lt;stdio.h&gt;
#include &lt;pthread.h&gt; // 목적파일 생성시 -lpthread 옵션 넣어주기
#include &lt;unistd.h&gt;

void* thread_main(void *arg){
    int i;
    int cnt = *((int*)arg);
    for(i=0; i&lt;cnt; i++){
        sleep(1);
        puts(&quot;running thread\n&quot;);
    }
    return NULL;
}

int main(int argc, char *argv[]){
    //printf(&quot;%d\n&quot;,argc); // result : argc = 1 , argc = 인자들의 갯수 ex)./test a , argc = 2 ./test a,b ,argc = 3

    //for(int i=0;i&lt;argc;i++){
    //    printf(&quot;%s\n&quot;,argv[i]);} // result : ./test

    pthread_t t_id;
    int thread_param = 5;

    if(pthread_create(&amp;t_id, NULL, thread_main,(void*)&amp;thread_param)!=0){
        puts(&quot;pthread_create&quot;);
        return -1;
    }

    sleep(10);
    puts(&quot;end of main\n&quot;);

    return 0;
}</code></pre>
<p><img src="https://velog.velcdn.com/images/no_lunch/post/23e1ee8d-0fe4-4f79-89a7-795303b60cc0/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[C++을 이용한 OpenCV(7)]]></title>
            <link>https://velog.io/@no_lunch/C%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%9C-OpenCV7</link>
            <guid>https://velog.io/@no_lunch/C%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%9C-OpenCV7</guid>
            <pubDate>Wed, 04 Oct 2023 10:39:20 GMT</pubDate>
            <description><![CDATA[<h3 id="스마트-포인터">스마트 포인터</h3>
<blockquote>
<p>포인터처럼 동작하는 클래스 템플릿으로, 사용이 끝난 메모리를 자동으로 해제, new 키워드를 사용해 기본 포인터가 실제 메모리를 가리키도록 초기화한 후에, 기본 포인터를 스마트 포인터에 대입하여 사용
이렇게 정의된 스마트 포인터의 수명이 다하면, 소멸자는 delete 키워드를 사용하여 할당된 메모리를 자동으로 해제
따라서 new 키워드가 반환하는 주소값을 스마트 포인터에 대입하면, 따로 메모리를 해제할 필요 없음</p>
</blockquote>
<pre><code class="language-cpp">#pragma once
#include&lt;opencv2/opencv.hpp&gt;

//smart pointer
static cv::Ptr&lt;cv::ml::KNearest&gt; train_knn() {
    cv::Mat digits = cv::imread(&quot;digits.png&quot;, cv::IMREAD_GRAYSCALE);
    if (digits.empty())return nullptr; 
    cv::Mat train_images;
    cv::Mat train_labels;
    for (int i = 0; i &lt; 50; ++i) {
        for (int j = 0; j &lt; 100; ++j) {
            cv::Mat roi = digits(cv::Rect(j * 20, i * 20, 20, 20));
            cv::Mat roi_float;
            roi.convertTo(roi_float, CV_32FC1);
            cv::Mat roi_flatten = roi_float.reshape(1, 1); 
            train_images.push_back(roi_flatten);
            train_labels.push_back(i / 5);
        }
    }
    cv::Ptr&lt;cv::ml::KNearest&gt; knn = cv::ml::KNearest::create(); //Singular
    knn-&gt;train(train_images, cv::ml::ROW_SAMPLE,train_labels);
    return knn;
}</code></pre>
<h3 id="마우스-클릭-감지">마우스 클릭 감지</h3>
<pre><code class="language-cpp">static cv::Point point_prev(-1, -1);
static void on_mouse(int event, int x, int y, int flag, void* userdata) {
    cv::Mat src = *(static_cast&lt;cv::Mat*&gt;(userdata));
    if (event == cv::EVENT_LBUTTONDOWN) {
        point_prev = cv::Point(x, y);
    }
    else if (event == cv::EVENT_LBUTTONUP){
        point_prev = cv::Point(-1, -1);
    }
    else if (event == cv::EVENT_MOUSEMOVE &amp;&amp; (flag &amp; cv::EVENT_FLAG_LBUTTON)) {
        cv::line(src, point_prev, cv::Point(x, y), cv::Scalar(255, 255, 255), 30, cv::LINE_AA, 0);
        point_prev = cv::Point(x, y);
        cv::imshow(&quot;DISPLAY&quot;, src);
    }
}</code></pre>
<h3 id="knn-알고리즘">KNN 알고리즘</h3>
<blockquote>
<p>최근접 알고리즘(KNN 알고리즘)은 분류 알고리즘으로 주변에 가까운 K개의 데이터를 보고 데이터가 속할 그룹을 판단
<img src="https://velog.velcdn.com/images/no_lunch/post/592309d6-66fb-441e-95f6-d3d6706afe51/image.png" alt=""></p>
</blockquote>
<pre><code class="language-cpp">void do_knn_machine_learning() {
    cv::Ptr&lt;cv::ml::KNearest&gt; knn = train_knn();
    if (knn.empty()) {
        std::cerr &lt;&lt; &quot;Train Error&quot; &lt;&lt; std::endl;
        return;
    }
    std::cout &lt;&lt; &quot;Train finished&quot; &lt;&lt; std::endl;
    cv::Mat input_display(200, 200, CV_8UC1);
    cv::namedWindow(&quot;DISPLAY&quot;, cv::WINDOW_NORMAL);
    cv::setMouseCallback(&quot;DISPLAY&quot;, on_mouse, (void*)&amp;input_display);
    while (true) {
        int keyboard_key = cv::waitKey();
        if (keyboard_key == 27)break;
        else if (keyboard_key == &#39; &#39;) { //input space bar
            cv::Mat img_resize;
            cv::Mat img_float; // Matrix to transform CV_32FC1 
            cv::Mat image_flatten;
            cv::Mat resource; // Matrix to save the result
            cv::resize(input_display, img_resize, cv::Size(20, 20), 0, 0, cv::INTER_AREA);
            img_resize.convertTo(img_float,CV_32FC1);
            image_flatten = img_float.reshape(1, 1); //flatten ( 1 x 400 )
            knn-&gt;findNearest(image_flatten, 5, resource); // k =5  optionable 3,5,7,9
            std::cout &lt;&lt; cvRound(resource.at&lt;float&gt;(0, 0)) &lt;&lt; std::endl;
            input_display.setTo(0);
            cv::imshow(&quot;DISPLAY&quot;, input_display);
        }
    }
    cv::destroyAllWindows();
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[C++을 이용한 OpenCV(6)]]></title>
            <link>https://velog.io/@no_lunch/C%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%9C-OpenCV6</link>
            <guid>https://velog.io/@no_lunch/C%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%9C-OpenCV6</guid>
            <pubDate>Wed, 04 Oct 2023 10:17:27 GMT</pubDate>
            <description><![CDATA[<h3 id="hue-색상-saturation-채도-및-value-명도-정보-분리">Hue (색상), Saturation (채도) 및 Value (명도) 정보 분리</h3>
<pre><code class="language-cpp">#pragma once
#include &lt;opencv2/opencv.hpp&gt;

void color_split() {
    cv::Mat src = cv::imread(&quot;candies.png&quot;);
    cv::Mat dst(src.size(), src.type());
    std::vector&lt;cv::Mat&gt;hsv_planes;
    cv::cvtColor(src, dst, cv::COLOR_BGR2HSV);
    cv::split(dst, hsv_planes);
    cv::imshow(&quot;SRC&quot;, src);
    cv::imshow(&quot;DST&quot;, dst);
    cv::imshow(&quot;H&quot;, hsv_planes[0]);
    cv::imshow(&quot;S&quot;, hsv_planes[1]);
    cv::imshow(&quot;V&quot;, hsv_planes[2]);
    cv::waitKey();
    cv::destroyAllWindows();
}</code></pre>
<h3 id="임계값-처리threshhold">임계값 처리(Threshhold)</h3>
<blockquote>
<p>바이너리 이미지(binary image)란 검은색과 흰색만으로 표현한 이미지를 만드는 방법으로,
여러 값을 어떤 임계점을 기준으로 두 가지 부류로 나누는 방법을 의미</p>
</blockquote>
<pre><code class="language-cpp">static void on_threshhold(int position, void* userdata) {
    cv::Mat src = *(static_cast&lt;cv::Mat*&gt;(userdata));
    cv::Mat dst;
}
void using_threshhold() {
    cv::Mat src = cv::imread(&quot;sudoku.jpg&quot;, cv::IMREAD_GRAYSCALE);
    if (src.empty())return;
    cv::namedWindow(&quot;SRC&quot;, cv::WINDOW_NORMAL);
    cv::namedWindow(&quot;DST&quot;, cv::WINDOW_NORMAL);
    cv::imshow(&quot;SRC&quot;, src);
    cv::createTrackbar(&quot;Threshhold&quot;, &quot;DST&quot;, 0, 255, on_threshhold, (void*)&amp;src);
    cv::setTrackbarPos(&quot;Threshhold&quot;, &quot;DST&quot;, 128);
    cv::waitKey();
    cv::destroyAllWindows();

}</code></pre>
<h3 id="트랙바-설정">트랙바 설정</h3>
<pre><code class="language-cpp">static void on_trackbar(int position, void* userdata) {
    cv::Mat src = *(static_cast&lt;cv::Mat*&gt;(userdata));
    int block_size = position;
    if (position % 2 == 0) --position;
    if (block_size &lt; 3) block_size = 3;
    cv::Mat dst;
    cv::adaptiveThreshold(src, dst, 255, \
        cv::ADAPTIVE_THRESH_GAUSSIAN_C, cv::THRESH_BINARY, block_size, 5.0);
    cv::imshow(&quot;DST&quot;, dst);
}</code></pre>
<h3 id="적응-임계값-처리">적응 임계값 처리</h3>
<pre><code class="language-cpp">void adapative_threshhold() {
    cv::Mat src = cv::imread(&quot;sudoku.jpg&quot;, cv::IMREAD_GRAYSCALE);
    if (src.empty())return;
    cv::namedWindow(&quot;DST&quot;,cv::WINDOW_NORMAL);
    cv::createTrackbar(&quot;BlockBuster&quot;, &quot;DST&quot;, nullptr, 200, on_trackbar, (void*)&amp;src);
    cv::setTrackbarPos(&quot;Blocksize&quot;, &quot;DST&quot;, 11);
    cv::waitKey();
    cv::destroyAllWindows();
}</code></pre>
<h3 id="이미지-침식--팽창">이미지 침식 &amp; 팽창</h3>
<pre><code class="language-cpp">void erode_dilate() {
    cv::Mat src{ cv::imread(&quot;milkdrop.bmp&quot;, cv::IMREAD_GRAYSCALE) };
    if (src.empty())return;
    cv::imshow(&quot;SRC&quot;, src);
    cv::Mat binary_img;
    cv::threshold(src, binary_img, 0.0,/*0.0 = for &quot;OTSU&quot; */255.0, cv::THRESH_BINARY | cv::THRESH_OTSU);
    cv::Mat dst_erode;
    cv::erode(binary_img, dst_erode, cv::Mat());//DEFAULT 3x3
    for (int i = 0; i &lt; 5; ++i) {
        cv::erode(dst_erode, dst_erode, cv::Mat());
        cv::imshow(&quot;ERODE&quot;,dst_erode);
        cv::waitKey();
    }
    cv::Mat dst_dilate;
    cv::dilate(binary_img, dst_dilate, cv::Mat());
    for (int i = 0; i &lt; 5; ++i) {
        cv::dilate(dst_dilate, dst_dilate, cv::Mat());
        cv::imshow(&quot;DILATE&quot;, dst_dilate);
        cv::waitKey();
    }
    cv::destroyAllWindows();
}</code></pre>
<p><img src="https://velog.velcdn.com/images/no_lunch/post/324856de-076a-4b51-a2e7-0089360483eb/image.png" alt=""></p>
<h3 id="오프닝--클로징-기법">오프닝 &amp; 클로징 기법</h3>
<blockquote>
<ol>
<li>Opening : 연결된 부분을 끊어주는 것, 침식연산 이후 팽창연산으로 구현<ol start="2">
<li>Closeing : 끊겨있는 부분을 이어주는 것, 팽창연산 이후 침식연산으로 구현</li>
</ol>
</li>
</ol>
</blockquote>
<pre><code class="language-cpp">void open_close() {
    cv::Mat src = cv::imread(&quot;milkdrop.bmp&quot;, cv::IMREAD_GRAYSCALE);
    if (src.empty())return;
    cv::Mat binary_img;
    cv::threshold(src, binary_img, 0.0, 255.0, cv::THRESH_BINARY | cv::THRESH_OTSU);
    cv::Mat dst_open;
    cv::Mat dst_close;
    cv::morphologyEx(binary_img, dst_open, cv::MORPH_OPEN, cv::Mat(),cv::Point(-1,-1),5);
    cv::morphologyEx(binary_img, dst_close, cv::MORPH_CLOSE, cv::Mat(), cv::Point(-1, -1), 5);
    cv::imshow(&quot;SRC&quot;, src);
    cv::imshow(&quot;B_IMG&quot;, binary_img);
    cv::imshow(&quot;DST_OPEN&quot;, dst_open);
    cv::imshow(&quot;DST_CLOSE&quot;, dst_close);
    cv::waitKey();
    cv::destroyAllWindows();
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[C++ 을 이용한 OpenCV(5)]]></title>
            <link>https://velog.io/@no_lunch/C-%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%9C-OpenCV5</link>
            <guid>https://velog.io/@no_lunch/C-%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%9C-OpenCV5</guid>
            <pubDate>Wed, 04 Oct 2023 08:05:57 GMT</pubDate>
            <description><![CDATA[<h3 id="이미지의-논리-연산">이미지의 논리 연산</h3>
<pre><code class="language-cpp">#pragma once
#include &lt;opencv2/opencv.hpp&gt;

void arithmetic1() {
    cv::Mat src1 = cv::imread(&quot;lenna256.bmp&quot;, cv::IMREAD_GRAYSCALE);
    cv::Mat src2 = cv::imread(&quot;square.bmp&quot;, cv::IMREAD_GRAYSCALE);

    if (src1.empty() or src2.empty()) return;

    std::cout &lt;&lt; src1.size &lt;&lt; std::endl; 
    std::cout &lt;&lt; src2.size &lt;&lt; std::endl;

    cv::Mat dst1;
    cv::add(src1,src2,dst1);
    //cv::Mat dst2 = src2 - src1;
    cv::Mat dst2;
    cv::subtract(src2, src1, dst2);
    cv::Mat dst3;
    cv::absdiff(src1, src2, dst3); //
    cv::Mat dst4;
    cv::namedWindow(&quot;ADDWEIGHTED&quot;);
    for (double i = 0; i &lt;= 1.0; i = i + 0.2) {
        cv::addWeighted(src1, i, src2, i - 1.0, 0.0, dst4);
        cv::imshow(&quot;ADDWEIGHTED&quot;, dst4);
        cv::waitKey();
    }
    cv::imshow(&quot;DST1&quot;, dst1);
    cv::imshow(&quot;DST2&quot;, dst2);
    cv::imshow(&quot;SRC1&quot;, src1);
    cv::imshow(&quot;SRC2&quot;, src2);
    cv::imshow(&quot;DST3&quot;, dst3);
    cv::waitKey();
    cv::destroyAllWindows();
}

void logical() {
    cv::Mat src1 = cv::imread(&quot;lenna256.bmp&quot;, cv::IMREAD_GRAYSCALE);
    cv::Mat src2 = cv::imread(&quot;square.bmp&quot;,cv::IMREAD_GRAYSCALE);
    if (src1.empty() or src2.empty())return;
    cv::Mat dst(256, 256, CV_8UC1);
    /*cv::bitwise_and(src1, src2, dst);
    cv::imshow(&quot;SRC1&quot;, src1);
    cv::imshow(&quot;SRC2&quot;, src2);
    cv::imshow(&quot;DST&quot;, dst);*/


    cv::bitwise_or(src1, src2, dst);
    cv::imshow(&quot;SRC1&quot;, src1);
    cv::imshow(&quot;SRC2&quot;, src2);
    cv::imshow(&quot;DST&quot;, dst);
    cv::waitKey();

    cv::bitwise_xor(src1, src2, dst);
    cv::imshow(&quot;SRC1&quot;, src1);
    cv::imshow(&quot;SRC2&quot;, src2);
    cv::imshow(&quot;DST&quot;, dst);
    cv::waitKey();

    cv::bitwise_not(src1, src2, dst);
    cv::imshow(&quot;SRC1&quot;, src1);
    cv::imshow(&quot;SRC2&quot;, src2);
    cv::imshow(&quot;DST&quot;, dst);
    cv::waitKey();

    cv::destroyAllWindows();
}</code></pre>
<h3 id="마우스-감지">마우스 감지</h3>
<p><code>static void on_mouse(int, int, int, int, void*);</code></p>
<h3 id="필터---엠보싱">필터 - 엠보싱</h3>
<blockquote>
<p>엠보싱 필터링(Embossing Filtering) : 컨벌루션 - 픽셀 간 차이 계산 - 밝기 조절의 순서로 이루어지며 주로 이미지의 경계 및 입체 느낌을 부각시키기 위해 적용</p>
</blockquote>
<pre><code class="language-cpp">void filter_embossing() {
    cv::Mat src = cv::imread(&quot;lenna.bmp&quot;, cv::IMREAD_GRAYSCALE);
    if (src.empty()) return;
    float fillter_data[] = { -1.0f,-1.0f, 0.0f, -1.0,0.0f,1.0f,0.0f,1.0f,1.0f };

    cv::Mat emboss_kernel(3, 3, CV_32FC1, fillter_data);

    cv::Mat dst;
    cv::filter2D(src, dst, -1, emboss_kernel, cv::Point(-1, -1), 80); // 80 -&gt; ligth up
    cv::imshow(&quot;SRC&quot;, src);
    cv::imshow(&quot;DST&quot;, dst);
    cv::waitKey();
    cv::destroyAllWindows();
}</code></pre>
<p><img src="https://velog.velcdn.com/images/no_lunch/post/ed1904c1-7050-43c0-81a6-4ed201a80233/image.png" alt=""></p>
<h3 id="필터---블러링">필터 - 블러링</h3>
<blockquote>
</blockquote>
<p>블러링 필터(Blurring Filter) : 컨벌루션 - 픽셀 간의 가중 평균 계산 - 흐리게 만들기의 순서로 진행되며 이미지의 노이즈를 줄이는 데 효과적이다. 
주로 이미지에서 잡음을 제거하거나 세부한 텍스처를 흐리게 만들어 감추는 데 사용</p>
<pre><code class="language-cpp">void filter_blurring() {
    cv::Mat src = cv::imread(&quot;lenna.bmp&quot;, cv::IMREAD_GRAYSCALE);
    if (src.empty())return;
    cv::Mat dst;
    float blur_filter[] = { 1 / 9.f,1 / 9.f,1 / 9.f, 1 / 9.f,1 / 9.f,1 / 9.f , 1 / 9.f,1 / 9.f,1 / 9.f };
    cv::Mat dst2(3, 3, CV_32FC1, blur_filter);
    cv::filter2D(src, dst, -1, dst2, cv::Point(-1, -1), 0);
    cv::imshow(&quot;SRC&quot;, src);
    cv::imshow(&quot;DST&quot;, dst);
    cv::waitKey();

    for (int ksize = 3; ksize &lt;= 7; ksize += 2) {
        cv::blur(src, dst, cv::Size(ksize, ksize));
        cv::String desc = cv::format(&quot;Mean : %d X %d&quot;, ksize, ksize);
        cv::putText(dst, desc, cv::Point(10, 30), cv::FONT_HERSHEY_SIMPLEX, 1.0, cv::Scalar(255), 1, cv::LINE_AA);
        cv::imshow(&quot;DST&quot;, dst);
        cv::waitKey();
    }

    cv::destroyAllWindows();
}</code></pre>
<p><img src="https://velog.velcdn.com/images/no_lunch/post/58a1e608-7d6a-46a6-9b9f-5b4b12f626b9/image.png" alt=""></p>
<h3 id="필터---가우시안-블러링">필터 - 가우시안 (블러링)</h3>
<blockquote>
<p>평균값 필터보다 자연스러운 블러링 결과를 만드는 핕터 ( 주로 평균이 0 )
 <em>가우시안 분포</em> : 평균을 중심으로 좌우 대칭의 종 모양을 갖는 확률 분포 ( 정규 분포 )</p>
</blockquote>
<pre><code class="language-cpp">void filter_gaussian() {
    cv::Mat src = cv::imread(&quot;rose.bmp&quot;, cv::IMREAD_GRAYSCALE);
    if (src.empty())return;
    cv::Mat dst;
    for (int sigma = 1; sigma &lt;= 5; ++sigma) {
        cv::GaussianBlur(src, dst, cv::Size(), static_cast&lt;double&gt;(sigma));
        cv::String text = cv::format(&quot;Sigma : %d&quot;, sigma);
        cv::putText(dst, text, cv::Point(10, 30), cv::FONT_HERSHEY_PLAIN, 1.0, cv::Scalar(255), 1, cv::LINE_AA);
        cv::imshow(text, dst);
        cv::waitKey();
    }
    cv::destroyAllWindows();
}</code></pre>
<p><img src="https://velog.velcdn.com/images/no_lunch/post/0926fafa-a22e-49df-be07-855e9b1e4377/image.png" alt=""></p>
<h3 id="필터샤프닝---언샤프-마스크-필터">필터/샤프닝 - 언샤프 마스크 필터</h3>
<blockquote>
<p>영상을 더 날카롭게 만듦</p>
</blockquote>
<pre><code class="language-cpp">void filter_unsharp_mask() {
    cv::Mat src = cv::imread(&quot;lenna.bmp&quot;, cv::IMREAD_GRAYSCALE);
    if (src.empty())return;
    cv::imshow(&quot;SRC&quot;, src);
    cv::Mat blurred;
    float alpha = 1.0f;
    for (int sigma = 1; sigma &lt;= 5; ++sigma) {
        cv::GaussianBlur(src, blurred, cv::Size(), sigma);
        cv::Mat dst = (1 + alpha) * src - (alpha * blurred);
        cv::String text = cv::format(&quot;Sigma : %d&quot;, sigma);
        cv::putText(dst, text, cv::Point(10, 30), cv::FONT_HERSHEY_SIMPLEX, 1.0, cv::Scalar(255), 1.0, cv::LINE_AA);
        cv::imshow(text, dst);
        cv::waitKey();
    }
    cv::destroyAllWindows();
}</code></pre>
<p><img src="https://velog.velcdn.com/images/no_lunch/post/a0bf179d-91e3-4b6e-963e-e7a8fd2d0a80/image.png" alt=""></p>
<h3 id="필터---노이즈-가우시안">필터 - 노이즈 가우시안</h3>
<blockquote>
<p>원본 영상에 잡음의 정도와 평균이 0, 분산이 1인 확률변수를 곱한 값을 더하는 방법으로 생성</p>
</blockquote>
<pre><code class="language-cpp">void noise_gaussian() {
    cv::Mat src = cv::imread(&quot;lenna.bmp&quot;,cv::IMREAD_GRAYSCALE);
    cv::Mat dst;

    for (int stddev = 10; stddev &lt;= 30; stddev += 10) {
        cv::Mat noise(src.size(), CV_32FC1);
        cv::randn(noise, 0, stddev);
        cv::add;
        cv::String text = cv::format(&quot;STDDEV : %d&quot;, stddev);
        cv::putText(dst, text, cv::Point(10, 30), cv::FONT_HERSHEY_SIMPLEX, 1.0, cv::Scalar(255), 1, cv::LINE_AA);
        cv::imshow(&quot;SRC&quot;, src);
        cv::imshow(&quot;DST&quot;, dst);
        cv::waitKey();
        cv::destroyAllWindows();
    }
}</code></pre>
<p><img src="https://velog.velcdn.com/images/no_lunch/post/f245701e-d937-4cea-9510-5544ed3d5692/image.png" alt=""></p>
<h3 id="필터---양방향-필터">필터 - 양방향 필터</h3>
<blockquote>
<p>기준 픽셀과 이웃 픽셀과의 거리, 그리고 픽셀 값의 차이를 함께 고려하여 블러링 정도를 조절하며
엣지가 아닌 부분에서만 블러링 실행</p>
</blockquote>
<pre><code class="language-cpp">void filter_bilateral(){
    cv::Mat src = cv::imread(&quot;lenna.bmp&quot;, cv::IMREAD_GRAYSCALE);
    if (src.empty())return;
    cv::Mat dst1;
    cv::Mat dst2;

    cv::Mat noise(src.size(), CV_32FC1);
    cv::randn(noise, 0, 5);
    cv::add(src, noise, src, cv::noArray(), CV_8UC1);

    cv::GaussianBlur(src, dst1, cv::Size(), 5); //sigma 5
    cv::bilateralFilter(src, dst2, -1, 20, 5);

    cv::imshow(&quot;SRC&quot;, src);
    cv::imshow(&quot;DST1&quot;, dst1);
    cv::imshow(&quot;DST2&quot;, dst2);

    cv::waitKey();
    cv::destroyAllWindows();
}</code></pre>
<h3 id="필터---미디움-필터-미디언-블러">필터 - 미디움 필터 (미디언 블러)</h3>
<blockquote>
<p>미디언 필터(Median filter)는 주변 픽셀들의 값들을 정렬하여 그 중앙값(median)으로 픽셀 값을 대체하며, 소금-후추 잡음 제거에 효과적이지만 화질이 좋지 않음.</p>
</blockquote>
<pre><code class="language-cpp">void filter_medium() {
    cv::Mat src = cv::imread(&quot;lenna.bmp&quot;, cv::IMREAD_GRAYSCALE);
    cv::imshow(&quot;SRC&quot;, src);

    int number = static_cast&lt;int&gt;(src.total() * 0.1);
    for (int i=0; i &lt; number; ++i) {
        int x = rand() % src.cols;
        int y = rand() % src.rows;
        src.at&lt;uchar&gt;(y, x) = (i % 2)*255;
    }
    cv::Mat dst1; //Gaussian Blur
    cv::Mat dst2; //Median blur

    cv::GaussianBlur(src, dst1, cv::Size(), 1);
    cv::medianBlur(src, dst2, 3);


    cv::imshow(&quot;SRC&quot;, src);
    cv::imshow(&quot;DST1&quot;, dst1);
    cv::imshow(&quot;DST2&quot;, dst2);
    cv::waitKey();
    cv::destroyAllWindows();
}</code></pre>
<h3 id="어파인-변환">어파인 변환</h3>
<blockquote>
<p>6개의 파라미터를 가지는 어파인 변환 행렬은 이동한 점의 개수가 최소 3개 이상이어야 구할 수 있으며, 이를 통해 영상의 크기, 모양, 방향을 수정할 수 있다.</p>
</blockquote>
<pre><code class="language-cpp">void affine_transform() {
    cv::Mat src = cv::imread(&quot;tekapo.bmp&quot;);
    if (src.empty())return;
    cv::Point2f srcPts[3];
    cv::Point2f dstPts[3];
    srcPts[0] = cv::Point2f(0, 0);
    srcPts[1] = cv::Point2f(src.cols - 1.0f, 0.0f);
    srcPts[2] = cv::Point2f(src.cols - 1.0f,src.rows-1.0f);
    dstPts[0] = cv::Point2f(50.0f,50.f);
    dstPts[1] = cv::Point2f(src.cols - 100.0f, 100.0f);
    dstPts[2] = cv::Point2f(src.cols - 50.0f,src.rows- 50.0f);
    cv::Mat M = cv::getAffineTransform(srcPts, dstPts);
    std::cout &lt;&lt; M &lt;&lt; std::endl;

    cv::Mat dst;
    cv::warpAffine(src, dst, M, cv::Size());
    cv::imshow(&quot;SRC&quot;, src);
    cv::imshow(&quot;DST&quot;, dst);
    cv::waitKey();
    cv::destroyAllWindows();
}</code></pre>
<h3 id="이미지-방향전환--90도-rotate-">이미지 방향전환 ( 90도 Rotate )</h3>
<pre><code class="language-cpp">void rotate_flip() {
    cv::Mat src = cv::imread(&quot;lenna.bmp&quot;);

    if (src.empty()) {
        std::cerr &lt;&lt; &quot;Failed to load image.&quot; &lt;&lt; std::endl;
        return;
    }

    cv::Mat dst1;
    cv::Mat dst2;

    // Rotate the image 90 degrees clockwise
    cv::rotate(src, dst1, cv::ROTATE_90_CLOCKWISE);

    // Flip the image horizontally and vertically
    cv::flip(src, dst2, -1);

    cv::imshow(&quot;Rotated Image&quot;, dst1);
    cv::imshow(&quot;Flipped Image&quot;, dst2);
    cv::waitKey(0);
    cv::destroyAllWindows();
}</code></pre>
<h3 id="소벨-엣지-검출기">소벨 엣지 검출기</h3>
<pre><code class="language-cpp">void sobel_edge() {
    cv::Mat src = cv::imread(&quot;lenna.bmp&quot;, cv::IMREAD_GRAYSCALE);
    if(src.empty())return;
    cv::Mat dx;
    cv::Mat dy;
    cv::Sobel(src, dx, CV_32FC1,1,0); 
    cv::Sobel(src, dy, CV_32FC1,0,1); 

    cv::imshow(&quot;SRC&quot;, src);
    cv::imshow(&quot;DX&quot;, dx);
    cv::imshow(&quot;DY&quot;, dy);

    cv::Mat mag;
    cv::magnitude(dx, dy, mag);
    //C++ float -&gt; imshow (opencv data)
    mag.convertTo(mag, CV_8UC1);

    cv::imshow(&quot;Mag&quot;, mag);

    cv::waitKey();
    cv::destroyAllWindows();
}</code></pre>
<h3 id="직선-검출">직선 검출</h3>
<pre><code class="language-cpp">void hough_lines() {
    cv::Mat src = cv::imread(&quot;building.jpg&quot;, cv::IMREAD_GRAYSCALE);
    if (src.empty())return;
    cv::Mat edge;
    cv::Canny(src, edge, 50, 150);
    cv::imshow(&quot;EDGE&quot;, edge);
    std::vector&lt;cv::Vec2f&gt; lines;
    cv::HoughLines(edge, lines, 1.0, CV_PI / 180, 230);
    cv::Mat dst;
    cv::cvtColor(src, dst, cv::COLOR_GRAY2BGR); //3channel ( Not colored )

    cv::imshow(&quot;DST&quot;,dst);
    for (int i = 0; i &lt; lines.size(); ++i)
    {
        float r = lines[i][0];
        float t = lines[i][1];
        double cos_t = cos(t);
        double sin_t = sin(t);
        double x0 = r * cos_t;
        double y0 = r * sin_t;
        double alpha = 1000;
        cv::Point pt1(cvRound(x0 + alpha * (-sin_t)), cvRound(y0 + alpha * cos_t));
        cv::Point pt2(cvRound(x0 - alpha * (-sin_t)), cvRound(y0 - alpha * cos_t));

        cv::line(dst, pt1, pt2, cv::Scalar(0, 0, 255), 2, cv::LINE_AA);
    }
    cv::imshow(&quot;DST&quot;, dst);
    cv::waitKey();
    cv::destroyAllWindows();
}</code></pre>
<p><img src="https://velog.velcdn.com/images/no_lunch/post/e74b5272-caba-4906-8e0e-53a4f826e284/image.png" alt=""></p>
<h3 id="원형-검출">원형 검출</h3>
<pre><code class="language-cpp">void hough_circles() {
    cv::Mat src = cv::imread(&quot;coins.png&quot;, cv::IMREAD_GRAYSCALE);
    if (src.empty()) return;

    cv::Mat blurred; // eliminate noise 
    cv::blur(src, blurred, cv::Size(3, 3));

    std::vector&lt;cv::Vec3f&gt; circles;
    cv::HoughCircles(blurred, circles, cv::HOUGH_GRADIENT,1,50,200,50);

    cv::Mat dst;
    cv::cvtColor(src, dst, cv::COLOR_GRAY2BGR);
    for (auto&amp;&amp; circle : circles) {
        cv::Point center(cvRound(circle[0]), cvRound(circle[1]));
        int radius = cvRound(circle[2]);
        cv::circle(dst, center, radius, cv::Scalar(255, 0, 0), 2, cv::LINE_AA);
    }

    cv::imshow(&quot;SRC&quot;,src);
    cv::imshow(&quot;DST&quot;,dst);
    cv::waitKey();
    cv::destroyAllWindows();
}</code></pre>
<p><img src="https://velog.velcdn.com/images/no_lunch/post/3c44b7ce-cccd-4ca5-85e9-b69bc991885e/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[C++ 을 이용한 OpenCV(4)]]></title>
            <link>https://velog.io/@no_lunch/C-%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%9C-OpenCV4</link>
            <guid>https://velog.io/@no_lunch/C-%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%9C-OpenCV4</guid>
            <pubDate>Wed, 27 Sep 2023 06:16:27 GMT</pubDate>
            <description><![CDATA[<h3 id="색상-변경--color---grayscale">색상 변경 ( COLOR -&gt; GRAYSCALE)</h3>
<pre><code class="language-cpp">#pragma once
#include&lt;opencv2/opencv.hpp&gt;
static cv::Mat getGrayHistImage(const cv::Mat&amp; hist);
static cv::Mat calcGrayHist(const cv::Mat&amp; hist);
void example() {
    cv::Mat img1 = cv::imread(&quot;lenna.bmp&quot;);
    cv::Mat img2;
    cv::cvtColor(img1, img2, cv::COLOR_BGR2GRAY); //BGR -&gt; GRAYSCALE
    cv::imshow(&quot;IMG1&quot;, img1);
    cv::imshow(&quot;IMG2&quot;, img2);
    cv::waitKey();
    cv::destroyAllWindows();

}</code></pre>
<h3 id="밝기-조절">밝기 조절</h3>
<pre><code class="language-cpp">void brightness() {
    cv::Mat src = cv::imread(&quot;lenna.bmp&quot;, cv::IMREAD_GRAYSCALE);
    if (src.empty()) return;
    cv::Mat dst(src.rows,src.cols,src.type());
    for (int i = 0; i &lt; src.rows; ++i) {
        for (int j = 0; j &lt; src.cols; ++j) {
            /*uchar temp1 = src.at&lt;uchar&gt;(i, j);
            int temp2 = temp1 + 100;
            if (temp2 &gt; 255) temp2 = 255;
            dst.at&lt;uchar&gt;(i, j) = static_cast&lt;uchar&gt;(temp2);*/
            //or
            //dst.at&lt;uchar&gt;(i, j) = cv::saturate_cast&lt;uchar&gt;(src.at&lt;uchar&gt;(i, j) + 100);
            //int temp = src.at&lt;uchar&gt;(i, j) + 100;
            //dst.at&lt;uchar&gt;(i, j) = temp &gt; 255 &gt; 255 temp &lt; 0 ? 0 : temp;
            dst.at&lt;uchar&gt;(i, j) = src.at&lt;uchar&gt;(i, j) + 100;
        }
    }
    cv::Mat dst2 = src + 100;

    cv::imshow(&quot;SRC&quot;, src);
    cv::imshow(&quot;DST2&quot;, dst2);
    cv::imshow(&quot;DST&quot;, dst);
    cv::waitKey();
    cv::destroyAllWindows();
}</code></pre>
<h3 id="밝기-대조">밝기 대조</h3>
<pre><code class="language-cpp">void contrast() {
    cv::Mat src = cv::imread(&quot;lenna.bmp&quot;, cv::IMREAD_GRAYSCALE);
    float alpha = 1.0f;
    cv::Mat dst = ((1 + alpha) * src - 128 * alpha);
    cv::imshow(&quot;SRC&quot;, src);
    cv::imshow(&quot;DST&quot;, dst);
    cv::waitKey();
    cv::destroyAllWindows();
}</code></pre>
<h3 id="히스토그램-사용">히스토그램 사용</h3>
<pre><code class="language-cpp">void show_hist() {
    cv::Mat src = cv::imread(&quot;hawks.bmp&quot;, cv::IMREAD_GRAYSCALE);
    if (src.empty()) return;
    cv::Mat hist1 = calcGrayHist(src);
    cv::Mat hist_img = getGrayHistImage(hist1);
    cv::imshow(&quot;HISTOGRAM&quot;, hist_img);
    cv::imshow(&quot;SRC&quot;, src);
    cv::waitKey();
    cv::destroyAllWindows();
}
cv::Mat calcGrayHist(const cv::Mat&amp; img) {
    cv::Mat hist;
    int channels[] = { 0 };
    int dims = 0;
    int histsize[] = { 256 };
    float graylevel[] = { 0, 256 };
    const float* ranges[] = { graylevel };
    cv::calcHist(&amp;img, 1, channels, cv::noArray(), hist,dims, histsize, ranges);
    return hist;
}

cv::Mat getGrayHistImage(const cv::Mat&amp; hist) {
    double histMax;
    cv::minMaxLoc(hist, 0, &amp;histMax);
    cv::Mat imgHist(100, 250, CV_8UC1, cv::Scalar(255));
    for (int i = 0; i &lt; 256; ++i) {
        cv::line(imgHist, cv::Point(i, 100),\
            cv::Point(i,100 - cvRound(hist.at&lt;float&gt;(i, 0) * 100 / histMax)), cv::Scalar(0));
    }
    return imgHist;
}</code></pre>
<pre><code class="language-cpp">void histogram_stretching() {
    cv::Mat src = cv::imread(&quot;hawkes.bmp&quot;, cv::IMREAD_GRAYSCALE);
    if (src.empty()) return;
    double min = 0.0;
    double max = 0.0;
    cv::minMaxLoc(src, &amp;min, &amp;max);
    cv::Mat dst = ((src - min) / (max - min)) * 255;
    cv::Mat hist1 = calcGrayHist(src);
    cv::Mat hist_img = getGrayHistImage(hist1);
    cv::imshow(&quot;SRC&quot;, src);
    cv::imshow(&quot;DST&quot;, dst);
    cv::imshow(&quot;HISTOGRAM&quot;, hist_img);
    cv::imshow(&quot;DST_IMG&quot;, getGrayHistImage(calcGrayHist(dst)));
    cv::waitKey();
    cv::destroyAllWindows();
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[C++을 이용한 OpenCV(3)]]></title>
            <link>https://velog.io/@no_lunch/C%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%9C-OpenCV3</link>
            <guid>https://velog.io/@no_lunch/C%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%9C-OpenCV3</guid>
            <pubDate>Wed, 27 Sep 2023 06:11:54 GMT</pubDate>
            <description><![CDATA[<h3 id="연결된-카메라-확인">연결된 카메라 확인</h3>
<pre><code class="language-cpp">#pragma once
#include &lt;opencv2/opencv.hpp&gt;
static void on_mouse(int, int, int, int, void*); // 함수의 원형
static void on_level_changed(int, void*);

void show_camera() {
    cv::VideoCapture cap(0); // 0 index 0 = first Camera, 1 =&gt; secondary Camera
    if (cap.isOpened()) {
        std::cout &lt;&lt; &quot;Connected&quot; &lt;&lt; std::endl;
    }
    else {
        std::cout &lt;&lt; &quot;Error Occured&quot; &lt;&lt; std::endl;
        return;
    }
    std::cout &lt;&lt; &quot;Frame width &quot; &lt;&lt; cvRound(cap.get(cv::CAP_PROP_FRAME_WIDTH)) &lt;&lt; std::endl;
    std::cout &lt;&lt; &quot;Frame Height &quot; &lt;&lt; cvRound(cap.get(cv::CAP_PROP_FRAME_HEIGHT)) &lt;&lt; std::endl;

    cv::Mat frame;
    cv::Mat inversed_frame;
    cv::namedWindow(&quot;FRAME&quot;, cv::WINDOW_NORMAL);
    cv::namedWindow(&quot;INVERSE&quot;, cv::WINDOW_NORMAL);
    while (true) {
        cap &gt;&gt; frame;
        if (frame.empty()) break;
        inversed_frame = ~frame;
        imshow(&quot;FRAME&quot;, frame);
        imshow(&quot;INVERSE&quot;, inversed_frame);
        if(cv::waitKey(10) == 27) break; // 27 =&gt; ESC
    }
    cv::destroyAllWindows();
}</code></pre>
<h3 id="연결된-카메라-영상연결">연결된 카메라 영상연결</h3>
<pre><code class="language-cpp">void show_movie() {
    cv::VideoCapture cap(&quot;stopwatch.avi&quot;);
    if (cap.isOpened())
    {
        std::cout &lt;&lt; &quot;video is connected&quot; &lt;&lt; std::endl;
    }
    else {
        std::cout &lt;&lt; &quot;There is no Video&quot; &lt;&lt; std::endl;
        return;
    }

    std::cout &lt;&lt; cvRound(cap.get(cv::CAP_PROP_FRAME_WIDTH)) &lt;&lt; std::endl;
    std::cout &lt;&lt; cvRound(cap.get(cv::CAP_PROP_FRAME_HEIGHT)) &lt;&lt; std::endl;

    double fps = cap.get(cv::CAP_PROP_FPS);
    std::cout &lt;&lt; &quot;FPS : &quot; &lt;&lt; fps &lt;&lt; std::endl;

    int delay = cvRound(1&#39;000 / fps);

    cv::namedWindow(&quot;STOPWATCH&quot;, cv::WINDOW_NORMAL);
    cv::Mat frame;

    cv::namedWindow(&quot;INVERSE&quot;, cv::WINDOW_NORMAL);

    while (true) {
        cap &gt;&gt; frame;
        if (frame.empty()) break;
        cv::imshow(&quot;STOPWATCH&quot;, frame);
        cv::imshow(&quot;INVERSED&quot;, ~frame);
        cv::waitKey(delay);        
    }
    cv::destroyAllWindows();
}</code></pre>
<h3 id="연결된-카메라를-통한-녹화-진행">연결된 카메라를 통한 녹화 진행</h3>
<pre><code class="language-cpp">void show_video_record() {
    cv::VideoCapture cap(0);
    if (cap.isOpened())
    {
        std::cout &lt;&lt; &quot;Camera is Connected&quot; &lt;&lt; std::endl;
    }
    else {
        std::cout &lt;&lt; &quot;Camera is Unconnected&quot; &lt;&lt; std::endl;
        return;
    }
    double fps = (cap.get(cv::CAP_PROP_FPS));
    int delay = cvRound(1000 / fps);
    int fourcc = cv::VideoWriter::fourcc(&#39;X&#39;, &#39;2&#39;, &#39;6&#39;, &#39;4&#39;);
    cv::Mat frame;
    cv::Mat inversed;

    // fps 함수 적용 안되면 직접 fps 때려박기..
    cv::VideoWriter output(&quot;recording.mp4&quot;, fourcc, 30, 
        cv::Size(cap.get(cv::CAP_PROP_FRAME_WIDTH),cap.get(cv::CAP_PROP_FRAME_HEIGHT)));
    if (output.isOpened()) {
        std::cout &lt;&lt; &quot;Recording is ready&quot; &lt;&lt; std::endl;
    }
    else {
        std::cout &lt;&lt; &quot;Recording is not ready&quot; &lt;&lt; std::endl;
        return;
    }
    cv::namedWindow(&quot;RECORDING&quot;);
    while (true) {
        cap &gt;&gt; frame;
        inversed = ~frame;
        if (frame.empty()) break;
        output &lt;&lt; inversed; // 영상 저장
        cv::imshow(&quot;RECORDING&quot;, frame);
        if (cv::waitKey(30) == 27) break;
    }
    cv::destroyAllWindows();
}</code></pre>
<h3 id="선-그리기">선 그리기</h3>
<pre><code class="language-cpp">void show_draw_lines() {
    cv::Mat canvas(800, 800, CV_8UC3, cv::Scalar(255,255,255));

    cv::line(canvas, cv::Point(50, 50), cv::Point(200, 50), cv::Scalar(0, 0, 255), 10);
    cv::line(canvas, cv::Point(50, 50), cv::Point(200, 100), cv::Scalar(255, 0, 255), 1);

    cv::arrowedLine(canvas, cv::Point(50, 200), cv::Point(150, 200), cv::Scalar(0, 255, 0), 2);
    cv::drawMarker(canvas, cv::Point(30,250),cv::Scalar(0,0,255),cv::MARKER_CROSS);

    cv::namedWindow(&quot;CANVAS&quot;, cv::WINDOW_NORMAL);
    cv::imshow(&quot;CANVAS&quot;, canvas);
    cv::waitKey();
    cv::destroyWindow(&quot;CANVAS&quot;); 
}</code></pre>
<h3 id="도형-그리기">도형 그리기</h3>
<pre><code class="language-cpp">void show_draw_polygons(){
    cv::Mat canvas = cv::Mat(500,500,CV_8UC3,cv::Scalar(255,255,255));
    cv::rectangle(canvas, cv::Rect(50, 50, 150, 50),cv::Scalar(0,0,255),3);
    cv::rectangle(canvas, cv::Rect(50, 150, 100, 50),cv::Scalar(0,0,255), -1);
    cv::circle(canvas, cv::Point(300, 120), 60, cv::Scalar(255, 255, 0), -1, cv::LINE_AA);
    cv::ellipse(canvas,cv::Point(120,300),cv::Size(60,30),20,0,270,cv::Scalar(0,255,0),-1,cv::LINE_AA);

    std::vector&lt;cv::Point&gt;points;
    points.push_back(cv::Point(250, 250));
    points.push_back(cv::Point(300, 250));
    points.push_back(cv::Point(300, 300));
    points.push_back(cv::Point(350, 300));
    points.push_back(cv::Point(350, 350));
    points.push_back(cv::Point(250, 350));

    cv::polylines(canvas, points, true, cv::Scalar(255, 0, 255), 5, -1);

    cv::namedWindow(&quot;CANVAS&quot;, cv::WINDOW_NORMAL);
    cv::imshow(&quot;CANVAS&quot;, canvas);
    cv::waitKey();
    cv::destroyAllWindows();
}</code></pre>
<h3 id="텍스트-삽입">텍스트 삽입</h3>
<pre><code class="language-cpp">void show_draw_text(){
    cv::Mat canvas = cv::imread(&quot;lenna.bmp&quot;);
    cv::putText(canvas, &quot;LENNA&quot;,cv::Point(250,450),cv::FONT_HERSHEY_TRIPLEX | \
    cv::FONT_ITALIC,2,cv::Scalar(255,0,0),5,-1);
    cv::namedWindow(&quot;LENNA&quot;, cv::WINDOW_NORMAL);
    cv::imshow(&quot;LENNA&quot;, canvas);
    cv::waitKey();
    cv::destroyAllWindows;
    }</code></pre>
<h3 id="키보드-입력에-대한-이벤트-종료">키보드 입력에 대한 이벤트 (종료)</h3>
<pre><code class="language-cpp">void keyboard_event(int key) {
    if (key == 27) {
        // ESC 키가 눌렸을 때 프로그램 종료
        std::cout &lt;&lt; &quot;ESC 키 눌림. 프로그램 종료.&quot; &lt;&lt; std::endl;
    }
}</code></pre>
<h3 id="마우스에-입력에-대한-이벤트">마우스에 입력에 대한 이벤트</h3>
<pre><code class="language-cpp">static cv::Mat img;
static cv::Point pt_old;
void mouse_event(int event, int x, int y, int flags, void* userdata) {
    if (event == cv::EVENT_LBUTTONDOWN) {
        // 왼쪽 마우스 버튼이 눌렸을 때
        pt_old = cv::Point(x, y);
    }
    else if (event == cv::EVENT_LBUTTONUP) {
        // 왼쪽 마우스 버튼이 떼어졌을 때
        cv::Point pt_new(x, y);
        cv::line(img, pt_old, pt_new, cv::Scalar(0, 0, 255), 2); // 빨간색 선으로 점을 연결
        cv::imshow(&quot;Image&quot;, img);
    }
}</code></pre>
<h3 id="마우스를-따라-이벤트">마우스를 따라 이벤트</h3>
<pre><code class="language-cpp">void on_mouse(int mouse_event, int mouse_x, int mouse_y, int flags, void* param) {
    // 이 함수는 마우스 이벤트가 발생할 때마다 호출됩니다.

    if (mouse_event == cv::EVENT_LBUTTONDOWN) {
        // 왼쪽 마우스 버튼이 눌렸을 때
        pt_old = cv::Point(mouse_x, mouse_y);
    }
    else if (mouse_event == cv::EVENT_LBUTTONUP) {
        // 왼쪽 마우스 버튼이 떼어졌을 때
        cv::Point pt_new(mouse_x, mouse_y);
        cv::line(img, pt_old, pt_new, cv::Scalar(0, 0, 255), 2); // 빨간색 선으로 점을 연결
        cv::imshow(&quot;Image&quot;, img);
    }
}</code></pre>
<h3 id="출력-이미지-상단에-trackbar-생성">출력 이미지 상단에 Trackbar 생성</h3>
<pre><code class="language-cpp">void trackbar_event() {
    cv::Mat canvas(800, 800, CV_8UC1);
    cv::namedWindow(&quot;CANVAS&quot;);
    cv::createTrackbar(&quot;Level&quot;, &quot;CANVAS&quot;, nullptr, 16, on_level_changed, (void*)&amp;canvas);
    cv::imshow(&quot;CANVAS&quot;, canvas);
    cv::waitKey();
    cv::destroyAllWindows();
}</code></pre>
<h3 id="trackbar-와-연동해서-레벨에-따라-바뀌도록-함">Trackbar 와 연동해서 레벨에 따라 바뀌도록 함</h3>
<pre><code class="language-cpp">void on_level_changed(int positition, void* userdata) {
    cv::Mat img = *(static_cast&lt;cv::Mat*&gt;(userdata));
    img.setTo(positition * 16);
    cv::imshow(&quot;CANVAS&quot;, img); //updating
}</code></pre>
<h3 id="특정-영역의-색을-바꿈">특정 영역의 색을 바꿈</h3>
<pre><code class="language-cpp">void mask_setTo() {
    cv::Mat src = cv::imread(&quot;lenna.bmp&quot;);
    cv::Mat mask = cv::imread(&quot;mask_smile.bmp&quot;,cv::IMREAD_GRAYSCALE);
    if (src.empty() or mask.empty()) return;
    src.setTo(cv::Scalar(0, 255, 0), mask); //mask 의 RGB 값을 src에 적용
    cv::imshow(&quot;SRC&quot;, src);
    cv::imshow(&quot;MASK&quot;, mask);
    cv::waitKey();
    cv::destroyAllWindows();
}</code></pre>
<h3 id="opencv를-통한-이미지-합성">OpenCV를 통한 이미지 합성</h3>
<pre><code class="language-cpp">void mask_copyTo() {
    cv::Mat src = cv::imread(&quot;airplane.bmp&quot;);
    cv::Mat mask = cv::imread(&quot;mask_plane.bmp&quot;, cv::IMREAD_GRAYSCALE);
    cv::Mat dst = cv::imread(&quot;field.bmp&quot;);
    if (src.empty() or mask.empty() or dst.empty()) return;

    cv::imshow(&quot;ORIGINAL&quot;, dst);
    cv::imshow(&quot;SRC&quot;, src);
    cv::imshow(&quot;MASK&quot;, mask);

    src.copyTo(dst, mask);
    cv::imshow(&quot;CHANGED&quot;, dst);
    cv::waitKey();
    cv::destroyAllWindows();
}</code></pre>
<h3 id="실행-소요-시간-측정">실행 소요 시간 측정</h3>
<pre><code class="language-cpp">void time_inverse(){
    cv::Mat img = cv::imread(&quot;lenna.bmp&quot;, cv::IMREAD_GRAYSCALE);
    if (img.empty()) return;
    cv::Mat dst(img.rows, img.cols, img.type());
    cv::TickMeter tick;
    tick.start();
    for (int i = 0; i &lt; img.rows; ++i) {
        for (int j = 0; j &lt; img.cols; ++j) {
            dst.at&lt;uchar&gt;(i, j) = 255 - img.at&lt;uchar&gt;(i, j);
        }
    }
    tick.stop();
    std::cout &lt;&lt; &quot;걸린 시간 : &quot; &lt;&lt; tick.getTimeSec() &lt;&lt; &quot;초&quot; &lt;&lt; std::endl;
    cv::imshow(&quot;IMG&quot;, img);
    cv::imshow(&quot;DST&quot;, dst);
    cv::waitKey();
    cv::destroyAllWindows();
}</code></pre>
<h3 id="min--max-함수">min &amp; max 함수</h3>
<pre><code class="language-cpp">void useful_funtions() {
    cv::Mat src = cv::imread(&quot;lenna.bmp&quot;, cv::IMREAD_GRAYSCALE);
    std::cout &lt;&lt; static_cast&lt;int&gt;(cv::sum(src)[0]) &lt;&lt; std::endl;
    std::cout &lt;&lt; static_cast&lt;int&gt;(cv::mean(src)[0]) &lt;&lt; std::endl;

    double min_value = 0.0;
    double max_value = 0.0;

    cv::Point min_point;
    cv::Point max_point;

    std::cout &lt;&lt; &quot;Min : &quot; &lt;&lt; min_value &lt;&lt; &quot; , &quot; &lt;&lt; &quot;Max : &quot; &lt;&lt; max_value &lt;&lt; std::endl;
    cv::minMaxLoc(src, &amp;min_value, &amp;max_value, &amp;min_point, &amp;max_point);
    std::cout &lt;&lt; &quot;Min : &quot; &lt;&lt; min_value &lt;&lt; &quot; , &quot; &lt;&lt; &quot;Max : &quot; &lt;&lt; max_value &lt;&lt; std::endl;
    std::cout &lt;&lt; &quot;Min Poisition X: &quot; &lt;&lt; min_point.x &lt;&lt; &quot; , &quot; &lt;&lt; &quot;Min Position: &quot; &lt;&lt; min_point.y &lt;&lt; std::endl;
    std::cout &lt;&lt; &quot;Max Poisition X: &quot; &lt;&lt; max_point.x &lt;&lt; &quot; , &quot; &lt;&lt; &quot;Max Position: &quot; &lt;&lt; max_point.y &lt;&lt; std::endl;

}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[C++을 이용한 OpenCV(2)]]></title>
            <link>https://velog.io/@no_lunch/C%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%9C-OpenCV2</link>
            <guid>https://velog.io/@no_lunch/C%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%9C-OpenCV2</guid>
            <pubDate>Wed, 27 Sep 2023 02:56:42 GMT</pubDate>
            <description><![CDATA[<h3 id="이미지-크기-지정해-출력">이미지 크기 지정해 출력</h3>
<pre><code class="language-cpp">#pragma once
#include &lt;opencv2/opencv.hpp&gt;
#define SEMICOLON ;  // Macro Function
#define PI 3.141592 ; 
#define SQUARE(x) ((x*x))
void show_code_3() {
    cv::Point pt1; //default constructor
    pt1.x = 5;
    pt1.y = 10;
    cv::Point pt2(pt1); // copy constructor
    cv::Point pt3 = pt1 + pt2;
    int dot1 = pt1.dot(pt2); // inner product

    std::cout &lt;&lt; pt2 &lt;&lt; std::endl;

    cv::Size sz1(10, 20);
    cv::Size sz2;
    cv::Size sz3 = sz1 + sz2;
    int sz4 = sz1.area();

    std::cout &lt;&lt; sz1 &lt;&lt; std::endl;

    cv::Rect rc1(0, 10, 0 + 60, 10 + 30);
    cv::Rect rc2 = rc1 + cv::Size(50, 40);
    cv::Rect rc3 = rc2 + cv::Point(60, 60);

    cv::Mat mat1(800, 800, CV_8UC1, cv::Scalar(255)); //CV_8UC1 = OpenCV type ( type for imshow())
    std::cout &lt;&lt; &quot;[ 10 , 20 ] : &quot; &lt;&lt; static_cast&lt;int&gt;(mat1.at&lt;uchar&gt;(10, 20)) &lt;&lt; std::endl;

    cv::Mat mat2(255+cv::Mat::zeros(900, 900, CV_8UC1));

    cv::Mat Mat3(255 * cv::Mat::ones(900, 900, CV_8UC1));
    cv::Mat mat4(255 * cv::Mat::eye(900, 900, CV_8UC1));
    cv::imshow(&quot;Mat&quot;, mat4);
    cv::waitKey();
    cv::destroyAllWindows();

}</code></pre>
<h3 id="얕은-복사--깊은-복사-예시">얕은 복사 &amp; 깊은 복사 예시</h3>
<pre><code class="language-cpp">void show_code_3_8() {
    cv::Mat img1{ cv::imread(&quot;dog.bmp&quot;) }; // c++11 uniform initializer
    if (img1.empty()) {
        std::cout &lt;&lt; &quot;No file&quot; &lt;&lt; std::endl;
        return;
    }
    std::cout &lt;&lt; img1.size &lt;&lt; std::endl;

    cv::Mat img2 = img1; //copy constructor , shallow copy

    cv::Mat img3 = img1.clone(); //deep copy

    cv::imshow(&quot;IMG1&quot;, img1);
    cv::imshow(&quot;IMG2&quot;, img2);
    cv::imshow(&quot;IMG3&quot;, img3);
    cv::waitKey();

    img1.setTo(cv::Scalar(0, 255, 255)); // 원본 이미지 변경 

    cv::imshow(&quot;IMG1&quot;, img1);
    cv::imshow(&quot;IMG2&quot;, img2);
    cv::imshow(&quot;IMG3&quot;, img3);
    cv::waitKey();

    cv::destroyAllWindows();
}</code></pre>
<h3 id="image-비트-반전-예시">Image 비트 반전 예시</h3>
<pre><code class="language-cpp">void show_code_3_9() {
    cv::Mat img1 = cv::imread(&quot;cat.bmp&quot;);
    if (img1.empty())
    {
        std::cout &lt;&lt; &quot;There is no file exist&quot; &lt;&lt; std::endl;
        return;
    }
    cv::Mat img2 = img1(cv::Rect(270, 120, 340, 240)); //() -&gt; operator overloading
    cv::Mat img3 = img1(cv::Rect(270, 120, 340, 240)).clone(); //() -&gt; deep copy
    img2 = ~img2; // not , bit 반전

    cv::imshow(&quot;IMG1&quot;, img1);
    cv::imshow(&quot;IMG2&quot;, img2);
    cv::waitKey();
    cv::destroyAllWindows();
}</code></pre>
<h3 id="get--set-함수-구현">get &amp; set 함수 구현</h3>
<pre><code class="language-cpp">void show_code_3_10() {
    cv::Mat mat1(cv::Mat::zeros(10,10,CV_8UC1));
    for (int i = 0; i &lt; mat1.rows;++i) {
        for (int j = 0; j &lt; mat1.cols; ++j) {
            std::cout &lt;&lt; static_cast&lt;int&gt;(mat1.at&lt;uchar&gt;(i, j)) &lt;&lt; &quot;\t&quot;; //get
        }
        std::cout &lt;&lt; std::endl;
    }

    std::cout &lt;&lt; &quot;=========================================&quot; &lt;&lt; std::endl;
    uchar value{ 0u };
    for (int i = 0; i &lt; mat1.rows; ++i) {
        for (int j = 0; j &lt; mat1.cols; ++j) {
            mat1.at&lt;uchar&gt;(i, j) = ++value; //set
        }
        std::cout &lt;&lt; std::endl;
    }

}</code></pre>
<h3 id="행렬을-이용한-이미지-표현">행렬을 이용한 이미지 표현</h3>
<pre><code class="language-cpp">void show_code_3_13() {
    cv::Mat img1 = cv::imread(&quot;lenna.bmp&quot;, cv::IMREAD_GRAYSCALE);
    cv::Mat img2;
    img1.convertTo(img2, CV_32FC1);
    uchar data1[] = { 1,2,3,4,5,6,7,8,9,10,11,12 };
    cv::Mat mat1(3, 4, CV_8UC1, data1);

    std::cout &lt;&lt; mat1 &lt;&lt; std::endl;
    cv::Mat mat2 = mat1.reshape(0, 1);
    std::cout &lt;&lt; mat2 &lt;&lt; std::endl;

    cv::Mat mat3 = cv::Mat::ones(1, 4, CV_8UC1) * 255;
    mat1.push_back(mat3);
    /*cv::imshow(&quot;IMG&quot;, img2);
    cv::waitKey();
    cv::destroyAllWindows();*/
}</code></pre>
<h3 id="rgb-값을-이용한-이미지-생성">RGB 값을 이용한 이미지 생성</h3>
<pre><code class="language-cpp">void show_code3_16() {
    cv::Scalar blue = 128;
    std::cout &lt;&lt; &quot;blue : &quot; &lt;&lt; blue &lt;&lt; std::endl;
    cv::Scalar yellow(0, 255, 255);
    std::cout &lt;&lt; yellow &lt;&lt; std::endl;
    cv::Mat img1(800, 800, CV_8UC3, yellow);

    cv::imshow(&quot;IMG1&quot;, img1);
    cv::waitKey();
    cv::destroyAllWindows();
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[Matter 알아보기...]]></title>
            <link>https://velog.io/@no_lunch/Matter-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0</link>
            <guid>https://velog.io/@no_lunch/Matter-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0</guid>
            <pubDate>Tue, 26 Sep 2023 06:28:45 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h3 id="matter-표준의-동작-방식">Matter 표준의 동작 방식</h3>
</blockquote>
<h3 id="1-ip-protocol-기반으로-동작---개별-device가-각각의-ip를-지님">1. IP Protocol 기반으로 동작 -&gt; 개별 Device가 각각의 IP를 지님</h3>
<pre><code>Wifi 나 Thread 같은 통신 Protocol을 기본적으로 지원</code></pre><h3 id="2-응용계층application-layer-표준">2. 응용계층(Application Layer) 표준</h3>
<p><img src="https://velog.velcdn.com/images/no_lunch/post/6c9e0016-9793-4ecd-8340-71e34d708854/image.jpg" alt=""></p>
<h3 id="3-네트워크-모습">3. 네트워크 모습</h3>
<p>Matter는 CSA에 의해 관리되고 Apache 2.0에 따라 라이선스가 부여되며 CSA에서는 회원이 자체 Matter 준수 장치 개발을 지원하기 위해 사용할 수 있는 표준 구현 및 애플리케이션 라이브러리를 유지 및 관리한다. 보안 및 사용자 개인정보 보호는 Matter의 주요 관심사이며, 라이브러리는 Matter 장치 환경 전반에서 일관된 보안 구현을 보장한다. 하드웨어의 측면에서 Matter는 엔드 노드, 에지 노드, 게이트웨이(컨트롤러라고도 함), 브리지, 경계 라우터를 포함합니다. 게이트웨이와 경계 라우터를 모두 ‘허브’라고도 하므로 혼동될 수 있으므로 구분</p>
<p><img src="https://velog.velcdn.com/images/no_lunch/post/41447494-a96d-41eb-a2d1-038ebf9cb146/image.png" alt=""></p>
<p>현재 Matter 의 버전은 1.1이다.
<a href="https://www.youtube.com/watch?v=MrUzTw6Xxmk">관련 영상</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[C++을 이용한 OpenCV(1)]]></title>
            <link>https://velog.io/@no_lunch/C%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%9C-OpenCV1</link>
            <guid>https://velog.io/@no_lunch/C%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%9C-OpenCV1</guid>
            <pubDate>Mon, 25 Sep 2023 04:15:16 GMT</pubDate>
            <description><![CDATA[<pre><code class="language-cpp">--- 초기 세팅 ---
&lt;Open CV 4.8.0 으로 진행&gt; 
 1. path ( C:\opencv\build\x64\vc16\bin )
 2. Visual Studio 에서 Prjoect -&gt; Attributes -&gt; C/C++ 
     추가 포함 디렉터리 C:\opencv\build\include
 3. 링커 -&gt; 추가 라이브러리 디렉터리 
      C:\opencv\build\x64\vc16\lib
 4. 링커 -&gt; 일반  -&gt; 추가 종속성 -&gt; 편집 opencv_world480d.lib 추가 (Debug Mode)
                                     opencv_world480.lib (Release Mode)</code></pre>
<h3 id="이미지-열기">이미지 열기</h3>
<pre><code class="language-cpp">#pragma once   //header 의 중복 선언 방지
#include &lt;opencv2/opencv.hpp&gt;
void show_images()
{
    cv::Mat img = cv::imread(&quot;lenna.bmp&quot;, cv::IMREAD_GRAYSCALE);
    cv::Mat img2 = cv::imread(&quot;dog.bmp&quot;, cv::IMREAD_COLOR); //Default 가 Color
    if (img.empty() or img2.empty()) {
        std::cout &lt;&lt; &quot;image file does not exist&quot; &lt;&lt; std::endl;
        return 1;
    }
    cv::namedWindow(&quot;LENNA&quot;, cv::WINDOW_NORMAL);
    cv::namedWindow(&quot;DOG&quot;); //WINDOW_NORMAL is default
    cv::imshow(&quot;LENNA&quot;, img);
    cv::imshow(&quot;DOG&quot;, img2);
    cv::waitKey(); // waitKey(1000) = 1sec
    cv::destroyAllWindows();
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[(09_11) C++ 학습일지]]></title>
            <link>https://velog.io/@no_lunch/0911-C-%ED%95%99%EC%8A%B5%EC%9D%BC%EC%A7%80</link>
            <guid>https://velog.io/@no_lunch/0911-C-%ED%95%99%EC%8A%B5%EC%9D%BC%EC%A7%80</guid>
            <pubDate>Mon, 25 Sep 2023 03:32:07 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h3>정적 바인딩( static binding ) vs 동적 바인딩( dynamic binding )</h3>
</blockquote>
<ul>
<li><p>*<em>바인딩 ( binding ) *</em> : 프로그램 소스에 쓰인 각종 내부 요소, 이름 식별자들에 대해 값 또는 속성이 확정되어 변경할 수 없어 묶이게(bind) 되는 과정(binding)</p>
</li>
<li><p><strong>정적 바인딩( static binding )</strong> : 프로그램 소스에 명시적으로 타입과 그 타입의 변수 명을 선언
컴파일 시 점프할 주소가 바인딩되며 비교적 속도가 빠르고 타입 오류시 해결이 쉬움</p>
<pre><code class="language-cpp">// 정적 바인딩 예시 &quot;int&quot; 라는 타입과 &quot;a&quot;라는 변수명을 가짐
int main()
{
  int a = 0 
}
</code></pre>
</li>
<li><p><strong>동적 바인딩( dynamic binding )</strong> : 실행(Runtime) 도중에 바인딩하므로 소스코드를 줄일 수 있고 유연하지만 정적 바인딩에 비해 실행 속도가 느리며 메모리 낭비가 발생할 수 있다.</p>
<pre><code class="language-cpp">class A
{
 virtual void print() {}
}
class B : A
{
 override void print() {}
}
int main()
{
 A* a = new A();
 a-&gt;print();

 B* b = new B();
 a = b;
 a-&gt;print();
}
</code></pre>
</li>
</ul>
<center>

<table>
<thead>
<tr>
<th align="center">정적 바인딩(Static binding)</th>
<th align="center">동적 바인딩(Dynamic binding)</th>
</tr>
</thead>
<tbody><tr>
<td align="center">Compile 시 바인딩</td>
<td align="center">Runtime 시 바인딩</td>
</tr>
<tr>
<td align="center">일반 함수 호출, 함수 오버로딩 및 연산자 오버로딩을 사용</td>
<td align="center">가상 함수를 사용</td>
</tr>
<tr>
<td align="center">유연하지 않음 / 속도 빠름</td>
<td align="center">유연함/ 속도 느림</td>
</tr>
</tbody></table>
</center>

<hr>
<blockquote>
<h3>Function Overloading Vs Function Overriding </h3>
</blockquote>
<center>

<table>
<thead>
<tr>
<th align="center">Function Overloading</th>
<th align="center">Function Overriding</th>
</tr>
</thead>
<tbody><tr>
<td align="center">함수의 중복</td>
<td align="center">함수의 재정의</td>
</tr>
<tr>
<td align="center">같은 이름의 함수를 사용(인자, 매개변수로 구분)</td>
<td align="center">상속받은 함수를 사용, 재정의</td>
</tr>
<tr>
<td align="center">리턴 타입만 바꿨을 때엔 적용되지 않음</td>
<td align="center"><code>virtual</code> 이나 <code>override</code> 키워드 사용</td>
</tr>
</tbody></table>
</center>

<hr>
<blockquote>
<h3> Abstract Base Class [ABC] </h3>
</blockquote>
<ul>
<li>순수 가상함수(Pure virtual function)
<code>virtual Animal Lion = 0</code> 의 형태를 취하며 파생 클래스에서 재정의가 가능하다.</li>
</ul>
<ul>
<li>추상 클래스 ( Abstract Class ) 는 하나 이상의 순수 가상함수를 가지며, 이 클래스로 부터 파생된 클래스는 반드시 가상함수를 재정의 해야한다.</li>
</ul>
<blockquote>
<h3 id="in-line-function">&lt; In-line function &gt;</h3>
</blockquote>
<ul>
<li>C++ 에서의 함수 호출 과정</li>
</ul>
<ol>
<li><p>함수의 호출 -&gt; 스택에 함수로 전달할 매개변수와 함께 호출이 끝난 뒤 돌아갈 반환 주소값을 저장</p>
</li>
<li><p>프로그램의 제어가 함수의 위치로 넘어와 함수 내에 선언된 지역 변수도 스택에 저장</p>
</li>
<li><p>함수의 모든 코드를 실행 -&gt; 실행 후 반환값을 넘겨 줌</p>
</li>
<li><p>프로그램의 제어는 스택에 저장된 돌아갈 반환 주소값으로 이동, 스택에 저장된 함수 호출 정보를 제거</p>
</li>
</ol>
<p>인라인 함수(In-line function)은 위 과정을 거치지 않고 실행하기 위해서 <code>inline</code> 키워드를 이용해 사용</p>
<pre><code class="language-cpp">int min(int x, int y)         -&gt; inline int min(int x, int y)
{                                {
    return x &gt; y ? y : x;           return x &gt; y ? y : x;
}                                }


int main()
{
    std::cout &lt;&lt; min(5, 6) &lt;&lt; &#39;\n&#39;;
    std::cout &lt;&lt; min(3, 2) &lt;&lt; &#39;\n&#39;;
    return 0;
}</code></pre>
<blockquote>
<h3 id="매크로-함수--macro-function-">매크로 함수 ( Macro function )</h3>
</blockquote>
<pre><code class="language-cpp">/* Macro function 예시 */
#include &lt;stdio.h&gt;
#define square(x) x *x  

int main(int argc, char **argv) {
  printf(&quot;square(4) : %d \n&quot;, square(4));

  return 0;
} </code></pre>
<p><code>#define square(x) x*x</code>처럼 매크로 함수는 <code>#define 함수명(인자) 치환할 것</code>으로 선언
 따라서 위 <code>실행 결과는 16</code>이 된다.</p>
<blockquote>
<h3 id="네임스페이스--namespace-">네임스페이스 ( Namespace )</h3>
</blockquote>
<ul>
<li>Namespace 란 C++에서는 변수, 함수, 구조체, 클래스 등을 서로 구분하기 위해서 이름으로 사용되는 다양한 내부 식별자(identifier)를 가지고 있지만 프로그램이 복잡해지고 외부 라이브러리가 많아지게 되면 충돌할 가능성이 생기므로 충돌하지 않기 위해 만들어진 개념</li>
<li>헤더 파일에서 정의</li>
<li><code>using</code> 키워드 사용시<ol>
<li>using 지시자 : <code>using namespace (네임스페이스 이름);</code> <ol start="2">
<li>using 선언 : <code>using 네임스페이스이름::이름;</code></li>
</ol>
</li>
</ol>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[(0907~0908) C++ 학습일지]]></title>
            <link>https://velog.io/@no_lunch/09070908-C-%ED%95%99%EC%8A%B5%EC%9D%BC%EC%A7%80</link>
            <guid>https://velog.io/@no_lunch/09070908-C-%ED%95%99%EC%8A%B5%EC%9D%BC%EC%A7%80</guid>
            <pubDate>Mon, 18 Sep 2023 05:45:18 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h3>다시 써보기 </h3>
</blockquote>
<hr>
<p> Queue() {} // <em>기본 생성자</em> 
 Queue(const Queue&amp; rhs){ memberwise copy } // <em>복사 생성자</em>
 ~Queue() {} //<em>소멸자</em>
Queue&amp; operator=(const Queue&amp; rhs) { memberwise copy } // <em>대입 연산자 오버로딩</em>
Queue <em>operator&amp;() {}  // *주소 연산자 오버로딩</em>
const Queue <em>operator&amp;() const{}  // *주소 연산자 오버로딩</em> </p>
<hr>
<blockquote>
<h3>explicit (명시적)</h3>
</blockquote>
<p><code>explicit</code>을 알기 위해선 C++ Compiler 에서 일어나는 <code>암시적 변환(implicit conversion)</code>에 대해서 알아야 한다. </p>
<ul>
<li>숫자 승격 (numeric promotion)
한 자료형의 값이 더 큰 유사한 자료형의 값으로 변환하는 경우로 데이터 손실 없음</li>
</ul>
<pre><code class="language-cpp">long   l(64);    // int -&gt; long
double d(0.12f); // float -&gt; double</code></pre>
<ul>
<li>숫자 변환 (numeric conversion)
큰 자료형의 값이 더 작은 유사한 자료형의 값으로 변환하거나 서로 다른 자료형 간에 변환하는 경우, 데이터 손실이 일어날 수도 있음</li>
</ul>
<pre><code class="language-cpp">double d = 3; // int -&gt; double ( type 이 다른 경우) 
short s = 2; // int -&gt; short (더 큰 자료형에서 작은 자료형으로)</code></pre>
<p>C++ 에서는 <code>explicit</code> 키워드를 통해서 암시적 변환을 할 수 없도록 컴파일러에게 알려 줄 수 있다.</p>
<hr>
<blockquote>
<h3>extern</h3>
</blockquote>
<p><code>extern</code> 은 다른 <code>cpp</code>에 존재하는 <code>전역변수</code>를 참조할 때 사용하거나,
외부에 있는 <code>함수</code>를 가져올 때 사용한다.</p>
<p>+) <code>extern &quot;C&quot;</code> 는 C++ 컴파일러가 정의된 함수 혹은 헤더파일에 대해 맹글링하지 말라는 의미</p>
<hr>
<blockquote>
<h3>상속 (inherit)</h3>
</blockquote>
<ul>
<li><p>상위(부모/기초) 클래스의 내용 ( 속성, 메소드 ) 를 하위(자식/파생) 클래스가 물려받는 것</p>
</li>
<li><p>접근제어 지시자
1.<code>public</code> : 어디에서든 멤버 변수와 메소드에 접근 가능</p>
<pre><code class="language-cpp">class Example : public p_class /*상속 선언시 private를 제외하고 상속 */</code></pre>
<p>2.<code>private</code> : 외부에서는 접근 불가</p>
<pre><code class="language-cpp">class Example : public p_class /*상속 선언시 private를 제외한 것들을 private로 상속 */</code></pre>
<p>3.<code>protected</code> : 하위(자식)클래스 에서만 해당 멤버 변수에 접근 가능하고 외부는 접근불가</p>
<pre><code class="language-cpp">class Example : protected p_class /*상속 선언시 public을 protected로 바꿔 상속 */</code></pre>
</li>
<li><p>상속의 조건</p>
<ol>
<li>is a <pre><code class="language-cpp">Lion is a Animal
Panda is a Animal /*Lion 과 Panda 는 Animal 이라는 기초 클래스를 상속하는 유도클래스이다.*/</code></pre>
<code>is a</code>의 조건으로는 <code>상속관계가 있을 때</code>, 아래로 갈 수록 <code>구체화</code> 혹은 <code>특수화(Specialization)</code>가 되어야하며 위로 갈 수록 <code>일반화(Generalization)</code>되어야한다.</li>
</ol>
<p>파생클래스는 기본클래스의 모든 특성을 포함하기에 <code>is a</code>관계로 포함.</p>
<ol start="2">
<li>has a
<code>has a</code>의 조건으로는 <code>객체 멤버에 의한 포함관계</code>나 <code>객체 포인터 멤버에 의한 포함관계</code>가 있다.
상속으로 묶인 두개의 클래스는 결합도가 강해지고 많은 제약을 줄 수있다.</li>
</ol>
</li>
</ul>
<blockquote>
<h3>다형성(Polymorphism)</h3>
</blockquote>
<ol>
<li>다양한 형태를 가지는 성질로써, 상위 클래스에 <code>가상 멤버 함수(virtual member function)</code>가 있어야 함 </li>
<li>하위 클래스에서 오버라이딩할 멤버함수가 없다면 상위 클래스의 소멸자를 가상함수로 만든다.</li>
<li>객체는 상위 클래스의 포인터나 참조자로 만들어야 함
<code>virtual</code> 키워드로 상위 클래스의 멤버함수 선언시 <code>override</code> 된 하위 클래스의 멤버함수를 사용가능<ol start="4">
<li>상위 클래스의 멤버함수에는 없는 하위 클래스의 멤버함수를 사용하려면 다운캐스팅해야함
<code>typeid</code>를 사용할 때에는 객체이거나 정의된 클래스로 자료형에 대한 정보 얻을 수 있음</li>
</ol>
</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[(0901~0904) C++ 학습일지]]></title>
            <link>https://velog.io/@no_lunch/09010904-C-%ED%95%99%EC%8A%B5%EC%9D%BC%EC%A7%80</link>
            <guid>https://velog.io/@no_lunch/09010904-C-%ED%95%99%EC%8A%B5%EC%9D%BC%EC%A7%80</guid>
            <pubDate>Sun, 10 Sep 2023 23:15:47 GMT</pubDate>
            <description><![CDATA[<blockquote>
<ol>
<li><strong>도우미 함수</strong> (helper func)</li>
</ol>
</blockquote>
<ol>
<li>도우미 함수는 최종 사용자가 인스턴스화하지 않지만 내부적으로 다른 클래스 내에서 사용되는 유용한 기능을 제공하는 함수</li>
<li>함수가 클래스의 멤버가 아니라 다른 클래스인 경우 C++ 프로그램은 다른 목적으로 데이터를 인쇄하거나 사용하는 도우미 함수를 생성</li>
<li>도우미 함수는 일반적으로 클래스의 작성자가 제공해 클래스의 표현에 직접 액세스할 필요가 없다. </li>
</ol>
<blockquote>
<p>Compiler 가 생성해주는 Member func ( Default 생성자는 다른 생성자가 존재하면 생성안됨)    </p>
</blockquote>
<ol>
<li><strong>디폴트 생성자(Default Constructor)</strong>:<ul>
<li>클래스에 생성자가 정의되지 않은 경우, 컴파일러는 디폴트 생성자를 자동으로 생성</li>
<li>디폴트 생성자는 객체를 초기화</li>
</ul>
</li>
</ol>
<pre><code class="language-cpp">class Array {
public:
    Array() { // 디폴트 생성자
    }
};</code></pre>
<ol start="2">
<li><strong>복사 생성자(Copy Constructor)</strong>:<ul>
<li>클래스의 객체가 다른 객체로 복사될 때, 컴파일러는 복사 생성자를 자동으로 생성.</li>
<li>이 복사 생성자는 얕은 복사(shallow copy)를 수행하며, 필요에 따라 사용자 정의로 오버로딩할 수 있음</li>
</ul>
</li>
</ol>
<pre><code class="language-cpp">class Array {
public:
    Array(const Array&amp; rhs) { // 복사 생성자
    }
};</code></pre>
<ol start="3">
<li><strong>대입 연산자 오버로딩(Assignment Operator Overloading)</strong>:<ul>
<li>객체가 다른 객체에 대입될 때, 컴파일러는 대입 연산자를 자동으로 생성</li>
<li>사용자 정의로 대입 연산자를 오버로딩하여 객체의 멤버 변수를 올바르게 복사하도록 할 수 있음</li>
</ul>
</li>
</ol>
<pre><code class="language-cpp">class Array {
public:
    Array&amp; operator=(const Array&amp; rhs) { // 대입 연산자 오버로딩
    }
};</code></pre>
<ol start="4">
<li><strong>소멸자(Destructor)</strong>:<ul>
<li>클래스에 사용자 정의 소멸자가 없는 경우, 컴파일러는 기본 소멸자를 자동으로 생성</li>
<li>소멸자는 객체가 파괴될 때 자동으로 호출되며, 메모리나 리소스의 정리를 수행하는 데 사용</li>
</ul>
</li>
</ol>
<pre><code class="language-cpp">class Array {
public:
    ~Array() { // 소멸자
    }
};</code></pre>
<blockquote>
<p>2 . <strong>Name Mangling</strong></p>
</blockquote>
<p>컴파일 과정에서 식별자(Identifier)는 같지만 다른 namespace에 속해 있거나, 다른 시그니쳐를 가지는 경우(ex. function overloading) 고유한 이름을 가지게 하기 위해 호출 규약(calling convention) 등에 따라서 함수나 변수의 이름을 컴파일러가 변경하는 것</p>
<p><code>C언어</code>에서는 name magling이 없으므로 <code>extern &quot;C&quot;</code>를 사용하여 C++ 컴파일러(현재 실행중인 프로그램 체계)에게, C로 작성한 코드이니 C문법을 적용하여 컴파일하라는 의미를 알려준다. 정확히 말하면, C++의 변수 맹글링(오버로딩)아닌 C의 변수 맹글링(동일한 함수명 사용 문법, 오버로딩 하지 않음)을 적용하라는 의미</p>
<blockquote>
<ol start="3">
<li><strong>++a ,a++ 구현</strong>
<code>a++</code>와 <code>++a</code>는 C++ 및 다른 C 기반 프로그래밍 언어에서 사용되는 증가 연산자(Increment Operator)입니다. 이 두 연산자는 변수의 값을 증가시키는 역할을 한다</li>
</ol>
</blockquote>
<ol>
<li><code>a++</code> (후위 증가 연산자, Post-increment):<ul>
<li><code>a++</code>는 변수 <code>a</code>의 현재 값을 사용한 후에 <code>a</code>를 1 증가</li>
<li><code>a</code>의 현재 값을 반환하고, 그 다음에 <code>a</code>가 1 증가</li>
</ul>
</li>
</ol>
<pre><code class="language-cpp">int a = 5;
int b = a++; // b는 5가 되고, a는 6이 됨</code></pre>
<ol start="2">
<li><code>++a</code> (전위 증가 연산자, Pre-increment):<ul>
<li><code>++a</code>는 변수 <code>a</code>를 1 증가시킨 후에 <code>a</code>의 증가된 값을 사용</li>
<li><code>a</code>를 1 증가시킨 후에 그 증가된 값을 반환</li>
</ul>
</li>
</ol>
<pre><code class="language-cpp">int a = 5;
int b = ++a; // a와 b 모두 6이 됨</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[(0831) C++ 학습일지]]></title>
            <link>https://velog.io/@no_lunch/0831-C-%ED%95%99%EC%8A%B5%EC%9D%BC%EC%A7%80</link>
            <guid>https://velog.io/@no_lunch/0831-C-%ED%95%99%EC%8A%B5%EC%9D%BC%EC%A7%80</guid>
            <pubDate>Sun, 03 Sep 2023 22:58:34 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h3 id="1-생성자">1. <strong>생성자</strong></h3>
</blockquote>
<ol>
<li><strong>기본 생성자 (Default Constructor):</strong><ul>
<li>매개변수를 가지지 않는 생성자</li>
<li>클래스가 다른 생성자를 가지지 않을 때 자동으로 제공</li>
<li>객체를 생성할 때 호출되며, 주로 멤버 변수를 기본값으로 초기화하는 데 사용</li>
</ul>
</li>
</ol>
<pre><code class="language-cpp">class Complex {
public:
    Complex() { // 기본 생성자
    }
};</code></pre>
<ol start="2">
<li><strong>매개변수가 있는 생성자 (Parameterized Constructor):</strong><ul>
<li>하나 이상의 매개변수를 가지는 생성자</li>
<li>객체를 생성할 때 호출되며, 매개변수를 사용하여 멤버 변수를 초기화할 수 있다</li>
</ul>
</li>
</ol>
<pre><code class="language-cpp">class Complex {
public:
    Complex(double re, double im) { // 매개변수가 있는 생성자
    }
};</code></pre>
<ol start="3">
<li><strong>복사 생성자 (Copy Constructor):</strong><ul>
<li>다른 객체로부터 생성자가 호출되는 생성자</li>
<li>객체를 복사하거나 객체를 인수로 받는 함수 호출 시 자동으로 호출</li>
</ul>
</li>
</ol>
<pre><code class="language-cpp">class Complex {
public:
    Complex(const Complex&amp; rhs) {
        // 복사 생성자
    }
};</code></pre>
<ol start="4">
<li><strong>복사 할당 연산자 (Copy Assignment Operator):</strong><ul>
<li>다른 객체의 값을 현재 객체에 할당</li>
<li>객체의 복사본을 생성하는 대신 기존 객체의 값을 업데이트</li>
</ul>
</li>
</ol>
<pre><code class="language-cpp">class Complex {
public:
    Complex&amp; operator=(const Complex&amp; rhs) {
        // 복사 할당 연산자
        if (this != &amp;rhs) {
            // 자기 자신과의 할당을 방지
        }
        return *this;
    }
};</code></pre>
<ul>
<li><strong>생성자의 무한복사 :</strong> <code>Call by Reference(&amp;)</code>가 아닌 <code>Call by value</code> 일때 복사 생성자를 호출하면,
<code>외부에서 객체를 복사 생성</code> -&gt; <code>복사생성자 호출</code> -&gt; <code>매개변수를 값으로 전달받을 경우 호출하는 쪽으로부터 매개변수가 복사 생성</code> -&gt; <code>복사생성자 호출</code> -&gt; <code>무한 반복....</code></li>
</ul>
<blockquote>
<h3 id="2-얕은-복사--깊은-복사">2. 얕은 복사 &amp; 깊은 복사</h3>
</blockquote>
<ol>
<li><p><strong>깊은 복사 (Deep Copy) :</strong></p>
<ul>
<li>깊은 복사는 복사 대상 객체의 모든 데이터나 멤버 변수를 완전히 복사</li>
<li>새로운 객체를 생성하고, 원본 객체의 모든 데이터를 복사하거나 복제합니다.</li>
<li>객체 내에 포인터 또는 동적 할당된 자원이 있는 경우, 깊은 복사는 해당 자원을 새로 할당하여 복사합니다.</li>
<li>따라서 깊은 복사를 수행한 후에는 원본과 복사본이 완전히 독립적이며, 한 쪽을 수정해도 다른 쪽은 영향을 받지 않는다</li>
</ul>
</li>
<li><p><strong>얕은 복사 (Shallow Copy) :</strong></p>
<ul>
<li>얕은 복사는 복사 대상 객체의 주소만 복사하는 것을 의미</li>
<li>복사본은 원본 객체와 동일한 데이터나 멤버 변수를 가리키며, 데이터나 멤버 변수를 공유</li>
<li>만약 객체 내에 포인터나 동적 할당된 자원이 있다면, 원본과 복사본이 같은 자원을 가리킴</li>
<li>이로 인해 한 객체에서 자원을 수정하면 다른 객체에서도 동일한 자원이 수정</li>
</ul>
</li>
</ol>
<ol start="3">
<li><p><strong>Complex c4 = c3, c4=c3의 차이 :</strong></p>
<ul>
<li><strong>Complex c4 = c3 :</strong>
객체 <code>c3</code>를 사용하여 객체 <code>c4</code>를 초기화하는 과정으로 생성자 또는 복사 생성자를 호출하여,
<code>c4</code>를 <code>c3</code>와 동일한 값으로 초기화시키며 <code>복사 초기화</code> 또는 <code>객체 초기화</code>라고 한다</li>
</ul>
<pre><code class="language-cpp">Complex c4 = c3; // 복사 초기화</code></pre>
<p><code>c3</code>와 <code>c4</code>는 별도의 독립적인 객체므로 변경이나 수정은 각 객체에 영향을 주지 않는다</p>
</li>
</ol>
<ol start="2">
<li><p><strong>c4 = c3 :</strong>
이미 생성된 객체 <code>c4</code>에 객체 <code>c3</code>의 값을 할당 -&gt; <code>할당 연산</code>이라고 한다</p>
<pre><code class="language-cpp">c4 = c3; // 할당 연산</code></pre>
<p><code>c3</code>의 값이 <code>c4</code>에 복사되는 것을 의미하고 변경하면 한 객체가 다른 객체에 영향을 미칠 수 있다</p>
</li>
</ol>
<blockquote>
<h3 id="3-함수중복">3. 함수중복</h3>
</blockquote>
<pre><code class="language-cpp"> class Complex{
 public:
    Complex()
    Complex(double re)
    complex(double re,double im)
 // 함수 이름을 같게 하되 입력 받는 매개변수를 다르게 함으로 써, 함수를 정의 </code></pre>
<blockquote>
<h3 id="4-디폴트-인수--default-argument-">4. <strong>디폴트 인수</strong> ( Default Argument )</h3>
</blockquote>
<ol>
<li><p>디폴트 인수(default argument)는 기본값이 미리 정의되어 있는 인수를 의미</p>
</li>
<li><p>함수를 호출할 때 인수를 전달하지 않으면, 함수는 자동으로 미리 정의되어 있는 디폴트 인수값을 사용</p>
</li>
</ol>
<p><code>Complex()</code>,<code>Complex(double re)</code>, <code>Complex(double re,double im)</code> 
-&gt; <code>Complex(double re = 0.0 , double im = 0.0)</code>로 대체 가능</p>
<blockquote>
<h3 id="friend">friend</h3>
</blockquote>
<ol>
<li><p><code>friend</code> 는 클래스의 멤버 함수가 다른 클래스의 비-멤버 함수를 호출하도록 허용하는 기능을 
-&gt;<code>friend</code> 함수는 클래스의 <code>private</code> 또는 <code>protected</code> 멤버에 접근할 수 있도록 허용</p>
</li>
<li><p><strong>두 클래스 간의 밀접한 관계:</strong> 두 클래스가 서로 밀접하게 관련되어 있으며 한 클래스가 다른 클래스의 비공개 멤버에 접근해야 하는 경우 <code>friend</code> 키워드를 사용</p>
</li>
<li><p><strong>연산자 오버로딩:</strong> 연산자 오버로딩 함수 중에서 두 개 이상의 클래스의 비공개 멤버에 접근해야 하는 경우에 <code>friend</code> 키워드를 사용</p>
</li>
</ol>
<p><code>friend</code> 함수를 정의할 때에는 해당 함수가 어떤 클래스의 <code>friend</code>인지를 지정해야 합니다. <code>friend</code> 함수는 클래스의 정의 내부 또는 외부에서 정의할 수 있으며, 함수 정의에서 <code>friend</code> 키워드를 사용하여 해당 클래스를 선언합니다.</p>
<pre><code class="language-cpp">class String{
friend std::ostream&amp; operator&lt;&lt; (std::ostream&amp; out, const String&amp; rhs);
private:
}</code></pre>
<p>+) 마주한 Error</p>
<ul>
<li>undefined reference to~ : header에는 선언 되었지만 cpp파일에는 없을 때 나오는 에러...</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[메모리 섹션(Memory Section)]]></title>
            <link>https://velog.io/@no_lunch/%EB%A9%94%EB%AA%A8%EB%A6%AC-%EC%84%B9%EC%85%98Memory-Section</link>
            <guid>https://velog.io/@no_lunch/%EB%A9%94%EB%AA%A8%EB%A6%AC-%EC%84%B9%EC%85%98Memory-Section</guid>
            <pubDate>Thu, 31 Aug 2023 20:58:25 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/no_lunch/post/29fc9940-c1b3-4933-9e2c-7bea70a7ccd0/image.png" alt=""></p>
<blockquote>
<ol>
<li><strong>Code Section (Text Section)</strong></li>
</ol>
</blockquote>
<ul>
<li>프로그램의 명령어들이 저장되며 프로세스 종료까지 유지되는 영역</li>
<li>프로그램 코드가 저장되며, 프로그램이 실행되면 CPU에 의해 실행
-&gt; Compile 이후 기계어로 저장</li>
<li><strong>읽기 전용</strong>으로 설정되어 있어 프로그램이 이 영역의 내용을 수정할 수 없다. </li>
<li><blockquote>
<p>작업이 들어오면 <code>access violation</code> 발생
<code>읽기 전용일때의 장점 : 한 종류의 프로그램을 여러 번 혹은 여러 개 실행해도, 공유가 가능</code></p>
</blockquote>
</li>
</ul>
<blockquote>
<ol start="2">
<li><strong>Data Section</strong></li>
</ol>
</blockquote>
<ul>
<li>초기화된 전역(global) 변수와 정적(static) 변수들이 저장되는 영역
-&gt; 상수, 포인터 변수의 값, 배열의 값, 구조체의 값</li>
<li>프로그램의 시작과 함께 할당되며, 프로그램의 종료 시까지 유지</li>
</ul>
<blockquote>
<ol start="3">
<li><strong>BSS (Block Started by Symbol) Section</strong></li>
</ol>
</blockquote>
<ul>
<li>Data Section 에 포함됨</li>
<li>초기화되지 않은 전역 변수와 정적 변수가 저장되는 영역
-&gt; (포인터 변수,배열,구조체)의 초기값 포함 </li>
<li>프로그램이 시작되면 메모리가 할당되고 초기화되지 않은 변수들은 자동으로 초기화</li>
</ul>
<blockquote>
<ol start="4">
<li><strong>Heap</strong></li>
</ol>
</blockquote>
<ul>
<li>동적으로 메모리를 할당하고 해제하는 데 사용되는 영역</li>
<li>사용자가 직접 제어하여 메모리 할당과 해제가 가능</li>
<li>메모리의 크기와 위치는 런타임에 동적으로 결정</li>
<li><code>new</code>, <code>malloc</code> 를 사용하여 힙에 메모리를 할당 <code>delete</code>, <code>free</code> 등을 사용하여 해제</li>
<li>C++의 경우에는 <code>garbage collector</code> 가 활동하면 자동으로 반환하는 경우도 있음</li>
<li>Heap 의 크기가 작으면 <strong>Heap Overflow</strong>가 발생할 수 도 있음</li>
</ul>
<blockquote>
<ol start="5">
<li><strong>Stack</strong></li>
</ol>
</blockquote>
<ul>
<li>스택은 함수 호출과 로컬 변수들의 저장에 사용되는 영역, 완료시 소멸</li>
<li>함수가 호출될 때마다 스택 프레임이 생성되며, 해당 함수의 지역 변수와 매개변수가 저장</li>
<li>함수가 종료되면 함수의 반환 값이 Stack에 저장되며, 해당 스택 프레임이 제거</li>
<li>후입선출(LIFO) 구조</li>
<li>Stack 의 크기가 작으면 <strong>Stack Overflow</strong>가 발생할 수도 있음</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[(0830) C++ 학습일지 (2)]]></title>
            <link>https://velog.io/@no_lunch/0830-C-%ED%95%99%EC%8A%B5%EC%9D%BC%EC%A7%80-2</link>
            <guid>https://velog.io/@no_lunch/0830-C-%ED%95%99%EC%8A%B5%EC%9D%BC%EC%A7%80-2</guid>
            <pubDate>Thu, 31 Aug 2023 18:45:09 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>*<em>연산자(Operator) : *</em>
특정한 작업을 수행하는 기호 또는 함수로 사용자 정의 연산자도 생성 가능</p>
</blockquote>
<ol>
<li><p><strong>산술 연산자 (Arithmetic Operators):</strong></p>
<ul>
<li><code>+</code>: 덧셈</li>
<li><code>-</code>: 뺄셈</li>
<li><code>*</code>: 곱셈</li>
<li><code>/</code>: 나눗셈</li>
<li><code>%</code>: 나머지</li>
</ul>
</li>
<li><p><strong>할당 연산자 (Assignment Operators):</strong></p>
<ul>
<li><code>=</code>: 대입</li>
<li><code>+=</code>: 덧셈 후 대입</li>
<li><code>-=</code>: 뺄셈 후 대입</li>
<li><code>*=</code>: 곱셈 후 대입</li>
<li><code>/=</code>: 나눗셈 후 대입</li>
<li><code>%=</code>: 나머지 후 대입</li>
</ul>
</li>
<li><p><strong>비교 연산자 (Comparison Operators):</strong></p>
<ul>
<li><code>==</code>: 동등</li>
<li><code>!=</code>: 부등</li>
<li><code>&lt;</code>: 작다</li>
<li><code>&gt;</code>: 크다</li>
<li><code>&lt;=</code>: 작거나 같다</li>
<li><code>&gt;=</code>: 크거나 같다</li>
</ul>
</li>
<li><p><strong>논리 연산자 (Logical Operators):</strong></p>
<ul>
<li><code>&amp;&amp;</code>: 논리적 AND</li>
<li><code>||</code>: 논리적 OR</li>
<li><code>!</code>: 논리적 NOT</li>
</ul>
</li>
<li><p><strong>증감 연산자 (Increment and Decrement Operators):</strong></p>
<ul>
<li><code>++</code>: 증가</li>
<li><code>--</code>: 감소</li>
</ul>
</li>
<li><p><strong>비트 연산자 (Bitwise Operators):</strong></p>
<ul>
<li><code>&amp;</code>: 비트 AND</li>
<li><code>|</code>: 비트 OR</li>
<li><code>^</code>: 비트 XOR</li>
<li><code>~</code>: 비트 NOT</li>
<li><code>&lt;&lt;</code>: 비트를 왼쪽으로 이동</li>
<li><code>&gt;&gt;</code>: 비트를 오른쪽으로 이동</li>
</ul>
</li>
<li><p><strong>조건(삼항) 연산자 (Conditional (Ternary) Operator):</strong></p>
<ul>
<li><code>condition ? value_if_true : value_if_false</code>: 조건이 참이면 첫 번째 값, 거짓이면 두 번째 값 반환</li>
</ul>
</li>
<li><p><strong>멤버 접근 연산자 (Member Access Operators):</strong></p>
<ul>
<li><code>.</code>: 멤버 접근 (객체)</li>
<li><code>-&gt;</code>: 멤버 접근 (포인터)</li>
</ul>
</li>
<li><p><strong>포인터 연산자 (Pointer Operators):</strong></p>
<ul>
<li><code>*</code>: 포인터 역참조</li>
<li><code>&amp;</code>: 주소 참조</li>
</ul>
</li>
<li><p><strong>타입 변환 연산자 (Type Conversion Operators):</strong></p>
<ul>
<li><code>static_cast</code>: 정적 타입 변환</li>
<li><code>dynamic_cast</code>: 동적 타입 변환 (상속 관련)</li>
<li><code>const_cast</code>: 상수 제거 변환</li>
<li><code>reinterpret_cast</code>: 재해석 변환</li>
</ul>
</li>
</ol>
<blockquote>
<p><strong>연산자 중복 (Operator Overloading) :</strong>
기존의 연산자를 사용자 정의 데이터 유형에 대해 새로 정의하거나 확장</p>
</blockquote>
<p>예를 들어, 두 개의 객체를 더하는 연산자 <code>+</code>를 사용자 정의 클래스에 대해 사용하고자 할 때, 연산자 중복을 이용할 수 있습니다.</p>
<pre><code class="language-cpp">//연산자 중복
std::cout &lt;&lt; &quot;Hello World&quot; &lt;&lt; std::endl;
operator&lt;&lt;(std::cout,&quot;Hello World&quot;).operator&lt;&lt;(std::endl); 
</code></pre>
<blockquote>
<p><strong>함수 중복(Function Overloading):</strong>
같은 이름의 함수를 여러 번 정의하는 기능 
동일한 이름의 함수를 다양한 매개변수 목록과 타입에 대해 정의 가능
호출 시 전달되는 인자에 따라 적절한 함수가 자동으로 선택되어 실행</p>
</blockquote>
<p>예를 들어, 동일한 함수 이름으로 여러 개의 함수를 정의하여 다양한 데이터 유형에 대해 동작을 제공할 수 있습니다.</p>
<pre><code class="language-cpp">//&lt;complex.h&gt;
#ifndef COMPLEX_H
#define COMPLEX_H

class Complex{
private:
    double re;
    double im;
public:
    Complex();
    Complex(double re);
    Complex(double re, double im);
    ~Complex();
    double real();
    double imag();
    void real(double re);
    void imag(double im);
};</code></pre>
<p>위에서는 <code>Complex</code> 함수를 인자가 없는 <code>Complex()</code> 와 
실수형을 받는 <code>Complex(double re)</code> 와 <code>Complex(double re, double im)</code> 로 만들어 준었다.</p>
<blockquote>
<p>*<em>Reference(aliasing) vs pointer *</em></p>
</blockquote>
<p><strong>레퍼런스(참조):</strong></p>
<ul>
<li>레퍼런스는 <code>반드시 초기화되어야 하며 선언과 동시에 변수에 바인딩</code></li>
<li><code>초기화되면 다른 변수에 바인딩되지 않음</code></li>
<li>널 포인터 문제와 같은 오류를 방지해 포인터보다 안전하게 사용가능</li>
<li><code>자동으로 간접 참조</code>되므로 포인터 연산이 필요하지 않음</li>
<li><code>주로 함수의 매개변수로 전달</code>하거나 <code>함수의 반환 값으로 사용</code></li>
</ul>
<p><strong>포인터:</strong></p>
<ul>
<li><code>주소를 저장하는 변수</code> 로 직접적인 메모리 주소를 가리킴</li>
<li>초기화하지 않거나 <code>널 포인터(NULL 포인터)</code>로 초기화할 수 있습니다.</li>
<li><code>여러 변수들과 공유</code> 될 수 있습니다.</li>
<li>포인터 연산을 사용하여 <code>간접 참조</code> , <code>값을 변경할 수 있음</code></li>
<li><code>동적 메모리 할당</code>, <code>배열 처리</code>, <code>객체의 동적 변화</code> 의 경우에 더 적합</li>
</ul>
<blockquote>
<p><strong>값에 의한 호출 (Call by value)</strong> </p>
</blockquote>
<ul>
<li>함수에 전달되는 <code>인자의 값을 복사</code>하여 함수 내부에 새로운 변수로 사용하므로,
함수 내에서 인자의 값이 변경되더라도 <code>원본 변수는 영향을 받지 않음</code></li>
<li>호출된 함수 안에서 매개변수로 전달된 값은 <code>로컬 변수로 취급</code> 
-&gt; 수정해도 원본 값에는 영향을 미치지 않음.</li>
</ul>
<blockquote>
<p>** 참조에 의한 호출 (Call by Reference) :**</p>
</blockquote>
<ul>
<li>함수에 전달되는 인자의 <code>메모리 주소를 전달</code>
-&gt; 함수 내부에서 <code>인자의 값이 변경되면 원본 변수도 변경</code></li>
<li>호출된 함수 안에서 매개변수로 전달된 레퍼런스를 통해 값에 접근하면,
원본 변수의 값이 직접 수정</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[(0829) C++ 학습일지(1)]]></title>
            <link>https://velog.io/@no_lunch/0829-C-%ED%95%99%EC%8A%B5%EC%9D%BC%EC%A7%801</link>
            <guid>https://velog.io/@no_lunch/0829-C-%ED%95%99%EC%8A%B5%EC%9D%BC%EC%A7%801</guid>
            <pubDate>Tue, 29 Aug 2023 22:55:34 GMT</pubDate>
            <description><![CDATA[<blockquote>
<ol>
<li>from C to C++</li>
</ol>
</blockquote>
<ol>
<li><p>확장자의 변경 from (.c) to (.cpp)</p>
<pre><code class="language-c++">// Ubuntu OS 
cp (디렉토리 지정)/ main.c main.cpp
cp (디렉토리 지정)/stack.h stack.h
cp (디렉토리 지정)/stack.c stack.cpp</code></pre>
<pre><code class="language-C++">// How to Compile in UbuntuOs
g++ -c stack.cpp
g++ -c main.cpp
g++ -c stack.h
g++ -o testStack main.o stack.o</code></pre>
<p><code>gedit으로 편집 : 
gedit main.cpp stack.h stack.cpp</code></p>
</li>
</ol>
<blockquote>
<ol start="2">
<li>push(&amp;s1,100) -&gt; s1.push(100)</li>
</ol>
</blockquote>
<ol>
<li>멤버함수는 반드시 객체를 통해서 호출한다 
<code>예시) s1.pop(), s2.pop()</code></li>
<li>모든 멤버함수는 자신과 호출된 객체를 가리키는 <code>this</code> 포인터를 갖는다.</li>
<li>데이터와 관련된 연산은 같은 멤버로 구성, <code>캡슐화(encapsulation)</code></li>
</ol>
<pre><code class="language-c++">//수정 전 코드
#include &lt;stdio.h&gt;
#include &quot;stack.h&quot;

int main(void)
{
    Stack s1, s2;
    initStack(&amp;s1, 10);
    initStack(&amp;s2, 100);

    push(&amp;s1, 100);
    push(&amp;s1, 200);
    push(&amp;s1, 300);

    printf(&quot;s1 1st pop() : %d\n&quot;, pop(&amp;s1));
    printf(&quot;s1 2nd pop() : %d\n&quot;, pop(&amp;s1));
    printf(&quot;s1 3rd pop() : %d\n&quot;, pop(&amp;s1));


    push(&amp;s2, 900);
    push(&amp;s2, 800);
    push(&amp;s2, 700);

    printf(&quot;s2 1st pop() : %d\n&quot;, pop(&amp;s2));
    printf(&quot;s2 2nd pop() : %d\n&quot;, pop(&amp;s2));
    printf(&quot;s2 3rd pop() : %d\n&quot;, pop(&amp;s2));

    cleanupStack(&amp;s1);
    cleanupStack(&amp;s2);
    return 0;
}</code></pre>
<pre><code>int main() {
    Stack s1(10);
    Stack s2(100);

    s1.push(100);
    s1.push(200);
    s1.push(300);

    printf(&quot;s1 1st pop() : %d\n&quot;, pop(&amp;s1));
    printf(&quot;s1 2nd pop() : %d\n&quot;, pop(&amp;s1));
    printf(&quot;s1 3rd pop() : %d\n&quot;, pop(&amp;s1));

    s2.push(900);
    s2.push(800);
    s2.push(700);

    printf(&quot;s2 1st pop() : %d\n&quot;, pop(&amp;s2));
    printf(&quot;s2 2nd pop() : %d\n&quot;, pop(&amp;s2));
    printf(&quot;s2 3rd pop() : %d\n&quot;, pop(&amp;s2));</code></pre><blockquote>
<ol start="3">
<li>malloc() / free() 함수 --&gt; new / delete  연산자</li>
</ol>
</blockquote>
<p><code>malloc() / free() 와 new / delete 에 대한 비교</code></p>
<ol>
<li><p><strong>메모리 할당:</strong></p>
<ul>
<li><p><strong>C (malloc):</strong> <code>malloc()</code> 함수는 동적으로 메모리를 할당하기 위해 사용
ex) <code>int* ptr = (int*)malloc(sizeof(int));</code>
<code>malloc()</code>은 할당한 메모리의 크기만큼의 바이트를 할당, 초기화 X</p>
</li>
<li><p><strong>C++ (new):</strong> <code>new</code> 는 C++에서 동적으로 메모리를 할당하기 위해 사용
ex) <code>int* ptr = new int;</code> 
<code>new</code>는 할당한 메모리를 초기화하며, 객체의 경우 생성자도 호출</p>
</li>
</ul>
</li>
<li><p><strong>메모리 해제:</strong></p>
<ul>
<li><strong>C (free):</strong> <code>free()</code>는 <code>malloc()</code>으로 할당된 메모리를 해제하는 데 사용
ex)<code>free(ptr);</code>
<code>free()</code>를 호출하면 해당 메모리 블록 해제, 포인터 유효하지 않음   </li>
<li><strong>C++ (delete):</strong> <code>delete</code>는 <code>new</code>로 할당된 메모리를 해제하는 데 사용
ex)<code>delete ptr;</code>
<code>delete</code>를 호출하면 해당 객체의 소멸자가 호출, 할당된 메모리 블록이 해제,포인터는 더 이상 유효하지 않음</li>
</ul>
</li>
<li><p><strong>배열 할당 및 해제:</strong></p>
<ul>
<li><p><strong>C (malloc + free):</strong> C에서 배열을 할당하려면 <code>malloc()</code>을 사용해야 하며, 해제할 때는 <code>free()</code>를 사용</p>
</li>
<li><p><strong>C++ (new[] + delete[]):</strong> C++에서 배열을 할당하려면 <code>new[]</code> 를 사용하고, 해제할 때는 <code>delete[]</code> 를 사용
<code>new[]</code>로 할당된 배열은 해당 크기 정보와 함께 메모리에 저장 <code>delete[]</code>를 호출하면 배열의 각 요소에 대해 소멸자가 호출되며 할당된 메모리 블록이 해제</p>
</li>
</ul>
</li>
<li><p><strong>예외 처리:</strong></p>
<ul>
<li><p><strong>C (malloc + free):</strong> <code>malloc()</code>과 <code>free()</code>는 예외 처리를 지원하지 않아 메모리 할당 또는 해제 과정에서 문제가 발생하면 프로그램이 비정상적으로 종료될 수 있다.</p>
</li>
<li><p><strong>C++ (new + delete):</strong> <code>new</code>와 <code>delete</code>는 C++에서 예외 처리를 지원함
할당 또는 해제 중에 문제가 발생하면 예외가 <code>throw</code>되어 적절한 예외 처리 메커니즘을 통해 처리가능</p>
</li>
</ul>
</li>
</ol>
<pre><code>//수정 전 코드 &lt;stack.cpp&gt;
#include &lt;stdlib.h&gt;
#include &lt;assert.h&gt;
#include &quot;stack.h&quot;

void initStack(Stack *ps, int size)
{
    ps-&gt;pArr = malloc(sizeof(int) * size);
    assert(ps-&gt;pArr /* != NULL */);

    ps-&gt;size = size;
    ps-&gt;tos = 0;
}

void cleanupStack(Stack *ps)
{
    free(ps-&gt;pArr);
}


void push(Stack *ps, int data)
{
    assert(ps-&gt;tos != ps-&gt;size);

    ps-&gt;pArr[ps-&gt;tos] = data;
    ++ps-&gt;tos;
}

int pop(Stack *ps)
{
    assert(ps-&gt;tos /* != 0 */);

    --ps-&gt;tos;
    return ps-&gt;pArr[ps-&gt;tos];
}</code></pre><pre><code>//수정 후 코드
#include &lt;cassert&gt; // &lt;cassert&gt; 로 변경
#include &quot;stack.h&quot;

class Stack {
private:
    int* pArr;
    int size;
    int tos;

public:
    Stack(int s) : size(s), tos(0) {
        pArr = new int[size]; // malloc() 에서 new[]로 변경
    }

    ~Stack() {
        delete[] pArr; // free()에서 delete[]로 변경
    }

    void push(int data) {
        assert(tos != size);
        pArr[tos] = data;
        ++tos;
    }

    int pop() {
        assert(tos != 0);
        --tos;
        return pArr[tos];
    }
};</code></pre><blockquote>
<ol start="4">
<li>구조체 멤버에 접근지정자 ( private / public ) 를 사용</li>
</ol>
</blockquote>
<ol>
<li><code>내부구현(implemetation)</code>은 숨기고, <code>인터페이스는(interface)</code>는 보인다.</li>
</ol>
<ol start="2">
<li>허용된 연산을 통해서 내부 구현에 접근할 수 있다.<ul>
<li><code>정보 은닉(information/data hiding) == 캡슐화(encapsulation)</code></li>
</ul>
</li>
</ol>
<pre><code>//수정 후 코드
#include &lt;cassert&gt; // &lt;cassert&gt; 로 변경
#include &quot;stack.h&quot;

class Stack {
private: //private로 지정 클래스 내부에서만 사용 가능
    int* pArr;
    int size;
    int tos;

public: // public 으로 지정 클래스 외부에서도 사용 가능
      Stack(int s) : size(s), tos(0) {
          pArr = new int[size]; 
      }

    ~Stack() {
          delete[] pArr; 
      }

    void push(int data) {
          assert(tos != size);
          pArr[tos] = data;
          ++tos;
      }</code></pre><blockquote>
<ol start="5">
<li>생성자(Constructor) / 소멸자(Destructor)</li>
</ol>
</blockquote>
<ol>
<li>생성자 : 객체가 생성될 때, 자동적으로 호출되는 멤버함수</li>
</ol>
<ol start="2">
<li>소멸자 : 객체가 소멸될 때, 자동적으로 호출되는 멤버함수</li>
</ol>
<pre><code>// 수정 후 코드
public: 
//생성자로써 initStack(Stack *ps,int size)에서 Stack(int s)으로 변경
      Stack(int s) : size(s), tos(0) { 
          pArr = new int[size]; 
      }
//소멸자로써 void cleanupStack(Stack *ps) 에서 Stack()으로 변경
    ~Stack() {
          delete[] pArr; 
      }</code></pre><blockquote>
<ol start="6">
<li>struct --&gt; class</li>
</ol>
</blockquote>
<p><code>class(C++) = struct(C) + 멤버함수 + 접근지정자</code></p>
<p>C의 <code>struct</code>와 C++의 <code>class</code>는 모두 데이터와 함수를 하나의 유닛으로 그룹화하는데 사용되지만, C++의 <code>class</code>는 더 많은 기능과 특성을 제공하여 객체 지향 프로그래밍의 원칙을 더 쉽게 적용할 수 있도록 한다. </p>
<ol>
<li><p><strong>캡슐화 (Encapsulation):</strong></p>
<ul>
<li><p><strong>C의 struct:</strong> C의 <code>struct</code>는 멤버 변수만을 가지며, 함수를 정의할 수 없다. 데이터의 그룹화는 가능하지만, 해당 데이터를 다루는 함수를 함께 묶을 수 없음</p>
</li>
<li><p><strong>C++의 class:</strong> C++의 <code>class</code>는 멤버 변수와 멤버 함수를 함께 포함하여 객체의 상태와 동작을 하나로 묶을 수 있다. 이를 통해 데이터와 데이터를 다루는 동작을 함께 캡슐화하여 더 모듈화된 코드를 작성할 수 있다.</p>
</li>
</ul>
</li>
<li><p><strong>접근 제어 (Access Control):</strong></p>
<ul>
<li><p><strong>C의 struct:</strong> C의 <code>struct</code>는 기본적으로 모든 멤버가 <code>public</code>으로 설정되어 외부에서 멤버 변수에 직접 접근이 가능하며, 캡슐화의 개념이 부족</p>
</li>
<li><p><strong>C++의 class:</strong> C++의 <code>class</code>는 기본적으로 모든 멤버가 <code>private</code>으로 설정, 이를 통해 외부에서 직접적으로 접근하는 것을 제한하고, <code>public</code>, <code>private</code>, <code>protected</code> 등의 접근 제어 지시자를 사용하여 적절한 접근을 조절</p>
</li>
</ul>
</li>
<li><p><strong>생성자와 소멸자 (Constructor and Destructor):</strong></p>
<ul>
<li><p><strong>C의 struct:</strong> C의 <code>struct</code>는 생성자와 소멸자를 가질 수 없다. 초기화 작업과 정리 작업을 구현할 수 없다.</p>
</li>
<li><p><strong>C++의 class:</strong> C++의 <code>class</code>는 생성자와 소멸자를 가질 수 있다. 객체의 초기화와 정리 작업을 효과적으로 관리할 수 있습니다.</p>
</li>
</ul>
</li>
<li><p><strong>상속 (Inheritance)과 다형성 (Polymorphism):</strong></p>
<ul>
<li><p><strong>C의 struct:</strong> C의 <code>struct</code>는 상속과 다형성을 지원하지 않는다.</p>
</li>
<li><p><strong>C++의 class:</strong> C++의 <code>class</code>는 상속과 다형성을 지원하여 객체 지향 프로그래밍의 핵심적인 개념을 적용할 수 있다.</p>
</li>
</ul>
</li>
<li><p><strong>멤버 함수 및 멤버 변수의 초기화:</strong></p>
<ul>
<li><p><strong>C의 struct:</strong> C의 <code>struct</code>는 멤버 변수를 초기화하지 않아 사용자가 수동으로 초기화해야 함</p>
</li>
<li><p><strong>C++의 class:</strong> C++의 <code>class</code>는 생성자를 통해 멤버 변수를 초기화할 수 있다. 이를 통해 객체 생성 시 초기값을 제공하거나, 초기화 로직을 더 효과적으로 관리할 수 있다.</p>
</li>
</ul>
</li>
</ol>
<p>간단하게 말해, C++의 <code>class</code>는 C의 <code>struct</code>보다 객체 지향 프로그래밍을 더 쉽게 적용하도록 해주는 다양한 특성과 기능을 제공, C++의 <code>class</code>를 사용하면 코드의 모듈화, 캡슐화, 상속, 다형성 등을 더 효과적으로 활용할 수 있다.</p>
<blockquote>
<ol start="7">
<li>printf() --&gt; cout &lt;&lt; ??</li>
</ol>
</blockquote>
<ol>
<li><strong>std::cout</strong>  (C++)은 <code>&lt;iostream&gt;</code>헤더에 속하며, 스트림의 유형의 객체이다.
출력하려는 값의 자료형을 컴파일러가 검사할 수 있다. <pre><code>std::cout &lt;&lt; 2 &lt;&lt; endl; //int형 출력 함수 호출
std::cout &lt;&lt;&quot;2&quot;&lt;&lt; endl; //string형 출력 함수 호출</code></pre><ul>
<li>파일 입출력(fstream) 스트링 입출력(stringstream)에서도 표준 입출력과 동일한 인터페이스를 사용하므로 편리함, printf()에 비해 속도가 느림</li>
<li><code>endl</code>사용</li>
</ul>
</li>
<li><strong>printf()</strong>는 <code>&lt;cstdio&gt;</code>헤더에 속하며, 형식화된 문자열을 표시하는데 주로 사용
<code>cout</code>과 달리 출력하려는 값의 자료형을 컴파일 할 수 없기 때문에, 
버그가 일어날 수 있지만, <code>cout</code>에 비해 처리 속도가 빠르다.</li>
</ol>
<ul>
<li><code>\n</code>사용</li>
</ul>
]]></description>
        </item>
    </channel>
</rss>