본문 바로가기
C언어/쉽게 풀어쓴 C언어 EXPRESS 개정4판

[7下] 쉽게 풀어쓴 C언어 EXPRESS 개정 4판 7장 PROGRAMMING (13~21번)

by EATSTAR 2023. 10. 1.
반응형

[ 1 ~ 6번 ]

 

[7上] 쉽게 풀어쓴 C언어 EXPRESS 개정 4판 7장 PROGRAMMING (1~6번)

[ 7 ~ 12번 ] [7中] 쉽게 풀어쓴 C언어 EXPRESS 개정 4판 7장 PROGRAMMING (7~12번) [ 1 ~ 6번 ] [7上] 쉽게 풀어쓴 C언어 EXPRESS 개정 4판 7장 PROGRAMMING (1~6번) [ 7 ~ 12번 ] (준비중) [ 13 ~ 18번 ] (준비중) * 본문은 Microso

eatstar.tistory.com

 

[ 7 ~ 12번 ]

 

[7中] 쉽게 풀어쓴 C언어 EXPRESS 개정 4판 7장 PROGRAMMING (7~12번)

[ 1 ~ 6번 ] [7上] 쉽게 풀어쓴 C언어 EXPRESS 개정 4판 7장 PROGRAMMING (1~6번) [ 7 ~ 12번 ] (준비중) [ 13 ~ 18번 ] (준비중) * 본문은 Microsoft Visual Studio 2022 버전 17.6.4를 사용하였으므로 다른 버전의 비쥬얼 스

eatstar.tistory.com

 

* 본문은 Microsoft Visual Studio 2022 버전 17.7.4를 사용하였으므로 다른 버전의 비쥬얼 스튜디오나 다른 C언어 작동 프로그램으로 작동할 경우 오류가 생길 수 있음을 양지해주세요.

13. (1+2+3+...+n)가 10000을 넘지 않으면서 가장 큰 값과 그 때의 n값을 구하라. (무한 루프와 break 이용 / HARD)

1부터 140까지의 합이 9870입니다.
문제 의도
i를 사용하여 n번째를 설정할 수 있는가?
또한 sum이 10000이 넘었을 때 반복문을 중지하고 sum-i를 통해 넘기 직전의 값을 호출할 수 있는가?
그리고 i--으로 몇 번째인지 정확히 파악할 수 있는가?
#include <stdio.h>

int main(void) {
	int sum = 0;
	int i = 1;
	
	while (1) {
		sum += i;
		i++;

		if (sum > 10000) {
			i--;
			sum -= i;
			printf("1부터 %d까지의 합이 %d입니다", i-1, sum);
			exit(0);
		}
	}

	return 0;
}
코드 설명
무한 반복 루프를 while(1)로 설정한다.
그리고 sum에 i를 더해 나가고 i도 i++를 통해 1씩 늘려 나간다.
sum이 10000이 넘는 시점에서 if 위의 연산을 무효화시켜주고 합을 출력한다.
break를 써서 한 번에 빠져나올 수 없기 때문에 exit(0)를 사용했으나, goto 문으로 return 앞에 end:를 생성해도 된다.

14. 피보나치 수열은 다음과 같이 정의되는 수열이다. (반복 루프 / HARD)

피보나치 수열에서는 앞의 2개의 원소를 합하여 뒤의 원소를 만든다. 피보나치 수열은 컴퓨터에서도 탐색 문제 등에 사용되기도 한다. 피보나치 수열을 생성하여 출력하는 프로그램을 작성하여보자.

몇번째 항까지 구할까요? 10
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55,
문제 의도
[전형적 순환 문제] 문제에 제시된 식 처럼, f0, f1을 각각 0과 1로 정의하고, 그 뒤에 것을 전전 수와 이전 수의 합으로 나타내는 것을 순환적으로 나타낼 수 있는가? 
#include <stdio.h> 

int main(void) {
	int a = 0;
	int b = 1;
	int c;
	int num;

	printf("몇항까지 구할까요? ");
	scanf_s("%d", &num);

	for (int i = 1; i <= num; i++) {
		if (i == 1) {
			printf("0, ");
		}
		if (i == 2) {
			printf("1, ");
		}
		else {
			c = a + b;
			a = b;
			b = c;

			printf("%d, ", c);
		}
	}

	return 0;
}
코드 설명
a와 b를 각각 0과 1로 정의하고, c에 더한다. 그리고 a에 b를 대입하고 b에 c를 대입하여
num(항의 수)이 끝날 때까지 계속 반복한다.

15. 서로 다른 n개에서 r개를 택하여 일렬로 나열하는 방법의 수를 순열이라고 하고, nPr로 표시한다. 순열은 다음과 같은 식을 이용하여 구할 수 있다. 순열을 구하는 프로그램을 작성하라. n과 r은 사용자가 입력하라 수 있도록 하라. (반복 구조에서 반복 횟수 지정 / HARD)

n의 값: 10
r의 값: 3
순열의 값은 720입니다.
문제 의도
주어진 식과 같이 n이 n-r-1이 될때까지 for문을 사용해 수를 반복해서 곱할 수 있는가?
#include <stdio.h>

int main(void) {
	int n = 0;
	int r = 0;
	int i = 0;
	int sum = 1;

	printf("n의 값: ");
	scanf_s("%d", &n);
	printf("r의 값: ");
	scanf_s("%d", &r);

	for (i = n; i >= (n-r+1); i--) {
		sum *= i;
	}

	printf("순열의 값은 %d입니다.", sum);

	return 0;
}
코드 설명
이 문제는 전체적인 구성은 간단하지만, for의 범위가 중요하다.
for의 범위가 교재 힌트에는 n-r-1로 나와있지만 실제로는 n-r+1로 설정해야 한다. (also i > n-r) 

16. 사용자가 입력한 특정한 정수의 자리수를 반대로 출력하는 프로그램을 작성하라. 예를 들어서 사용자가 정수 1206을 입력하였다면 6021이 출력되어야 한다. do...while 문을 사용하여 보라. (반복 루프와 수치 연산 / HARD)

정수를 입력하시오: 1206
6021
문제 의도
do ... while 문을 사용하여 정수를 거꾸로 표시할 수 있는가?
#include <stdio.h>

int main(void) {
    int num = 0;
    int div = 1;
    int sum = 0;
    int tmp = 0;

    printf("정수를 입력하시오: ");
    scanf_s("%d", &num);

    do {
        tmp = num % 10;
        sum += tmp * (1000 / div);
        div *= 10;
        num /= 10;
    } while (div <= 1000);

    printf("%d", sum);

    return 0;
}
코드 설명
num은 사용자의 정수 입력을 저장한다. div은 숫자를 역순으로 배치하기 위해서는 더할 때 10씩 자릿수를 줄여야 하므로 필요하다. sum은 최종적으로 더하는 곳이고, tmp는 sum의 이전 단계로, 임시로 수가 머무르는 곳이다.
범위는 div가 1000일 때까지만 한다. (do-while이라 헷갈릴 수는 있지만 1번째가 div 10, 2번쨰가 div 100 3번쨰가 div 1000, 그리고 4번째가 div 10000이므로 범위를 이렇게 설정한다. 물론 div < 10000도 가능할 것이다. div 1000이라는 범위는 일반적인 while 문을 구성할 때의 범위로 간편화되어있다.)
일단 tmp에 숫자의 첫째자리를 판별한다. 그리고 그 tmp를 1000/div로 곱하는데, div가 1이므로 1000을 곱해 sum의 천의 자리 수에 들어간다. div를 10 곱해주고, num을 10 나눠 3자리 수로 나눈다. 그리고 그 num의 마지막 자리 수, 즉 처음의 십의 자리 수를 %10 하여 십의 자리 수를 구하고.. 이러한 과정을 반복한다.
이 코드는 4자리 숫자로 가정했으므로 개선의 여지가 있다.

17. 앞장에서 간단한 정수 계산기를 만들어본 적이 있다. 이 계산기 프로그램에 메뉴를 추가하도록 한다. 다음과 같은 메뉴를 화면에 출력하고 사용자가 메뉴 중에서 하나를 선택할 때까지 반복을 계속한다. 만약 사용자가 A, S, M, D, Q가 아닌 다른 문자를 입력하면 "연산을 선택하시오:" 메시지를 계속해서 출력한다. 하나의 메뉴가 선택되면 해당되는 연산을 실행하고 다시 메뉴를 선택할 수 있도록 하라. (do-while 반복문 / HARD)

*****************
A---- Add
S---- Subtract
M---- Multiply
D---- Divide
Q---- Quit
*****************
연산을 선택하시오:A
두수를 공백으로 분리하여 입력하시오: 10 20
30
문제 의도
적절하게 계산기를 제작할 수 있는가?
#include <stdio.h>
#include <stdlib.h>

int main(void) {
    char option;
    int num1 = 0;
    int num2 = 0;
    int sum = 0;

    printf("*****************\n"
        "A----Add\n"
        "S----Subtract\n"
        "M----Multiply\n"
        "D----Divide\n"
        "Q----Quit\n"
        "*****************\n");
    do {
        printf("연산을 선택하시오:");
        scanf_s("%c", &option); 

        switch (option) {
        case 'A':
            printf("두 수를 공백으로 분리하여 입력하시오: ");
            scanf_s("%d %d", &num1, &num2);
            sum = num1 + num2;
            printf("%d\n", sum);
            break;
        case 'S':
            printf("두 수를 공백으로 분리하여 입력하시오: ");
            scanf_s("%d %d", &num1, &num2);
            sum = num1 - num2;
            printf("%d\n", sum);
            break;
        case 'M':
            printf("두 수를 공백으로 분리하여 입력하시오: ");
            scanf_s("%d %d", &num1, &num2);
            sum = num1 * num2;
            printf("%d\n", sum);
            break;
        case 'D':
            printf("두 수를 공백으로 분리하여 입력하시오: ");
            scanf_s("%d %d", &num1, &num2);
            sum = num1 / num2;
            printf("%d\n", sum);
            break;
        case 'Q':
            exit(0);
        default:
            printf("다시 입력하세요.\n");
        }
    } while (sum == 0);

    return 0;
}
코드 설명
속았다. do-while 문을 쓰는 것처럼 교재에 나와있지만 답지는 그냥 while문과 if문을 썼다.
아무튼, 코드만 봐도 간단한 switch문 계산기 임을 알 수 있다.
<stdlib.h>는 exit 함수를 위해 추가했다.
다음의 교재 답지와 같이, if 문으로도 쉽게 구성 가능하다.
#include <stdio.h>

int main(void)
{
	char op;
	int x, y;

	while(1){
		printf("*****************\n");
		printf("A---- Add \n");
		printf("S---- Subtract \n");
		printf("M---- Multiply \n");
		printf("D---- Divide \n");
		printf("Q---- Quit \n");
		printf("*****************\n");
		printf("연산을 선택하시오:");
		scanf(" %c", &op);
		if( op == 'Q' ) 
			break;
		printf("두수를 공백으로 분리하여 입력하시오: ");
		scanf("%d %d", &x, &y);

		if( op == 'A' )
			printf("%d \n", x + y);
		else if( op == 'S' )
			printf("%d \n", x - y);
		else if( op == 'M' )
			printf("%d \n", x * y);
		else if( op == 'D' )
			printf("%d \n", x / y);
		else 
			printf("지원되지 않는 연산자입니다. \n");
	}
	return 0;
}
한번 화면을 클리어할 것도 아니면서 while문을 너무 광범위하게 썼다.
그러나 나의 switch 문보다는 간단하다(..)

18. 사용자로부터 n을 입력받아서 조화 수열의 합을 표시하는 프로그램을 C로 작성해보자. 조화 수열은 각 항의 역수가 등차 수열을 이루는 수열로서 각 항은 점차 작아져서 0에 한없이 가까워지지만, 그 역수의 합은 무한대가 된다고 알려져 있다. 사실일까? 컴퓨터로 천만개까지 계산해보자.

항의 개수: 10000000
수열의 합=16.695311
문제 의도
for문을 이용해 등차 수열을 많이 반복하여 더할 수 있는가?
#include <stdio.h>

int main(void) {
	int num = 0;
	int i = 0;
	double sum = 0;

	printf("항의 개수: ");
	scanf_s("%d", &num);

	for (i = 1; i <= num; i++) {
		sum += 1.0 / i;
	}
	printf("수열의 합=%lf", sum);

	return 0;
}
코드 설명
상대적으로 쉬운 코딩이다. 사용자가 입력한 num까지 식대로 더하면 된다.
소수점을 나타내야 하므로 double을 쓰는 것에 유의하자.

19번 문제는 난해하므로 교재 답지로 대체한다.

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <math.h>
#include <stdlib.h>

int main(void) {

    srand(time(NULL));
    int niter, inside_dots = 0;
    double x, y, z, pi;

    printf("반복횟수:  ");
    scanf_s("%d", &niter);

    inside_dots = 0;

    for (int i = 0; i < niter; i++) {
        x = (double)rand() / RAND_MAX;
        y = (double)rand() / RAND_MAX;
        z = x * x + y * y;
        if (z <= 1) inside_dots++;
    }
    pi = (double)inside_dots / niter * 4;
    printf("파이 = %lf\n\n", pi);
    return(0);
}

20,21번은 나중에..

반응형