프로그래밍 언어/C++

C++ 기초: 배열과 입력 검증 개선하기

로안님 2024. 12. 24. 23:59

저번 포스트에서 우리는 C++의 배열과 예외 처리를 활용해 사용자로부터 입력받은 숫자들의 합계와 평균을 계산하는 프로그램을 작성했습니다. 이번 포스트에서는 이전 코드의 문제점을 분석하고 이를 해결하며 프로그램을 개선한 내용을 공유합니다.


저번 코드의 문제점

  1. 숫자의 조건
    • 기존에는 "1 이상의 숫자만 입력 가능"이라는 제한을 두었지만, 소수점도 허용된다는 점에서 이 조건이 부자연스러웠습니다.
    • 이를 개선하여 음수를 포함한 모든 실수를 입력받을 수 있도록 변경했습니다.
  2. 배열 크기 입력 오류
    • 사용자가 배열 크기를 입력할 때 std::cin이 입력값을 지정된 타입(int)에 맞게 변환하려고 시도한다는 점을 알게 되었습니다.
    • 예를 들어, 소수를 입력하면 소수점 이하 값은 무시되고 정수 부분만 저장되었기에 프로그램의 의도와 다르게 동작했습니다.
    • 이를 해결하기 위해 입력값이 정수가 아니면 다시 입력받도록 정수 여부 확인 로직을 추가했습니다.
  3. 사용자 편의성 부족
    • 이전에는 입력 진행 상황이나 현재까지 입력된 값들을 사용자에게 보여주지 않았습니다.
    • 이를 보완하기 위해 입력 진행 상황과 이전에 입력된 값들을 출력하는 기능을 추가했습니다.

개선된 코드

아래는 문제점을 해결하고 추가 기능을 반영한 개선된 코드입니다.

#include <iostream>
#include <limits>
using namespace std;

// 문자열 입력 여부 확인 함수
bool isInvalidInput() {
    if (cin.fail()) { // 입력 실패 확인
        cin.clear(); // 스트림 상태 초기화
        cin.ignore(numeric_limits<streamsize>::max(), '\n'); // 잘못된 입력 무시
        return true; // 잘못된 입력
    }
    return false; // 올바른 입력
}

// 사용자로부터 숫자를 입력받아 배열에 저장하는 함수
void inputNumbers(double array[], int count) {
    int inputCount = 0;

    for (int i = 0; i < count; i++) {
        cout << "입력 진행 상황: " << inputCount + 1 << "/" << count << endl;

        // 현재까지 입력된 값 출력
        cout << "입력값(번호): ";
        for (int j = 0; j < inputCount; j++) {
            cout << array[j] << "(" << j + 1 << "), ";
        }
        cout << endl;

        cout << "숫자를 입력하세요 : ";

        while (true) {
            cin >> array[inputCount];
            if (isInvalidInput()) {
                cout << "문자열 입력은 허용되지 않습니다." << endl << "숫자를 다시 입력해주세요 : ";
            } else {
                inputCount++;
                break;
            }
        }
        cout << endl;
    }
}

// 배열의 합을 계산하는 함수
double calculateSum(const double array[], int count) {
    double sum = 0;
    for (int i = 0; i < count; i++) {
        sum += array[i]; // 배열 요소를 더함
    }
    return sum;
}

// 배열의 평균을 계산하는 함수
double calculateAverage(const double array[], int count) {
    double sum = calculateSum(array, count); // 합 계산
    return sum / count; // 평균 계산
}

// 정수 여부 확인 함수
bool isInteger(double value) {
    return value == static_cast<int>(value);
}

int main() {
    int count; // 개수는 int 선언
    const int MAX_SIZE = 100; 
    double numbers[MAX_SIZE];
    double input;

    // 숫자 개수 입력
    cout << "입력할 숫자의 개수를 정하세요. (2~100, 정수만) : ";

    while (true) {
        cin >> input;
        if (isInvalidInput()) {
            cout << "문자열 입력은 허용되지 않습니다. " << endl << "숫자를 다시 입력해주세요 : ";
        } else if (input >= 2 && input <= MAX_SIZE && isInteger(input)) {
            count = static_cast<int>(input); // 정상 입력 처리
            cout << endl;
            break;
        } else {
            cout << "입력값은 2 이상 100 이하의 정수만 가능합니다. 다시 입력해주세요: ";
        }
    }
    inputNumbers(numbers, count);

    // 배열의 합과 평균 계산
    double totalSum = calculateSum(numbers, count);
    double average = calculateAverage(numbers, count);

    // 결과 출력
    cout << "입력된 숫자의 합은: " << totalSum << endl;
    cout << "입력된 숫자의 평균은: " << average << endl;

    return 0;
}



개선된 내용 요약

  1. 입력 조건 완화
    • 1 이상의 숫자만 받던 제한을 제거하고 음수와 소수까지 포함하여 입력받을 수 있도록 변경했습니다.
  2. 정수 여부 확인 로직 추가
    • 배열 크기를 입력받는 과정에서 소수점 입력 시에도 오류 없이 처리되던 문제를 해결하기 위해 isInteger 함수를 추가했습니다.
  3. 사용자 편의성 개선
    • 입력 진행 상황과 현재까지 입력된 값을 출력함으로써 사용자가 자신의 입력값을 확인할 수 있도록 했습니다.

배운 점

  1. 입력 검증의 중요성
    • 프로그램의 입력 검증은 안정성과 신뢰성을 높이는 중요한 요소입니다. 사용자 경험을 고려한 검증 로직은 프로그램의 완성도를 크게 향상시킵니다.
  2. 유연한 조건 설계
    • 입력 조건을 지나치게 제한하지 않도록 주의하며, 유연하게 처리할 수 있는 설계를 고민해야 합니다.
  3. 사용자 피드백 제공
    • 입력 진행 상황과 입력값을 보여주는 방식은 사용자에게 큰 도움이 됩니다. 이는 프로그램의 직관성을 높이는 요소입니다.

다음 계획

  1. Remove 기능 추가
    • 사용자가 입력한 배열 값 중 특정 값을 제거할 수 있는 기능을 추가합니다.
    • 제거 이후 배열은 자동으로 재구성되어야 하며, 남은 값들을 기반으로 합계와 평균을 다시 계산할 수 있어야 합니다.
  2. Edit 기능 추가
    • 배열의 특정 값(인덱스 기준)을 수정할 수 있도록 합니다.
    • 수정 후에도 변경된 배열 값을 기반으로 결과를 갱신하도록 설계합니다.
  3. 출력 부분 개선
    • 현재 마지막 출력 형식을 좀 더 깔끔하고 가독성 좋게 정리합니다.
  4. 오름차순/내림차순 기능 추가
    • 사용자가 입력한 배열 값을 오름차순 및 내림차순으로 정렬할 수 있는 기능을 구현합니다.
    • std::sort를 사용하지 않고 직접 정렬 알고리즘(예: 버블 정렬, 선택 정렬)을 구현하여 학습 효과를 높이는 방식으로 설계합니다.