C++/기초를 탄탄히 세워주는 C++ 프로그래밍 입문(황준하 저)

기초를 탄탄히 세워주는 C++ 프로그래밍 입문 1장 연습문제

꾸준함. 2017. 6. 20. 10:00

[1.1]

/*

2개의 double형 값(x, y)을 입력받고 두 값에 대한 사칙연산(+, -, *, /) 결과값을 출력해 보라.

실행 결과는 다음과 같다. y의 값은 0이 아니라고 가정하라

*/

#include <stdio.h>

 

int main(void)

{

        double num1, num2;

        printf("두개의 실수 입력:");

        scanf("%lf %lf", &num1, &num2);

       

        printf("%lf+%lf=%lf\n", num1, num2, num1 + num2);

        printf("%lf-%lf=%lf\n", num1, num2, num1 - num2);

        printf("%lf*%lf=%lf\n", num1, num2, num1 * num2);

        printf("%lf/%lf=%lf\n", num1, num2, num1 / num2);

        return 0;

}


[1.2]

/*

2개의 int형 값(x, y) scanf 함수를 사용하여 읽어 들이도록 한다.이때 x y보다 작다고 가정한다.

그리고 실행화면을 참고하여 x y 사이의 값들에 대한 제곱값과 나누기 3을 한값을 각각 출력해 보도록 합시다.

, 실행화면과 같이 각 출력값들에 대해 적절한 크기의 필드를 지정하고 오른쪽 정렬로 출력하도록 한다.

나누기 3을 한 값의 결과는 실수로 처리될 수 있어야하며 소수점 이하 첫 번째 자리까지만 출력하도록 한다.

*/

#include <stdio.h>

 

int main(void)

{

        int x, y;

        printf("두개의 정수 입력:(, 첫번째 정수가 두번째 정수보다 작다)");

        scanf("%d %d", &x, &y);

        while (x >= y)

        {

               printf("첫번째 정수가 두번째 정수보다 작아야합니다\n");

               printf("다시 입력:");

               scanf("%d %d", &x, &y);

        }

        for (int i = x; i <= y; i++)

        {

               printf("%d\t%d\t%.1f\n", i, i*i, (double)i / 3); //소수점 첫번째 자리까지 .1

        }

        return 0;

}


[1.3]

/*

10개의 원소를 가지는 int형 배열을 선언하고 각각 자신의 index의 제곱값으로 채운다.

그리고 화면 출력을 통해 제대로 채워졌는지 확인해 보도록 한다.

이 문제는 1차원 배열의 사용 방법을 연습하기 위한 문제이다

*/

#include <stdio.h>

 

int main(void)

{

        int arr[10]; //배열

       

        for (int i = 0; i < 10; i++)

        {

               arr[i] = i*i; //각각 자신의 index의 제곱값

        }

 

        for (int i = 0; i < 10; i++)

        {

               printf("%d ", arr[i]);

        }

        printf("\n");

        return 0;

}


[1.4]

/*

5 5열의 원소를 가지는 char형 배열을 선언하고 실행 결과와 같이 마름모 모양으로 '*'문자를 채워보도록 한다

마름모 이외의 영역은 공백 문자로 채우면 된다

*/

#include <stdio.h>

 

int main(void)

{

        for (int i = 0; i < 3; i++) //위 삼각형

        {

               int j = 2;

               while (i < j)

               {

                       printf(" "); //공백문자

                       j--;

               }

               for (int k = 0; k <= i*2; k++) //*문자

                       printf("*");

               printf("\n");

        }

        for (int i = 1; i >=0; i--) //아래 삼각형

        {

               int j = 2;

               while (i < j)

               {

                       printf(" "); //공백문자

                       j--;

               }

               for (int k = 0; k <= i*2; k++) //*문자

                       printf("*");

               printf("\n");

        }

        return 0;

}


[1.5]

/*

2개의 int형 변수를 선언하고 각각 1, 2로 초기화한다.

그리고 하나의 int형 포인터 변수를 선언하고 포인터 변수만을 사용하여 앞서 선언한 2개의 변수를 번갈아 가리키면서 각 변수의 값을 100 200으로 변경한다.

그리고 마찬가지로 포인터 변수만을 사용하여 각 변수의 값을 출력한다

*/

#include <stdio.h>

 

int main(void)

{

        int num1 = 1, num2 = 2; //각각 1, 2로 초기화

        int *ptr; //하나의 포인터 변수 선언

        printf("기존의 num1의 값은:%d\n", num1);

        ptr = &num1;

        *ptr = 100;

        printf("바뀐 num1의 값은:%d\n", *ptr);

       

        printf("기존의 num2의 값은:%d\n", num2);

        ptr = &num2;

        *ptr = 200; //변경

        printf("num2의 값은:%d\n", *ptr);

        return 0;

}


[1.6]

/*

int형 포인터 변수 하나를 만들고 이를 통해 10개의 원소를 가진 int형 배열을 동적으로 할당해본다.

그리고 int형 포인터 변수를 추가로 하나 더 만들도록 한다.

이제 새롭게 만든 포인터 변수만을 사용하여 동적으로 할당한 배열의 각 원소의 값을 무작위 값으로 채우고,

역시 두 번째 포인터 변수를 사용하여 배열의 값들을 화면에 출력한다.

이문 제를 통해 메모리 동적할당에 대해 연습하고 포인터 변수만을 가지고 배열을 자유롭게 다룰 수 있는지 확인한다

*/

#include <stdio.h>

#include <stdlib.h>

#include <time.h>

 

int main(void)

{

        int *ptr = (int*)malloc(sizeof(int) * 10);

        int *ptr2; //새로운 포인터 변수

 

        srand((unsigned)time(NULL));

        ptr2 = ptr;

        for (int i = 0; i < 10; i++)

               ptr2[i] = rand();

        for (int i = 0; i < 10; i++)

               printf("%d ", ptr2[i]);

        printf("\n");

        return 0;

}


[1.7]

/*

다음 프로그램의 출력 결과가 무엇인지 예상하고 왜 그런지 설명한다.

과연 예상한 대로 출력이 되는지 확인한다

*/

#include <stdio.h>

 

int main(void)

{

        int ary[3][2] = { {1, 2}, {3, 4}, {5, 6} };

        int(*pAry)[2] = ary;

 

        printf("%d\n", **pAry);

        printf("%d\n", *(*pAry + 1));

 

        pAry++;

        printf("%d\n", **pAry);

        printf("%d\n", *(*pAry + 1));

 

        pAry++;

        printf("%d\n", **pAry);

        printf("%d\n", *(*pAry + 1));

 

        return 0;

}

 


[1.8]

/*

두 개의 문자열(char*)을 매개변수로 전달받아 두 번째 문자열을 첫 번째 문자열 뒤에 추가하는 함수를 작성한다.

함수명은 StrCat으로 한다.

다음 main 함수의 실행결과를 참고하도록 한다.

, 첫번째 매개변수로 전달된 문자열의 버퍼(char 배열)는 두 번째 문자열까지 수용할만큼 충분한 크기를 확보하고 있다고 가정한다.

*/

 

#include <stdio.h>

#include <string.h>

 

void StrCat(char *str1, char *str2);

 

int main(void)

{

        char str1[100] = "C++ ";

        char *str2 = "Programming";

 

        StrCat(str1, str2);

 

        printf("str1:%s\n", str1);

 

        return 0;

}

 

void StrCat(char *str1, char *str2)

{

        int len = strlen(str1);

        str1[len] = 0; //\n을 지워준다

        memcpy(str1+len, str2, strlen(str2)); //주소값을 이용해 붙인다

}


[1.9]

/*

(예제 1.5)에서 x^y을 계산하는 power 함수를 구현하였다.

이번에는 이 함수를 재귀 함수(recursive function)로 구현한다.

재귀 함수는 특정함수 내에서 또 다시 그 함수를 호출하는 함수를 의미한다.

다음 예는 재귀함수를 사용하여 특정 문자열을 지정한 횟수만큼 출력하는 프로그램이다.

Prinmt 함수의 내부인 8라인에서 또 다시 Print 함수를 호출하고 있다.

이 때 count 1 감소시켜 호출함으로써 0에 도달할 경우 문자열 출력 및 Print 함수의 호출을 멈추게 된다

#include <stdio.h>

 

void Print(char *str, int count)

{

        if (count <= 0)

               return;

        printf("%s\n", str);

        Print(str, count - 1);

}

 

int main(void)

{

        Print("recursive function", 5);

 

        return 0;

}

*/

#include <stdio.h>

 

int power(int x, int y)

{

        if (y > 0)

               return x * power(x, y - 1); //재귀 함수

        else

               return 1;

}

 

int main(void)

{

        int a = 2;

        int b = 3;

        int result = power(a, b);

        printf("%d^%d:%d\n", a, b, result);

 

        a = 3;

        b = 4;

        result = power(a, b);

        printf("%d^%d:%d\n", a, b, result);

 

        return 0;

}

 


[1.10]

/*

다음 프로그램에서 Print 함수는 첫 번째 매개변수로 int형 배열을 받고 있다.

그런데 const 포인터로 선언하고 있다.

여기서 프로그래머가 const로 선언한 의도가 무엇인지 설명해본다

*/

#include <stdio.h>

 

void Print(const int *ary, int count)

//const로 선언한 이유: 전달받은 배열의 내용이 변하지 않도록 const로 선언하였다.

//const 키워드를 삭제하면 컴파일되지 않는 이유:ary1 배열이 const로 선언되었기 때문이다.

{

        int i;

 

        for (i = 0; i < count; i++)

               printf("%d ", ary[i]);

        printf("\n");

}

 

int main(void)

{

        const int ary1[3] = { 1, 2, 3 };

        int ary2[5] = { 4, 5, 6, 7, 8 };

 

        Print(ary1, 3);

        Print(ary2, 5);

 

        return 0;

}


[1.11]

/*

struct Point를 사용하여 다음과 같은 프로그램을 작성한다.

swap 함수를 작성하되 기존의 int형을 struct Point형으로만 대체하면 된다.

그 결과는 두 개의 구조체 변수의 값이 교체되는 것이며 int형일 때와 마찬가지로 실매개 변수의 값도 교체되어야 한다.

여기서 swap 함수는 생각하는 것보다 훨씬 간단하게 작성될 수 잇다는 것을 알아야 한다.

int형에 대한 swap과 내용 상 다를 바가 없다.

*/

#include <stdio.h>

 

struct Point

{

        int x;

        int y;

};

 

void Swap(struct Point &p1, struct Point &p2) //참조형 전달

{

        struct Point temp = p1;

        p1 = p2;

        p2 = temp;

}

 

int main(void)

{

        struct Point p1 = { 1, 2 };

        struct Point p2 = { 3, 4 };

        printf("구조체 p1:[%d, %d]\n", p1.x, p1.y);

        printf("구조체 p2:[%d, %d]\n", p2.x, p2.y);

 

        printf("변경 후\n");

        Swap(p1, p2);

        printf("구조체 p1:[%d, %d]\n", p1.x, p1.y);

        printf("구조체 p2:[%d, %d]\n", p2.x, p2.y);

        return 0;

}


[1.12]

/*

양방향 링크드 리스트를 사용하여 [그림 1.10]과 같은 트리를 만들어 본다.

노드로 추가될 데이터는 int형 변수이며 사용자로부터 5회 입력을 받아들인다.

각 입력 시마다 새로운 노드를 생성하고 현재 트리에 삽입하면 되는데 삽입 기준은 다음과 같다.

만약 추가해야 할 노드의 data 값이 root노드의 data 값보다 작다면 왼쪽으로 이동하고, 같거나 크다면 오른쪽으로 이동하도록 한다.

그리고 이동한 노드를 대상으로 동일한 과정을 반복하여 말단 노드까지 이동한 후 해당 위치에 삽입하면 된다.

마지막으로 트리 상의 가장 왼쪽 노드로부터 시작하여 오른쪽으로 이동하면서 차례로 해당 노드의 data 값을 출력한다.

출력 결과는 data 값들의 오름차순으로 출력되어야 한다.

*/

#include <stdio.h>

#include <time.h>

#include <stdlib.h>

 

typedef struct _node

{

        int data;

        struct _node *left; //왼쪽

        struct _node *right; //오른쪽

}Node;

 

void InorderTraverse(Node *Root) //중위순회

{

        if (Root == NULL)

               return;

 

        InorderTraverse(Root->left);

        printf("%d ", Root->data);

        InorderTraverse(Root->right);

}

 

int main(void)

{

        int i;

        Node *Root = NULL; //루트 노드

        Node *InitialRoot; //기존 루트노드

        Node *Parent = NULL; //부모 노드

        Node *Current;

 

        for (i = 1; i <= 5; i++)

        {

               //노드 생성

               Current = (Node*)malloc(sizeof(Node));

               Current->data = rand() % 10 + 1;

               printf("%d번째 데이터:%d\n", i, Current->data);

               Current->left = NULL;

               Current->right = NULL;

 

               if (Root == NULL)

               {

                       Root = Current;

                       printf("%d번째 노드 루트에 저장되었습니다\n", i);

                       InitialRoot = Root; //기존 루트노드 저장

                       continue;

               }

               while (1)

               {

                       Parent = InitialRoot;

                       printf("InitialRoot:%d\n", InitialRoot->data);

                       if (InitialRoot->data > Current->data)

                       {

                              if (InitialRoot->left) //왼쪽 데이터가 존재한다면

                                      InitialRoot = InitialRoot->left;

                              else //데이터 삽입

                              {

                                      InitialRoot->left = Current;

                                      printf("%d번째 데이터 왼쪽으로 갔습니다\n", i);

                                      break;

                              }

                       }

                       else

                       {

                              if(InitialRoot->right)

                                      InitialRoot = InitialRoot->right;

                              else

                              {

                                      InitialRoot->right = Current;

                                      printf("%d번째 데이터 오른쪽으로 갔습니다\n", i);

                                      break;

                              }

                       }

               }

               Parent = Current;

               InitialRoot = Root; //초기화

        }

 

        InorderTraverse(InitialRoot);

 

        return 0;

}

 


[1.13]

/*

다음 프로그램은 컴파일이 되지 않는 불완전한 프로그램이다.

또한 논리적으로 문제가 있는 프로그램이다.

Visual C++ 11.0을 사용하여 이 프로그램을 작성하고 디버깅해본다.

*/

#include <stdio.h>

 

struct Point

{

        int x, y;

};

 

struct Point GetSum(const struct Point *pAry, int count)

{

        int i;

        struct Point Po = { 0, 0 };

 

        for (int i = 0; i <= count; i++)

        {

               Po.x += pAry[i].x;

               Po.y += pAry[i].y;

        }

 

        return Po;

}

 

int main(void)

{

        //struct Point Ary[3] = { {1, 1}, {2, 2}, {3, 3}, {4, 4} }; //주석 처리 된 부분이 틀린 부분

        const struct Point Ary[4] = { {1,1}, {2,2}, {3,3}, {4,4} };

        struct Point PSum = GetSum(Ary, 3);

 

        printf("Sum:[%d, %d]\n", PSum.x, PSum.y);

 

        return 0;

}

 



개발 환경:Visual Studio 2017


지적, 조언, 질문 환영입니다! 댓글 남겨주세요~


[참고] 기초를 탄탄히 세워주는 C++ 프로그래밍 입문 황준하 저



반응형