CPP Moudle 공통항목

  1. c++ -Wall -Wextra -Werror -std=c+98로 컴파일
  2. 과제는 모두 C++98 standard를 사용, 이후(C++11 등)에 추가된 기능들은 활용할 수 없음
  3. class 이름은 UpperCamelCase 포멧을 사용하고 class 코드를 포함한 파일은 해당 class에 맞게 이름지어야함
  4. 구체적 지시가 있는 것이 아니라면 출력은 항상 개행으로 끝내야함
  5. Norminette 졸업!
  6. 서브젝트에서 특별히 금지한 것이 아니라면 표준 라이브러리를 자유롭게 활용 가능
  7. 외부 라이브러리는 금지(C++11과 Boost 라이브러리 등), *printf(), *alloc(), free()도 금지
  8. using namespace <>friend도 금지
  9. STL은 Moudle 08에서만 사용 가능 - 즉, vector, list 등의 컨테이너 및 <algorithm> 헤더에 정의된 기능들 사용 금지
  10. 당연히 메모리 누수는 존재해서는 안됨
  11. Module 02-08에서는 모든 클래스들이 Orthdox Canonical Form을 따라야 함
  12. 함수 템플릿이 아닌 이상 헤더파일에 함수 구현부가 포함되어있으면 안됨
  13. 각 헤더를 서로 독립적으로 사용할 수 있어야하며, 모든 종속성을 포함하면서 double inclusion을 방지하기 위해 include guards를 사용해야 함
  14. 필요하다면 코드를 나누기 위해 파일을 추가할 수 있음

Exercise 00 : Megaphone

문제에 관해서는 크게 서술하지 않고, 해당 문제에서 새롭게 배웠거나 다시 익힌 내용들에 대해서만 정리할 예정임

std::strlen의 경우 <cstring> 헤더파일에 정의되어있음
그러나 mac에서는 <cstring> 헤더파일을 선언하지 않고 <iostrem> 헤더파일만 선언해도 사용이 가능했는데, 이는 컴파일러나 툴에 따라 <iostream> 안에 <cstring>이 포함되어있을 수 있기 때문
따라서 모든 환경에서도 에러 없이 동작하기를 원하면 정당하게 <cstring> 헤더파일도 넣어주어야 함
해당 주제에 대한 stackoverflow 글 링크



대소문자 변환의 경우 std::toupper함수를 이용하여 한글자씩 변환해주어야 함

  • std::toupper의 반환값은 int형이므로 곧바로 std::cout에 넣었을 경우 정수가 출력되기 때문에 char형으로 변환하는 과정이 필요
  • argv로 받아오는 문자열을 string으로 변환하고(새로운 string 변수를 선언하여 argv의 내용을 대입), c++11이 사용 가능했다면
    • for(auto & x : str)와 같이 사용하여 더 편리하게 구현할 수 있음
    • std::transform(str.begin(), str.end(), str.begin(), ::toupper);의 문법도 사용 가능
    • boost::to_upper()으로 한번에 변경할 수도 있음

Exercise 01 : My Awesome PhoneBook

std::cin >> str 형식으로 문자열을 입력받았을 경우 whitespace가 나올때까지 읽어들임
따라서 ADD adsfasf의 형식으로 입력해도 str에는 ADD만 저장되기 때문에 형식에 맞지 않게 되고, 버퍼에는 여전히 뒷 내용이 남아 문제 발생

  • 버퍼를 지우고 싶을 때는 std::cin.ignore(len, '\n')을 사용

그러므로 std::getline(std::cin, str)을 사용하여 개행 전까지 한줄을 통째로 읽어들이는 방법을 사용

  • string.empty() 함수로 개행만 입력되는 경우는 걸러낼 수 있음
  • 그러나 공백만 읽어들일 경우에도 입력이 되기 때문에 이를 방지하는 것이 필요
  • 따라서 string.find_first_not_of() 함수를 활용하여 whitespace를 걸러내는 작업을 수행
    해당 주제에 대한 stackoverflow 글 링크



cin.getline()char형 배열에 문자를 저장

  • istream의 멤버함수
  • istream& getline (char* s, streamsize n ); 또는 istream& getline (char* s, streamsize n, char delim );의 형태로서 저장할 문자열의 크기 지정이 반드시 필요함
    getline()string에 문자를 저장
  • std namespace에 선언된 일반함수
  • istream& getline (istream& is, string& str); 또는 istream& getline (istream& is, string& str, char delim);의 형태로서 크기 지정 없이 사용 가능



<iomanip> 헤더파일에 있는 조정자들을 활용하면 출력 형식을 지정할 수 있음

  • std::setw() : 출력 필드 넓이 지정, 비어있는 부분은 공백으로 처리
    • 단, 처음 한번의 출력에만 필드 넓이가 지정됨
    • std::setw()를 한 후 std::cout << "abcde" << "12345를 했을 경우 앞의 abcde 문자열에만 필드 넓이가 지정됨에 유의
  • std::setfill() : 출력 필드에서 비어있는 부분을 매개변수로 받는 문자로 채움
  • std::setprecision() : 소수점 출력 길이 지정



while(!(std::cin >> num))과 같이 사용할 경우

  • num이 정상적으로 입력되지 않으면 std::cinfailbit를 키면서 FALSE를 리턴
  • 이 경우 버퍼를 건드리지 않기 때문에 while 루프를 통해 돌면 다시 같은 버퍼를 읽으며 똑같은 행동이 무한루프됨
  • 따라서 버퍼에 남아있는 것을 지워주는 std::cin.ignore() 함수를 호출해야함
  • failbit 또한 여전히 켜져있는 상태이기 때문에 이를 꺼주기 위한 std::cin.clear() 함수도 호출해야함

Exercise 02 : The Job Of Your Dreams

#ifndef ~ #endif 구문을 #pragma once가 대체할 수 있음

  • #ifndef~ 구문은 일단 헤더 파일을 연 후 ifndef 구문을 통해 사용 여부를 판명
  • #pragma once는 해당 헤더 파일이 컴파일동안 단 한번만 포함되도록 하므로 중복으로 열리지 않음
  • 따라서 #pragma once가 효율이 좀 더 좋기는 하나, 구형 컴파일러에서는 동작하지 않을 수 있음



std::for_each() : 지시된 함수를 매개변수로 받은 이터레이터로 정의된 범위의 원소들에 적용
std::mem_fun_ref() : 멤버함수를 f(x) 형태로 바꾸어 함수 객체로 호출

  • for_each() 함수에서 매개변수로 사용되는 함수는 f(x) 형태이기 때문에 이를 활용하기 위해 사용
  • 단, 인자가 하나인 멤버함수만 지원 가능



시간을 받아오는 용도로 time_t형 변수와 tm 구조체를 사용

  • time() 함수로 time_t형 변수에 현재 시간을 나타내는 숫자를 저장
    • 매개변수가 NULL일 경우 1970년 1월 1일 0시 0분 0초부터 경과된 시간을 초단위로 나타내는 숫자를 반환
    • 매개변수에 다른 time_t형 변수의 포인터를 넣을 경우 해당 변수의 값을 반환
  • localtime() 함수로 time_t형 변수의 값을 바탕으로 tm 구조체에 시간 관련 정보 저장



클래스 내의 변수가 static으로 선언된 경우 해당 변수의 값은 클래스의 모든 객체가 공유

  • 객체 생성 전에도 메모리를 차지하며, 따라서 미리 초기화를 해두어야함
  • 이 때 초기화는 클래스 내에서는 불가능하며, 전역 범위에서 이루어짐
  • 이는 private으로 선언된 static 멤버 변수에도 똑같이 적용
  • 단, static const 멤버 변수는 객체끼리 공유함과 동시에 값을 변경하는 것이 불가능하므로 클래스 내 초기화가 가능함