728x90

외부 교육이 있어 오랜만에 강남방문!

10시부터 17시까기 교육을 열심히(?) 듣고 법인카드를 받은 우리는 강남 맛집을 열심히 찾다가 강남 곱창 맛집인

강남곱


에서 회식을 하기로 했다





수요미식회에 나온 맛집이라는 블로그 글을보고 방문했다

매장은 1, 2층이 있는거같다



매장 규모는 넓지도 좁지도 않은 규모다

테이블간 간격이 넓어서 답답하다는 느낌은 없다

메뉴판 보고 가자


저렴한 가격은 아니다 사실 회식비가 아니라면 고민했을 가격과 과연 내돈이면 먹을수 있을까? 라는 의문이 드는 가격이지만 일단 먹어보기로 하고 모둠2인분과 마늘곱창 1인분을 주문
(주류가격은 천원정도 더 비씨다)



기본 테이블셋팅할때 떡볶이가 나오고 끓여서 다 먹을때쯤 초벌된 곱창이 나온다

내인생 이렇게 맛있는 곱창은 처음이다

내돈내고 먹을 의사 10000%

마늘곱창은 마늘향이 걍해 마늘곱창과 일반곱창이나 모둠을 섞어서 주문하는걸 추천한다
(개인적인 의견)

볶음밥등 다른건 먹지 않았다

오로지 곱창ㅋㅋㅋㅋㅋ

하이볼 한잔 곱창한점



후회하지않을 맛집

우리가 나갈때쯤은 이미 만석에 웨이팅

평일인대 웨이팅?!

맛집인정


728x90
728x90

함수 매개변수의 default 값 지정

C++에서는 함수 매개변수에 default 값을 지정할 수 있다.

#include <iostream>

int add(int n1 = 10, int n2 = 20, int n3 = 30)
{
    return n1 + n2 + n3;
}

int main()
{
    std::cout << add() << std::endl;

    return 0;
}

3번째 줄 add함수의 매개변수 n1, n2, n3에 default 값 10, 20, 30이 지정돼 있다. 이와 같이 함수의 매개변수에 default 값을 지정할 수 있다. add함수를 호출 할 때 별도의 값을 매개변수에 전달하지 않으면 add함수의 매개변수 n1, n2, n3는 지정된 default 값으로 초기화된다. 따라서 위 코드의 실행 결과는 아래와 같다.

실행결과
60

매개변수의 default 값 지정은 오른쪽에서 왼쪽으로 지정해야 한다.

함수 매개변수에 default 값을 지정할 때 반드시 오른쪽에서 왼쪽 순서로 지정해야 한다.

#include <iostream>

int add(int n1, int n2, int n3 = 30)
{
    return n1 + n2 + n3;
}

int main()
{
    std::cout << add(1, 2) << std::endl;

    return 0;
}

함수를 호출 할 때 전달 인자가 전달되는 순서를 생각해보자. 위 코드와 같이 add함수를 호출하고 전달 인자로 1과 2를 전달하면 1은 n1에 전달되고, 2는 n2에 전달된다. n3에는 default 값으로 30이 지정되어 있기 때문에 실행 결과는 다음과 같을 것이다.

실행결과
33

아래와 같이 가장 왼쪽의 n1에 default 값을 지정하고 컴파일 해보면 에러가 발생하는 것을 확인 할 수 있다.

#include <iostream>

int add(int n1 = 10, int n2, int n3)
{
    return n1 + n2 + n3;
}

int main()
{
    std::cout << add(1, 2) << std::endl;

    return 0;
}

add함수를 호출하면서 1과 2를 전달하면 1은 n1에 전달되고 2는 n2에 전달된다. n3에는 어떠한 값도 지정되지 않았기 때문에 컴파일 에러가 발생한다.

**매개변수에 default 값을 지정할 때는 반드시 오른쪽에서 왼쪽 순서로 지정을 해야 한다.

default 값 표현은 함수의 선언 부분에만 표시해야 한다.

아래 코드는 main()함수 위에 add함수가 선언되어 있고 n3에 default 값이 지정되어 있기 때문에 정상적으로 컴파일 된다.

#include <iostream>

int add(int n1, int n2, int n3 = 30)
{
    return n1 + n2 + n3;
}

int main()
{
    std::cout << add(1, 2) << std::endl;

    return 0;
}

이와 같은 형태가 아니라 함수 원형을 별도로 선언하는 경우 매개변수의 default 값은 함수 원형 선언 할 때 같이 지정해 줘야 한다.

#include <iostream>

int add(int n1, int n2, int n3 = 30);

int main()
{
    std::cout << add(1, 2) << std::endl;

    return 0;
}

int add(int n1, int n2, int n3)
{
    return n1 + n2 + n3;
}

함수 원형이 .h파일에 선언된 경우도 동일하고, class에 선언된 경우도 동일하게 적용된다.

default 값 지정과 함수 오버로딩(Function Overloading)

#include <iostream>

void print(int a)
{
    std::cout << a << std::endl;
}

void print(int a, int b = 10)
{
    std::cout << a <<", "<< b << std::endl;
}

int main()
{
    print(10);
}

위 코드와 같은 경우 함수 오버로딩이 적용되지만, 8번째 줄에 선언된 void print(int a, int b = 10)함수에서 default value를 지정하고 있기 때문에 default 매개변수를 사용한 함수*와 *오버로딩된 함수 사이에 모호성이 발생할 수 있다.
16번째 라인에서 print(10) 함수를 호출하게 되면 컴파일러는 아래 두 가지 가능성을 두고 혼란을 겪게 되어 컴파일 에러를 발생한다.

  1. void print(int a)함수 호출
  2. void print(int a, int b = 10) 함수 호출
    16번째 라인에서 print(10) 함수 호출은 두 가지 경우 모두 만족하는 경우기 때문에 모호성이 발생한다.

default 값은 반드시 상수여야 한다.

매개변수의 default 값을 지정 할 때는 반드시 상수로 지정해야 한다. 함수의 호출 결과를 default 값으로 사용 할 수 없다.

함수 포인터 사용 시 매개변수의 default 값

#include <iostream>

void Func(int a = 10)
{
    std:;cout << a << std::endl;
}

int main()
{
    void(*FuncPtr)(int) = Func;
    FuncPtr(20);
}

10번째 줄(void(*FuncPtr)(int) = Func)에서 Func 함수를 포인터로 지정할 때 Func매개변수의 default 값은 사라진다. 따라서 반드시 매개변수에 어떠한 값을 전달해 줘야 한다.

Class 상속에서 매개변수의 default 값

[[상속(Inheritance)]]
[[Class]]

Class 상속에서 기본 클래스의 default 매개변수 값은 유도 클래스에서 상속되지 않는다. 따라서 기본 클래스의 디폴트 매개변수를 변경해도 유도 클래스는 영향을 받지 않는다.

class Base {
public:
    virtual void Print(int x = 10) {
        std::cout << "Base: " << x << std::endl;
    }
};

class Derived : public Base {
public:
    void Print(int x = 20) override {
        std::cout << "Derived: " << x << std::endl;
    }
};

int main() {
    Base* basePtr = new Derived;
    basePtr->Print();  // 출력: "Derived: 10" -> Base 클래스의 디폴트 값 사용
}
728x90
728x90

for_each()

for_each란?

algorithm 헤더에 정의된 STL함수로 주어진 범위 내의 모든 요소를 순회하면 요소 값을 함수에 전달하는 기능을 수행한다.

std::for_each(시작 iterator, 끝 iterator, 함수 또는 람다 표현식)

vector의 요소를 출력하는 예제

#include <iostream>
#include <vector>
#include <algorithm>

void print(int value)
{
    std::cout << value << ", ";
}

int main()
{
    std::vector<int> numbers = {1, 2, 3, 4, 5};

    std::for_each(numbers.begin(), numbers.end(), print);

    return 0;
}

실행 결과는 다음과 같다.

1, 2, 3, 4, 5

[[vector]]로 선언된 numbers의 시작(begin())과 끝(end())의 [[iterator]]를 for_each 함수의 매개변수에 전달 인자로 전달하고, numbers의 요소를 전달하면서 실행할 함수를 마지막 매개변수 위치에 넣어준다.

for_each()의 전달 인자가 되는 함수에 매개변수가 존재하지 않는 경우?

[[#vector의 요소를 출력하는 예제]]에서 void print(int value) 함수에 매개변수 int valeu가 없다면 컴파일러는 다음과 같은 에러를 발생 시킨다.

void print()
{
    std::cout << "print()";
}

int main()
{
    std::vector<int> numbers = {1, 2, 3, 4, 5};

    std::for_each(numbers.begin(), numbers.end(), print);

    return 0;
}

위와 같이 코드를 작성할 경우 void print() 함수는 매개변수가 없기 때문에 전달받은 vector요소를 처리할 수 없어 에러가 발생하게 된다.

for_each컴파일 에러

for_each에서 호출하는 함수의 반환형

for_each에 매개변수로 전달해 실행하는 함수의 반환형은 무시된다. 아래 코드는 컴파일 에러도 발생하지 않고 [[#vector의 요소를 출력하는 예제]]에서 제시한 코드의 실행결과와 동일한 실행결과를 보인다.

#include <iostream>
#include <vector>
#include <algorithm>

int print(int value)
{
    std::cout << value << ", ";

    return 1;
}

int main()
{
    std::vector<int> numbers = {1, 2, 3, 4, 5};
    std::for_each(numbers.begin(), numbers.end(), print);
    return 0;
}

for_each()의 전달 인자가 되는 함수의 매개 변수가 두 개 이상인 경우?

[[#for_each()의 전달 인자가 되는 함수에 매개변수가 존재하지 않는 경우?]]와 마찬가지로 컴파일 에러가 발생한다. for_each()에 전달 인자로 전달되는 함수의 전달 인자는 반드시 1개여야 한다.

for_each()에 [[lambda(람다)]]적용

vector의 요소를 출력하는 예제(lambda)

[[#vector의 요소를 출력하는 예제]]에서 void print(int value)를 람다식으로 대체해보자.

#include <iostream>
#include <vector>
#include <algorithm>

int main()
{
    std:;vector<int> numbers = {1, 2, 3, 4, 5};

    std::for_each(numbers.begin(), numbers.end(), [](int value)) {
        std::cout<< value << ", ";    
    };

    return 0;
}

람다를 사용하면 코드를 더 짧고 명확하게 작성 할 수 있다.

for_each()를 왜 사용해야 하는가?

for_each()for 반복문 비교

for_each()와 전통적인 for 반복문의 성능 차이는 거의 없다고 봐도 무방하다. for_each()가 더 효율적이고 간결하다고 말하는 이유는 코드의 가독성표현력에 대한 차이점 때문이다.
for_each()를 사용하는 이유 중 하나는 코드의 간결성함수형 프로그래밍스타일을 강조 할 수 있다는 점이 있다.

std::for_each(numbers.begin(), numbers.end(), print)

이 코드는 컨테이너의 모든 요소를 pinrt함수의 매개 변수에 전달 인자로 전달한다는 것을 명확하게 보여준다. 또한 컨테이너와 알고리즘(여기서는 print함수)을 분리해서 코드의 의도를 더 명확하게 표현할 수 있다.

반면에 for문을 사용하면

for(int i = 0; i < 5; i++){
    std:;cout << numbers[i] << ", ";
}

이 방식도 for_each()를 사용한 경우와 같은 결과를 보이지만 iterator의 범위를 직접 제어하고 인덱스를 사용해야 하므로 코드가 조금 더 절차적이고 덜 추상화된 형태가 된다. 따라서 코드 길이가 길어지거나 복잡해질 경우 개발자의 실수를 유발할 가능성이 있다.

알고리즘과 데이터를 분리

for를 사용하게 되면 알고리즘과 데이터가 엉켜서 명령형 코딩 스타일을 따르게 된다. for_each()를 사용하게 되면 함수형 스타일로 처리를 할 수 있게 한다.

아래 코드와 같이 for문을 사용하면 각 요소에 대해 무엇을 할 것인가?(알고리즘)컨테이너에서 데이터를 어떻게 가져올 것인가?(데이터 처리) 를 혼합해서 작성해야 한다.

for(int i = 0; i < numbers.size(); ++i) { // 데이터를 어떻게 가져올 것인가 ?
    numbers[i] *= 2; // 알고리즘
}

하지만 for_each()를 사용하면 데이터 처리는 컨테이너에 위임하고, 알고리즘 x2만을 집중해서 처리할 수 있다.

std::for_each(numbers.begin(), numbers.end(), [](double& num)) {
    num *= 2;
}

이렇게 람다식을 적용하면 데이터와 알고리즘의 책임이 분리되어 코드의 유지보수성이 높아진다.

동일한 코드 패턴의 재사용성

반복 작업에 대해 동일한 패턴을 재사용 할 수 있다. 예를 들어 여러 vectorlist를 처리할 때, 코드를 반복해서 작성하지 않고 동일한 패턴으로 쉽게 적용 할 수 있다.

void print(double i)
{
    std::cout << i << ", ";
}

std::vector<double> nums1 = {1.0, 2.0, 3.0};
std::vector<double> nums2 = {11.0, 12.0, 13.0};

std::for_each(nums1.begin(), nums1.end(), print);
std::for_each(nums2.begin(), nums2.end(), print);

이와 같이 작성하면 코드 중복을 줄이고 같은 패턴의 작업을 효율적으로 처리할 수 있다. 필요에 따라 람다식이나 함수 객체로 바꿔 줄 수 있다.

모든 iterator 사용 가능

계속해서 예를 들고 있는 vector뿐만 아니라 [[list]], [[set]], [[map]] 등 다양한 컨테이너에서 사용 가능하다.

직관적인 의미 전달

코드의 의미를 직관적으로 전달할 수 있는 장점이 있다. for문은 순회를 직접 제어하는 명령형 프로그래밍 스타일로 코드가 복잡해질 수 있지만, for_each각 요소에 대해 어떤 작업을 할지 라는 개념을 쉽게 표현할 수 있다.

std::for_each(numbers.begin(), numbers.end(), print);

이 코드는 vector의 각 요소를 print함수로 출력한다. 라는 적을 직관적으로 이해 할 수 있다.

-끝-

728x90
728x90

오늘의 포스팅은 수원 성균관대학교 인근에 위치한 일월수목원

주말에는 차량이 꽤 많으니 주차가 어렵다면 빠르게 성균관대학교에 주차하고 가는 것을 추천한다.


일월수목원은 부담스럽지 않은 입장료가있다. 
수원 시민인 경우 성인 2,000원, 청소년 1,500, 미취학 1,000원
일반시민 성인 4,000원, 청소년 2,500, 미취학 1,500원
다자녀인 경우는 성인 1,000원 청소년, 미취학 500원이다.

처음에는 입장료가 왜 이렇게 싸지?라는 생각을 했는데 들어가 보니 정말 적당한 입장료라는 생각이 들었다.



둘 다 주소지가 인천으로 되어있는 신분증이라 당황했지만 안내표시에 도민카드로 인증이 가능하다는 안내가 있었다.

경기똑 D 어플 설치

건물안에 들어서면 키오스키도 있다. 


입장권 받고 입장! 
(건물 안에 성균관대학교 주차장 이용안내도 있다.)

 

실내에 들어서자마자 창문너머로 수목원이 보인다. 내부는 넓고 깔끔하다. 화장실도 깔끔

 

 

들어가서 좌측은 커피숍과 출구가 있고 우측으로 꽃집과 수목원에 입장할 수 있는 게이트가 있다.
화장실은 실내, 수목원 내부에 모두 있다.

 

아래사진은 수목원 사진이다. 사실 딱히 볼 건 없다 :)


한 바퀴 다 도는데 30분에서 1시간? 정도 소요되는 것 같다. 그렇게 넓지 않고 특별히 볼 게 없어서 가볍게 산책하고 나와서 카페로 향했다.

 

카페에 앉아서 바라본 수목원 풍경~~~ 나쁘지않다.

 

 

카페 메뉴판은 아래 그림 참고

 

우리는 아아 두 잔 주문했다.

 

다 마시고 나왔더니 입장 종료
주차는 주차정산기에서 주차. 얼마 나왔더라.. 흠 

일월수목원, 야간개장이 있다고 하니 여름철 야간개장때 한번 와봐야겠다.

728x90
728x90

옵시디언에서 이미지 파일을 드래그해서 추가하면 메모파일이 있는 경로에 이미지가 함께 저장된다. 이게 너무 보기싫어서 이미지를 .md파일에 포함시켜서 저장하는 방법을 찾다가 Base64로 전환하고 전환된 코드를 추가하는 방법이 있다는걸 알게됬다.

구글에서 Base64 Encoder라고 검색하면 많은 온라인 인코더 사이트가 나오지만 난 개인적으로 아래 홈페이지 추천! 깔끔해보인다.

https://www.base64-image.de/

 

Base64 Image Encoder

show code opens a modal with image preview, usage examples, image width & height, ... copy image copies this base64 code to your clipboard: data:image/jpeg;base64,/9j/4AA... copy css copies this base64 code to your clipboard: url('data:image/jpeg;base64,/9

www.base64-image.de

 

 

여기에 이미지를 올리면 Base64코드로 변환해준다. 

 

우측에 Show code를 누르면 변환된 Base64 코드가 나온다. For use in <img> elements: 아래 있는 코드르 복사하면 된다. copy to clipboard를 누르면 복사가 된다. 

 

옵시디언으로 돌아가서 코드를 입력해주면된다.

![이미지 설명](Base64 코드)

[] 괄호안에 이미지 설명을 써주고 () 괄호안에 복사한 코드를 붙여넣기 하면 끝이다. 

 

 

728x90

+ Recent posts