반응형
1주차에 작성한 학과명, 학번, 이름, 생년월일, 나이, 현재날짜를 출력하는 C++ 프로그램을 수정하여 다음 기능을 포함하도록 작성하라.
- Exception handling을 구현하기 위한 try-catch의 구조를 이용하여 사용자의 입력 데이터에 오류가 있을 때 처리하는 프로그램을 작성하라. (사용자의 입력 오류로 프로그램이 오작동하는 경우가 발생하지 않도록 최대한 대처할 수 있도록 할 것)
- 예: 생일 입력시 "2000/03/33"과 같이 잘못된 날짜를 입력한 경우 다시 입력할 것을 요구함
Code
// use class Date
// 이름, 학부(과)명에 숫자가 들어가지 않고, 학번에는 숫자만 들어간다고 가정했습니다.
#include <iostream>
#include <cstdlib>
#include <string>
#include <vector>
#include <ctime>
#pragma warning(disable:4996)
using namespace std;
const string currentDate() // returns current date as string yyyy/mm/dd
{
time_t current_time = time(NULL); // save current time to now as type current_time
struct tm timeinfo;
char buf[80];
timeinfo = *localtime(¤t_time);
strftime(buf, sizeof(buf), "%Y/%m/%d", &timeinfo); // yyyy/mm/dd
return buf;
}
class Date
{
public:
void input(string whatday); // '/'
void output(); // 날짜출력형식
void set(int newMonth, int newDay); // year is not to be defined, month and day should form a possible date
void check_match(int newMonth, int newDay); // 예외처리 - if the month and the date doesn't match such as 4/31
void check_lunar(int newYear, int newMonth, int newDay); // 예외처리 - 2월 윤달인지 아닌지
int getYear() { return year; } // read the private member year
int getMonth() { return month; } // read month
int getDay() { return day; } // read day
private:
int year;
int month;
int day;
};
class Information
{
public:
string whole_info;
void input(); // ','
void output();
int Age();
string getBirthday() { return birthday; }
private:
string department;
string id_number;
string name;
string birthday;
int age;
string current_date;
};
void Date::set(int newMonth, int newDay) // data conditions
{
if (((newMonth < 1) || (newMonth > 12)) && ((newDay < 1) || (newDay > 31)))
throw 3;
if ((newMonth >= 1) && (newMonth <= 12))
month = newMonth;
else throw 1;
if ((newDay >= 1) && (newDay <= 31))
day = newDay;
else throw 2;
}
void Date::check_match(int newMonth, int newDay) // does the month and date match each other?
{
// 1/31, 2/28, 3/31, 4/30, 5/31, 6/30, 7/30, 8/31, 9/30, 10/31, 11/30, 12/31 - 4,6,7,9,11
if ((newMonth == 4) && (newDay > 30) && (newDay <= 31) || (newMonth == 6) && (newDay > 30) && (newDay <= 31) || (newMonth == 7) && (newDay > 30) && (newDay <= 31)
|| (newMonth == 9) && (newDay > 30) && (newDay <= 31) || (newMonth == 11) && (newDay > 30) && (newDay <= 31))
throw 4;
}
void Date::check_lunar(int newYear, int newMonth, int newDay) // 윤년에 대한 예외처리
{
if ((newYear % 4 == 0) && (newYear % 100 != 0) || (newYear % 400 == 0)) {
if ((newMonth == 2) && (newDay > 29) && (newDay <= 31))
throw 5;
}
else {
if ((newMonth == 2) && (newDay > 28) && (newDay <= 31))
throw 6;
}
}
void Date::input(string whatday) // parse string into year, month and day
{
// slash 기준으로 string parsing 후 int로 형변환하고 각각 맞는 private 변수에 저장
int count_slash = 0;
string delimiter = "/";
size_t last = 0;
size_t next = 0;
string token;
vector<string> date_token;
while ((next = whatday.find(delimiter, last)) != string::npos)
{
token = whatday.substr(last, next - last);
date_token.push_back(token);
last = next + 1;
count_slash++;
}
date_token.push_back(whatday.substr(last));
// slash 2개 아니면 다시 입력
if (count_slash != 2) throw 13;
// 예외처리 - 입력값에 숫자 아닌게 섞였는지 판별
for (int i = 0; i < 3; i++)
{
for (int idx = 0; idx < (date_token[i].length()); idx++) {
if ((date_token[i][idx] <= 57) && (date_token[i][idx] >= 48)) {}
else throw 13;
}
}
year = stoi(date_token[0]);
month = stoi(date_token[1]);
day = stoi(date_token[2]);
set(month, day); // month, day 가 유효한 값인지 확인
check_match(month, day); // 입력한 날짜가 진짜 정상적인지 확인
check_lunar(year, month, day); // 윤년인지 아닌지 확인
}
void Date::output() // ~년~월~일
{
cout << year << "년" << month << "월" << day << "일";
}
void Information::input() // 예외처리 - 4가지 중 하나라도 입력 안 했을 때. 아무것도 입력 안 했을 때
{
cout << "환영합니다! 학과명, 학번, 이름, 생년월일(yyyy/mm/dd)을 입력하세요> ";
department.clear();
id_number.clear();
name.clear();
birthday.clear();
whole_info.clear(); // 초기화
// 쉼표+공백 때문에 while 돌려서 전체 입력값 저장
getline(cin, whole_info);
if (whole_info.length() == 0) throw 14; // 입력값이 아무것도 없으면 throw
int count_comma = 0;
for (int check_comma = 0; check_comma < whole_info.length(); check_comma++)
{
if (whole_info[check_comma] == ',') { count_comma++; }
}
// 쉼표 3개 아니면 다시 입력
if (count_comma != 3) throw 8;
count_comma = 0;
for (int check_parse = 0; check_parse < whole_info.length(); check_parse++)
{
if (whole_info[check_parse] == ',') { count_comma++; }
if (whole_info[check_parse] == ' ') {}
if ((whole_info[check_parse] != ',') && (whole_info[check_parse] != ' ')) {
if (count_comma == 0) department += whole_info[check_parse];
if (count_comma == 1) id_number += whole_info[check_parse];
if (count_comma == 2) name += whole_info[check_parse];
if (count_comma == 3) birthday += whole_info[check_parse];
}
}
// 쉼표는 3개지만 입력값이 비었을 때
if (department.length() == 0) throw 9;
if (id_number.length() == 0) throw 10;
if (name.length() == 0) throw 11;
if (birthday.length() == 0) throw 12;
// 예외처리 - 학부(과)명 입력할 곳에 숫자가 있을 때
for (int idx = 0; idx < (department.length()); idx++) {
if ((department[idx] <= 57) && (department[idx] >= 48)) throw 8; // ascii
}
// 예외처리 - 이름 입력할 곳에 숫자가 있을 때
for (int idx = 0; idx < (name.length()); idx++) {
if ((name[idx] <= 57) && (name[idx] >= 48)) throw 8;
}
// 예외처리 - 학번 입력할 곳에 숫자가 없을 때
for (int idx = 0; idx < (id_number.length()); idx++) {
if ((id_number[idx] <= 57) && (id_number[idx] >= 48)) {}
else throw 8;
}
// 예외처리 - 생일 입력할 곳에 숫자,/ 외 다른 것이 입력됐을 때, /의 위치가 이상할 때
for (int idx = 0; idx < (birthday.length()); idx++) {
if ((birthday[idx] <= 57) && (birthday[idx] >= 47)) {} // numbers and slash
else throw 13;
}
Date date;
date.input(birthday);
}
int Information::Age() // 만 나이 = 생일 지났으면 (현재년도-출생년도), 생일 안 지났으면 (현재년도-출생년도-1)
{
Date date;
string currentdate = currentDate();
date.input(currentdate);
int currentyear = date.getYear();
int currentmonth = date.getMonth();
int currentday = date.getDay();
date.input(birthday);
int birthyear = date.getYear();
int birthmonth = date.getMonth();
int birthday = date.getDay();
// 현재 날짜가 생월을 지난 경우
if (currentmonth > birthmonth) age = currentyear - birthyear;
// 현재 날짜가 생월인 경우 : 생일이거나 지남 or 생일 전
if (currentmonth == birthmonth && currentday >= birthday) age = currentyear - birthyear;
if (currentmonth == birthmonth && currentday < birthday) age = currentyear - birthyear - 1;
// 현재 날짜가 생월 이전인 경우
if (currentmonth < birthmonth) age = currentyear - birthyear - 1;
// 예외처리 - 현재 날짜보다 생일 날짜가 뒤에 있는 경우
if ((currentyear < birthyear) || (currentyear == birthyear) && (currentmonth < birthmonth) || (currentyear == birthyear) && (currentmonth == birthmonth) && (currentday < birthday))
throw 7;
return age;
}
void Information::output() // department, id_number, name, birthday, age, current_date
{
Date date;
date.input(birthday);
Age();
cout << ">> " << department << " " << id_number << " " << name << "님 ";
date.output();
cout << "생 ";
date.input(currentDate());
date.output();
cout << " 현재 " << age << "세입니다." << endl;
}
int main()
{
Information info;
while (1)
{
try {
info.input();
}
catch (int i) {
cout << "\n";
if (i == 1) { cout << "생월 입력값이 잘못되었습니다." << endl; }
if (i == 2) { cout << "생일 입력값이 잘못되었습니다." << endl; }
if (i == 3) { cout << "생월, 생일 입력값이 모두 잘못되었습니다." << endl; }
if (i == 4) { cout << "해당 생월에 존재하지 않는 날짜입니다." << endl; }
if (i == 5) { cout << "윤년에 존재하지 않는 날짜입니다." << endl; }
if (i == 6) { cout << "존재하지 않는 날짜입니다." << endl; }
if (i == 8) { cout << "입력값 4가지를 모두 순서, 조건에 맞게 입력했는지 확인해주세요." << endl; }
if (i == 9) { cout << "학부(과)명을 입력했는지 확인해주세요." << endl; }
if (i == 10) { cout << "학번을 입력했는지 확인해주세요." << endl; }
if (i == 11) { cout << "이름을 입력했는지 확인해주세요." << endl; }
if (i == 12) { cout << "생년월일을 입력했는지 확인해주세요." << endl; }
if (i == 13) { cout << "생년월일을 정확히 입력했는지 확인해주세요." << endl; }
if (i == 14) { cout << "입력값이 없습니다." << endl; }
cout << "이름, 학부(과)명에는 숫자를 입력할 수 없고, 학번에는 숫자만 입력 가능합니다.\n확인 후 다시 입력해주세요.\n" << endl;
i = 0;
continue;
}
try {
info.output();
}
catch (int j) {
if (j == 7) { cout << "유효하지 않은 생년월일입니다." << endl; }
cout << "확인 후 다시 입력해주세요.\n" << endl;
j = 0;
continue;
}
break;
}
}
실행결과
점수 10/10
❤와 댓글은 큰 힘이 됩니다. 감사합니다 :-)
반응형
'Schoolwork > 자료구조와 C++프로그래밍' 카테고리의 다른 글
[C++] 9주차 과제6 (0) | 2020.08.05 |
---|---|
[C++] 7주차 과제5 (0) | 2020.08.05 |
[C++] 5주차 과제4 (0) | 2020.08.05 |
[C++] 3주차 과제3 (0) | 2020.08.05 |
[C++] 1주차 과제1 (0) | 2020.08.05 |