Chapter 02 문제

김민성·2022년 7월 11일
post-thumbnail

문제 02-1 [참조자 기반의 Call-by-reference 구현]

문제 1

참조자를 이용해서 다음 요구사행에 부합하는 함수를 각각 정의하여라.
-> 인자로 전달된 int형 변수의 값을 1씩 증가시키는 함수
-> 인자로 전달된 int형 변수의 부호를 바꾸는 함수

#include <iostream>
using namespace std;

void IncreOne(int &num) {
    num++;
}

void InverSign(int &num) {
    num *= -1;
}

int main(void) {
    int val=20;
    IncreOne(val);
    cout<<val<<endl;

    InverSign(val);
    cout<<val<<endl;
    return 0;
}
21
-21

위의 코드를 분석해보자.

void InverSign(int &num) {
    num *= -1;
}

이는 인자로 전달된 int형 변수의 값을 1씩 증가시키는 함수이다.

void InverSign(int &num) {
    num *= -1;
}

이는 인자로 전달된 int형 변수의 부호를 바꾸는 함수이다.

val이라는 int형 변수를 선언하고 각각의 함수를 호출하니 위와 같은 실행결과가 나온다.

위의 코드는 교재에 있던 코드이며, 나는 아래와 같이 작성했었다.

#include <iostream>
using namespace std;

void RefRetFunOne(int &ref1) {
    ref1++;
}

void RefRetFunTwo(int &ref2) {
    ref2 = ref2*(-1);
}

int main(void) {
    int a1 = 1;
    int b1 = 1;
    RefRetFunOne(a1);
    RefRetFunTwo(b1);

   
    cout <<"a1: "<<a1<<endl;
    cout <<"b1: "<<b1<<endl;
    return 0;
}

사람마다 코드를 짜는 방식이 다르니 참고하길 바란다.

문제 2

앞서 소개한 예제 RefSwap.cpp의 SwapByRef2 함수를 다음의 형태로 호출하면 컴파일 에러가 발생한다.
SwapByRef2(23, 45);
컴파일 에러가 발생하는 이유가 무엇인지 설명해보자.

매개변수의 선언위치에 참조자가 선언되었다. 그런데 참조자는 상수를 참조할 수 없기 떄문에 매개변수의 인자로는 반드시 변수가 등장해야한다. 그래서 상수를 전달하는 SwapByRef2 함수의 호출에는 컴파일 에러가 발생한다.

문제 3

문제의 제시에 앞서 먼저 다음 코드를 보자.
int main(void) {
int num1 = 5;
int ptr1 = &num1;
int num2 = 10;
int
ptr2 = &num2;
. . . .
}
위의 코드를 보면 ptr1과 ptr2가 각각 num1과 num2를 가리키고 있다. 이 때 ptr1과 ptr2를 대상으로 다음과 같이 함수를 호출하고 나면,
SwapPointer(ptr1, ptr2);
ptr1과 ptr2가 가리키는 대상이 서로 바뀌도록 SwapPointer 함수를 정의해보자.

ptr1과 ptr2가 가리키는 대상이 서로 바뀌도록 SwapPointer 함수를 정의하려면 받는 인자가 ptr1과 ptr2의 참조자이어야 한다. 그러므로 아래와 같다.

void SwapPointer(int *(&pref1), int *(&pref2)) {
    int * ptr =pref1;
    pref1=pref2;
    pref2=ptr;
}

이를 바탕으로 전체 코드를 작성하면 다음과 같다.

#include <iostream>
using namespace std;

void SwapPointer(int *(&pref1), int *(&pref2)) {
    int * ptr =pref1;
    pref1=pref2;
    pref2=ptr;
}

int main(void) {
    int num1 = 5;
    int *ptr1 = &num1;

    int num2 = 10;
    int *ptr2 = &num2;

    cout<<*ptr1<<endl;
    cout<<*ptr2<<endl;

    SwapPointer(ptr1, ptr2);
    
    cout<<*ptr1<<endl;
    cout<<*ptr2<<endl;
    return 0;
}
5
10
10
5

문제 02-2 [const 포인터와 const 참조자]

문제 1

const 포인터에 대한 복습을 겸할 수 있는 문제를 제시하겠다. 다음의 상수선언을 보자.
const int num = 12;
포인터 변수를 선언해서 위 변수를 가리키게 해보자. 그리고 이 포인터 변수를 참조하는 참조자를 하나 선언하자. 마지막으로 이렇게 선언된 포인터 변수와 참조자를 이용해서 num에 저장된 값을 출력하는 예제를 완성해보자.

#include <iostream>
using namespace std;

int main(void) {
    const int num = 12;
    const int *ptr = &num;
    const int *(&ref) = ptr;

    cout<< *ptr <<endl;
    cout<< *ref <<endl;
    return 0;
}
12
12

상수화된 num을 가리키는 포인터 변수, 그리고 이 포인터 변수를 참조하는 참조자를 위와 같이 선언할 수 있다.

문제 02-3 [구조체에 대한 new & delete 연산]

문제 1

구조체에 대한 복습을 겸할 수 있는 문제를 제시하겠다. 2차원 평면상에서의 좌표를 표현할 수 있는 구조체를 다음과 같이 정의하였다.
typedef struct __Point {
int xpos;
int ypos;
}Point;
위의 구조체를 기반으로 두 점의 합을 계산하는 함수를 다음의 형태로 정의하고(덧셈결과는 함수의 반환을 통해서 얻게 한다).
Point& PntAdder(const Point &p1, const Point &p2)
임의의 두 점을 선언하여 위 함수를 이용한 덧셈연산을 진행하는 main 함수를 정의해보자. 단, 구조체 Point 관련 변수의 선언은 무조건 new 연산자를 이용해서 진행해야 하며, 할당된 메모리 공간의 소멸도 철저해야 한다. 참고로 이 문제의 해결을 위해서는 다음 두 질문에 답을 할 수 있어야 한다.

  • 동적할당한 변수를 함수의 참조형 매개변수의 인자로 어떻게 전달해야 하는가?
  • 함수 내에 선언된 변수를 참조형으로 반환하려면 해당 변수는 어떻게 선언해야 하는가?

구조체에 있는 xpos(x좌표), ypos(y좌표)를 이용해 함수를 정의해야 한다. new 연산자를 이용해 Point 변수를 선언하고, 이에 해당하는 xpos, ypos의 값을 보내줘야 한다. 그러므로 다음과 같이 코드를 작성할 수 있다.

#include <iostream>
using namespace std;

typedef struct __Point {
    int xpos;
    int ypos;
}Point;

Point& PntAdder(const Point &p1, const Point &p2) {
    Point * pptr = new Point;
    pptr->xpos = p1.xpos+p2.xpos;
    pptr->ypos = p1.ypos+p2.ypos;
    return *pptr;
}

int main(void) {
    Point *pptr1=new Point;
    pptr1->xpos=3;
    pptr1->ypos=30;

    Point *pptr2=new Point;
    pptr2->xpos=7;
    pptr2->ypos=70;

   Point &pref=PntAdder(*pptr1, *pptr2);
   cout<<"["<<pref.xpos<<", "<<pref.ypos<<"]"<<endl;

   delete pptr1;
   delete pptr2;
   delete &pref;
   return 0;
}
[10, 100]

문제 02-4 [C++의 표준함수 호출]

문제 1

다음 표준함수를 호출하는 예제를 만들되, C++의 헤더를 선언해서 만들어보자. 그리고 예제의 내용은 상관이 없지만, 아래의 함수들을 최소 1회 이상 호출해야 한다. 참고로 다음 함수들은 C언어의 경우 <string.h>에 선언되어 있다.

  • strlen 문자열의 길이 계산
  • strcat 문자열의 뒤에 덧붙이기
  • strcpy 문자열 복사
  • strcmp 문자열의 비교

다음과 같은 함수들을 활용하기 위해 다음과 같이 문자열을 선언하자.

char *str1 = "ABC 123 ";
char *str2 = "DEF 456 ";
char str3[50];

str1, str2 문자열의 길이를 계산하고 출력하기 위해 strlen을 이용해 다음과 같이 작성했다.

cout<<strlen(str1)<<endl;
cout<<strlen(str2)<<endl;

str1을 str3에 복사하기 위해 strcpy을 이용해 다음과 같이 작성했다.

strcpy(str3, str1);

이어서 str3 뒤에 str2를 덧붙이기 위해 strcat을 이용해 다음과 같이 작성했다.

strcat(str3, str2);

str1과 str2를 서로 같은지 다른지 비교하기 위해 strcmp를 이용해 다음과 같이 작성했다.

  if(strcmp(str1, str2)==0)
        cout<<"문자열이 같다."<<endl;
    else
        cout<<"문자열이 같지않다."<<endl;

위의 코드들을 종합해보자.

#include <iostream>
#include <cstring>
using namespace std;

int main(void) {
    char *str1 = "ABC 123 ";
    char *str2 = "DEF 456 ";
    char str3[50];

    cout<<strlen(str1)<<endl;
    cout<<strlen(str2)<<endl;
    strcpy(str3, str1);
    strcat(str3, str2);
    cout<<str3<<endl;

    if(strcmp(str1, str2)==0)
        cout<<"문자열이 같다."<<endl;
    else
        cout<<"문자열이 같지않다."<<endl;
    return 0;
}
8
8
ABC 123 DEF 456 
문자열이 같지않다.

문제 2

다음 세 함수를 이용해서 0이상 100미만의 난수를 총 5개 생성하는 예제를 만들되, C++의 헤더를 선언해서 작성해보자. 참고로 C언어의 경우 time 함수는 <time.h>에 선언되어 있고, rand 함수와 srand 함수는 <stdlib.h>에 선언되어 있다.
rand, srand, time

C++의 헤더로 선언하려면 다음과 같이 선언할 수 있다.

#include <cstdlib>
#include <ctime>

난수를 생성하기 위해서는 srand함수, time함수, rand함수를 호출해야 한다. 그러므로 코드를 작성하면 다음과 같다.

#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;

int main(void) {
    srand(time(NULL));
    for(int i=0; i<5; i++)
        printf("Random number #%d: %d\n", i, rand()%100);
    return 0;
}
Random number #0: 90
Random number #1: 89
Random number #2: 63
Random number #3: 36
Random number #4: 15
profile
다양한 활동을 통해 인사이트를 얻는 것을 즐깁니다. 저 또한 인사이트를 주는 사람이 되고자 합니다.

0개의 댓글