2024. 12. 3. 11:03ㆍC++프로그래밍/수업 내용 및 수업 후 과제
여기서 10~20점 정도 시험 문제가 나옴
제네릭 프로그래밍
데이터 타입에 의존하지 않고 하나의 값이 여러 다른 데이터 타입들을 가질 수 있는 기술에 중점을 두어
재사용성을 높일 수 있는 프로그래밍 방식이다.
이 방식의 주요 목적은 :
타입 안정성 향상: 컴파일 시점에 타입 체크를 수행하여 런타임 오류의 가능성을 줄임.
코드 재사용성 증가: 하나의 코드를 여러 타입에 대해 재사용할 수 있어 코드 중복을 줄이고 유지보수성을 향상
알고리즘과 데이터 구조의 일반화: 특정 데이터 타입에 종속되지 않는 일반적인 알고리즘과 데이터 구조를 구현
제네릭 프로그래밍의 핵심 개념은 타입 파라미터를 사용하는 것입니다.
자료형이 나중에(컴파일할때가 아닌 실행할때 결정이 된다)(시험에 나올듯)
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
1. 작년 시험 문제 7점
int Max(int i, int j)
{
return i>j ?i:j;
}
이부분을 포괄적인 함수로 만드시오
2. class 대신 typename 써도 된다 2점 문제
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
함수 중첩으로 만족하지 말자!
임의의 형의 두 매개변수 중 큰 값을 반환하는 Max()라는 함수를 작성하시오.
즉, Max()함수가 매개변수로 int, double, char 등을 모두 가질 수 있도록 함수를 중첩시키시오.
#include <iostream>
using std::cout;
using std::endl;
int Max(int i, int j)
{
return i>j ?i:j;
}
double Max(double i, double j)
{
return i>j ?i:j;
}
char Max(char i, char j)
{
return i>j ?i:j;
}
int main()
{
cout<< "Max값은=" << Max(1,2)<<endl;
cout<< "Max값은=" << Max(7.5,3.6)<<endl;
cout<< "Max값은=" << Max('A','B');
return 0;
}
위의 예제 코드를
아래 변경(템플릿(template)사용)
#include <iostream>
using std::cout;
using std::endl;
template <class T> // class 대신 typename 써도 된다
// 이 코드 처럼 함수 만들때는 typename 많이 씀
// class 만들때 class 많이 씀
T Max(T i, T j) // int대신 T로 변경<T>를 써서
{
return i > j ? i : j;
}
int main()
{
cout << "Max값은=" << Max(1, 2) << endl;
cout << "Max값은=" << Max(7.5, 3.6) << endl;
cout << "Max값은=" << Max('A', 'B');
return 0;
}
출력결과
Max값은=2
Max값은=7.5
Max값은=B
세 개의 Max()함수를 중첩시키고 있다.
이렇게 함수의 실행 코드가 모두 같은 경우에는 템플릿(template)을 사용하는 것이 더 좋다.
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
GPT 설명
이 코드는 제네릭 프로그래밍의 좋은 예시입니다.
템플릿을 사용하여 다양한 데이터 타입에 대해 동작하는 Max 함수를 구현하고 있습니다.
코드의 주요 부분을 설명하겠습니다:
템플릿 함수 정의
cpp
template <T>
T Max(T i, T j)
{
return i > j ? i : j;
}
이 부분은 제네릭 Max 함수를 정의합니다. template <T>는 템플릿 선언으로, T는 타입 파라미터입니다.
이 함수는 같은 타입 T의 두 인자를 받아 더 큰 값을 반환합니다.
주석 처리된 코드
주석 처리된 부분은 각 데이터 타입(int, double, char)에 대해 별도로 Max 함수를 오버로딩한 것입니다.
템플릿을 사용함으로써 이러한 중복 코드를 제거할 수 있습니다.
main 함수
cpp
int main()
{
cout << "Max값은=" << Max(1, 2) << endl;
cout << "Max값은=" << Max(7.5, 3.6) << endl;
cout << "Max값은=" << Max('A', 'B');
return 0;
}
main 함수에서는 템플릿 함수 Max를 다양한 타입(int, double, char)에 대해 호출하고 있습니다.
컴파일러는 각 호출에 대해 적절한 타입의 Max 함수를 자동으로 생성합니다.
코드의 장점
코드 재사용성: 하나의 템플릿 함수로 여러 데이터 타입에 대해 동작할 수 있습니다.
타입 안정성: 컴파일 시점에 타입 검사가 이루어져 런타임 오류를 줄일 수 있습니다.
유지보수성: 함수 로직을 한 곳에서 관리할 수 있어 유지보수가 용이합니다.
이 코드는 제네릭 프로그래밍의 핵심 개념을 잘 보여주는 예시로,
다양한 데이터 타입에 대해 동일한 로직을 적용할 수 있는 유연성을 제공합니다.
재작년 시험문제
실습 10-2: 템플릿의 구현 2
탬플릿을 이용해서 함수를 만드는것
class를 매번 써야하는것을 주의 할것
#include <iostream>
using std::cout;
using std::endl;
template <class T1, class T2, class T3> void fun(T1 x, T2 y, T3 z)
{ // 두 개의 매개변수 자료형이 T1과 T2로 다르다.
cout << x << " " << y << endl;
}
int main()
{
fun("Han", 30, 1); // T1은 문자열(const char *),T2는 정수형(int)
fun(25, 50.5, 1.2); // T1은 정수형(int), T2는 double형
fun(1, 2, 3);
fun('a', 3.5, 1);
return 0;
}
컴파일러는 템플릿 함수를 처리할 때 여러 개의 함수 코드를 만든다.
개발자가 만들어야 할 코드를 컴파일러가 대신 만든다.
템플릿을 사용하더라도 코드는 줄어들지 않는다.
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
gpt 설명
이 코드는 C++에서 템플릿을 사용한 제네릭 프로그래밍의 예시입니다. 주요 부분을 상세히 설명하겠습니다:
## 템플릿 함수 정의
```cpp
template <class T1, class T2, class T3> void fun(T1 x, T2 y, T3 z)
{
cout << x << " " << y << endl;
}
```
이 부분은 세 개의 타입 파라미터 `T1`, `T2`, `T3`를 가진 템플릿 함수 `fun`을 정의합니다:
- 함수는 세 개의 인자 `x`, `y`, `z`를 받습니다.
- 각 인자의 타입은 템플릿 파라미터 `T1`, `T2`, `T3`에 의해 결정됩니다.
- 함수 내부에서는 첫 두 개의 인자 `x`와 `y`만 출력합니다.
## main 함수
```cpp
int main()
{
fun("Han", 30, 1);
fun(25, 50.5, 1.2);
fun(1, 2, 3);
fun('a', 3.5, 1);
return 0;
}
```
`main` 함수에서는 `fun` 함수를 다양한 타입의 인자로 네 번 호출합니다:
1. `fun("Han", 30, 1)`:
- `T1`은 `const char*` (문자열 리터럴)
- `T2`는 `int`
- `T3`는 `int`
- 출력: "Han 30"
2. `fun(25, 50.5, 1.2)`:
- `T1`은 `int`
- `T2`는 `double`
- `T3`는 `double`
- 출력: "25 50.5"
3. `fun(1, 2, 3)`:
- `T1`, `T2`, `T3` 모두 `int`
- 출력: "1 2"
4. `fun('a', 3.5, 1)`:
- `T1`은 `char`
- `T2`는 `double`
- `T3`는 `int`
- 출력: "a 3.5"
## 코드의 특징
1. **타입 유연성**: 함수는 다양한 타입의 인자를 받을 수 있습니다.
2. **자동 타입 추론**: 컴파일러가 함수 호출 시 인자의 타입을 보고 템플릿 파라미터의
실제 타입을 자동으로 결정합니다.
3. **코드 재사용**: 하나의 템플릿 함수로 여러 타입에 대해 동작하는 코드를 작성할 수 있습니다.
## 주의사항
- 함수가 세 개의 인자를 받지만 두 개만 사용하는 점은 주의가 필요합니다.
세 번째 인자 `z`는 함수 내에서 사용되지 않습니다.
- 템플릿 함수는 컴파일 시간에 각 호출에 대해 별도의 함수를 생성합니다.
이는 코드 크기를 증가시킬 수 있지만, 타입 안정성과 성능을 향상시킵니다.
이 예제는 C++의 템플릿을 사용한 제네릭 프로그래밍의 기본적인 사용법을 잘 보여주고 있습니다.
다양한 타입의 데이터를 처리할 수 있는 유연한 함수를 작성할 수 있음을 확인할 수 있습니다.
매년 시험에 내는 문제
p.33
이 소스를 템플릿을 이용하여 일반화된 클래스로 구현
(탬플릿 클래스)
#include <iostream>
using std::cout;
using std::endl;
class CCC1
{
int x;
int y;
public:
CCC1(int xx, int yy) { x = xx; y = yy; }
void Print() { cout << x << ',' << y << endl; }
};
class CCC2
{
double x;
double y;
public:
CCC2(double xx, double yy) { x = xx; y = yy; }
void Print() { cout << x << ',' << y << endl; }
};
class CCC3 // 자료형이 2개이기 떄문에 T1, T2 두개를 만들어야함
{
char x;
const char* y;
public:
CCC3(char xx, const char* yy) { x = xx; y = yy; }
void Print() { cout << x << ',' << y << endl; }
};
int main()
{
CCC1 c1(10, 20);
CCC2 c2(3.5, 5.5);
CCC3 c3('I', "Love You!");
c1.Print();
c2.Print();
c3.Print();
return 0;
}
위의 코드를 변경
1단계 템플릿
#include <iostream>
using std::cout;
using std::endl;
template<>
class CCC1
{
int x;
int y;
public:
CCC1(int xx, int yy) { x = xx; y = yy; }
void Print() { cout << x << ',' << y << endl; }
};
class CCC2
{
double x;
double y;
public:
CCC2(double xx, double yy) { x = xx; y = yy; }
void Print() { cout << x << ',' << y << endl; }
};
class CCC3
{
char x;
const char* y;
public:
CCC3(char xx, const char* yy) { x = xx; y = yy; }
void Print() { cout << x << ',' << y << endl; }
};
int main()
{
CCC1 c1(10, 20);
CCC2 c2(3.5, 5.5);
CCC3 c3('I', "Love You!");
c1.Print();
c2.Print();
c3.Print();
return 0;
}
2단계 결정되지 않은 자료형 CCC3 때문에 2개 만들기
#include <iostream>
using std::cout;
using std::endl;
template<class T1, class T2>
class CCC1
{
int x;
int y;
public:
CCC1(int xx, int yy) { x = xx; y = yy; }
void Print() { cout << x << ',' << y << endl; }
};
class CCC2
{
double x;
double y;
public:
CCC2(double xx, double yy) { x = xx; y = yy; }
void Print() { cout << x << ',' << y << endl; }
};
class CCC3
{
char x;
const char* y;
public:
CCC3(char xx, const char* yy) { x = xx; y = yy; }
void Print() { cout << x << ',' << y << endl; }
};
int main()
{
CCC1 c1(10, 20);
CCC2 c2(3.5, 5.5);
CCC3 c3('I', "Love You!");
c1.Print();
c2.Print();
c3.Print();
return 0;
}
3단계 템플릿 클래스 만들기
#include <iostream>
using std::cout;
using std::endl;
template<class T1, class T2>
class CCC1
{
T1 x;
T2 y;
public:
CCC(T1 xx, T2 yy) { x = xx; y = yy; }
void Print() { cout << x << ',' << y << endl; }
};
int main()
{
CCC1 c1(10, 20);
CCC2 c2(3.5, 5.5);
CCC3 c3('I', "Love You!");
c1.Print();
c2.Print();
c3.Print();
return 0;
}
4단계 템플릿 클래스를 만들었기 때문에 아직은 메인함수에서 오류가 나기때문에 수정
앞쪽에 무슨 자료형인지 써서 알려주기
#include <iostream>
using std::cout;
using std::endl;
template <class T1, class T2> //class를 만들었기 때문에 typename보단 class 선호
class CCC
{
T1 x;
T2 y;
public:
CCC(T1 xx, T2 yy) { x = xx; y = yy; }
void Print() { cout << x << ',' << y << endl; }
};
int main()
{
CCC <int, int> c1(10, 20);
CCC <double, double> c2(3.5, 5.5);
CCC <char, const char*> c3('I', "Love You!");
// 위의 3개부분 자료형(타입)이 나중에 (실행될 때) 결정
c1.Print();
c2.Print();
c3.Print();
return 0;
}
출력결과
10,20
3.5,5.5
I,Love You!
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
gpt 설명
이 코드에 주석을 달아 설명하겠습니다:
```cpp
#include <iostream>
using std::cout;
using std::endl;
// 두 개의 타입 매개변수 T1과 T2를 가진 템플릿 클래스 CCC 정의
template <class T1, class T2>
class CCC
{
T1 x; // T1 타입의 멤버 변수 x
T2 y; // T2 타입의 멤버 변수 y
public:
// 생성자: T1 타입의 xx와 T2 타입의 yy를 받아 멤버 변수 초기화
CCC(T1 xx, T2 yy) { x = xx; y = yy; }
// 멤버 변수 x와 y를 출력하는 메서드
void Print() { cout << x << ',' << y << endl; }
};
int main()
{
// int 타입의 x와 y를 가진 CCC 객체 c1 생성
CCC <int, int> c1(10, 20);
// double 타입의 x와 y를 가진 CCC 객체 c2 생성
CCC <double, double> c2(3.5, 5.5);
// char 타입의 x와 const char* 타입의 y를 가진 CCC 객체 c3 생성
CCC <char, const char*> c3('I', "Love You!");
// 각 객체의 Print 메서드 호출
c1.Print(); // 출력: 10,20
c2.Print(); // 출력: 3.5,5.5
c3.Print(); // 출력: I,Love You!
return 0;
}
```
이 코드는 C++의 템플릿을 사용한 제네릭 클래스의 예시입니다.
`CCC` 클래스는 두 개의 타입 매개변수를 사용하여 다양한 타입의 데이터 쌍을 저장하고 출력할 수 있습니다.
`main` 함수에서는 서로 다른 타입 조합으로 `CCC` 클래스의 객체를 생성하고 각각의 데이터를 출력합니다.
이를 통해 하나의 클래스 템플릿으로 여러 타입에 대해 동작하는 유연한 코드를 작성할 수 있음을 보여줍니다.
vector 컨테이너
백터 클래스에서 가장 많이 사용하는 함수
pushback(작년 시험문제)
크기를 알고 싶다면 size
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector <int> x; //int x[10]와 차이
// 여러 개 int형을 가지고 노는 배열 공간을 만들고 싶어요
x.push_back(1);
x.push_back(2);
x.push_back(5);
for (int i = 0; i < x.size(); i++)
cout << x[i] << endl;
return 0;
}
char형으로
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector <char> x; //int x[10]와 차이
// 여러 개 int형을 가지고 노는 배열 공간을 만들고 싶어요
x.push_back('a');
x.push_back('b');
x.push_back('c');
for (int i = 0; i < x.size(); i++)
cout << x[i] << endl;
return 0;
}
double형
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector <double> x; //int x[10]와 차이
여러 개 int형을 가지고 노는 배열 공간을 만들고 싶어요
x.push_back(1.3);
x.push_back(1.5);
x.push_back(2.6);
for (int i = 0; i < x.size(); i++)
cout << x[i] << endl;
return 0;
}
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
gpt 질문
Exception handling은 프로그램 실행 중 발생할 수 있는 예외적인 상황이나 오류를 관리하고
처리하는 프로그래밍 기법입니다.
이를 통해 프로그램이 예기치 않은 상황에서도 정상적으로 동작하거나 우아하게 종료될 수 있도록 합니다.
Exception handling의 주요 목적은 다음과 같습니다:
프로그램의 안정성 향상
오류 발생 시 적절한 대응 가능
디버깅 및 문제 해결 용이성 증대
코드의 가독성과 유지보수성 개선
다양한 프로그래밍 언어에서 exception handling을 위해 사용하는 키워드를 표로 정리하면 다음과 같습니다:
| 언어 | Exception Handling 키워드 |
| Java | try, catch, finally, throw, throws |
| C++ | try, catch, throw |
| Python | try, except, else, finally, raise |
| JavaScript | try, catch, finally, throw |
| C# | try, catch, finally, throw |
| Ruby | begin, rescue, ensure, raise |
| Go | defer, panic, recover |
| Swift | do, try, catch, throw |
| Kotlin | try, catch, finally, throw |
각 언어마다 exception handling을 구현하는 방식에 약간의 차이가 있지만,
대부분 비슷한 개념을 공유하고 있습니다.
예를 들어, 'try'는 예외가 발생할 수 있는 코드 블록을 정의하고,
'catch'나 'except'는 발생한 예외를 처리하는 데 사용됩니다.
'finally'는 예외 발생 여부와 관계없이 항상 실행되는 코드 블록을 정의하며,
'throw'나 'raise'는 명시적으로 예외를 발생시키는 데 사용됩니다.
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
예외처리(exception handling, error handling)
프로그래밍 하고 제일 마지막에 하는 작업

시험에 자주 나옴 ↓
throw 예외값;
}
catch(자료형){ // 예외 처리 블럭
}
catch(자료형){ // 예외 처리 블럭
}
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
예외처리 예시
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
void Div(double ja, double mo)
{
cout << "결과:" << ja / mo << endl;
}
int main()
{
double x, y;
cout << "분자를 입력하세요=";
cin >> x;
cout << "분모를 입력하세요=";
cin >> y;
Div(x, y);
return 0;
}
위의 코드로 실행하게 되면
0으로 나누면 inf(무한)이 나오면서 나중에 문제가 생길 수 있다
분자를 입력하세요=3
분모를 입력하세요=0
결과:inf
따라서 if문을 사용해서 코드를 만들면
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
void Div(double ja, double mo)
{
if (mo != 0)
cout << "결과:" << ja / mo << endl;
}
int main()
{
double x, y;
cout << "분자를 입력하세요=";
cin >> x;
cout << "분모를 입력하세요=";
cin >> y;
Div(x, y);
return 0;
}
출력 결과는
분자를 입력하세요=5
분모를 입력하세요=0
분모가 0이 되면 나누기를 하지 않는다
하지만 계속 쓰면 어려울 수 있으니 예외처리로 하면
1단계 실행할때 예외가 발생할 수 있는 소스(부분)을 try 블럭으로 묶는다
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
void Div(double ja, double mo)
{
try { // 이부분
cout << "결과:" << ja / mo << endl;
}
}
int main()
{
double x, y;
cout << "분자를 입력하세요=";
cin >> x;
cout << "분모를 입력하세요=";
cin >> y;
Div(x, y);
return 0;
}
2단계 예외 값을 던짐 (던지는 키워드 throw)
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
void Div(double ja, double mo)
{
try {
if (mo==0) throw mo; // 이부분
cout << "결과:" << ja / mo << endl;
}
}
int main()
{
double x, y;
cout << "분자를 입력하세요=";
cin >> x;
cout << "분모를 입력하세요=";
cin >> y;
Div(x, y);
return 0;
}
3단계 catch 추가
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
void Div(double ja, double mo)
{
try {
if (mo==0) throw mo;
cout << "결과:" << ja / mo << endl;
}
catch (int) { // catch는 여러개의 블럭을 만들 수 있고
// 그거에 맞는 자료형으로 실행된다.
cout << "11오류:영으로 나눌 수 없음";
}
catch (double) { // 괄호 안에 던져지는 예외값의 자료형을 쓴다
cout << "22오류:영으로 나눌 수 없음";
}
}
int main()
{
double x, y;
cout << "분자를 입력하세요=";
cin >> x;
cout << "분모를 입력하세요=";
cin >> y;
Div(x, y);
return 0;
}
출력결과
분자를 입력하세요=3
분모를 입력하세요=0
22오류:영으로 나눌 수 없음
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
gpt 설명
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
// 두 개의 double 타입 인자를 받아 나눗셈을 수행하는 함수
void Div(double ja, double mo)
{
try {
// 분모가 0인 경우 예외 발생
if (mo == 0) throw mo;
// 정상적인 경우 나눗셈 결과 출력
cout << "결과:" << ja / mo << endl;
}
// int 타입의 예외를 잡는 catch 블록
catch (int) {
// 이 catch 블록은 실행되지 않음 (throw mo가 double 타입이므로)
cout << "11오류:영으로 나눌 수 없음";
}
// double 타입의 예외를 잡는 catch 블록
catch (double) {
// 분모가 0일 때 이 블록이 실행됨
cout << "22오류:영으로 나눌 수 없음";
}
}
int main()
{
double x, y;
// 사용자로부터 분자 입력 받기
cout << "분자를 입력하세요=";
cin >> x;
// 사용자로부터 분모 입력 받기
cout << "분모를 입력하세요=";
cin >> y;
// Div 함수 호출
Div(x, y);
return 0;
}
```
이 코드는 C++에서 예외 처리(exception handling)를 사용하는 예시입니다.
주요 포인트는 다음과 같습니다:
1. `Div` 함수 내에서 `try-catch` 블록을 사용하여 예외를 처리합니다.
2. 분모가 0인 경우 `throw` 키워드를 사용하여 예외를 발생시킵니다.
3. `catch` 블록은 여러 개를 사용할 수 있으며, 발생한 예외의 타입에 따라 적절한 블록이 실행됩니다.
4. 이 경우, `throw mo`가 `double` 타입이므로 두 번째 `catch` 블록이 실행됩니다.
5. `main` 함수에서는 사용자로부터 입력을 받아 `Div` 함수를 호출합니다.
이 예제는 예외 처리를 통해 프로그램이 0으로 나누는 오류 상황을 안전하게 처리하는 방법을 보여줍니다.
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
C++에서 <>, [], {}, () 기호들은 각각 다른 용도로 사용됩니다:
<>: 앵글 브래킷
템플릿 매개변수를 정의할 때 사용
헤더 파일을 포함할 때 사용 (예: #include <iostream>)
STL 컨테이너를 선언할 때 사용 (예: vector<int>)
[]: 대괄호
배열의 요소에 접근할 때 사용
문자열의 개별 문자에 접근할 때 사용
객체의 속성에 접근할 때 사용 가능
{}: 중괄호
코드 블록을 정의할 때 사용 (함수, 클래스, 조건문, 반복문 등)
초기화 리스트를 정의할 때 사용
구조체나 클래스의 멤버를 초기화할 때 사용
(): 소괄호
함수의 매개변수를 정의하거나 함수를 호출할 때 사용
조건문이나 반복문의 조건을 정의할 때 사용
연산의 우선순위를 지정할 때 사용
타입 캐스팅을 할 때 사용
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
참조자(reference) : 매우 중요 시험에 무조건 나옴
- c++에서는 참조자 때문에 포인터를 사용하지 않아도 된다.
아래 예시
#include <iostream>
using std::cout;
using std::endl;
int main(void)
{
int x = 10;
int rx = x; // 그냥 변수 선언한것임
cout << x << " " << rx << endl;
rx = rx + 10;
cout << x << " " << rx << endl; //참조자(rx)에 변화를 주면 그 타켓(x)도 변함
x = x + 10;
cout << x << " " << rx << endl; //타켓(x)에 변화를 주면 그 참조자(rx)도 변함
return 0;
}
출력결과
10 10
10 20
20 20
#include <iostream>
using std::cout;
using std::endl;
int main(void)
{
int x = 10;
int& rx = x; // rx는 x의 참조자 => x가 바뀌면 rx가 바뀌고 rx가 바뀌면 x도 바뀜
cout << x << " " << rx << endl;
rx = rx + 10;
cout << x << " " << rx << endl; //참조자(rx)에 변화를 주면 그 타켓(x)도 변함
x = x + 10;
cout << x << " " << rx << endl; //타켓(x)에 변화를 주면 그 참조자(rx)도 변함
return 0;
}
출력결과
10 10
20 20
30 30
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
gpt 설명
이 코드는 C++의 참조자(reference)를 설명하는 예제입니다. 주요 부분을 설명하겠습니다:
1. `int x = 10;`
- 정수형 변수 x를 선언하고 10으로 초기화합니다.
2. `int& rx = x;`
- rx는 x의 참조자로 선언됩니다. 이는 rx가 x의 별칭(alias)이 됨을 의미합니다.
3. `cout << x << " " << rx << endl;`
- x와 rx의 값을 출력합니다. 둘 다 10이 출력됩니다.
4. `rx = rx + 10;`
- rx에 10을 더합니다. rx는 x의 참조자이므로, 이 연산은 실제로 x의 값을 변경합니다.
5. `cout << x << " " << rx << endl;`
- 변경된 x와 rx의 값을 출력합니다. 둘 다 20이 출력됩니다.
6. `x = x + 10;`
- x에 직접 10을 더합니다.
7. `cout << x << " " << rx << endl;`
- 다시 x와 rx의 값을 출력합니다. 둘 다 30이 출력됩니다.
이 코드는 참조자의 핵심 특성을 보여줍니다:
- 참조자는 변수의 별칭으로 작동합니다.
- 참조자를 통해 값을 변경하면 원본 변수의 값도 변경됩니다.
- 원본 변수의 값을 변경하면 참조자를 통해 접근한 값도 변경됩니다.
참조자는 포인터와 유사하지만 더 안전하고 사용하기 쉽습니다.
함수 매개변수 전달, 함수 반환 값, 별칭 생성 등에 자주 사용됩니다.
c++ 13 p.19 예제
실습 11-2: 형식 설정 멤버함수
- ios 클래스에는 플래그의 값을 다루는 멤버함수 이외에 자료의 출력시 폭(width),
정밀도(precision) 등을 설정하는 멤버함수가 제공된다
- int width(int w);
출력 폭을 w로 지정
- int precision(int p);
소수점을 포함하지 않는 전체 자리수를 p로 지정,
소수점 이하 자리수를 지정하고 싶으면 cout<<fixed를 먼저 지정
- int fill(char ch);
남는 필드의 위치에 ch문자로 채움
- width() 함수의 영향은 일시적이므로 매 출력 시마다 지정해 주어야 한다.
- fill() 함수는 한번 지정하면 그 효과가 계속 유지된다.
#include <iostream>
using namespace std;
int main(){
cout << "디폴트\n";
cout.width(10);
cout << -50 << endl;
cout << "[ * fill ]\n";
cout.fill('*');
cout.width(10);
cout << -50 << endl;
cout.width(10);
cout << 100.25 << endl;
cout.width(10);
cout << "HanSH"<<endl;
cout.fill(' ');
cout.precision(6); //소수점을 제외한 전체 자리수
cout<< 12.34567<<endl;
cout << fixed; //소수점 이하의 자리수만 다루게 함
cout.precision(3);
cout << 12.34567 << endl;
return 0;
}
출력결과
디폴트
-50
[ * fill ]
*******-50
****100.25
*****HanSH
12.3457
12.346
변형
한문제 나옴
#include <iostream>
using namespace std;
int main() {
cout << "디폴트\n";
cout.width(10);
cout << -50 << endl;
cout << "[ * fill ]\n";
cout.fill('#');
cout.width(5);
cout << 50 << endl;
cout.width(10);
cout << 100.25 << endl;
cout.width(10);
cout << "HanSH" << endl;
cout.fill(' ');
cout.precision(5); //소수점을 제외한 전체 자리수
cout << 12.34567 << endl;
cout << fixed; //소수점 이하의 자리수만 다루게 함
cout.precision(1);
cout << 12.34567 << endl;
return 0;
}
출력결과
디폴트
- 50
[*fill]
###50
####100.25
#####HanSH
12.346
12.3
입출력 조절자(I/O manipulator)
- cout<<setw(5)<<50 //50을 5칸으로 출력실습 11-3: setw()/setfill()
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
cout << "abcdefg\n";
cout << 12345 << endl;
cout << 123.45 << endl;
cout << "10칸\n";
cout << setfill('*') ;
cout << setw(10) << "abcdefg" <<endl;
cout << setw(10) << 12345 <<endl;
cout << setw(10) << 123.45 << endl;
return 0;
}
출력결과
abcdefg
12345
123.45
10칸
***abcdefg
*****12345
****123.45
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
더 편하지만 setfill()이나 setw()를 쓰려면 #include <iomanip>를 반드시 포함시켜야한다
작년 시험 문제!!
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
파일 입출력 작년 5점 시험 문제


출처 : smile 한의 c++ 프로그래밍
'C++프로그래밍 > 수업 내용 및 수업 후 과제' 카테고리의 다른 글
| C++ 13주차 수업 내용 및 수업 후 과제 (1) | 2024.11.26 |
|---|---|
| C++ 12주차 수업 내용 및 수업 후 과제 (1) | 2024.11.19 |
| C++ 수업내용 및 수업 후 과제 (0) | 2024.11.12 |
| c++ 수업 내용 및 수업 후 과제 (3) | 2024.11.05 |
| c++ 9주차 수업 내용 및 수업 후 과제 (0) | 2024.10.29 |