프로그래밍 언어/C++
C++ 기초: 배열과 입력 검증 개선하기
로안님
2024. 12. 24. 23:59
저번 포스트에서 우리는 C++의 배열과 예외 처리를 활용해 사용자로부터 입력받은 숫자들의 합계와 평균을 계산하는 프로그램을 작성했습니다. 이번 포스트에서는 이전 코드의 문제점을 분석하고 이를 해결하며 프로그램을 개선한 내용을 공유합니다.
저번 코드의 문제점
- 숫자의 조건
- 기존에는 "1 이상의 숫자만 입력 가능"이라는 제한을 두었지만, 소수점도 허용된다는 점에서 이 조건이 부자연스러웠습니다.
- 이를 개선하여 음수를 포함한 모든 실수를 입력받을 수 있도록 변경했습니다.
- 배열 크기 입력 오류
- 사용자가 배열 크기를 입력할 때 std::cin이 입력값을 지정된 타입(int)에 맞게 변환하려고 시도한다는 점을 알게 되었습니다.
- 예를 들어, 소수를 입력하면 소수점 이하 값은 무시되고 정수 부분만 저장되었기에 프로그램의 의도와 다르게 동작했습니다.
- 이를 해결하기 위해 입력값이 정수가 아니면 다시 입력받도록 정수 여부 확인 로직을 추가했습니다.
- 사용자 편의성 부족
- 이전에는 입력 진행 상황이나 현재까지 입력된 값들을 사용자에게 보여주지 않았습니다.
- 이를 보완하기 위해 입력 진행 상황과 이전에 입력된 값들을 출력하는 기능을 추가했습니다.
개선된 코드
아래는 문제점을 해결하고 추가 기능을 반영한 개선된 코드입니다.
#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 이상의 숫자만 받던 제한을 제거하고 음수와 소수까지 포함하여 입력받을 수 있도록 변경했습니다.
- 정수 여부 확인 로직 추가
- 배열 크기를 입력받는 과정에서 소수점 입력 시에도 오류 없이 처리되던 문제를 해결하기 위해 isInteger 함수를 추가했습니다.
- 사용자 편의성 개선
- 입력 진행 상황과 현재까지 입력된 값을 출력함으로써 사용자가 자신의 입력값을 확인할 수 있도록 했습니다.
배운 점
- 입력 검증의 중요성
- 프로그램의 입력 검증은 안정성과 신뢰성을 높이는 중요한 요소입니다. 사용자 경험을 고려한 검증 로직은 프로그램의 완성도를 크게 향상시킵니다.
- 유연한 조건 설계
- 입력 조건을 지나치게 제한하지 않도록 주의하며, 유연하게 처리할 수 있는 설계를 고민해야 합니다.
- 사용자 피드백 제공
- 입력 진행 상황과 입력값을 보여주는 방식은 사용자에게 큰 도움이 됩니다. 이는 프로그램의 직관성을 높이는 요소입니다.
다음 계획
- Remove 기능 추가
- 사용자가 입력한 배열 값 중 특정 값을 제거할 수 있는 기능을 추가합니다.
- 제거 이후 배열은 자동으로 재구성되어야 하며, 남은 값들을 기반으로 합계와 평균을 다시 계산할 수 있어야 합니다.
- Edit 기능 추가
- 배열의 특정 값(인덱스 기준)을 수정할 수 있도록 합니다.
- 수정 후에도 변경된 배열 값을 기반으로 결과를 갱신하도록 설계합니다.
- 출력 부분 개선
- 현재 마지막 출력 형식을 좀 더 깔끔하고 가독성 좋게 정리합니다.
- 오름차순/내림차순 기능 추가
- 사용자가 입력한 배열 값을 오름차순 및 내림차순으로 정렬할 수 있는 기능을 구현합니다.
- std::sort를 사용하지 않고 직접 정렬 알고리즘(예: 버블 정렬, 선택 정렬)을 구현하여 학습 효과를 높이는 방식으로 설계합니다.