[42seoul] 4 circle - CPP Module 00

하이초·2022년 10월 14일
0

42seoul

목록 보기
1/11
post-thumbnail

CPP00 github 😋

1. ex00

🥨 iostream

  • c++에서 입출력을 수행하는데 필요한 헤더

🥨 cctype

  • isalnum(), isalpha(), tolower(), toupper()와 같이 문자열을 위한 함수가 포함되어 있는 라이브러리
  • ex00에서 요구하는 대문자 변환을 위해 필요한 헤더

🥨 static_cast

  • c++ 스타일의 형 변환 객체로, c에서 (char *)var와 같이 형변환을 해주었다면, c++에서는 static_cast<type>을 활용하는 것이 좋다
  • 이유는? 맞지 않는 형태로 변환할 경우 컴파일 시에 오류를 잡아줄 수 있기 때문이다
	double* double_p = new double(42.4242);
  	int* int_p1 = double_p; // 묵시적 형변환
  	int* int_p2 = (int*)double_p; // 명시적 형변환
  	int* static_p = static_cast<int*>(double_p); // 오류 발생
  • 위 코드와 같이 형이 맞지 않는 형변환 시 묵시적-명시적 형변환은 컴파일 시에 오류로 잡히지 않고 넘어간다. 그렇다고 해서 정상적인 값이 출력되는 것은 아니고 오류가 발생한다.

❗️ 하지만 상속관계에 따른 형변환은 타입체크가 제대로 되지 않으므로 그때는 dynamic_cast를 사용해야 한다

2. ex01

👀 ex01은 PhoneBook class와 Contact class를 만들고 PhoneBook 객체 안에 Contact 객체들을 저장하여 하나의 전화번호부를 만드는 과제였다

  • cpp과제부터는 norm을 맞출 필요는 없지만, UpperCamelCase 형태로 클래스명을 작성해야 한다
  • hpp, cpp 파일이 분리되어 있어서 자바로 OOP 언어를 처음다뤄본 나로서는 처음에 굉장히 많이 헤맸다... OOP를 어설프게 알아서 더 고생한 그런 느낌,, ㅠㅠ 여전히 포인터의 개념이 남아 있어서 더 헷갈렸당ㅎㅎㅎㅎ
  • c++98에 맞춰야 하기 때문에 '-std=c++98' 플래그를 사용해서 컴파일해야 한다.
  • 문제는 이 플래그를 삽입해도 잡히지 않는 함수들이 있다고 들어서, 이 🍯 문서 를 참고하고 있다

🥨 iomanip

  • setw(num), setfill('char')와 같이입출력을 조절할 수 있는 함수들을 제공한다

🥨 임시 객체

  • 메모리 누수에 관하여.. 과제에서 요구하는 사항 중 하나인 turncate를 만족하기 위해 substr과 '+' 연산자를 활용하여 새 문자열을 반환하였는데, 이때 호출한 곳에서 반환 받은 문자열을 free해주지 않고 계속해서 함수를 호출해도 leak이 나지 않아서 찾다가 임시 객체라는 개념을 찾게 되었다
  • 함수가 반환한 값을 대입하지 않더라도 이름 없는 임시 객체는 알아서 생성되고 소멸한다고 한다..!
  • 또한 참조나 포인터형이 아닌 일반 string 변수로 보냈기 때문에 원본 문자열에도 영향을 미치지 않는다. 객체 복사가 이루어졌기 때문이다.
  • 아직 cpp00~01?까지는 나오지 않는 내용이지만 복사 생성자를 만들어 두지 않으면 얕은 복사 생성자를 컴파일러에서 만들어 진행하므로 메모리 문제가 발생할 수 있다고 한다. 이부분은 더 알아봐야 할듯..
  • 사실 아직 완벽히 체감되는 개념은 아니다 계속 공부해야할 것 같다

🥨 cin, getline 예외 처리

  • 과제에 따른 입력을 받기 위해서는 getline함수나 cin함수를 사용해야 한다
  • getline은 개행 문자는 포함하지 않고 반환한다
  • 입력 오류가 발생 시 cin객체에 오류 상황에 따라 failbit, badbit 등의 flag가 켜진다. 이를 통해 예외 처리를 해줄 수 있다.
    if(!std::getline(std::cin >> std::ws, cmd) || std::cin.eof()) {
    		if (std::cin.eof()) {
       		std::cout << "\nEOF: Goodbye~!\n";
    			break;
        }
    		std::cout << "\nAn error occurred in the input. Please try again.\n";
    		std::cin.clear();
    		std::cin.ignore(4096, '\n');
    		continue;
       }
  • 나의 경우 위와 같이 예외처리를 진행했다. 입력에 오류가 발생하거나, eof가 들어와 입력 종료가 되었을 경우에 따른 예외처리다.
    - eof를 만나는 경우에 프로그램을 종료시킨다
    - 입력 오류가 발생할 경우에는 cin.clear()로 오류 flag들을 다시 초기화하고, cin.ignore()를 통해 입력 버퍼를 비워주는 식으로 진행했다

🚨 다만 여기서 한 가지 내가 해결하지 못한 것이 있는데!

while (true) {
		displayPhoneBook();
		std::cout << "Enter the index number(0 ~ " << len - 1 << "): ";
		std::cin >> search;
		if (std::cin.eof())
			return ;
		if (std::cin.fail() || search < 0 || search >= len) {
			std::cout << "\nAn error occurred in the input. Please try again.\n";
			std::cin.clear();
			std::cin.ignore(4096, '\n');
			continue;
		}
		break;
}
  • add, search, exit과 같은 명령어를 받는 부분을 제외하고 add와 search 명령어를 실행하는 도중에 eof를 만나면 해당 명령어에 대해서만 입력을 종료하고 프로그램은 유지를 시키고 싶었다. 사람을 추가할라구 했는데 생각해보니 멈추고 싶기도 하구,, 검색도 그만하고 싶을 수도 있쟈나...
if (std::cin.eof()) {
	std::cin.clear();
    std::cin.ignore(4096, EOF);
    break;
}
  • 그래서 위와 같은 방식으로 초기화하고 메인으로 return 하여 새로운 명령어를 입력 받기를 희망했다.. 그런데 아무리해도 eof에 대한 초기화가 진행되지 않았다. 그래서 main문에서 그냥 eof를 만나 프로그램이 종료되었다.. 또르륵.. 😥 주변에도 조금 물어보았으나 여전히 미해결.. 누군가 보고있다면, 정답을 알려줘 🆘

3. ex02

👀 ex02는 주어진 hpp파일과 test파일을 통해 정의 된 함수들을 구현하는 과제였다. 확신의 노가다 과제..

  • 나는 주어진 test파일에 있는 함수들이 "나는 displayStatus 함수"와 같이 자기 함수 이름을 출력 하게끔하는 cpp파일을 먼저 만들었다. 그리고 나온 결과와 주어진 log파일을 비교하며 각 함수들이 무엇을 뱉어야 하는지 확인했다.

🥨 mem_fun_ref - 멤버 함수 어댑터

  • 이름에서 추측할 수 있듯이 멤버 함수를 참조할 수 있도록 해주는 템플릿 함수다
  • 멤버 포인터는 멤버가 속하는 클래스의 객체에 멤버 포인터 연산자를 적용해야 호출할 수 있다
    • void (Class::*class_mem_fun)() = &Class::fun;;
    • (c.*class_mem_fun)();
    • 함수 호출 연산자()의 우선 순위가 멤버 포인터 연산자보다 높기 때문에 (c.*class_mem_fun)() 과 같이 괄호로 감싸주어야 한다.
  • 그래서 왜쓰냐? 멤버 함수의 경우 이름답게 멤버 객체가 있어야지만 사용할 수 있는데, 멤버 함수를 객체처럼 호출할 수 있도록 하는 것이 바로 mem_fun_ref인 것이다
  • 주의! 인자가 하나인 멤버 함수까지만 지원할 수 있다!

🥨 static 변수의 초기화

  • static 변수의 경우 class 생성때가 아닌 프로그램 시작 시 메모리에 존재하게 된다
  • 따라서 객체 생성 전에 반드시 미리 초기화를 해주어야 한다
  • 또한 static 변수는 모든 객체가 공유해야 하므로 전역 범위에서 초기화해야 한다
    • 요걸 몰라가지고 첨에 계속 컴파일 오류가 나서 매우 당황했지 모야,,

🥨 소멸자

  • 처음으로 소멸자 개념이 나온 과제!
  • 주어진 log파일과 내가 만든 프로그램의 결과를 비교해보면 딱 하나, 프로그램 종료 시 account들이 소멸되는 순서들이 다르다
  • 써치해 본 결과, 리눅스와 우분투의 차이라고 한다. 우분투의 경우 생성한 순서대로 소멸되지만, 우분투의 경우 생성 역순으로, 그러니까 마지막으로 생성된 것 부터 소멸된다. 큐나 스택이냐의 차이인 것 같은데,, 옛날 과제에는 우분투 환경에서 돌리라는 제약 조건이 있었다고 하는데 현재는 사라진 조건이라 이 소멸 순서에 따른 차이는 평가에 영향을 미치지 않는 것이 맞다고 본다. 다만 그 차이가 왜 발생하는 지는 알아두는 것이 좋지 않을까?

이 외에는 사실 딱히 쓸 말이 없는 단순 노가다 과제!! 잘 더해주고, 빼주고, 입금 금액보다 많은 금액은 출금 못하게 하고.. 당연함. 그것이 은행 계좌임.

🚴 CPP 가보자고!

profile
개발국대가 되는 그 날까지. 지금은 개발 응애.

0개의 댓글