쉽풀C - 9장 함수와 변수

2023. 2. 5. 20:44·Category/C
728x90

1. 덧셈, 뺄셈, 곱셈, 나눗셈을 지원하는 계산기 프로그램을 작성하여 보자. 이번에는 각 연산들이 몇 번씩 계산되었는지를 기억하게 하자. 각 연산을 지원하는 함수들은 자신이 호출된 횟수를 화면에 출력한다.

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>

int add(int, int);
int sub(int, int);
int mul(int, int);
int div(int, int);

int x, y, result; // 전역 변수
char op; // 전역 변수

int main(void) {
	while (1) {
		printf("연산을 입력하시오: ");
		scanf("%d%c%d", &x, &op, &y);

		switch (op) {
		case '+': result = add(x, y); break;
		case '-': result = sub(x, y); break;
		case '*': result = mul(x, y); break;
		case '/': result = div(x, y); 
		}
		printf("연산 결과: %d\n", result);
	}

	return 0;
}

int add(int x, int y) {
	static int count = 0; // 정적 지역 변수
	printf("덧셈은 총 %d번 실행되었습니다.\n", ++count);
	return x + y; 
}
int sub(int x, int y) { 
	static int count = 0; // 정적 지역 변수
	printf("뺄셈은 총 %d번 실행되었습니다.\n", ++count);
	return x - y; 
}
int mul(int x, int y) { 
	static int count = 0; // 정적 지역 변수
	printf("곱셈은 총 %d번 실행되었습니다.\n", ++count);
	return x * y; 
}
int div(int x, int y) { 
	static int count = 0; // 정적 지역 변수
	printf("나눗셈은 총 %d번 실행되었습니다.\n", ++count);
	return x / y; 
}

 

 

2. 주사위를 던져서 각각의 면이 몇 번 나왔는지를 출력하는 프로그램을 작성하라. 주사위의 면은 난수를 이용하여 생성한다. 주사위를 던지는 함수 get_dice_face()를 만들고 이 함수 안에서 각각의 면이 나올 때마다 그 횟수를 정적 지역 변수를 이용하여 기억하게 하라. get_dice_face() 호출 횟수가 100이 되면 각 면의 횟수를 출력한다.

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

// 주사위 던지는 함수. 각 면이 몇 번 나왔는지 저장되며, 100번 호출될 때마다 각 면이 나온 횟수를 출력.
void get_dice_face(); 

int main(void) {

	srand((unsigned)time(NULL)); // 시드 설정

	for (int i = 0; i < 200; i++) { // 100번 호출될 때마다 출력되는지 확인하기 위해 200번 호출함.
		get_dice_face();
	}
	
	return 0;
}

void get_dice_face() {
	static int n1 = 0, n2 = 0, n3 = 0, n4 = 0, n5 = 0, n6 = 0;
	int rand_num; // 랜덤으로 지정된 1~6 범위의 수(주사위의 면)
	static int func_call_count = 0; // 함수 호출 횟수

	rand_num = rand() % 6 + 1; // 1 ~ 6 범위의 수 랜덤 지정
	switch (rand_num) {
	case 1: n1++; break;
	case 2: n2++; break;
	case 3: n3++; break;
	case 4: n4++; break;
	case 5: n5++; break;
	case 6: n6++;
	}
	func_call_count++;
	if (func_call_count == 100) {
		printf("%d->%d\n", 1, n1);
		printf("%d->%d\n", 2, n2);
		printf("%d->%d\n", 3, n3);
		printf("%d->%d\n", 4, n4);
		printf("%d->%d\n", 5, n5);
		printf("%d->%d\n\n", 6, n6);
		func_call_count = 0;
		n1 = 0, n2 = 0, n3 = 0, n4 = 0, n5 = 0, n6 = 0;
	}
}

 

 

3. 로그인시에 비밀번호를 검사하는 함수 int check()를 작성해서 테스트하라. check()가 한 번 호출될 때마다 비밀번호를 질문하고 일치여부를 0과 1로 반환한다. 비밀번호는 숫자 1234로 고정되어 있다고 가정한다. check()가 3번 이상 호출되고 아이디가 일치하지 않으면 check()는 "로그인 시도 횟수 초과" 메시지를 출력한다. check() 함수 안에 정적 변수를 선언하여 사용해보자.

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>

int check(); // 로그인 시, 비밀번호를 검사하는 함수. 3번 시도 안에 비밀번호를 맞추면 1, 그렇지 않으면 0을 반환

int main(void) {
	while (check() == 0) { } // 로그인에 성공할 때까지 무한 반복한다.
	return 0;
}

int check() {
	static int func_call_count = 0; // 함수 호출 횟수. 3번 호출시마다 0으로 초기화
	int key = 1234; // 비밀번호는 1234로 고정됨
	int pass; // 사용자가 입력한 비밀번호

	func_call_count++;

	printf("비밀번호: ");
	scanf("%d", &pass);

	if (pass == key && func_call_count<=3) { // 3번 안에 비밀번호를 맞춘 경우
		printf("로그인 성공!\n");
		func_call_count = 0;
		return 1;
	}
	else if (pass != key && func_call_count >= 3) {
		printf("로그인 시도 횟수 초과\n\n");
		func_call_count = 0;
	}
	return 0; // 비밀번호를 틀린 경우 0을 반환
}

 

 

4. 본문에서 설명한 바와 같이 정적 변수는 초기화를 딱 한 번만 수행하는 경우에도 사용된다. 난수를 생성하여 반환하는 함수 get_random()을 작성하여 테스트하라. get_random()이 처음으로 호출되는 경우에는 srand()를 호출하여서 난수의 시드를 초기화하고 그렇지 않으면 단순히 rand()를 호출하여 난수를 반환한다.

#include<stdio.h>
#include<stdlib.h>
#include<time.h>

int get_random(); // 난수를 생성하여 반환하는 함수. 처음 호출되는 경우에만 난수의 시드를 초기화한다.

int main(void) {	
	for (int i = 0; i < 3; i++) 
		printf("%d\n", get_random());

	return 0;
}

int get_random() {
	static int inited = 0; // 시드 초기화 여부

	if (inited == 0) {
		srand((unsigned)time(NULL)); // 난수의 시드 초기화
		printf("초기화 실행\n");
		inited = 1;
	}
	return rand();
}

 

 

5. 1부터 n까지의 합 (1+2+3+...+n)을 계산하는 문제를 순환기법을 이용하여 작성해보자.

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>

int sum(int);

int main(void) {
	int n;

	printf("정수를 입력하시오: ");
	scanf("%d", &n);
	
	printf("1부터 %d까지의 합=%d\n", n, sum(n));

	return 0;
}

int sum(int n) { // 순환기법을 이용하여 1부터 n까지의 합을 구하는 함수
	if (n == 1)return 1;
	else return n + sum(n - 1);
}

 

 

6. 순환기법을 이용하여 지수값을 계산하는 함수 power(int base, int power_raised)를 작성하고 테스트해보자.

power(2, 3)가 호출되면 2^3을 계산하여 반환한다.

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>

int pow(int, int); // 순환기법을 이용하여 지수값을 계산하는 함수

int main(void) {
	int base, power_raised;

	printf("밑수: ");
	scanf("%d", &base);

	printf("지수: ");
	scanf("%d", &power_raised);
	
	printf("%d^%d = %d\n", base, power_raised, pow(base, power_raised));

	return 0;
}

int pow(int base,int power_raised) {
	if (power_raised == 1)return base;
	else return base * pow(base, power_raised - 1);
}

 

 

7. 순환 호출을 이용하여 정수의 각 자리수를 출력하는 함수 show_digit(int x)를 작성하고 테스트하라. 즉 정수가 1234이면 화면에 1 2 3 4와 같이 출력한다. 함수는 일의 자리를 출력하고 나머지 부분을 대상으로 다시 같은 함수를 순환 호출한다. 예를 들어서 1234의 4를 출력하고 나머지 123을 가지고 다시 같은 함수를 순환 호출한다. 1234를 10으로 나누면 123이 되고 4는 1234를 10으로 나눈 나머지이다. 

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>

void show_digit(int); // 순환 호출을 이용하여 정수의 각 자리수를 출력하는 함수

int main(void) {
	int n;

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

	show_digit(n);

	return 0;
}

void show_digit(int n) {
	if (n > 0) {
		show_digit(n / 10);
		printf("%d ", n % 10); // 일의 자리 출력
	}
}

 

 

8. 주어진 정수가 몇 개의 자리수를 가지고 있는지를 계산하는 프로그램을 순환을 이용하여 작성해보자. 예를 들어서 12345의 경우에는 5가 출력된다.

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>

int count_digit(int); // 주어진 정수가 몇 개의 자리수를 가지고 있는지 계산해서 그 값을 반환

int main(void) {
	int n;

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

	printf("자리수의 개수: %d\n", count_digit(n));

	return 0;
}

int count_digit(int n) {
	static int count = 0; // 자리수의 개수를 저장하는 변수
	int return_value; // 최종적으로 리턴될 값(=자리수의 개수)

	if (n < 1) {
		return_value = count; // 정적 지역 변수인 count를 초기화하기 전에 그 값을 저장해 둔다.
		count = 0; // 함수의 재사용을 위해서 정적 지역 변수를 초기화한다.
		return return_value;
	}
	else {
		count++;
		return count_digit(n / 10);	
	}
}

 

 

9. 앞의 문제와 유사한 문제이다. 자리수의 합계를 계산하는 프로그램을 순환을 이용하여 작성해보자. 예를 들어서 123의 경우에는 6이 출력된다.

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>

int get_digit_sum(int); // 각 자리수의 합계를 반환하는 함수

int main(void) {
	int n;

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

	printf("자리수의 합: %d\n", get_digit_sum(n));

	return 0;
}

int get_digit_sum(int n) {
	if (n < 10)return n;
	return n % 10 + get_digit_sum(n / 10);
}

 

 

10. 다음과 같은 수식의 값을 계산하는 순환적인 프로그램을 작성하라.

1/1 + 1/2 + 1/3 + ... + 1/n

#include<stdio.h>

double recursive(int);

int main(void) {
	printf("%lf\n", recursive(10));
	return 0;
}

double recursive(int n) {
	if (n > 1) {
		return 1. / n + recursive(n - 1);
	}
	return 1.;
}

 

 

11. 이항 계수(binomial coefficient)를 계산하는 순환 함수를 작성하라. 이항 계수는 다음과 같이 순환적으로 정의된다.

HINT - 순환적으로 정의된 수학식을 그대로 변환하면 된다.

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>

int recursive(int, int);

int main(void) {
	int n, k;

	printf("n=");
	scanf("%d", &n);

	printf("k=");
	scanf("%d", &k);

	printf("%d\n", recursive(n, k));

	return 0;
}

int recursive(int n, int k) {
	if (k == 0 || k == n)
		return 1;
	return recursive(n - 1, k - 1) + recursive(n - 1, k);
}

 

 

12. 순환 호출을 이용하여 피보나치 수열을 계산해 보자. 피보나치 수열이란 다음과 같이 정의되는 수열이다. 즉 일반적인 경우, 앞의 두 개의 숫자를 더해서 뒤의 숫자를 만들면 된다. 정의에 따라 수열을 만들어 보면 다음과 같다.

0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...

#include<stdio.h>

int fib(int);

int main(void) {

	for (int i = 0; i < 10; i++)
		printf("fib(%d) = %d\n", i, fib(i));

	return 0;
}

int fib(int n) {
	if (n <= 1)return n; 

	return fib(n - 2) + fib(n - 1);
}
728x90

'Category > C' 카테고리의 다른 글

쉽풀C - 11장 포인터  (0) 2023.02.07
쉽풀C - 10장 배열  (0) 2023.02.06
쉽풀C - 8장 함수  (0) 2023.02.04
쉽풀C - 7장 반복문  (0) 2023.02.03
쉽풀C - 6장 조건문  (1) 2023.02.02
'Category/C' 카테고리의 다른 글
  • 쉽풀C - 11장 포인터
  • 쉽풀C - 10장 배열
  • 쉽풀C - 8장 함수
  • 쉽풀C - 7장 반복문
Corinee
Corinee
  • Corinee
    Coding Note
    Corinee
  • 전체
    오늘
    어제
    • 분류 전체보기 (352)
      • Category (347)
        • Algorithm (7)
        • SQL (1)
        • Java (4)
        • C (9)
        • React (6)
        • JavaScript (9)
        • CSS (2)
        • Node (1)
        • SpringBoot (26)
        • Database (3)
        • Network (1)
        • Django (6)
        • Python (21)
        • Flask (4)
        • iOS (25)
        • Swift (4)
        • Flutter (11)
        • Dart (3)
        • Git (1)
        • Firebase (1)
        • Gof (1)
        • 정보처리기사 (112)
        • AI (5)
        • NestJs (4)
        • Docker (1)
        • Chrome Extension (1)
        • Note (76)
        • Socket (1)
        • 개인 정보 처리 방침 (1)
        • 회고 (0)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    core web vitals
    mermaid-cli
    styled-components
    프로세스 강제 종료
    react router
    inp
    named export vs default export
    쉽게 풀어쓴 C언어 Express
    Jest
    ajax (asynchronous javascript and xml)
    중첩 함수(nested function)
    javascript 필수 문법
    useEffect
    jackson 라이브러리
    defaultdict
    public vs assets
    counter
    x.y.z (메이저.마이너.패치)
    원시값(primitive)
    react
    stdlib.h
    semver)
    math.h
    intellij 콘솔 한글 깨짐
    Collections
    structuredclone()
    json.parse(json.stringify())
    소프트웨어 버전 관리
    시맨틱 버전(semantic versioning
    chrome extension 자동 배포
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
Corinee
쉽풀C - 9장 함수와 변수
상단으로

티스토리툴바