C 언어로 팩토리얼 계산기 만들기

CBeginner
지금 연습하기

소개

이 랩에서는 C 프로그래밍 언어로 팩토리얼 계산기를 만드는 방법을 배우게 됩니다. 이 랩은 for 루프의 구문 이해, 배열 요소 반복, 팩토리얼 계산 구현, 예외 처리, 팩토리얼 계산기 테스트 및 디버깅과 같은 필수 주제를 다룹니다. 이 랩을 마치면 이러한 기본적인 프로그래밍 개념에 대한 확실한 이해를 갖게 되며, 이를 활용하여 기능적인 팩토리얼 계산기를 구축할 수 있게 됩니다.

이 랩은 팩토리얼 계산기를 만드는 과정을 안내하기 위해 단계별 지침과 코드 예제를 제공합니다. 먼저, 배열을 반복하고 반복적인 작업을 수행하는 데 중요한 for 루프의 기본 구문을 배우게 됩니다. 그런 다음, 팩토리얼 계산에 필수적인 배열 요소에 접근하고 조작하는 방법을 탐구할 것입니다. 또한, 이 랩에서는 팩토리얼 계산 구현, 예외 처리, 최종 프로그램 테스트 및 디버깅을 다룹니다.

For 루프 구문 이해하기

이 단계에서는 C 프로그래밍에서 배열을 반복하고 팩토리얼 계산과 같은 반복적인 작업을 수행하는 데 필수적인 for 루프의 기본적인 구문에 대해 배우게 됩니다.

기본적인 for 루프 구문을 보여주는 간단한 C 프로그램을 만들어 시작해 보겠습니다. WebIDE 를 열고 ~/project 디렉토리에 loop_example.c라는 새 파일을 만듭니다.

cd ~/project
touch loop_example.c
#include <stdio.h>

int main() {
    // Basic for loop syntax: for (initialization; condition; increment/decrement)
    for (int i = 0; i < 5; i++) {
        printf("Current iteration: %d\n", i);
    }
    return 0;
}

예시 출력:

Current iteration: 0
Current iteration: 1
Current iteration: 2
Current iteration: 3
Current iteration: 4

for 루프 구문을 자세히 살펴보겠습니다.

  • int i = 0: 초기화 (Initialization) - 루프 카운터 변수를 초기 값으로 설정합니다.
  • i < 5: 조건 (Condition) - 이 조건이 참인 동안 루프를 계속합니다.
  • i++: 증가 (Increment) - 각 반복 후 루프 카운터를 증가시킵니다.

이제 프로그램을 컴파일하고 실행하여 루프가 어떻게 작동하는지 확인합니다.

gcc loop_example.c -o loop_example
./loop_example

for 루프는 반복 프로세스를 정확하게 제어할 수 있기 때문에 강력합니다. 배열을 순회하거나 계산을 수행하는 등 다양한 프로그래밍 요구 사항에 맞게 초기화, 조건 및 증가/감소 부분을 수정할 수 있습니다.

배열 요소 순회하기

이 단계에서는 C 에서 배열 요소를 반복하는 방법을 배우게 됩니다. 이는 팩토리얼 계산기를 구현하는 데 매우 중요합니다. 이전 단계의 for 루프 지식을 바탕으로, 배열 요소에 접근하고 조작하는 방법을 살펴보겠습니다.

배열 반복을 보여주기 위해 ~/project 디렉토리에 array_iteration.c라는 새 파일을 만들어 보겠습니다.

cd ~/project
touch array_iteration.c
#include <stdio.h>

int main() {
    // Declare and initialize an array of integers
    int numbers[5] = {10, 20, 30, 40, 50};

    // Iterate through the array using a for loop
    for (int i = 0; i < 5; i++) {
        printf("Element at index %d is: %d\n", i, numbers[i]);
    }

    return 0;
}

예시 출력:

Element at index 0 is: 10
Element at index 1 is: 20
Element at index 2 is: 30
Element at index 3 is: 40
Element at index 4 is: 50

주요 개념을 자세히 살펴보겠습니다.

  • int numbers[5]는 5 개의 정수 요소를 저장할 수 있는 배열을 생성합니다.
  • {10, 20, 30, 40, 50}은 특정 값으로 배열을 초기화합니다.
  • numbers[i]는 인덱스를 사용하여 개별 배열 요소에 접근합니다.
  • for 루프는 i를 인덱스로 사용하여 각 요소에 순차적으로 접근합니다.

이제 프로그램을 컴파일하고 실행합니다.

gcc array_iteration.c -o array_iteration
./array_iteration

반복을 더 실용적으로 만들기 위해 배열 요소의 합을 계산하는 예제를 만들어 보겠습니다.

#include <stdio.h>

int main() {
    int numbers[5] = {10, 20, 30, 40, 50};
    int sum = 0;

    // Calculate sum using array iteration
    for (int i = 0; i < 5; i++) {
        sum += numbers[i];
    }

    printf("Sum of array elements: %d\n", sum);

    return 0;
}

예시 출력:

Sum of array elements: 150

이것은 for 루프를 사용하여 배열 요소에 대한 연산을 수행하는 방법을 보여줍니다. 이는 곧 구현할 팩토리얼 계산기에서 매우 중요할 것입니다.

팩토리얼 계산 구현하기

이 단계에서는 이전 단계에서 배운 루프 반복 기술을 사용하여 C 에서 팩토리얼 계산 함수를 구현하는 방법을 배우게 됩니다. 팩토리얼은 숫자를 그보다 작은 모든 양의 정수로 곱하는 수학적 연산입니다.

~/project 디렉토리에 factorial_calculator.c라는 새 파일을 만들어 보겠습니다.

cd ~/project
touch factorial_calculator.c
#include <stdio.h>

// Function to calculate factorial
int calculateFactorial(int n) {
    // Initialize result to 1
    int factorial = 1;

    // Use for loop to multiply numbers from 1 to n
    for (int i = 1; i <= n; i++) {
        factorial *= i;
    }

    return factorial;
}

int main() {
    // Test factorial calculation for different numbers
    int numbers[] = {0, 1, 5, 7};

    // Iterate through the numbers and calculate their factorials
    for (int j = 0; j < 4; j++) {
        int num = numbers[j];
        int result = calculateFactorial(num);

        printf("Factorial of %d is: %d\n", num, result);
    }

    return 0;
}

예시 출력:

Factorial of 0 is: 1
Factorial of 1 is: 1
Factorial of 5 is: 120
Factorial of 7 is: 5040

팩토리얼 계산을 자세히 살펴보겠습니다.

  • 0 과 1 의 팩토리얼은 1 입니다.
  • n 의 팩토리얼 (n!) = 1 2 3 ... n
  • calculateFactorial() 함수는 for 루프를 사용하여 숫자를 곱합니다.
  • 팩토리얼을 1 부터 시작하여 n 까지의 각 숫자로 곱합니다.

프로그램을 컴파일하고 실행합니다.

gcc factorial_calculator.c -o factorial_calculator
./factorial_calculator

계산기를 더 대화형으로 만들기 위해 사용자 입력을 받도록 프로그램을 수정해 보겠습니다.

#include <stdio.h>

int calculateFactorial(int n) {
    int factorial = 1;
    for (int i = 1; i <= n; i++) {
        factorial *= i;
    }
    return factorial;
}

int main() {
    int number;

    // Prompt user for input
    printf("Enter a number to calculate its factorial: ");
    scanf("%d", &number);

    // Calculate and display factorial
    int result = calculateFactorial(number);
    printf("Factorial of %d is: %d\n", number, result);

    return 0;
}

예시 상호 작용:

Enter a number to calculate its factorial: 6
Factorial of 6 is: 720

예외 상황 처리

이 단계에서는 팩토리얼 계산기에서 음수와 정수 오버플로우를 일으킬 수 있는 큰 입력과 같은 엣지 케이스를 처리하는 방법을 배우게 됩니다. 안정적인 소프트웨어를 만들기 위해서는 강력한 오류 처리가 필수적입니다.

팩토리얼 계산기를 수정하여 이러한 엣지 케이스를 처리해 보겠습니다. ~/project 디렉토리에 factorial_edge_cases.c라는 새 파일을 만듭니다.

cd ~/project
touch factorial_edge_cases.c
#include <stdio.h>
#include <limits.h>

// Function to calculate factorial with error handling
int calculateFactorial(int n) {
    // Check for negative numbers
    if (n < 0) {
        printf("Error: Factorial is not defined for negative numbers.\n");
        return -1;
    }

    // Initialize result to 1
    int factorial = 1;

    // Check for potential integer overflow
    for (int i = 1; i <= n; i++) {
        // Check if multiplication will cause overflow
        if (factorial > INT_MAX / i) {
            printf("Error: Factorial result exceeds integer limit.\n");
            return -1;
        }
        factorial *= i;
    }

    return factorial;
}

int main() {
    // Test various edge cases
    int test_cases[] = {-5, 0, 1, 12, 13};

    for (int i = 0; i < 5; i++) {
        int number = test_cases[i];
        int result = calculateFactorial(number);

        // Only print result if calculation was successful
        if (result != -1) {
            printf("Factorial of %d is: %d\n", number, result);
        }
    }

    return 0;
}

예시 출력:

Error: Factorial is not defined for negative numbers.
Factorial of 0 is: 1
Factorial of 1 is: 1
Factorial of 12 is: 479001600
Error: Factorial result exceeds integer limit.

주요 오류 처리 기술:

  • 계산 전에 음수 확인
  • 정수 오버플로우를 방지하기 위해 INT_MAX 사용
  • 계산 오류를 나타내기 위해 -1 반환
  • 유익한 오류 메시지 제공

프로그램을 컴파일하고 실행합니다.

gcc factorial_edge_cases.c -o factorial_edge_cases
./factorial_edge_cases

더 사용자 친화적인 입력 처리를 위해 프로그램을 개선해 보겠습니다.

#include <stdio.h>
#include <limits.h>

int calculateFactorial(int n) {
    if (n < 0) {
        printf("Error: Factorial is not defined for negative numbers.\n");
        return -1;
    }

    int factorial = 1;

    for (int i = 1; i <= n; i++) {
        if (factorial > INT_MAX / i) {
            printf("Error: Factorial result exceeds integer limit.\n");
            return -1;
        }
        factorial *= i;
    }

    return factorial;
}

int main() {
    int number;

    while (1) {
        printf("Enter a non-negative integer (or negative to exit): ");

        // Check if input is valid
        if (scanf("%d", &number) != 1) {
            printf("Invalid input. Please enter an integer.\n");
            // Clear input buffer
            while (getchar() != '\n');
            continue;
        }

        // Exit condition
        if (number < 0) {
            printf("Exiting factorial calculator.\n");
            break;
        }

        // Calculate and display factorial
        int result = calculateFactorial(number);
        if (result != -1) {
            printf("Factorial of %d is: %d\n", number, result);
        }
    }

    return 0;
}

예시 상호 작용:

Enter a non-negative integer (or negative to exit): 10
Factorial of 10 is: 3628800
Enter a non-negative integer (or negative to exit): -1
Exiting factorial calculator.

팩토리얼 계산기 테스트 및 디버깅

이 마지막 단계에서는 다양한 테스트 기술과 디버깅 전략을 사용하여 팩토리얼 계산기를 철저하게 테스트하고 디버깅하는 방법을 배우게 됩니다.

다중 테스트 케이스와 디버깅 기능을 포함하는 포괄적인 테스트 프로그램을 만들어 보겠습니다. ~/project 디렉토리에 factorial_test.c라는 파일을 만듭니다.

cd ~/project
touch factorial_test.c
#include <stdio.h>
#include <assert.h>
#include <limits.h>

// Factorial calculation function with detailed error checking
int calculateFactorial(int n) {
    // Debug print to track function calls
    printf("DEBUG: Calculating factorial for %d\n", n);

    // Validate input range
    if (n < 0) {
        fprintf(stderr, "ERROR: Factorial undefined for negative numbers\n");
        return -1;
    }

    // Handle special cases
    if (n == 0 || n == 1) return 1;

    // Factorial calculation with overflow protection
    long long factorial = 1;
    for (int i = 2; i <= n; i++) {
        factorial *= i;

        // Overflow check
        if (factorial > INT_MAX) {
            fprintf(stderr, "ERROR: Factorial exceeds integer limit\n");
            return -1;
        }
    }

    return (int)factorial;
}

// Test function to verify factorial calculations
void runTests() {
    // Test cases with expected results
    struct TestCase {
        int input;
        int expected;
    } tests[] = {
        {0, 1},    // Edge case: 0!
        {1, 1},    // Edge case: 1!
        {5, 120},  // Normal case: 5!
        {10, 3628800}  // Larger number
    };

    int numTests = sizeof(tests) / sizeof(tests[0]);

    printf("Running %d test cases...\n", numTests);

    // Iterate through test cases
    for (int i = 0; i < numTests; i++) {
        int result = calculateFactorial(tests[i].input);

        // Assertion-style testing
        if (result == tests[i].expected) {
            printf("Test case %d PASSED: factorial(%d) = %d\n",
                   i+1, tests[i].input, result);
        } else {
            printf("Test case %d FAILED: Expected %d, Got %d\n",
                   i+1, tests[i].expected, result);
        }
    }
}

int main() {
    // Run comprehensive test suite
    runTests();

    // Interactive testing mode
    int number;
    printf("\nEnter a number to calculate its factorial (or negative to exit): ");
    while (scanf("%d", &number) == 1 && number >= 0) {
        int result = calculateFactorial(number);
        if (result != -1) {
            printf("Factorial of %d is: %d\n", number, result);
        }

        printf("\nEnter another number (or negative to exit): ");
    }

    return 0;
}

프로그램을 컴파일하고 실행합니다.

gcc factorial_test.c -o factorial_test
./factorial_test

예시 출력은 다음과 같습니다.

Running 4 test cases...
DEBUG: Calculating factorial for 0
Test case 1 PASSED: factorial(0) = 1
DEBUG: Calculating factorial for 1
Test case 2 PASSED: factorial(1) = 1
DEBUG: Calculating factorial for 5
Test case 3 PASSED: factorial(5) = 120
DEBUG: Calculating factorial for 10
Test case 4 PASSED: factorial(10) = 3628800

Enter a number to calculate its factorial (or negative to exit):

시연된 주요 디버깅 및 테스트 기술:

  • 함수 실행을 추적하기 위한 디버그 출력문
  • 엣지 케이스를 다루는 포괄적인 테스트 케이스
  • 잘못된 입력에 대한 오류 처리
  • 오버플로우 방지
  • 어설션 스타일 테스트
  • 대화형 테스트 모드

디버깅 팁:

  1. 로깅 및 함수 호출 추적에 printf() 사용
  2. 엣지 케이스를 명시적으로 처리
  3. 입력 유효성 검사 구현
  4. 더 큰 숫자 계산에 long long 사용
  5. 다양한 시나리오를 확인하기 위해 테스트 스위트 만들기

요약

이 랩에서는 C 프로그래밍에서 for 루프의 기본적인 구문을 배웠습니다. 이는 배열을 반복하고 팩토리얼 계산과 같은 반복적인 작업을 수행하는 데 필수적입니다. 또한 팩토리얼 계산기를 구현하는 데 중요한 배열 요소를 반복하는 방법도 살펴보았습니다.

기본적인 for 루프 구문을 보여주는 간단한 C 프로그램을 만들어 루프의 초기화, 조건 및 증가/감소 부분을 이해하는 것으로 시작했습니다. 그런 다음 for 루프를 사용하여 정수 배열을 반복하고 배열 요소에 액세스하고 조작하는 방법을 배웠습니다.