언젠지 기억이 나지 않지만 인벤토리에 들어갈 아이템 정보를 기입하는 알고리즘이였는데 당시에는 아이템 이름은 string형이지만 공격력은 int형, 공격속도는 char형이였다.
이런 자료형에 대한 입력을 받기도 애매했고 구분하기도 애매했다.
아래 코드를 통해 살펴보자
먼저 입력받을 정보에 대한 클래스를 생성한다.
class Person
{
public:
string m_name; // NOT NULL
short m_age; // NOT NULL
char m_sex; // NOT NULL // 'M' or 'F'
int m_birth; // YYYYMMDD;
};
Person 클래스를 생성하여 속성으로 이름, 나이, 성별, 생일을 가지도록 한다. (사실 생년월일을 보통 int형으로 하진 않는데.. 그냥 넘어가자)
while (1)
{
Person person;
getline(cin, strLine);
if (strLine == "x" || strLine == "X")
break;
person.m_name = readVal(strLine);
person.m_age = atoi(readVal(strLine).c_str());
person.m_sex = readVal(strLine)[0];
// 여기까진 NOT NULL
if (!strLine.empty())
person.m_birth = atoi(readVal(strLine).c_str());
else
person.m_birth = NULL;
vecList.push_back(person);
}
그리고 띄어쓰기로 구분하며 해당 정보를 채워나간다.
ex. 홍길동 26 M 19920101 (엔터)
입력은 x나 X가 들어올 때까지 입력을 무한대로 받을 것이다.
그런데 여기서 한 가지 조건을 추가하였다. 생년월일은 입력을 하여도, 하지 않아도 무관하다는 조건이다.
그럼 해당 반복문에서 readVal에 대한 구현을 살펴보자
string readVal(string& line)
{
int i = 0;
string read = "";
while (line.at(i) != ' ')
{
read += line.at(i);
if (i + 1 == line.length())
break;
i++;
};
line.erase(0, i + 1);
return read;
}
주의깊게 볼 사항은 먼저 string 객체를 인자로 받을 때 참조자를 사용하였다. 이는 12Line에서 읽은 값은 이미 read에 저장되어 있으므로 읽은 범위만큼 삭제하는 것이다.
여기서 참조자를 사용하지 않을 경우 strLine에 대한 복사본이 넘어와 실질적인 Erase는 되지 않는다.
나머지 부분은 전 시간 숫자를 읽는 것과 동일하기 때문에 어려움이 없을 것인데 9번 라인의 경우 문자열의 마지막(생년월일 또는 성별)에 해당하는 string이 넘어올 경우 인덱스 오류를 일으킨다.
디버그 모드로 저 부분에 중단점을 찍어보면 자세히 알 수 있겠지만..
굳이 설명을 하자면 line이 abc일 경우 c까지 읽고 i값을 증가시킬 것이다. 그럼 i는 3이 되는데 while문의 조건에서 line.at(3) 은 존재하지 않기 때문에 에러를 발생시킨다. 따라서 i값을 증가시키기 전 length를 통해 증가가 가능한지 확인하자.
'Language > C++' 카테고리의 다른 글
C++ Reference and friend (0) | 2018.12.28 |
---|---|
C++ 더블 포인터 정리 (0) | 2018.12.27 |
지역변수, static, extern 정리 (0) | 2018.12.27 |
C4996 error in visual studio – Scanf Error (0) | 2018.12.27 |
C언어 malloc에 대하여 (0) | 2018.12.27 |