이 문서에서는 C 언어를 사용하여 여러 가지 일반적인 프로그래밍 문제에 대한 해결책을 탐구합니다. 점수 등급 변환, 숫자의 자릿수 합 계산, 거듭제곱 연산, 삼각형 분류, 조합 계산, 최대공약수(GCD) 찾기, 그리고 특정 문자 패턴 출력과 같은 다양한 시나리오를 다루며, 각 문제에 대한 함수 구현과 로직을 분석합니다.
1. 점수 등급 변환
주어진 점수를 기준으로 학점을 부여하는 함수를 구현합니다. 일반적으로 90점 이상은 'A', 80점 이상은 'B', 70점 이상은 'C', 60점 이상은 'D', 그 외는 'F'로 분류합니다. 이 예시에서는 60점 미만을 'E'로 처리합니다.
#include <stdio.h>
// 학점을 계산하는 함수 선언
char getGradeFromScore(int numericScore);
int main() {
int inputScore;
char assignedGrade;
printf("점수를 입력하세요 (EOF로 종료): \n");
while(scanf("%d", &inputScore) != EOF) {
if (inputScore < 0 || inputScore > 100) {
printf("유효하지 않은 점수: %d. 0-100 사이의 점수를 입력하세요.\n\n", inputScore);
continue;
}
assignedGrade = getGradeFromScore(inputScore); // 함수 호출
printf("입력 점수: %d, 부여 등급: %c\n\n", inputScore, assignedGrade);
}
return 0;
}
// 학점을 계산하는 함수 정의
char getGradeFromScore(int numericScore) {
if (numericScore >= 90) {
return 'A';
} else if (numericScore >= 80) {
return 'B';
} else if (numericScore >= 70) {
return 'C';
} else if (numericScore >= 60) {
return 'D';
} else {
return 'E';
}
}
2. 숫자의 각 자릿수 합 계산
양의 정수를 입력받아 그 숫자를 구성하는 각 자릿수의 합을 계산하는 함수를 작성합니다. 예를 들어, 123을 입력하면 1 + 2 + 3 = 6을 반환합니다.
#include <stdio.h>
// 재귀를 사용하여 자릿수 합을 계산하는 함수 선언
int calculateDigitSum(int number);
int main() {
int inputNumber;
int digitSumResult;
printf("정수를 입력하세요 (EOF로 종료): \n");
while(scanf("%d", &inputNumber) != EOF) {
if (inputNumber < 0) {
printf("음수는 처리할 수 없습니다. 양수를 입력하세요.\n\n");
continue;
}
digitSumResult = calculateDigitSum(inputNumber); // 함수 호출
printf("입력 숫자: %d, 자릿수 합계: %d\n\n", inputNumber, digitSumResult);
}
return 0;
}
// 재귀를 사용하여 자릿수 합을 계산하는 함수 정의
int calculateDigitSum(int number) {
if (number == 0) {
return 0; // 숫자가 0이 되면 재귀 종료
} else {
// 현재 자릿수를 더하고 나머지 숫자에 대해 재귀 호출
return (number % 10) + calculateDigitSum(number / 10);
}
}
3. 거듭제곱(Power) 함수 구현
두 정수 x와 n을 입력받아 x의 n제곱(x^n)을 효율적으로 계산하는 함수를 구현합니다. 특히 n이 큰 경우를 고려하여 재귀적 분할 정복 방식을 사용합니다.
#include <stdio.h>
// 거듭제곱을 계산하는 함수 선언
long long powerEfficient(int base, int exponent);
int main() {
int val_x, val_n;
long long result_power;
printf("밑(x)과 지수(n)를 입력하세요 (EOF로 종료): \n");
while(scanf("%d%d", &val_x, &val_n) != EOF) {
if (val_n < 0) {
printf("음수 지수는 처리하지 않습니다. 양수 또는 0 지수를 입력하세요.\n\n");
continue;
}
result_power = powerEfficient(val_x, val_n); // 함수 호출
printf("%d의 %d제곱 = %lld\n\n", val_x, val_n, result_power);
}
return 0;
}
// 거듭제곱을 효율적으로 계산하는 함수 정의 (재귀)
long long powerEfficient(int base, int exponent) {
if (exponent == 0) {
return 1; // 어떤 수의 0제곱은 1
}
long long half_power = powerEfficient(base, exponent / 2); // 절반 지수에 대한 거듭제곱 계산
if (exponent % 2 == 0) {
return half_power * half_power; // 지수가 짝수이면 (x^(n/2))^2
} else {
return base * half_power * half_power; // 지수가 홀수이면 x * (x^(n/2))^2
}
}
4. 삼각형의 종류 분류
세 변의 길이를 입력받아 해당 변들로 삼각형을 구성할 수 있는지 여부와, 구성할 수 있다면 어떤 종류의 삼각형(정삼각형, 이등변삼각형, 직각삼각형, 일반삼각형)인지 분류하는 함수를 작성합니다.
#include <stdio.h>
#include <math.h> // for sqrt, pow if needed, but not strictly for this integer version
// 삼각형 분류 결과를 나타내는 enum
typedef enum {
INVALID_TRIANGLE = 0,
SCALENE_TRIANGLE, // 일반 삼각형
EQUILATERAL_TRIANGLE, // 정삼각형
ISOSCELES_TRIANGLE, // 이등변 삼각형
RIGHT_TRIANGLE // 직각 삼각형
} TriangleType;
// 삼각형을 분류하는 함수 선언
TriangleType determineTriangleType(int sideA, int sideB, int sideC);
int main() {
int s1, s2, s3;
TriangleType typeResult;
printf("세 변의 길이를 입력하세요 (EOF로 종료): \n");
while (scanf("%d%d%d", &s1, &s2, &s3) != EOF) {
typeResult = determineTriangleType(s1, s2, s3);
switch (typeResult) {
case INVALID_TRIANGLE:
printf("유효하지 않은 삼각형입니다.\n");
break;
case SCALENE_TRIANGLE:
printf("일반 삼각형입니다.\n");
break;
case EQUILATERAL_TRIANGLE:
printf("정삼각형입니다.\n");
break;
case ISOSCELES_TRIANGLE:
printf("이등변 삼각형입니다.\n");
break;
case RIGHT_TRIANGLE:
printf("직각 삼각형입니다.\n");
break;
default:
printf("알 수 없는 오류 발생.\n");
}
printf("\n");
}
return 0;
}
// 삼각형을 분류하는 함수 정의
TriangleType determineTriangleType(int sideA, int sideB, int sideC) {
// 1. 유효성 검사: 변의 길이는 양수여야 함
if (sideA <= 0 || sideB <= 0 || sideC <= 0) {
return INVALID_TRIANGLE;
}
// 2. 유효성 검사: 삼각형 부등식 (두 변의 합은 나머지 한 변보다 커야 함)
if (sideA + sideB <= sideC || sideA + sideC <= sideB || sideB + sideC <= sideA) {
return INVALID_TRIANGLE;
}
// 3. 정삼각형 확인
if (sideA == sideB && sideB == sideC) {
return EQUILATERAL_TRIANGLE;
}
// 4. 직각삼각형 확인 (피타고라스 정리: a^2 + b^2 = c^2)
// 최대 변을 찾고 나머지 두 변과의 관계 확인
long long a_sq = (long long)sideA * sideA;
long long b_sq = (long long)sideB * sideB;
long long c_sq = (long long)sideC * sideC;
if (a_sq + b_sq == c_sq || a_sq + c_sq == b_sq || b_sq + c_sq == a_sq) {
return RIGHT_TRIANGLE;
}
// 5. 이등변삼각형 확인 (두 변의 길이가 같음)
if (sideA == sideB || sideA == sideC || sideB == sideC) {
return ISOSCELES_TRIANGLE;
}
// 6. 위의 모든 조건에 해당하지 않으면 일반 삼각형
return SCALENE_TRIANGLE;
}
5. 조합(Combination) 계산
n개의 항목 중 m개를 선택하는 조합의 수 (nCm)를 계산하는 함수를 구현합니다. 조합은 순서에 상관없이 요소를 선택하는 경우의 수를 나타냅니다. 이 예제에서는 반복적인 방법으로 조합의 수를 계산합니다.
#include <stdio.h>
// 조합의 수를 계산하는 함수 선언 (nCm)
long long calculateCombinations(int n, int m);
int main() {
int totalItems, chosenItems;
long long combinationResult;
printf("총 항목 수(n)와 선택할 항목 수(m)를 입력하세요 (EOF로 종료): \n");
while (scanf("%d%d", &totalItems, &chosenItems) != EOF) {
combinationResult = calculateCombinations(totalItems, chosenItems);
printf("C(%d, %d) = %lld\n\n", totalItems, chosenItems, combinationResult);
}
return 0;
}
// 조합의 수를 계산하는 함수 정의 (반복문 사용)
long long calculateCombinations(int n, int m) {
// 1. 유효성 검사
if (m < 0 || m > n) {
return 0; // 선택할 항목 수가 음수이거나 전체 항목 수보다 많으면 0
}
if (m == 0 || m == n) {
return 1; // 0개 또는 n개를 선택하는 경우의 수는 1
}
// 2. 대칭성 활용: C(n, m) = C(n, n-m)
// 계산량을 줄이기 위해 m이 n/2보다 크면 n-m으로 대체
if (m > n / 2) {
m = n - m;
}
// 3. 반복문을 사용하여 조합 계산
// C(n, m) = (n * (n-1) * ... * (n-m+1)) / (m * (m-1) * ... * 1)
// 각 항을 곱하고 나누면서 중간 오버플로우를 방지하기 위해
// (res * (n - i + 1)) / i 형태로 계산
long long currentResult = 1;
for (int i = 1; i <= m; i++) {
currentResult = currentResult * (n - i + 1) / i;
}
return currentResult;
}
6. 세 정수의 최대공약수(GCD) 계산
세 정수 a, b, c의 최대공약수(Greatest Common Divisor, GCD)를 계산하는 함수를 작성합니다. 세 수의 GCD는 두 수의 GCD를 확장하여 구할 수 있습니다: GCD(a, b, c) = GCD(GCD(a, b), c).
#include <stdio.h>
// 두 정수의 GCD를 유클리드 호제법으로 계산하는 함수 선언
int euclideanGCD(int num1, int num2);
// 세 정수의 GCD를 계산하는 함수 선언
int findThreeNumGCD(int val1, int val2, int val3);
int main() {
int n1, n2, n3;
int commonDivisor;
printf("세 정수를 입력하세요 (EOF로 종료): \n");
while (scanf("%d%d%d", &n1, &n2, &n3) != EOF) {
if (n1 <= 0 || n2 <= 0 || n3 <= 0) {
printf("양의 정수만 입력하세요.\n\n");
continue;
}
commonDivisor = findThreeNumGCD(n1, n2, n3);
printf("%d, %d, %d의 최대공약수: %d\n\n", n1, n2, n3, commonDivisor);
}
return 0;
}
// 두 정수의 GCD를 유클리드 호제법으로 계산하는 함수 정의
int euclideanGCD(int num1, int num2) {
while (num2 != 0) {
int temp = num2;
num2 = num1 % num2;
num1 = temp;
}
return num1;
}
// 세 정수의 GCD를 계산하는 함수 정의
int findThreeNumGCD(int val1, int val2, int val3) {
int gcd_ab = euclideanGCD(val1, val2);
int gcd_abc = euclideanGCD(gcd_ab, val3);
return gcd_abc;
}
7. 사용자 지정 크기의 문자 패턴 출력
정수 n을 입력받아 n의 크기에 해당하는 특정 문자 패턴을 출력하는 함수를 구현합니다. 이 패턴은 위에서 아래로 갈수록 폭이 좁아지는 형태의 'O', '<H>', 'I I' 문자로 구성됩니다.
#include <stdio.h>
// 특정 문자 패턴을 출력하는 함수 선언
void printShrinkingPattern(int size);
int main() {
int patternSize;
printf("패턴 크기 (n)를 입력하세요: ");
scanf("%d", &patternSize);
if (patternSize <= 0) {
printf("양의 정수를 입력해야 합니다.\n");
return 1;
}
printShrinkingPattern(patternSize);
return 0;
}
// 특정 문자 패턴을 출력하는 함수 정의
void printShrinkingPattern(int size) {
// 각 층은 3줄로 구성됨: 'O', '<H>', 'I I'
// 'n'은 가장 넓은 부분의 블록 수를 결정. 가장 위는 2n-1 블록
// 각 층마다 블록 수가 2개씩 줄어듬
for (int currentLayer = 0; currentLayer < size; currentLayer++) {
int numBlocks = (2 * size - 1) - (2 * currentLayer); // 현재 층의 블록 수
int totalWidth = (2 * size - 1) * 4; // 최대 너비 (각 블록은 4칸 차지)
int currentLayerWidth = numBlocks * 4;
int leadingSpaces = (totalWidth - currentLayerWidth) / 2; // 중앙 정렬을 위한 앞 공백 수
// 1. 'O' 줄 출력
for (int i = 0; i < leadingSpaces; i++) printf(" ");
for (int i = 0; i < numBlocks; i++) printf(" O ");
printf("\n");
// 2. '<H>' 줄 출력
for (int i = 0; i < leadingSpaces; i++) printf(" ");
for (int i = 0; i < numBlocks; i++) printf("<H> ");
printf("\n");
// 3. 'I I' 줄 출력
for (int i = 0; i < leadingSpaces; i++) printf(" ");
for (int i = 0; i < numBlocks; i++) printf("I I ");
printf("\n");
}
}