반응형
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
❤와 댓글은 큰 힘이 됩니다. 감사합니다 :-)
반응형
'archive. > Schoolwork' 카테고리의 다른 글
[C++] 자료구조 5주차 과제4 (0) | 2020.08.05 |
---|---|
[C++] 자료구조 3주차 과제3 (0) | 2020.08.05 |
[C++] 자료구조 1주차 과제1 (0) | 2020.08.05 |
[C++] 문제해결기법 과제 4: 가장 큰 수 (0) | 2020.08.05 |
[C++] 문제해결기법 과제 3: 칸 채우기 (0) | 2020.08.05 |