관리 메뉴

공부 기록장 💻

C언어 Express 7장 Programming 심화 문제 추가 본문

# Language & Tools/C

C언어 Express 7장 Programming 심화 문제 추가

dream_for 2021. 1. 22. 23:42

 

 

1. 초기값 입력 받아 1씩 감소시키며 0이 될 때까지 반복하여 출력

(+1. for문 사용 / 2. while문 사용)

 

for문을 사용할 때엔 제어 변수의 초기값을 n으로 하여, 0이 될 때 까지 1씩 감소하는 i를 출력한다.

#include <stdio.h>

int main(void) {
	
	int n;

	printf("카운터의 초기값: ");
	scanf_s("%d", &n);

	for (int i = n;i > 0;i--)
		printf("%d ", i);
	printf("\n");
	
	return 0;
}

 

while문을 사용할 때엔 후위 연산자를 이용하여 n의 값을 1씩 감소시키도록 하여 n의 값을 출력한다.

#include <stdio.h>

int main(void) {
	
	int n;

	printf("카운터의 초기값: ");
	scanf_s("%d", &n);

	while (n > 0)
		printf("%d ", n--);
	printf("\a\n");
	
	return 0;
}

 

 

 

2. 정수를 입력받고, 1부터 해당 정수 사이의 모든 3의 배수의 합을 구하는 프로그램

 

#include <stdio.h>

int main(void) {
	
	int n, sum = 0;

	printf("정수 입력: ");
	scanf_s("%d", &n);

	for (int i = 1;i <= n;i++) {
		if (i % 3 == 0)
			sum += i;
	}

	printf("1부터 %d 사이의 모든 3의 배수의 합은 %d입니다.\n", n, sum);
	
	return 0;
}

 

어떤 숫자의 배수라는 뜻은, 그 수로 나누어 떨어지는 나머지가 0이라는 것임을 참고하면 된다.

합을 저장할 변수 sum의 초기값은 0이다.

 

 

 

 

 

 

 

 

3. 사용자가 입력한 정수의 모든 약수를 출력하는 프로그램

 

#include <stdio.h>

int main(void) {
	
	int n;

	printf("정수 입력: ");
	scanf_s("%d", &n);

	for (int i = 1;i <= n;i++) {
		if (n % i == 0)
			printf("%d ", i);
	}
	printf("\n");
	
	return 0;
}

 

해당 제어 변수가 약수라면, 입력받은 정수에 의해 나누어 떨어진다는 것을 참조하여 작성하면 된다.

 

 

 

4. 정수 입력 받아 해당 수의 높이만큼, 오른쪽 계단식으로 정렬된 별찍기 프로그램

 

#include <stdio.h>

int main(void) {
	
	int n;

	printf("정수 입력: ");
	scanf_s("%d", &n);

	for (int i = 1;i <= n;i++) {
		for (int j = 1;j <= n - i;j++)
			printf(" ");
		for (int k = 1;k <= i;k++)
			printf("*");
		printf("\n");
	}
	
	return 0;
}

 

 

 

 

 

 

중첩 for문을 사용한다. 

이런 별찍기 반복문 문제는 먼저 계단의 층 높이를 바깥 for문의 제어 변수를 이용해 식을 완성하고,

이후에 공백과 별의 개수의 변화를 살펴 이를 반복문 식으로 완성하면 조금 더 수월해진다.

보통은 제어 변수의 초기값을 0으로 두어 입력받은 정수까지 변수가 증가하도록 식을 세우는 경우가 있지만,

조금 복잡해지는 경우 각 계단의 층을 그대로 수로 (1~n) 사용하는 것이 안쪽 for문의 제어식을 세울 때 편하다고 생각해서

1부터 시작하는 편이다.

 

별찍기 문제는

무엇이 얼만큼 증가하고, 무엇이 얼만큼 감소하는지 판단하여,

이를 얼마나 간결하게 반복문의 식으로 작성하느냐가 관건이라 할 수 있겠다!

나는 반복문을 사용하면서부터 '아, 이래서 코딩할때 수학적 사고력이 필요하다는 거구나' 라는 생각을 했던 것 같다.

 

 

 

5. 정수를 입력 받아, 수가 하나씩 증가하며 왼쪽 계단식으로 정렬되어 출력되는 프로그램 

#include <stdio.h>

int main(void) {
	
	int n;

	printf("정수 입력: ");
	scanf_s("%d", &n);

	for (int i = 1;i <= n;i++) {
		for (int j = 1;j <= i;j++)
			printf("%d ", j);
		printf("\n");
	}
	
	return 0;
}

 

 

 

 

 

 

별찍기 문제와 다르게 이번엔 '숫자'를 출력하는 문제이다.

역시나 층의 높이는 바깥 for문의 제어 변수로 설정하고,

각 층에 출력되는 수는 안쪽 for문의 제어 변수를 이용한다.

살펴보면 1층(위에서부터)부터 차례대로 층이 높아지면서 출력되는 숫자 또한 같은 양상으로 증가하기 때문에

안쪽 for문의 제어변수가 1~증가하는층수 까지 증가하도록 반복문을 작성하면 된다.

 

 

 

 

6. 계산기 프로그램

 - do~while문 이용하여 메뉴 중 하나를 선택할 때까지 '연산을 선택하시오'를 반복 출력

 - 연산 실행 뒤 또 메뉴를 선택할 수 있도록 반복하기

 (A: Add, S: Subtract, M: Multiply, D: Divide, Q: Quit)

(+함수로 구현)

#include <stdio.h>

void menu();
int add(int x, int y);
int subtract(int x, int y);
int multiply(int x, int y);
int divide(int x, int y);

int main(void) {
	
	int x, y, result;
	char op;
	
	menu();
	while (1) {

		do {
			printf("연산을 선택하시오: ");
			scanf_s(" %c", &op);
		} while (op != 'A' && op != 'S' && op != 'M' && op != 'D' && op != 'Q');
		if (op == 'Q')break;

		printf("두 수를 공백으로 분리하여 입력: ");
		scanf_s("%d %d", &x, &y);

		switch (op) {
		case 'A': printf("%d\n", add(x, y));break;
		case 'S': printf("%d\n", subtract(x, y));break;
		case 'M': printf("%d\n", multiply(x, y));break;
		case 'D': printf("%d\n", divide(x, y));break;
		default:break;
		}
	}
	
	
	return 0;
}

void menu() {
	printf("*******************\n");
	printf("A---- Add\n");
	printf("S---- Subtract\n");
	printf("M---- Multiply\n");
	printf("D---- Divide\n");
	printf("Q---- Quit\n");
	printf("*******************\n\n");
};

int add(int x, int y) {
	return x + y;
}
int subtract(int x, int y) {
	return x - y;
}
int multiply(int x, int y) {
	return x * y;
}
int divide(int x, int y) {
	return x / y;
}

 

 

 

 

 

 

1) do~while문을 이용해서 무조건 한 번은 해당 문장이 실행되어 op 문자변수를 입력받도록 한다.

while(); 문장이 거짓이 될 때 ( =입력받은 op변수가 A, S, M, D, Q가 아닌 경우) 다시 반복하도록 코드를 작성한다.

 

2) 위 문장이 참으로 성립된 후, op변수가 만약 Q라면 전체 반복문을 빠져나가도록 설정. (while & break 문 사용)

 

 

 

 

7. 소수 찾는 프로그램

(+함수로 구현하고, 두 개의 정수를 입력 받아 그 사이의 소수를 모두 출력하도록)

 

#include <stdio.h>

void getPrime(int x, int y);

int main(void) {

	int x, y;

	printf("두 정수 입력 : ");
	scanf_s("%d %d", &x, &y);
	getPrime(x, y);

	return 0;
}

void getPrime(int x, int y) {
	
	int i, j;
	
	for (i = x;i <= y;i++) {
		for (j = 2;j < i;j++)
			if (i % j == 0)break;
		if (i == j)
			printf("%d ", i);
	}
	printf("\n");
}

 

 

 

 

 

 

소수를 구하기 위한 getPrime 함수를 작성한다.

이 함수에는 두 가지의 제어 변수가 존재함.

1) 입력받은 두 정수 사이의 숫자를 의미하는 바깥 for문의 제어변수 i

2) i가 소수인지 판별하기 위한 보조 제어변수 j

 

소수의 약수가 1과 자기 자신 뿐이라는 개념을 이용하여,

변수 i의 숫자를 2~(자기자신-1) 까지의 숫자로 나누어본다.

이 때, 왜 j는 i보다 1이 작아야 하느냐? 

안쪽 for문이 작동된 직후, i와 j가 같은 경우 소수로 판단하여 이 수를 출력하는 조건문이 나오기 때문.

 

j변수가 i보다 1 작은 경우, 한마디로 마지막으로 안쪽 for문이 실행되는 경우에는,

증감식으로 인해 j의 값이 i와 같아지고, 그 반복문은 실행하지 않고 다음 조건문으로 넘어가게 된다.

이 때 i와 j의 값이 같아졌다는 것은, i가 2부터 (j-1)까지 그 어떠한 수로도 나누어지지 않았다는 뜻이므로

소수로 판별되어 출력된다.

 

이 문제를 처음 마주했을때, 정말 어려웠다.

for문에서 각 제어변수의 증감문과, 제어식을 올바르게 이해하고 넘어가는 것이 중요하다는 것을 깨달았다.

프로그래밍 언어의 문법을 배울 땐, 정말 꼼꼼히 완벽하게 이해를 하는 것이 중요하다 !

 

 

 

 

 

8. (1+2+3+...+n)가 10000을 넘지 않으면서 가장 큰 값과 그 때의 n의 값 구하는 프로그램

 

#include <stdio.h>

int main(void) {

	int n=1, sum = 0;
    
	while (1) {
		sum += n;
		if (sum > 10000) break;
		n++;
	}
	n--;
	sum -= n;

	printf("1부터 %d까지의 합은 %d입니다.\n", n, sum);

	return 0;
}

 

 

 

 

 

while문을 이용해 작성하는 프로그램이다.

두 가지의 방법이 있는데, 첫번째는 무한 반복문 속에 break문을 추가하는 방법이고,

두번째는 조건식을 이용해 참, 거짓을 판별하여 반복문을 제어하는 방법이다.

개인적으로 반복문을 처음 접하여 이 문제를 풀 때 매우 헷갈렸다.

논리적 사고력이 부족한 나에게 두 변수를 동시에 생각하는 연습을 하도록 도와준 문제라고 생각한다.

break문의 위치와 1씩 증가하는 변수 n, 변화하는 n의 값을 저장하는 변수 sum의 증감을 잘 파악하여서

while문이 끝난 뒤에, sum과 n의 값을 다시 감소시키는 것이 관건이다.

 

#include <stdio.h>

int main(void) {

	int n=1, sum = 0;

	while (sum < 10000) {
		sum += n;
		n++;
	}
	n--;
	sum -= n;
	n--;

	printf("1부터 %d까지의 합은 %d입니다.\n", n, sum);

	return 0;
}

 

무한 루프를 사용하는 방법을 잘 몰랐던 나는,

이 두번째 방법을 처음에 사용했고 계속 올바른 값이 나오지 않아 애를 썼었다.

n의 값이 마지막에 증가되기 때문에 

반복문이 끝난 후 증가된 값을 다시 감소시키는 과정이 어렵게 다가왔던 것이 기억이 난다.

 

 

 

9. 실수의 거듭 제곱값을 계산하는 프로그램

(+실수 r과 거듭 제곱 횟수인 정수 n을 매개변수로 하여 결과값 실수를 반환하는 함수 추가 작성)

 

#include <stdio.h>

double power(int r, int n);

int main(void) {
	
	double r;
	int n;

	printf("실수의 값: ");
	scanf_s("%lf", &r);
	printf("거듭제곱 횟수: ");
	scanf_s("%d", &n);

	printf("결과값은 %f\n", power(r, n));

	return 0;
}

double power(int r, int n) {
	int result = 1;
	
	for (int i = 0;i < n;i++)
		result *= r;

	return result;
}

 

실수 r이 n번만큼 거듭해서 곱해져야 하기 때문에, 

for 반복문을 사용하면 된다.

변수 result의 초기값을 1로 설정하고 n번만큼 반복문이 실행되어 r이 반복해서 곱해지도록 작성한다.

 

 

 

10. 1부터 n까지 각 수의 제곱을 더하여 계산하는 프로그램

(+위와 같은 방법으로 별도의 함수로 작성)

 

#include <stdio.h>

int sumofDouble(int n);

int main(void) {
	
	int n;

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

	printf("1부터 %d의 제곱의 합의 결과값은 %d\n", n, sumofDouble(n));

	return 0;
}

int sumofDouble(int n) {
	int sum = 0;
	
	for (int i = 1;i <= n;i++)
		sum += i * i;

	return sum;
}

 

이번엔 변수 sum의 초기값을 0으로 하고,

반복문의 초기식의 i값은 1로, 그리고 조건식은 i가 n 이하일 때까지로 설정하도록 한다.

그리고 i의 제곱의 값의 합을 저장하기 위해 적절한 식을 작성해준다.

 

 

 

 

11. 사용자가 입력한 특정한 정수의 자리수를 반대로 출력하는 프로그램 작성

 

#include <stdio.h>

int main(void) {

	int n;

	printf("정수 입력: ");
	scanf_s("%d", &n);

	do {
		printf("%d", n % 10);
		n /= 10;
	} while (n > 0);

	printf("\n");

	return 0;
}

 

 

 

반복문에서 빠질 수 없는 문제인 것 같다. 수를 입력받아 반대로 출력하는 문제!

나머지/나눗셈의 원리를 잘 이해하면 쉽다.

처음에는 많이 당황케 한 유형의 문제이지만, 원리를 이해하다 보면 익숙해지고 더 어려운 문제를 만나도 쉽게 풀 수 있게 되는 것 같다.

어떤 수를 10으로 나눈 나머지를 출력하고, 남은 몫을 변수에 다시금 저장하는 방법이다.

 

 

#include <stdio.h>

int main(void) {

	int n;

	printf("정수 입력: ");
	scanf_s("%d", &n);

	do {
		printf("n = %d , %d %% 10 = %d\n", n, n, n % 10);
		n /= 10;
	} while (n > 0);

	printf("\n");

	return 0;
}

 

 

 

 

이를 제대로 확인해 보기위해 출력 부분에 일부 문장을 더 추가해본다.

연산자를 출력하고 싶은 경우에는 해당 기호를 두 번 사용하면 된다.

마지막 문장을 실행한 뒤 n은 0이 되어 조건식이 거짓으로 판별되기 때문에 더 이상 해당 반복문은 실행되지 않게 된다.

 

 

 

 

728x90
반응형
Comments