[C++ Programming] Chapters 3 : Objects, types, and values
🧑🏫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';
}
cin
과cout
- 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
- 실수를 줄이는 방법
- 가독성
- 적절한 문법 사용
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;
}