Sister Nosilv story

[쉽풀C] 8장 함수_중간점검 도전문제 Exercise Programming 해설

by 노실언니

쉽게 풀어쓴 C언어 Express - 천인국 - 생능출판사 - 개정3판

Chapter 8. 함수

- 함수의 #개념 #장점 이해하기

- #함수와 함수 사이에서 정보를 전달하고 받는 메커니즘 이해하기

 

<Function≒Procedure≒Subroutine>

* 내 식대로 챕터정리

# 함수선언(Declaration): 함수가 정의되기 전, 해당 함수가 정의 될 거라고 원형을 통해 미리 알려주는 것

  └ 함수원형(Prototype): 반환형 함수명 (매개변수의 자료형);

# 함수정의(Definition): 반환형 함수명 (자료형 매개변수parameter, ···) { 명령들; } = 함수헤더 { 함수바디 }

# 함수호출(Call):  함수명 (argument···);

 

# C언어 (표준) Library ∋ { Header Files , Library Files } [한글] [영문] [설명이 잘 되어있음]

 - (표준 : 해당언어 컴파일러가 기본으로 탑재하고 있는)

  └ Header File: 주로 함수Prototype이 들어있는 파일

  └ Library File:  실제로 함수를 구현하는 부분이 미리 컴파일된 파일

 - 전처리기 지시어 #include <헤더파일명>를 사용하면,

  별도의 사용자 정의없이도 해당 라이브러리 구성물(함수, 상수 등)사용가능

└ 입출력 <stdio.h>

└ <stdlib.h> srand(unsigned time(NULL)); rand(); exit(0); system("명령어");

<stdlib.h> 난수 / 프로세스 제어 / 동적 메모리관리 / 문자열 변환 / 검색&정렬 / 정수산술(절댓값&나누기)
NULL		// 아무런 메모리개체를 가리키지않는 포인터 상수
int rand ( void );					// 0부터 RAND_MAX 사이의 의사 난수를 반환
void srand ( unsigned int seed );	// 의사 난수 발생기를 seed로 초기화
RAND_MAX	// rand 함수가 반환하는 가장 큰 값(int:0 ~ 2의 15제곱-1=32768)
void exit ( int status );
EXIT_SUCCESS	// 매크로 상수; exit 함수의 인자 - 성공적 종료의미
EXIT_FAILURE
int system ( const char * command );	// command의 시스템 명령 실행
int abs ( int n );					// 정수의 절댓값 반환
long int labs ( long int n );

<time.h> time(NULL);

<time.h>
time_t time ( time_t * timer );

└ <math.h


p323. 중간점검

1️⃣. 함수가 필요한 이유는 무엇인가?

 🢩 ① 재사용가능 ② 가독성상승=개발&관리용이 ③ 이식성

∵ 355p. Ch8.7 함수를 사용하는 이유

  ① 중복코드 제거 ← 한번 만들어진 함수는 여러번 호출가능

  ② 전체 프로그램을 한 덩어리로 두는 것보다

   작은 부분들[모듈MODULE]로 나눠두면(≒작업별 분류)

   보다 체계적이 되고 가독성이 높아지므로,

   개발과정과 유지보수가 더 쉬워진다.

  ③ 다른 프로그램을 만들때도 그대로 이용가능 ← 이미 디버깅을 마친 검증된 함수

2️⃣. 함수와 프로그램의 관계는?

 🢩 프로그램 ∋ 함수; 하나의 작품(프로그램)을 구성하는 블록(함수)

3️⃣. 컴파일러에서 지원되는 함수를          함수라고 한다.

 🢩 컴파일러에서 지원되는 함수를 라이브러리 함수라고 한다.

 

p328. 중간점검

1️⃣. 함수의 반환형이 없는 경우에는 어떻게 표시하는가?

 🢩 ① return문을 아예 사용하지 않음 ② return; ③ return 0; ④ return(0);

2️⃣. 수식 (x+y+z)의 값을 반환하는 문장을 작성하여 보자.

 🢩 return (x+y+z);

3️⃣. double형 변수f를 매개 변수로 가지고 double형의 값을 반환하는 fabs()함수 헤더를 정의하여 보자.

 🢩 double fabs(double f)

double fabs(double f){	// Header
	if (f<0) f *= -1;	// Body
    return f;
}

 

p330. 도전문제

happyBirthday() 함수가 "생일축하 합니다!"를 지정된 횟수만큼 반복하도록 수정하라. 즉 happyBirthday(5)라고 호출하면 5번 반복한다.

 🢩

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

void happy_birthday(int n);

int main(void) {
	int count;
	printf("축하를 몇 번 할까요? _\b");
	scanf("%d", &count);
	happy_birthday(count);
	return 0;
}

void happy_birthday(int n) {
	for (; n > 0; n--)
		printf("생일축하 합니다!\n");
	return;
}

 

p333. 중간점검

1️⃣. 인수와 매개 변수는 어떤 관계가 있는가?

 🢩 함수는 입력받은 인수 값⚾️을 → 매개 변수📦에 할당해서 사용한다. (내용물⚾️ → 담는상자📦)

2️⃣. 반환값이 실수로 정의된 함수에서 실수로 정수를 반환하면 어떤 일이 발생하는가?

 🢩 함수가 정수를 실수형으로 자동형변환한 후에 반환한다.

* 실수형 함수명() { return 정수형; } 직접해 봤는데 에러메세지도 안 뜸!

 

p338. 도전문제

1️⃣. 1부터 사용자가 입력한 숫자 n 사이의 모든 소수를 찾도록 위의 프로그램을 변경하여 보자.

 🢩

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int is_prime(int num);

int main(void) {
	int num;
	printf("[ Is it 'Prime'? ]\n");
	printf("Range: 1 ~ _\b");
	scanf("%d", &num);
	printf("Prime list: ");

	for (int n = 2; n <= num; n++) {
		if (is_prime(n))
			printf("%d ", n);
	}
	printf("- END\n");
	return 0;
}

int is_prime(int num) {
//	if (num == 1) return 0;			// 소수 정의 1) 1보다 큰 자연수
	for (int i = 2; i < num; i++)	// 소수 정의 2) 1과 자기자신으로'만' 나눠지는 자연수
		if (num % i == 0) return 0;
	return 1;
}

* 1은 왜 소수가 아닐까?

 

p341. 중간점검

⒈ 함수 정의의 첫 번째 줄에는 어떤 정보들이 포함되는가? 이것을 무엇이라고 부르는가?

 🢩 출력값의 자료형, 함수명, 입력받을 값들을 담을 파라미터(=매개변수)이름/갯수/자료형 ··· 함수헤더

⒉ 함수가 반환할 수 있는 값의 개수는?

 🢩 1

⒊ 함수가 값을 반환하지 않는다면 반환형은 어떻게 정의되어야 하는가?

 🢩 void

⒋ 함수 정의와 함수 원형의 차이점은 무엇인가?

 🢩 ① 용도의 차이 ② 코드형태의 차이

  ① Definition : 말그대로 정의, 함수에 대한 모든 정보를 담는 용도 

   - Prototype : 해당 함수의 존재와 필요한 자료형과 변수갯수를 컴파일러에게 미리 선언(declaration)하는 용도

  ② Definition : 출력형 함수名 (입력형 파라미터名, ···) { 해당 함수가 해야할 명령; } 

   - Prototype : 출력형 함수名 (입력형 파라미터名, ···) ;

* [ 정의 - 원형 ] 보다 [ 정의 - 선언 ]이 대응되는 것 같다. 

⒌ 함수 원형에 반드시 필요한 것은 아니지만 대개 매개 변수들의 이름을 추가하는 이유는 무엇인가?

 🢩 프로그래머의 코딩편의, 가독성을 위해서

⒍ 다음과 같은 함수 원형을 보고 우리가 알 수 있는 정보는 어떤 것들인가?

double pow(double, double);

 🢩 pow 함수는 double형 데이터 2개입력받은 후, double형 데이터를 출력할 것이다. 

 

 

p345. 도전문제

1️⃣. 컴퓨터와 사람이 대결하는 가위, 바위, 보 게임을 작성해보자. 컴퓨터는 난수를 발생시켜서 가위, 바위, 보 중에서 하나를 선택한다.

 🢩 

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

int answer(void);

int main(void) {
	int user, com;
	while (1) {
		printf("[ ROCK! PAPER! SCISSORS! ]\n");
		printf("- Rock :	0\n");
		printf("- Paper :	1\n");
		printf("- Scissors :	2\n");
		printf("- Quie : etc.\n");
		printf("-----------------\n");
		printf("- User : _ ← Answer only 0 or 1 or 2");
		for (int i = 0; i < 28; i++) printf("\b");
		scanf(" %d", &user);
		if (user != 0 && user != 1 && user != 2) break;
		com = answer();
		for (int i = 0; i < 5; i++) {
			printf("· ");
			Sleep(500);	// delay 1s
		}
		printf("\n");
		printf("- Com : %d\n\n", com);
		Sleep(500);
		int result = user - com;
		switch (result) {
			case 0:
				printf("→ DRAW \n");
				break;
			case 1:
			case -2:
				printf("→ USER WIN :)\n");
				break;
			case -1:
			case 2:
				printf("→ COM WIN :(\n");
				break;
		}
		printf("\n\n");
	}
	return 0;
}

int answer(void) {
	srand((unsigned)time(NULL));
	return (rand() % 3);	/// rock0 paper1 scissors2
}

 

p347. 도전문제

1️⃣. 자동차를 3개로 늘려보자.

 🢩

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

void display_car(int car_number, int distance);
int distance_car(void);

int main(void) {
	srand((unsigned)time(NULL));
	printf("[ CAR RACING ]\n\n");
	for(int i=1;i<4;i++){
		display_car(i, distance_car());
		printf("│││││││││││││││││││││││││││││││││││\n");
	}
	return 0;
}

void display_car(int car_number, int distance) {
	Sleep(300);
	printf("[ %d ] ", car_number);
	Sleep(300);
	for (int i = 3; i > 0; i--) {
		printf("%d",i);
		Sleep(500);
		printf("\b");
	}
	printf("GO!\n");
	Sleep(100);

	for (; distance > 0; distance--) {
		printf("▶");
		Sleep(100);
	}
	printf("\n");
	return;
}

int distance_car(void) {
	return (rand() % 20 + 1);
}

 

p352. 중간점검

1️⃣. 45도에서의 싸인값을 계산하는 문장을 작성하여 보라.

 🢩 sin(3.1415926535/4)

* 45º = π/4

2️⃣. rand() % 10 이 계산하는 값의 범위는?

 🢩 0~9 의 정수 (10개)

 

p354. 도전문제

1️⃣. "도(degree)"의 단위의 각도를 받아서 "라디안(radian)"단위의 각도로 변환하는 함수 degree_to_radian() 을 작성하여 위의 프로그램을 다시 작성해보자.

 🢩

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

double degree_to_radian(double degree);

int main(void) {
	double height, distance, tree_height, degrees, radians;
	printf("my height(m): ");
	scanf("%lf", &height);
	printf("tree-me(m): ");
	scanf("%lf", &distance);
	printf("degree(º): ");
	scanf("%lf", &degrees);
	radians = degree_to_radian(degrees);
	tree_height = (tan(radians) * distance) + height;
	printf("tree height(m): %lf\n", tree_height);

	return 0;
}

double degree_to_radian(double degree) {
	return degree * 3.1415926535 / 180;
}

 

p359. 도전문제

1️⃣. 실수들의 덧셈, 뺄셈, 곱셈, 나눗셈을 수행하는 함수 add(), sub(), mul(), div()도 작성하여 본다. 이들을 사용하여 실수 계산기 프로그램을 다시 작성해보자. 메뉴를 표시하는 함수 disp_menu()도 작성해서 사용해보자.

 🢩

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

void display_menu(void);
double get_double(void);
char get_char(void);
double add(double a, double b);
double sub(double a, double b);
double mul(double a, double b);
double div(double a, double b);

int main(void) {
	while (1) {
		double a, b, result;
		char operator;

		display_menu();
		a = get_double();
		operator = get_char();
		if (operator != '+' && operator != '-' && operator != '*' && operator != '/') break;
		b = get_double();
		switch (operator) {
			case'+':
				result = add(a, b);
				break;
			case'-':
				result = sub(a, b);
				break;
			case'*':
				result = mul(a, b);
				break;
			case'/':
				result = div(a, b);
				break;
			default:
				break;
		}
		printf("%lf %c %lf = %lf\n\n", a, operator, b, result);
	}
	return 0;
}

void display_menu(void) {
	printf("┌─────────────────────┐\n");
	printf("│ [Double Calculator] │\n");
	printf("│ ─────────────────── │\n");
	printf("│  +  -  *  / │\n");
	printf("│ ─────────────────── │\n");
	printf("│ etc → QUIT   │\n");
	printf("└─────────────────────┘\n\n");
	return;
}

double get_double(void) {
	double real;
	printf("real number: ");
	scanf(" %lf", &real);
	return real;
}

char get_char(void) {
	char character;
	printf("character: ");
	scanf(" %c", &character);
	return character;
}

double add(double a, double b) {
	return a + b;
}

double sub(double a, double b) {
	return a - b;
}

double mul(double a, double b) {
	return a * b;
}

double div(double a, double b) {
	return a / b;
}

p363. Summary

int square(int n);		// [Declaration선언] 함수 prototype
						// 함수名: square/ int형을 return할 것/
                        // int형 argument값을 입력받아서
                        // n이란 이름의 파라미터에 할당해서 함수내부에서 이용할 것임
int main(void){
	int result;
    result = square(10);		// [Call 호출]
    printf("%d\n", result);
	return 0;
}

int square(int n){		// [Definition정의]
	return (n*n);
}

▶ square() 함수 앞에 적어주는 int는 square() 함수가 int 형의 데이터를 반환한다는 의미이다.

▶ square() 함수를 호출할 때 전달하는 데이터를 반환값 이라고 한다. ··· 나는 인자(argument)같은데...

▶ square() 함수에서 외부에 전달되는 데이터를 받는 변수를 파라미터 라고 한다.

▶ 함수를 크게 분류하면 프로그래머가 작성하는 사용자 정의 함수와 컴파일러에서 지원되는 라이브러리 함수로 나눌 수 있다.

▶ 함수 몸체는 { 기호로 시작하고 } 기호로 종료한다.

  for, if, while···문에서 한 줄이면 { } 를 생략해도 되는 것과는 달리, 함수 몸체의 { }는 생략할 수 없다.

▶ 함수가 반환할 수 있는 값의 개수는 한 개 이다.

▶ 함수가 값을 반환하지 않는다면 반환형은 void 로 정의되어야 한다.


p364. Exercise

1️⃣. 함수에 대한 설명 중 잘못된 것은?

  함수를 정의하기 전에 반드시 함수 원형 정의가 있어야 한다. (X)

  └ main함수보다 먼저 정의를 할 때는 원형 정의를 할 필요가 없다.

 ② 함수의 매개 변수는 전혀 없을 수도 있다.

 ③ 함수는 값을 반환하지 않을 수도 있다.

 ④ 함수 안에 문장이 하나도 없을 수도 있다.

  └  해보니 Warning 도 안 뜸

 

2️⃣. 다음 함수 원형 정의 중에서 int형을 반환하는 함수는?

 ① void func(int); - (x) int형을 입력받고, 반환값 없음

 ② double func(int, int); - (x) int형을 두 개 입력받고, double형 반환

  int func(double x); - (o) double형을 입력받고, int형 반환

 ④ void func(void); - (x) 입력/반환값 없음

 

3️⃣. 다음의 함수 원형 정의 중에서 잘못된 것은?

  int func(int x, y); - (error)

error C2081: 'y': name in formal parameter list illegal

 ② void func(x, y); - (error나 warning은 안 나지만, 논리적으로 잘못될 위험성 有)

float get_area(radius, pi) {
	printf("%f\n", (float)radius);
	printf("%f\n", (float)pi);
	return (float)radius * radius * pi;
}

int main(void) {
	printf("%f\n", get_area(1, 2));			// 2.000000 출력
	printf("-------------------\n");
	printf("%f\n", get_area(1.0, 2.0));		// 2.000000이 아닌 0.000000 (?)
    
    
float get_area(radius, pi) {
	return (float)radius * radius * pi;
}

/* 콘솔창
* 1.000000
* 2.000000
* 2.000000
* -------------------
* 0.000000
* 0.000000
* 0.000000
* 으로 출력 됨
*/

 

 ③ char func(double); - (ok) 

  void func(void, void);  - (error)

error C2860: 'void' cannot be an argument type, except for '(void)'

 

4️⃣. int func(int); 의 원형을 가지는 함수의 호출로 옳은 것은?

  func(10);

 

5️⃣. 다음 라이브러리 함수 호출의 반환값을 쓰라

 ⒜ fabs(-1.72) → 1.72 (double형)

 ⒝ floor(1.72) → 1 (double형)

 ⒞ ceil(1.72) → 2 (double형)

 

6️⃣. 다음 수식의 반환값의 범위는?

 ⒜ rand()%10 → 0~9 (10개)

 ⒝ rand()%5 → 2~6 (5개)

 

7️⃣. 다음의 수학식을 계산하는 문장을 작성해보자.

 ⒜ y = log10x + e^x

y = log10(x) + exp(x);

 ⒝ y = sin(x) + √(x^2-2a) + 2^10

y = sin(x) + sqrt(x * x - 2 * a) + ldexp(1.0, 10);

 

8️⃣. 다음과 같은 기술에 부합하는 함수 원형을 작성하라.

 ⒜ int형 매개 변수 n을 받아서 아무것도 반환하지 않는 print_error() 함수

void print_error(int n);

 ⒝ double형 매개 변수 x, y를 받아서 double 형을 반환하는 larger_of() 함수

double larger_of(double x, double y);

 ⒞ 어떠한 매개 변수도 갖지 않고 아무것도 반환하지 않는 side_effect() 함수

void side_effect(void);

 

9️⃣. 왼쪽 박스의 함수 원형 정의에 적합한 return 문을 오른쪽 박스에서 찾아서 서로 연결하라.

  • int f(void); ··· return 10 + 20;  ∵ int형
  • void g(int, int); ··· return;  ∵ void
  • double h(double, int); ··· return 1.0;  ∵ double형

 

🔟. 다음은 1부터 10까지의 합을 계산하는 프로그램이다. 프로그램의 빈칸을 채워라.

#include <stdio.h>

int f(int n);

int main(void) {
	printf("result: %d\n", f(10));
	return 0;
}

int f(int n) {
	int i, result = 0;

	for (i = 0; i <= n; i++)
		result += i;

	return result;
}

 

⓫. 다음 함수의 원형 정의가 올바른지를 결정하고 만약 잘못된 점이 있다면 이유를 설명하고 바르게 수정하라.

 ⒜ double f(double x, y);

  └ (X) Wrong - x의 자료형은 잘 정의되어있는데, y의 자료형만 불분명하다.

error C2081: 'y': name in formal parameter list illegal

  └수정→ double f(double x, double y);  자료형을 명확하게 적어주기

 ⒝ (int) f(double x, double y);

  └ (X) Wrong - (자료형) = 형변환

괄호를 사용하면 int형 데이터를 return하는 함수라는 의미가 사라진다.

error C2059: syntax error: '<parameter-list>'

  └수정→ int f(double x, double y);  괄호제거

 ⒞ int f((int)x, (int) y);

  └ (X) Wrong - ⒝와 같은 이유; (자료형)=형변환

괄호를 사용하면 int형 데이터를 return하는 함수라는 의미가 사라진다.

error C2143: syntax error: missing ')' before '('
error C2059: syntax error: ')', '('

  └수정→ int f(int x, int y);  괄호제거

 ⒟ float get_area(radius, pi);

  └ (X) 자료형을 안 정해주면 문제가 될 것 같은데,

   직접 해보니 컴파일 에러도 안 나고 경고도 안 생겨서 괜찮아보임...그러나

   출력값을 까보니 논리적 오류가 생김→정수입력은 문제없으나 실수는 0으로 받음

  └수정→ float get_area(float radius, float pi);  자료형을 명확하게 적어주기

float get_area(radius, pi) {
	printf("%f\n", (float)radius);
	printf("%f\n", (float)pi);
	return (float)radius * radius * pi;
}

int main(void) {
	printf("%f\n", get_area(1, 2));			// 2.000000 출력
	printf("-------------------\n");
	printf("%f\n", get_area(1.0, 2.0));		// 2.000000이 아닌 0.000000 (?)
    
    
float get_area(radius, pi) {
	return (float)radius * radius * pi;
}

/* 콘솔창
* 1.000000
* 2.000000
* 2.000000
* -------------------
* 0.000000
* 0.000000
* 0.000000
* 으로 출력 됨
*/

 

⓬ 다음의 프로그램에서 붉은 색으로 표시된 부분을 함수로 작성하여 프로그램을 수정하시오. 함수는 인수와 반환값을 갖도록 설계하라.

#include <stdio.h>

int sum_one2n(int n);

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

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

	return 0;
}

int sum_one2n(int n) {
	int result = 0;
	for (; n > 0; n--)
		result += n;
	return result;
}

 

⓭ 다음 코드에서 잘못된 곳(컴파일 오류 및 경고)을 지적하라. 논리적인 오류도 지적하라.

 ⒜

int half_of(int x);	// 정의할 땐, ; 쓰면 안 됨
{
	return x / 2;	// int형 출력형식에 맞긴 하지만..논리적 오류일지도
}

double half_of(int x)	// 논리적 오류가 아니라면 int로 해도 괜찮음
{
	return x / 2.0;	// 논리적 오류가 아니라면 2로 해도 괜찮음
}

 ⒝

void print_message(void);

int main(void)
{
	print_message(3); // '경고' 입력형 void → 실제 3 입력
//	warning C4087: 'print_message': declared with 'void' parameter list
}

void print_message(void);

int main(void)
{
	print_message(); // 입력형과 실제 입력을 일치시켜주기
    return 0;
}

 ⒞

double half_of(int);

int main(void) {
	printf("%f", half_of(10.0));	// 함수원형의 입력형(int) ≠ 실제 데이터의 자료형(double)
	return 0;
}

double half_of(double) {	//  파라미터 누락
	return x / 2.0;
}

double half_of(double x);

int main(void) {
	printf("%f", half_of(10.0));
	return 0;
}

double half_of(double x) {
	return x / 2.0;
}

 ⒟

int sum(int x, int y) {
	sum = x + y;	// 변수 sum 선언 누락
}

int sum(int x, int y) {
	return x + y;	// 변수선언대신 바로 반환해줍시다
}

 ⒠

void sum(void) {		// 출력 안 한다고(void) 했으나
	int x = 1, y = 2, z = 3;
	return x + y + z;	// ≠ 실제로는 정수출력함
}

int sum(void) {
	int x = 1, y = 2, z = 3;
	return x + y + z;
}

p.367 Programming

1️⃣. 주어진 실수를 제곱하여 반환하는 함수 double square(double)을 작성한다. square() 함수를 테스트하는 프로그램을 작성하라.

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

double square(double x);

int main(void) {
	double x;
	printf("정수를 입력하시오: ");
	scanf("%lf", &x);
	printf("주어진 정수 %lf의 제곱은 %lf입니다.\n", x, square(x));
	return 0;
}

double square(double x) {
	return x * x;
}

* 2를 입력해도, 2.000000으로 잘 변환되어서 나옴

 

2️⃣. 전달된 문자가 알파벳 문자인지 아닌지를 검사하는 함수 check_alpha()를 작성하고 이것을 호출하여서 사용자가 입력한 문자가 알파벳('a'에서 'z'까지)인지를 판단하여 출력하는 프로그램을 작성하라.

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int check_alpha(char a);

int main(void) {
	char a;
	printf("문자를 입력하시오: ");
	scanf(" %c", &a);
	printf("%c는 알파벳 문자%s니다.\n", a, (check_alpha(a) ? "입" : "가 아닙"));
	return 0;
}

int check_alpha(char a) {
	if ('a' <= a && a <= 'z') return 1;
    // 그런데, 이렇게하면 소문자만 알파벳문자로 취급하므로
	// if (('a' <= a && a <= 'z') || ('A' <= a && a <= 'Z')) 가 더 의미에 적합
	return 0;
}

 

3️⃣. 원의 면적을 구하는 문제를 함수로 작성하여 보자. 다음과 같은 식을 이용하라. 원의 면적을 구하는 함수 cal_area(double radius)를 작성하고 함수를 호출하여 원의 면적을 출력하는 전체 프로그램을 완성하라.

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#define PI 3.141592

double cal_area(double radius);

int main(void) {
	double r;

	printf("RADIUS: _\b");
	scanf("%lf", &r);

	printf("AREA: %lf\n", cal_area(r));
	return 0;
}

double cal_area(double radius) {
	return radius * radius * PI;
}

 

4️⃣. 우리는 앞에서 윤년을 구하는 알고리즘을 학습하였다. 이것을 함수 is_leap(int year) 함수로 작성하고 이 함수를 사용하여서 사용자가 입력한 연도가 윤년인지를 출력하는 프로그램을 작성하라.

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int is_leap(int year);

int main(void) {
	int year;
	printf("year: ____\b\b\b\b");
	scanf("%d", &year);

	if (is_leap(year))
		printf("%d년은 윤년으로 366일입니다.\n", year);
	else
		printf("%d년은 평년으로 365일입니다.\n", year);

	return 0;
}

int is_leap(int year) {
	return ((year % 400 == 0) || (year % 4 == 0 && year % 100 != 0));
}

 

5️⃣. 실수를 정수로 변환하면 소수점 이하는 잘려서 없어지게 된다. 예를 들어서 6.999를 정수로 변환하면 6이 된다. 실수에 0.5를 더하여 소수점 이하를 버리는 반올림 연산을 수행하는 round(double f)를 작성하고 테스트하라. 단 f는 양수라고 가정하라.

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int round(double f);

int main(void) {
	double f;
	printf("실수: _\b");
	scanf("%lf", &f);

	printf("반올림: %d\n", round(f));
	return 0;
}

int round(double f) {
	if (f >= 0)
		return ((int)(f + 0.5));
	else
		return ((int)(f - 0.5));
}

* 그냥 음수도 이 기준에 맞춰서 함

 

6️⃣. 다음과 같은 간단한 기능을 하는 함수들을 작성하고, 사용자로부터 임의의 값을 입력받은 후에 작성한 함수들을 테스트하여 보자.

(1) 주어진 정수가 짝수이면 1을 반환하고 홀수이면 0을 반환하는 함수 int even(int n)

(2) 주어진 정수의 절댓값을 구하는 함수 int absolute(int n)

(3) 주어진 정수가 음수이면 -1을, 양수이면 1을 0이면 0을 반환하는 함수 int sign(int n)

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int even(int n);
int absolute(int n);
int sign(int n);

int main(void) {
	int n;
	printf("정수: _\b");
	scanf("%d", &n);

	printf("짝수?	%s\n", (even(n) ? "짝수" : "홀수"));
	printf("절댓값?	%d\n", absolute(n));
	printf("부호?	");
	switch (sign(n)) {
		case -1:
			printf("음수\n");
			break;
		case 0:
			printf("0\n");
			break;
		case 1:
			printf("양수\n");
			break;
	}
	return 0;
}

int even(int n) {
	return !(n % 2);
}

int absolute(int n){
	return (n >= 0 ? n : -n);
}

int sign(int n) {
	return (n == 0 ? 0 : (n > 0 ? 1 : -1));
}

콘솔

 

7️⃣. 월급에 붙는 소득세를 계산하는 함수 get_tax(int income)를 작성하고 테스트하여 보자. 과표 구간은 1000만 원 이하 8%, 1000만 원 초과는 10%로 되어 있다고 가정한다. 사용자로부터 소득을 입력받아서 세금을 계산하는 프로그램을 작성하라. 

* 만원 단위만 취급 = 천원 단위 절삭해버림(절삭안하려면 double형 이용)

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int get_tax(int income);

int main(void) {
	int income;
	printf("소득(만원): ");
	scanf("%d", &income);
	printf("소득세(만원): %d\n",get_tax(income));
	return 0;
}

int get_tax(int income) {
	if (income > 1000)
		return (int) (80 + 0.1 * (income - 1000));
	else
		return (int)(income * 0.08);
}

 

8️⃣. sin() 라이브러리 함수를 호출하여서 0도부터 180도까지 10도 단위로 사인 함수 값을 출력하여 보자. 추가적으로 아예 각도를 받아서 사인값을 반환하는 함수 sin_degree(double degree)를 작성하여 문제를 해결할 수 있는가?

* C언어 PI 상수(M_PI) → include <math.h>

define _USE_MATH_DEFINES

둘 다 써야함

#define _USE_MATH_DEFINES		// math.h의 M_PI(파이값)를 사용하기위함
#include <stdio.h>
#include <math.h>

double sin_degree(double degree);

int main(void) {
	for (double degree = 0; degree <= 180; degree += 10)
		printf("sin(%.0lf˚)=	%lf\n", degree, sin_degree(degree));
	return 0;
}

double sin_degree(double degree) {
	return sin(degree*M_PI/180);
}

/*
// Definitions of useful mathematical constants
//
// Define _USE_MATH_DEFINES before including <math.h> to expose these macro
// definitions for common math constants.  These are placed under an #ifdef
// since these commonly-defined names are not part of the C or C++ standards
* #define M_E        2.71828182845904523536   // e
* #define M_LOG2E    1.44269504088896340736   // log2(e)
* #define M_LOG10E   0.434294481903251827651  // log10(e)
* #define M_LN2      0.693147180559945309417  // ln(2)
* #define M_LN10     2.30258509299404568402   // ln(10)
* #define M_PI       3.14159265358979323846   // pi
* #define M_PI_2     1.57079632679489661923   // pi/2
* #define M_PI_4     0.785398163397448309616  // pi/4
* #define M_1_PI     0.318309886183790671538  // 1/pi
* #define M_2_PI     0.636619772367581343076  // 2/pi
* #define M_2_SQRTPI 1.12837916709551257390   // 2/sqrt(pi)
* #define M_SQRT2    1.41421356237309504880   // sqrt(2)
* #define M_SQRT1_2  0.707106781186547524401  // 1/sqrt(2)
*/

* windows.h랑 HDC hdc로 사인 그래프 그린거 가물가물(354~5p)

 

9️⃣. 난수(random number)는 컴퓨터를 이용한 문제 해결에서 많이 사용된다. 특히 수학적인 분석이 너무 복잡한 경우에 시뮬레이션을 사용하면 실제로 제품을 제작하지 않고서도 많은 실험을 할 수 있다. Visual Studio의 경우, rand()가 한번 호출될 때마다 0에서 32767(RAND_MAX)까지의 정수를 같은 확률로 선택하여 반환한다. rand() 함수를 이용하여 0 또는 1값을 무작위로 반환하는 함수 b_rand()를 작성하고 5번 호출하여 보자.

* rand범위가 0짝~32767홀로 끝나서 진짜 반반

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

int b_rand(void);

int main(void) {
	srand((unsigned) time(NULL));

	for (int i = 0; i < 5; i++)
		printf("%d ", b_rand());
	printf("\n");
	return 0;
}

int b_rand(void) {
	return (rand() % 2);
}

복권사러가까

 

🔟. 앞에서 작성한 b_rand()함수를 이용하여 간단한 동전 던지기 게임을 시뮬레이션하여 보자. 컴퓨터가 동전을 던지고 사용자는 앞뒤를 말한다. 컴퓨터는 b_rand()를 이용하여 생성된 난수가 1이면 동잔의 앞면으로 간주하고 0이면 동전의 뒷면으로 간주한다.

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

int b_rand(void);

int main(void) {
	srand((unsigned) time(NULL));
	char keep;
	printf("홀짝게임 <시작하려면 아무키나 누르세요>\n");
	_getch();
	do {
		int answer = b_rand();
		int user;
		printf("앞? 뒤? (앞이면 1, 뒤면 0입력): _\b");
		scanf("%d", &user);
		for (int i = 0; i < 3; i++) {
			printf(". ");
			Sleep(300);
		}
		if (user == answer)
			printf("정답!\n");
		else
			printf("땡!\n");

		printf("계속하시겠습니까? (중단을 원할시 n을 입력해주세요)\n");
		keep=_getch();
	} while (keep!='n');

	return 0;
}

int b_rand(void) {
	return (rand() % 2);
}

 

⒒ 0.0부터 1.0까지의 난수를 반환하는 함수 f_rand()를 작성하고 5번 호출하여 본다.

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

double f_rand(void);

int main(void) {
	srand((unsigned)time(NULL));
	for (int i = 0; i < 5; i++)
		printf("%lf  ", f_rand());
	printf("\b\b\n");
	return 0;
}

double f_rand(void) {
	return ((double)rand()) / RAND_MAX;
}

 

⒓ 화면에 세로로 막대 그래프를 그리는 프로그램을 작성하여 보자. 인수의 값만큼의 별표 문자를 출력하는 함수 print_value(int n)을 작성하라. 반복적으로 사용자로부터 값을 입력받아서 print_value()를 호출하여 입력값만큼 막대를 그리는 프로그램을 완성하라. 사용자가 음수를 입력하면 반복을 중단하라.

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

void print_value(int n);

int main(void) {
	printf("[막대 그래프 생성기]\n");
	int n;
	do {
		printf("너비값을 입력하시오(음수 입력시 종료): _\b");
		scanf("%d", &n);
		print_value(n);
	} while (n>=0);
	return 0;
}

void print_value(int n) {
	for (; n > 0; n--)
		printf("*");
	printf("\n");
}

 

⒔ 두 개의 정수 n, m을 입력받아서 n이 m의 배수이면 1을 반환하고 그렇지 않으면 0을 반환하는 함수 is_multiple(int n, int m)를 작성하고 테스트하여 보자.

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int is_multiple(int n, int m);

int main(void) {
	int n, m;
	printf("[◆이 ◈의 배수일까?]\n");
	printf("◆과 ◈을 입력하세요: ");
	scanf("%d %d", &n, &m);

	if (is_multiple(n, m))
		printf("%d는 %d의 배수입니다.  ∵ %d = %d × %d\n", n, m, n, m, n / m);
	else
		printf("%d는 %d의 배수가 아닙니다.\n", n, m);

	return 0;
}
int is_multiple(int n, int m) {
	if (n % m)
		return 0;
	else
		return 1;
}

 

⒕ 두 점사이의 거리를 계산하는 함수를 작성하여 보자. 2차원 공간에서 두 점 사이의 거리를 계산하는 get_distance(double x1, double y1, double, x2, double y2)를 작성하시오. 다음과 같은 두 점 사이의 거리를 계산하는 공식을 사용하라. 제곱근은 sqrt() 라이브러리 함수를 사용하라.

* 정수 성분만 받는 것처럼 출력함

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

double get_distance(double x1, double y1, double x2, double y2);

int main(void) {
	double x1, x2, y1, y2;
	printf("점1. (x, y) 입력: ");
	scanf("%lf %lf", &x1, &y1);
	printf("점2. (x, y) 입력: ");
	scanf("%lf %lf", &x2, &y2);
	printf("두 점 사이의 거리는 %lf 입니다.\n", get_distance(x1, y1, x2, y2));
	printf("식: √{(%.0lf-%.0lf)^2 + (%.0lf-%.0lf)^2}\n", x1, x2, y1, y2);
	return 0;
}

double get_distance(double x1, double y1, double x2, double y2) {
	return sqrt((x1 - x2) * (x1 - x2) + (x1 - x2) * (x1 - x2));
}

 

⒖ 주어진 정수가 소수인지를 검사하는 함수 is_prime()을 작성하라. 이 함수를 이용하여 2부터 100 사이의 모든 소수를 출력하라.

#include <stdio.h>

int is_prime(int n);

int main(void) {
	for (int i = 2; i <= 100; i++) {
		if (is_prime(i))
			printf("%d  ", i);
	}
	return 0;
}

int is_prime(int n) {
	switch (n) {
		case 1:
			return 0;
		case 2:
			return 1;
		default:
			if (n % 2 == 0) return 0;	// 2외의 짝수는 소수가 절대 아님
			int max = n / 2;
			for (int i = 3; i <= max; i += 2) {
				if (n % i == 0) return 0;
			}
			return 1;
	}
}

 

⒗ 오일러의 수 e는 자연 로그의 밑수로 사용된다. 이 값은 다음과 같은 식에 의하여 근사치를 구할 수 있다. 본문에 있는 팩토리얼 값을 계산하는 함수 factorial()을 호출하여서 오일러의 수를 계산하는 프로그램을 작성하라.

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int factorial(int n);

int main(void) {
	int i;
	double result = 1;
	printf("[ 오일러의 수(자연상수) e ]\n");
	printf("몇 번째 항까지 계산할까요? _\b");
	scanf("%d", &i);

	for (; i > 0; i--) {		// i: 초기i값~1
		result += 1.0 / factorial(i);
	}
	printf("오일러의 수는 %lf입니다.\n", result);
	return 0;
}

int factorial(int n) {
	int result = 1;
	for (; n > 1; n--)
		result *= n;
	return result;
}

 

⒘ 두 개의 부동 소수점 수가 근사적으로 같은 값이면 1을 반환하고 근사적으로 같지 않으면 0을 넘겨주는 함수 f_equal(a, b)을 작성하시오. 근사적으로 같다고 하는 것은 다음의 부등식을 만족하는 경우라고 가정한다. 부동 소수점 수의 절대값을 구하는 함수와 두 수 중에서 최소값을 찾는 함수는 스스로 제작하여 사용하라. e는 상수로서 0.000001로 정의된다.

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

double f_abs(double x);
double f_min(double x, double y);
int f_equal(double x, double y);

int main(void) {
	double x, y;
	printf("두 실수를 입력하시오: ");
	scanf("%lf %lf", &x, &y);

	if (f_equal(x, y))
		printf("두 실수는 서로 같음\n");
	else
		printf("두 실수는 서로 다름\n");

	return 0;
}

double f_abs(double x) {
	return (x > 0 ? x : -x);
}

double f_min(double x, double y) {
	return (x < y ? x : y);
}

int f_equal(double x, double y) {
	if ((f_abs(x - y) / f_min(f_abs(x), f_abs(y))) < 0.000001)
		return 1;
	return 0;
}

 

⒙ 사용자로부터 2개의 숫자를 받아서 덧셈, 뺄셈, 곱셈, 나눗셈, 나머지 연산의 결과를 계산해주는 프로그램을 작성해보자. 다음과 같은 메뉴를 화면에 표시한다. 프로그램 작성시에 최대한 함수를 많이 사용해보자.

*최대한 많이 사용하긴 했는데, 너무 복잡하지않낭

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

void show_menu(void);
int pick_menu(void);
int add(int a, int b);
int minus(int a, int b);
int multiple(int a, int b);
double division(int a, int b);
int remainder(int a, int b);
void calculate(int n);

int main(void) {
	char keep;
	do {
		show_menu();
		int pick = pick_menu();
		calculate(pick);
		printf("계속하려면 y를 누르시오.\n");
		keep = _getch();
	} while (keep == 'y');
	return 0;
}

void show_menu(void) {
	printf("================\n");
	printf("[정수계산기 MENU]\n");
	printf("================\n");
	printf("1. 덧셈\n");
	printf("2. 뺄셈\n");
	printf("3. 곱셈\n");
	printf("4. 나눗셈\n");
	printf("5. 나머지\n");
}

int add(int a, int b) {
	return a + b;
}
int minus(int a, int b) {
	return a - b;
}
int multiple(int a, int b) {
	return a * b;
}
double division(int a, int b) {
	return a / (double)b;
}
int remainder(int a, int b) {
	return a % b;
}

int pick_menu(void) {
	int pick;
	do {
	printf("원하시는 메뉴를 선택하세요(1~5 정수): _\b");
	scanf("%d", &pick);
	} while (pick != 1 && pick != 2 && pick != 3 && pick != 4 && pick != 5);
	return pick;
}

void calculate(int n) {
	int a, b;
	printf("정수 2개를 입력하세요: ");
	scanf("%d %d", &a, &b);

	switch (n) {
		case 1:
			printf("연산결과: %d = %d + %d\n", add(a, b), a, b);
			break;
		case 2:
			printf("연산결과: %d = %d - %d\n", minus(a, b), a, b);
			break;
		case 3:
			printf("연산결과: %d = %d × %d\n", multiple(a, b), a, b);
			break;
		case 4:
			printf("연산결과: %lf = %d ÷ %d\n", division(a, b), a, b);
			break;
		case 5:
			printf("연산결과: %d = %d ÷ %d의 나머지\n", remainder(a, b), a, b);
			break;
		default:
			printf("ERR\n");
			break;
	}
}

~END~

 

반응형

블로그의 정보

노력하는 실버티어

노실언니

활동하기