윤성우의 열혈 C 프로그래밍 - 함수 정의

Yumin Jung·2023년 5월 14일
0
post-thumbnail

복습을 하던 중, 함수 파트가 매우 취약함을 느꼈고, 개념을 다시 정리 후 옛날에 풀어봤던 연습문제를 다시 한 번 풀어보는 계기가 되었다.

9-1-문제1 (p.221)

세 개의 정수를 인자로 전달받아서 그 중 가장 큰 수를 반환하는 함수와 가장 작은 수를 반환하는 정수를 정의해보자. 그리고 이 함수들을 호출하는 적절한 main 함수도 작성해보자.

#include <stdio.h>

void MostBigSmall(int a, int b, int c) {
	if (a > b) {
		if (a > c) {
			printf("가장 큰 정수는 %d입니다\n", a);
			if (b > c)
				printf("가장 작은 정수는 %d입니다\n", c);
			else
				printf("가장 작은 정수는 %d입니다\n", b);
		}
		else {
			printf("가장 큰 정수는 %d입니다\n", c);
			printf("가장 작은 정수는 %d입니다\n", b);
		}
	}
	if (a < b) {
		if (a > c) {
			printf("가장 큰 정수는 %d입니다\n", b);
			printf("가장 작은 정수는 %d입니다\n", c);
		}
		else {
			printf("가장 작은 정수는 %d입니다\n", a);
			if (b < c)
				printf("가장 큰 정수는 %d입니다\n", c);
			else
				printf("가장 큰 정수는 %d입니다\n", b);
		}
	}
}

int main(void) {
	int a, b, c;
	printf("세 정수를 받아 크기를 비교하여 
    가장 큰 정수와 가장 작은 정수를 반환하는 프로그램입니다."
		" 비교할 세개의 정수를 입력하세요 : ");
	scanf_s("%d %d %d", &a, &b, &c);
	MostBigSmall(a, b, c);
}

중첩 if문을 사용하여 문제를 해결하였으나, 뭔가 기분이 꺼름직했다. 더 쉽게 풀 방법이 있을 것 같았다.

해설의 도움을 받아 if, else 문을 조건연산자로 바꿀 수 있다는 것을 깨달았다. 조건연산자가 무엇인지는 제대로 알지만, 막상 프로그래밍 할 때에 조건연산자를 떠올리지 못하는게 나의 miss였다.

그리고 MostBigSmall 함수에서 printf 함수를 호출한게 아니라 main함수에서 한 번에 호출함으로서, 내가 한 것과 같이 반복적으로

printf("가장 큰 정수는 %d입니다\n", c);
printf("가장 작은 정수는 %d입니다\n", b);

이런식으로 쓸 이유가 없었다.
여기서 내가 깨달은 점은 무조건 main함수부터 작성해서 맞추는 것이 프로그래밍을 하는데 있어서 좀 더 효율적이라는 것이다.

#include <stdio.h>

int MostBig(int n1, int n2, int n3)
{
	if (n1 > n2)
		return (n1 > n3) ? n1 : n3;
	else
		return (n2 > n3) ? n2 : n3;
	}

int MostSmall(int n1, int n2, int n3)
{
	if (n1 < n2)
		return (n1 < n3) ? n1 : n3;
	else
		return (n2 < n3) ? n2 : n3;
}

int main(void)
{
	int num1, num2, num3;
	printf("세 개 정수를 입력하면 그 중 제일 큰 것과 제일 작은 것 알려줄게요.\n\n-------------------------------------------\n입력: ");
	scanf_s("%d, %d, %d", &num1, &num2, &num3);
	printf("가장 큰 수 : %d\n", MostBig(num1, num2, num3));
	printf("가장 작은 수 : %d\n", MostSmall(num1, num2, num3));
	return 0;
}

자자, 답지와 다를 것 없이 똑같이 했는데 실행이 이상하게 된다. 5시간 동안 다른 점을 찾아 해맸지만 없는 것으로 보아 컴파일러의 문제인것 같다. - 라고 했지만 역시 내 실수였다. 온라인 컴파일러를 이용하여 그대로 복붙하여 실행했지만 결과값이 똑같이 잘못되어 나왔다.

뭐가 틀린지 원인을 모른 채 메인 함수를 다시 지우고 작성한 후, 온라인 컴파일러에서 실행하니 잘 되었다. 다시 작성한 메인함수와 이전에 계속 오류났던 메인함수를 비교해봤지만 도대체가 뭐가 잘못되었는지 차이점을 알 수가 없었다. 내 눈이 문제인건가.

/*오류 난 메인함수*/
int main(void)
{
	int num1, num2, num3;
	printf("세 개 정수를 입력하면 그 중 제일 큰 것과 제일 작은 것 알려줄게요.\n\n-------------------------------------------\n입력: ");
	scanf_s("%d, %d, %d", &num1, &num2, &num3);
	printf("가장 큰 수 : %d\n", MostBig(num1, num2, num3));
	printf("가장 작은 수 : %d\n", MostSmall(num1, num2, num3));
	return 0;
}
/*오류 안 난 메인함수*/
int main(void)
{
	int num1, num2, num3;
	printf("세 개 정수 입력 : ");
	scanf_s("%d %d %d", &num1, &num2, &num3);
	printf("제일 큰 수: %d\n", MostBig(num1, num2, num3));
	printf("제일 작은 수: %d", MostSmall(num1, num2, num3));
	return 0;
}

뭐가 잘못됐는지 알려줄사람.. 댓글로

9-1-2

섭씨(Cel)온도를 입력하면 화씨(Fah) 온도를 반환하는 CelToFah라는 이름의 함수와 그 반대로 화씨 온도를 입력하면 섭씨 온도를 반환하는 FahToCel라는 이름의 함수를 정의하고 이 두 함수를 호출하는 예제를 완성해보자. 참고로 섭씨와 화씨간 온도변화의 공식은 다음과 같다.
Fah=1.8 * Cel + 32

#include <stdio.h>

void CelToFah(double Cel) {
	double Fah = 1.8 * Cel + 32;
	printf("섭씨 %lf는 화씨 %lf입니다\n\n\n\n\n", Cel, Fah);
}

void FahToCel(double Fah) {
	double Cel = (Fah - 32) / 1.8;
	printf("화씨 %lf는 섭씨 %lf입니다\n\n\n\n\n", Fah, Cel);
}

int main(void) {
	int num;
	double Cel;
	double Fah;
	printf("섭씨를 화씨로, 또는 화씨를 섭씨로 바꿔주는 프로그램입니다.\n---------------------------------\n\n1번: 섭씨를 화씨로\n\n2번: 화씨를 섭씨로\n\n\n 옵션에 해당하는 번호를 입력하세요: ");
	scanf_s("%d", &num);

	if (num = 1) {
		printf("섭씨 온도를 입력하세요: ");
		scanf_s("%lf", &Cel);
		CelToFah(Cel);
		return 0;
	}
	if (num = 2) {
		printf("화씨 온도를 입력하세요: ");
		scanf_s("%lf", &Fah);
		FahToCel(Fah);
		return 0;
	}
	else
		printf("번호 잘못 입력하셨어요, 다시 입력해주세요");
}

아주 잘 한 것 같지만 틀렸다. 변환은 성공적으로 되었지만 옵션 번호를 입력하는 과정에서 if (num = 1) 대입 연산자가 아닌 if (num == 1) 동등 연산자를 사용했어야 했다. 으이그.
그리고, if문을 이용하여 메뉴에 없는 잘못된 번호를 입력했을때 다시 되돌아가는 방식으로 짜는 방법을 모르겠다. 어떻게 하는지 알아내면 이것은 수정해서 다시 작성하도록 하겠다.

더 좋은 방법으로는 case switch 문이 있었다,(까먹고 있었음) 작성해보았다.

#include <stdio.h>

void CelToFah(double Cel) {
	double Fah = 1.8 * Cel + 32;
	printf("섭씨 %lf는 화씨 %lf입니다\n\n\n\n\n", Cel, Fah);
}

void FahToCel(double Fah) {
	double Cel = (Fah - 32) / 1.8;
	printf("화씨 %lf는 섭씨 %lf입니다\n\n\n\n\n", Fah, Cel);
}

int main(void) {
	int num;
	double Cel;
	double Fah;
	printf("섭씨를 화씨로, 또는 화씨를 섭씨로 바꿔주는 프로그램입니다.\n---------------------------------------------------------\n\n1번: 섭씨를 화씨로\n\n2번: 화씨를 섭씨로\n\n\n 옵션에 해당하는 번호를 입력하세요: ");
	scanf_s("%d", &num);

	switch (num)
	{
	case 1:
		printf("섭씨 온도를 입력하세요: ");
		scanf_s("%lf", &Cel);
		CelToFah(Cel);
		break;

	case 2:
		printf("화씨 온도를 입력하세요: ");
		scanf_s("%lf", &Fah);
		FahToCel(Fah);
		break;

	default:
		printf("\n\n\n번호 잘못 입력하셨어요, 다시 입력해주세요\n\n\n\n\n\n\n");
		main();
	}
	return 0;
}

default영역에 main()함수 시작으로 다시 돌아가는 소스와 함께 작성을 마무리 했다.

9-1-3

인자로 전달된 수만큼의 피보나치 수열을 출력하는 함수를 정의해보자. 예를 들어서 프로그램 사용자가 5를 입력하면 0에서부터 시작해서 총 5개의 피보나치 수열을 출력해야 한다. 참고로 피보나치 수열은 다음과 같다.
0, 1, 1, 2, 3, 5, 8, 13, 21, 34 ~
이렇듯 피보나치 수열은 0과 1에서 시작한다. 그리고 세 번째 이후의 수열부터는 이전의 두 값의 합으로 구성된다. 즉, 세 번째 수는 0과 1의 합으로 이뤄져서 1이 되고, 네 번째 수는 1과 1의 합으로 이뤄져서 2가 된다.

#include <stdio.h>

void Pibonachi(int n) {
	int n1 = 0, n2 = 1, n3, i;

	if (n == 1)
		printf("%d ", n1);
	else/*무조건 거치게 된다!*/
		printf("%d %d ", n1, n2);

	for (i = 0; i < n - 2; i++) {
		n3 = n1 + n2;
		printf("%d ", n3);
		n1 = n2;
		n2 = n3;
	}
}
int main(void) {
	int user;
	printf("피보나치 수열을 작성하는 프로그램입니다. 개수를 작성하세요: ");
	scanf_s("%d", &user);
	if (user < 1) {
		printf("1이상의 값을 선택하세요.\n\n\n\n");
		return -1;
	}
	Pibonachi(user);
	return 0;
}

코드를 내 스스로 전체 작성&실행까지 가지 못하였다. 답지의 도움을 받았다.

Pibonachi 함수를 작성하지 못하였다. 세번째 이상의 수열을 요청했을 경우 두번째까지는 if else 함수를 이용하여 표현하게끔 하는 것을 생각하지 못했다.

그리고 1이상의 값을 선택안했을때 return -1을 사용한 것이 나는 다시 돌아가게 하는 줄 알았다. 9-1-2번 문제에서 마땅한 방법이 생각나지 않아 main함수로 다시 돌아가게 표현했는데, 오 ! 저런 방법이 있다니! 하며 실행을 해보았지만,, 근데 안되네..? 왜 return -1을 한거지?

"0이 아닌 수(-1, 1... etc)도 다 되지만, 일반적으로 0을 리턴하면 해당 함수를 성공적으로 끝냈다는 의미"

라고 한다. 그럼 그냥 return 0으로 통일하면 되는걸 왜 답지에서는 return -1이라고 했을까. 추후 알게되면 다시 오겠다.

profile
문과를 정말로 존중해

0개의 댓글