7 minute read

🧑‍🏫Chapters 3 : Objects, types, and values

📟Lecture

Input and Output

    #include "std_lib_facilities.h" // our course header
    #include <iostream>
    #include <string>

    using namespace std;

    int main()
    {
        cout << "Please enter your first name (followed " << "by 'enter'):\n";
        string first_name;
        cin >> first_name;
        cout << "Hello, " << first_name << '\n';
    }
  • cincout
    • string이라는 userdefined type은 길이에 대해 좀 더 자유로워지고 더 많은 멤버변수를 지원해준다.
    • 기본적으로 printf와 scanf를 지원한다. C의 stdio 라이브러리가 더 확장된 버전이 C++의 iostream이라고 할 수 있다. C++의 문법이 좀 더 직관적이고 편리하다.

    이때, int와 main은 컴파일러 입장에서 하드코드로써 컴파일러가 알아들을 수 있는 코드이고 그 외의 cin, cout, string은 하나도 모른다. 따라서 사용자가 직접 컴파일러에게 선언해서 알려주거나 헤더파일을 include 해주어야 한다.

  • include
    • 라이브러리가 기본적으로 제공해주는 선언을 모아놓은 것이 헤더파일이다.

    • 헤더파일을 include함으로써 컴파일러가 알 수 있도록 한다.

  • using namespace std

    객체지향의 중요한 특징 중 하나는 다형성이다.

    • C 에서는 함수의 이름이 고유했어야 했다. 그러나 이름이 겹치지 않기 위해서 함수의 이름이 복잡해지게 된다. 함수의 이름이 복잡해진다면, 객체지향이 추구하는 생산성을 위한 코드의 재사용면에서 힘들어지게 된다.

    • 다형성이 말하는 바는 일일이 함수를 찾아가며 힘들게 찾아 쓰는 대신, 코드를 재사용을 편하게 하기 위해 같은 이름으로 지정할 수 있도록 하는 것이다. 변수나 함수, 클래스 등 이름이 겹쳐도 그가 소속된 곳을 보고 구분할 수 있게 된다. 이때 발생하는 모호성을 해소하기 위해서 namespace를 가져왔다.

    예를 들면 “타다”라는 이름의 함수가 있을 때, 무엇을 탈지에 대한 모호성을 namespace로 구분한다. namespace bike 소속의 “타다”라면 “자전거를 탄다”가 되는 것이다.

    • std안에 cin, cout이 존재한다. 풀네임은 std::cin, std::cout이다. 이 때, 매번 풀네임을 쓰기엔 귀찮기 때문에 using namespace std를 명시해준다.
  • #
    • #이 붙은 문장은 컴파일러가 보지 못한다. 즉 컴파일러에게 input을 주기 전에 미리 코드를 바꿔치기 하는 것과 같다

    • 즉 include 앞에 #이 붙은 것은, 헤더파일의 소스코드를 해당 위치에 바꿔놓고 컴파일러가 일을 시작하게 한다. 컴파일러가 일하기 전, 전처리기가 처리한다.


Source files

  • #include “std_lib_facilities.h”

  • 책의 저자가 독자들의 편의를 위해 일일이 include하는 대신 저 파일하나만 include하면 모두 컴파일 되도록 만들어 놓은 것이다.


String input

    #include <iostream>
    #include <string>
    
    int main()
    {
        cout << "please enter your first and second names\n";
        string first;
        string second;
        cin >> first >> second; // read two strings
        string name = first + ' ' + second; // concatenate strings
        // separated by a space
        cout << "Hello, "<< name << '\n';
    }

  • 문자형의 + 연산자

    • 연산자에 대한 다형성 또한 지원한다.
    • 이러한 다형성을 기반으로 연산자 오버로딩이 존재한다.
    • 문자열끼리 붙이고 없애는 개념이 +,- 와 같은 연산자와 비슷하기 때문에 별도의 함수를 만드는 대신 +연산자를 함수로 보고 재정의함으로써 다형성의 철학을 지킨다.

    • C에서는 scanf를 쓸 때, printf와 달리 입력받은 데이터를 저장할 변수의 주소를 &를 사용하여 알려준다. 따라서 scanf를 쓰면 주소를 알 수 있기 때문에 직접

    • call-by-value, call-by-reference
      • call-by-value : 안정성을 위해 서로의 데이터에 대해 물리적 공간을 공유하지 못한다. 따라서 값을 파라미터에 복사한다. 따라서 값은 같지만 저장공간은 다른 두 개의 변수가 존재하는 것과 같다. 따라서 함수를 호출하는 시점에서 데이터에 대한 안정성이 보장된다. C언어는 오직 call-by-value만을 지원한다.
        그러나, 단점은 복사해야할 양이 많을수록 효율성이 떨어진다.

      • call-by-reference : 물리적 저장 공간 자체를 가져간다. 위와 반대로 효율성은 좋아지지만, 데이터에 대한 안정성이 떨어진다.

      • C에서는 물리적 공간을 공유하지 못하기 때문에 포인터의 개념이 생긴다. 주소를 배껴가는 call by value이지만, 주소를 알기 때문에 그 값에 접근할 수 있게 되어 call by reference의 효과가 나타난다.

    C++에서 &를 쓰지 않고 꺽쇠만을 쓰는 이유는 C++은 이미 call by reference로 정의되어 있기 때문이다. 다형성에 기반한 <<에 대한 오버로딩과 참조는 cpp의 중요한 특징이다.


Integers

  • << 가 자료형별로 정의되어 있기 때문에 정수형이든, 문자열이든 cin, cout 할 수 있다.

  • 사용자 정의 자료형을 만든다면 그에 맞는 <<를 오버로딩 해줌으로써 사용할 수 있다.

다형성 POLYMORPHISM은 사람이 수 많은 함수의 이름을 일일이 외우지 않도록 도와준다.


Names

  • 코드의 규모가 방대해질 수록 버그는 필연적이다. 근본적인 원인은 사람의 실수이므로 실수를 줄이는 것이 매우 중요하다. 실수를 줄이는 것은, 코드에 대한 가독성이 좋아야한다. indentation, readability가 중요하다.


Const

  • 값이 바뀌지 않도록 overwrite을 방지함
  • const를 붙여놓음으로 실수를 줄이고 안정성을 높인다.


Types, and literals

  • 이미 정의되어 있는 타입
    • bool : false, baill(4바이트)
    • char : 무한히 작을수 있음, (1바이트}
    • float : 실수형 (8바이트)
    • double : 실수형(8비트형)


Type Safety

  • 타입을 엄격하게 검사하긴 하지만 완벽한 static 타입을 추구하는 것은 아니다.
    • static safety : 한번 Declaration으로 부여된 type은 끝까지 그 type을 유지해야 한다.
    • dynamic safety : 파이썬과 같은 인터프리터 언어는 한 줄 한 줄 읽을 때, 해당 변수의 쓰임을 보고 타입을 결정하기 때문에 비교적 type 변환이 자유롭다.


About Efficiency

  • 현재 이 수업에서는 효율을 집중적으로 다루진 않는다.


Another simple conputation

  • 실수를 줄이는 방법
    1. 가독성
    2. 적절한 문법 사용
      int main(void){
          const double cm_per_inch = 2.54;
          int val;
          char unit;
          while(cin>>val>>unit){
              if(unit == 'i')         // inch 값이 입력된 경우
                  cout<<val<<"in ==" << val*com_per_inch << "cm\n";
              else if(unit == 'c')    // cm 값이 입력된 경우
                  cout<<val<<"cm ==" << val*com_per_inch << "in\n";
              else
                  return 0;
          }
      }
    
    • c++ 문법적 특징: scanf/printf 대신 cin/cout을 사용
    • cin/cout이 수행된 뒤 다시 cin/cout을 리턴한다고 생각하자


C++ 11 hint

  • machine defendency가 있는 언어이기 때문에 최소한으로 지킬 표준을 만듦. 제일 최근 2014년도에 다시 업데이트함.


💻Practice

Practice 1

    #include<iostream>
    using namespace std;

    int main(void) {
        int val1, val2;		// 선언과 정의를 한번에 한 경우
                            // extern : 선언만 하게 해줌
        extern int K;		// (전역변수)K 라는 변수가 다른 파일 어딘가에 정의되어있으니 에러를 띄우지 말아라는 뜻. 메모리가 잡히지 않은 상태

        cout << "Please enter two integers : ";
        cin >> val1 >> val2;

        int smallest, largest, sum, difference, mul, ratio;	// 초기화를 하는 습관이 좋음
        
        if (val1 < val2) {
            smallest = val1;
            largest = val2;
        }
        else{
            smallest = val2;
            largest = val1;
        }

        sum = val1 + val2;
        difference = largest - smallest;
        ratio = largest / smallest;
        mul = largest * smallest;

        cout << "smallest = " << smallest << "\n";		// \n보다는 endl을 권장하는 이유: machine defendency를 피할 수 있는 좋은 습관
        cout << "largest = " << largest << "\n";
        cout << "sum = " << sum << "\n";
        //cout << "sum = " << largest + smallest << "\n";	// 연산자 우선순위는 <<보다 +가 더 우선됨. 헷갈린다면 괄호로 명시
        //cout << "sum = " << (largest + smallest) << "\n";	
        cout << "difference = " << difference << "\n";
        cout << "mul = " << mul << "\n";
        cout << "ratio = " << ratio << "\n";
        
        
        return 0;

    }

Practice 2

    #include<iostream>
    #include<algorithm>

    using namespace std;

    int main(void) {

        // First Way
        // Using Array
        int arr[3];

        cout << " Please Enter three integers: ";

        for (int i = 0; i < 3; i++) {
            cin >> arr[i];
        }
        sort(arr, arr + 3);

        cout << arr[0] << ", " << arr[1] << ", " << arr[2] << endl;


        
        // Second Way
        // Considering all case
        int n1, n2, n3; 
        int first, second, third;
        cout << " Please Enter three integers: ";

        cin >> n1 >> n2 >> n3;

        if (n1 > n2 && n1 > n3) {
            if (n2 > n3) {
                second = n2;
                third = n3;
            }
            else {
                second = n3;
                third = n2;
            }
            first = n1;
        }
        else if (n2 > n3 && n2 > n1) {
            if (n1 > n3) {
                second = n1;
                third = n3;
            }
            else {
                second = n3;
                third = n1;
            }
            first = n2;
        }
        else {
            if (n1 > n2) {
                second = n1;
                third = n2;
            }
            else {
                second = n2;
                third = n1;
            }
            first = n3;
        }

        cout << first << ", " << second << ", " << third << endl;

        return 0;
    }

Practice 3

    #include<iostream>

    using namespace std;

    int main(void) {
        int num;
        string cat;

        cin >> num;
        cout << "Please Enter a Integer: ";

        if (num % 2 == 0) {
            cat = "EVEN";
        }
        else{
            cat = "ODD";	
        }

        cout << "The Value " << num << " is an " << cat << " number.";
        
        return 0;
    }
        //방광 터져요ㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜ아 화장실 갔다올까 말까 갈까말까 진짜 지릴순 없어...

Practice 4

    #include<iostream>
    using namespace std;

    int main(void) {
        string str;
        cout << "Please Enter String : ";
        cin >> str;

        if (str == "zero") {	// JAVA에서는 ==연산자는 주소를 비교하지만, C++에서는 문자열이 같은지 비교한다.
            cout << 0;
        }
        else if (str == "one") {
            cout << 1;
        }
        else if (str == "two") {
            cout << 2;
        }
        else if (str == "three") {
            cout << 3;
        }
        else if (str == "four") {
            cout << 4;
        }
        else {
            cout << "Nan";
        }


        // switch문을 사용한다면?
        /*
        switch (str) {		// 에러발생. switch문은 사용자 정의 변수를 받지 않는다. 
                            // primitive value만 받기 때문
            case "zero":
                cout << 0;
            case "one":
                cout << 1;
        }
        
        */

        return 0;
    }

Practice 5

    #include<iostream>
    using namespace std;

    int main(void) {
        double op1, op2;
        string op;

        cin >> op >> op1 >> op2;

        // 1.Using String
        if (op == "+") {
            cout << op1 + op2 << endl;
        }
        else if (op == "-"){
            cout<< op1 - op2 << endl;
        }
        else if (op == "*"){
            cout << op1 * op2 << endl;
        }
        else {
            cout << op1 / op2 << endl;
        }


        // 2.Using Char --> Able to use Switch
        char cOp;

        cin >> cOp >> op1 >> op2;

        switch (cOp) {

        case '+':
            cout << op1 + op2;
            break;
        
        case '-':
            cout << op1 - op2;
            break;
        
        case '*':
            cout << op1 * op2;
            break;
        
        case '/':
            cout << op1 / op2;
            break;

        default:
            cout << "Cannnot Operate";
        }
        

        return 0;

    }