3 minute read

🏫Chapters 5 : Errors

📖Errors

“코딩 뿐만 아니라 인생에 있어서 내가 한 실수를 바로잡는 데에 가장 많은 시간을 보냈다”
-Maurice Wilkes, 1949


📖Your Program

  • 우리들의 코드는 모든 정상적인 인풋에 대해 정상적인 아웃풋을 리턴해야 한다.

  • 우리들의 코드에 기대하지 않은 인풋(비정상적 인풋)이 얼마든지 들어올 수 있다.

  • 하드웨어가 오동작 할 가능성이 있다.

  • 운영체제에 오류가 있을 가능성이 있다.


📖Sources of errors

  • 왜 에러가 발생하는 가
    • 프로그램 문제가 명확하지 않은 경우
    • 내가 코딩을 잘못한 경우
    • 인풋이 비정상인 경우


📖Kinds of Errors

  • 컴파일 에러
    • 문법 오류
    • 형 오류
  • 링크 에러
    • 정의가 없는 경우
  • 컴파일/링크 에러는 배포되기 전 오직 개발자만 볼 수 있고, 에러메세지가 친절하므로 가장 쉬운 에러

  • 런타임 에러
    • 잘 돌아가다가 발생하는 에러
    • 난이도가 높다
  • 로직 에러
    • 프로그램이 죽지도 않고 잘 돌아가는데 엉뚱한 아웃풋을 내는 경우
    • 수정하기도 어렵고 큰 피해의 가능성도 있는,,


📖Bad function arguments

  • 정상적이지 않은, 기대하지 않은 input에 대한 고려를 충분히 해야한다.
  • 사람들은 내가 원하는대로만 움직이지 않는다.


📖How to report an error

  • 오류에 대한 철학

    C “내가 처리해야 할 정상적인 과정 중 하나”
    C++ “문법적으로 두 가지 경우(문제상황과 오류상황)을 분류”

  • 예를 들면, 편의점에서 알바하다가 강도가 칼을 들고 들어와 100만원을 요구하는 상황에서 C는 “죄송합니다, 100만원이 없습니다” 라고 틀리지는 않은 대답을 돌려주는 것과 같다. 겉으로 봐서는 정상인지 아닌지 모른다. 의미를 분석하는 것과 거리가 멀다.
    C++은 이러한 대처방법을 비효율적으로 보고 에러 처리에 대한 문법을 새로 만든 것이다.

  • 에러에 대처하는 예시 코드

    • C
      int errno = 0; // used to indicate errors
      int area(int length, int width)
        
      {
          if (length<=0 || width<=0) errno = 7; // || means or
          return length*width;
      }
    
    • C++
      int z = area(x,y);
      if (errno==7) error("bad area computation");
      // ...
    


📖Exceptions

  • 예제

          #include<iostream>
          using namespace std;
    
          class myerror {};
            
          int div(int a, int b){
              return a / b;
          }
    
          int main(){
              int ans = div(1, 0);        // 컴파일 에러는 뜨지 않음. 그러나 런타임에러 (ERROR : divided by 0)
              cout << ans;
    
              return 0;
          }
    
  • C 스타일

      int div(int a, int b){
          if(b == 0){
              return -9999;
          }
          else return a / b;
      }
    
    • 코드에 대해 충분히 알지 못하고 있다면 -9999의 의미를 모르고 정상처리로 생각하게 된다.
    • 즉, 문법적으로 정상적인 플로우와 비정상적인 플로우를 구분하지 못한다.
  • C++ 스타일

      int div(int a, int b){
          if(b == 0){
              throw myerror();
          }
          else return a / b;
      }
    
      int main(){
          int ans = div(1, 0);      
          cout << ans;
    
          try{
              int ans = div(1, 0);
              cout << ans;
          }
          catch(myerror e){
              cout << "my error";         
          }
    
          return 0;
      }
    
    • 이런 경우 정상종료 된다. 문제상황에 대해 처리를 실행한 뒤 종료된다.


💻실습

  • 📝문제 설명 (실습 9)
    정수 배열 array와 정수 n이 매개변수로 주어질 때, array에 들어있는 정수 중 n과 가장 가까운 수를 return 하도록 solution 함수를 완성해주세요.

  • ⚠️제한사항

    • 1 ≤ array의 길이 ≤ 100
    • 1 ≤ array의 원소 ≤ 100
    • 1 ≤ n ≤ 100
    • 가장 가까운 수가 여러 개일 경우 더 작은 수를 return 합니다.
    #include <string>
    #include <vector>

    using namespace std;

    ////////////// My solution //////////////
    int solution(vector<int> array, int n) {
        int answer = 0;
        
        // 차이로 풀기
        int difference;
        vector<int> differ;
        
        // 각 배열의 차이를 담은 벡터
        for(int i=0; i<array.size(); i++){
            difference = n - array[i];
            differ.push_back(difference);
        }
        
        // -있으면 +로 바꿔주기
        for(int i=0;i<differ.size();i++){
            if(differ[i]<0){
                differ[i] = -differ[i];
            }
        }
        
        // 가장 작은 differ 값 구하기
        int min = 100;
        for(int i=0;i<differ.size();i++){
            if(differ[i] < min){
                min = differ[i];
            }
        }
        
        // 가장 작은 array 값 구하기
        int min_arr = 100;
        for(int i=0;i<differ.size();i++){
            if(differ[i] == min){
                if(array[i] < min_arr){
                    min_arr = array[i];
                }                
            }
        }
        
        answer = min_arr;
        return answer;
    }


    /////////// Professor Solution ///////////
    int getDiff(int n, int m);

    int solution(vector<int> array, int n){
        int answer = -200;
        for(int i = 0; i < array.size(); i++){
            if(getDiff(array[i], n) < getDiff(answer, n) 
                || ((getDiff(array[i], n) == getDiff(answer, n)) && (answer > array[i]))){
                answer = array[i];
            }
        }

        return answer;
    }

    int getDiff(int n, int m){
        if(n > m){
            return n-m;
        }
        else
            return m-n;
    }


  • 📝문제 설명 (실습 10)

    머쓱이는 프로그래머스에 로그인하려고 합니다.
    머쓱이가 입력한 아이디와 패스워드가 담긴 배열 id_pw와 회원들의 정보가 담긴 2차원 배열 db가 주어질 때, 다음과 같이 로그인 성공,
    실패에 따른 메시지를 return하도록 solution 함수를 완성해주세요.

    아이디와 비밀번호가 모두 일치하는 회원정보가 있으면 "login"을 return합니다.
    로그인이 실패했을 때 아이디가 일치하는 회원이 없다면 “fail”를, 아이디는 일치하지만 비밀번호가 일치하는 회원이 없다면 “wrong pw”를 return 합니다.

    #include <string>
    #include <vector>

    using namespace std;

    string solution(vector<string> id_pw, vector<vector<string>> db) {

        for(int i=0;i<db.size();i++){
            if(id_pw[0] == db[i][0]){
                if(id_pw[1] == db[i][1])
                    return "login";
                else return "wrong pw";
            }
        }
        
        return "fail";
    }