1. C++ 시작
#include <iostream> // 선행처리 지시자
using namespace std; // 정의 가시화
int main()
{
cout << "Hello World!" << endl; // 메시지 출력
cout << endl; // 새로운 행 시작
cout << "c++의 스터디 시작" << endl; // 또 다른 메시지 출력
return 0; // 메인 함수 종료
}
- iostream 헤더파일 안에 cout 과 endl이 정의 되어있다.
- using 선언으로 std 이름공간에 cout과 endl이 속해있다.
- cout은 문자열을 출력하고 나서 다음 행의 시작 위치로 커서를 자동으로 넘겨주지 않는다.
- endl을 사용하여 화면 커서가 다음 행의 시작 위치로 간다. 또는 "\n"을 붙여 개행문자 사용
(단, "\n"은 문자열에 넣어 사용 그밖의 경우에는 "<< endl;" 사용한다.)
[출력]
인터페이스 역할을 하는 main() 함수
**인터페이스란 ?
즉, 인터페이스 클래스에는 가상 소멸자와 순수 가상함수만 포함된다.
인터페이스 클래스는 다형성 인터페이스, 즉 순수 가상 함수 선언을 기본 클래스로 지정하는 클래스이다.
**순수 가상함수란?
함수의 정의는 없으며 오직 다형성 파생 클래스에 오버라이드(override)만으로 적용되는 함수입니다.
* 주의 *
>> c++ 프로그램에서는 반드시 main() 함수가 반드시 하나 있어야 한다. main() 함수가 없으면 완전한 프로그램이 아니다.
C++ 전처리기와 iostream 파일
C++의 일반적인 일출력 기능을 사용하려면 꼭 필요한 선언!!!!
#include <iostream>
using namespace std;
이름공간 (namespace)
프로그램을 작성할 때 여러 소프트웨어 개발업체들이 제공하는 코드들을 사용할 수 있도록 도와준다.
즉, 구조체 내의 변수를 불러올때 같은 개념
using namespace std;
std 이름공간에 정의되어있는 이름들을(함수 or 변수)들을 사용할 수 있다.
*using : 자신에게 필요한 이름들만 선택해서 사용할 수 있게 한다.
C++ 기본 구문
#include <iostream> // 선행처리 지시자
int main()
{
using namespace std;
int carrots; // 정수 변수를 선언한다.
carrots = 25; // 변수에 값 대입한다.
cout << "나는 당근을 ";
cout << carrots; // 변수의 값을 출력한다.
cout << "개 가지고 있다.";
cout << endl;
carrots = carrots -1;
cout << "아삭아삭, 이제 당근은 " << carrots << "개이다." << endl;
return 0; // 메인 함수 종료
}
C++ 입력 객체(cin)
// getinfo.cpp -- input and output
#include <iostream>
int main()
{
using namespace std;
int carrots;
cout << "당근을 몇개나 가지고 있니?" << endl;
cin >> carrots; // C++ input
cout << "여기 두 개가 더있다. ";
carrots = carrots + 2;
// 다음 라인은 출력을 연결한다.
cout << "이제 당근은 모두 " << carrots << " 개이다." << endl;
cin.get();
cin.get();
return 0;
}
C++ 함수사용
[void형 함수]
// ourfunc.cpp -- 사용자가 작성하는 함수를 정의한다.
#include <iostream>
void simon(int); // simon() 함수원형
int main()
{
using namespace std;
simon(3); // simon() 함수호출
cout << "정수 하나 입력하세요: ";
int count;
cin >> count;
simon(count); // 함수를 다시 호출한다.
cout << "끝!" << endl;
// cin.get();
// cin.get();
return 0;
}
void simon(int n) // 함수 정의
{
using namespace std;
cout << "Simon 왈, 발가가락을 " << n << " 번 두드려라." << endl;
} // void형 함수에는 return 이 필요없다.
[int형 함수]
// convert.cpp -- 스톤을 파운드로 환산한다.
#include <iostream>
int stonetolb(int); // 함수선언
int main()
{
using namespace std;
int stone;
cout << "체중을 스톤 단위로 입력하세요: ";
cin >> stone;
int pounds = stonetolb(stone);
cout << stone << " 스톤은 = ";
cout << pounds << " 파운드입니다." << endl;
// cin.get();
// cin.get();
return 0;
}
int stonetolb(int sts)
{
return 14 * sts;
}
변수 초기화
// limits.cpp -- 정수 한계값
#include <iostream>
#include <climits>
int main()
{
using namespace std;
int n_int = INT_MAX; // n_int를 int형의 최대값으로 초기화
short n_short = SHRT_MAX; // limits.h 파일에 정의된 기호상수
long n_long = LONG_MAX;
long long n_llong = LLONG_MAX;
// sizeof 연산자는 데이터형이나 변수의 크기를 알아낸다.
cout << "int is " << sizeof (int) << " bytes." << endl;
cout << "short is " << sizeof n_short << " bytes." << endl;
cout << "long is " << sizeof n_long << " bytes." << endl;
cout << "long long is " << sizeof n_llong << " bytes." << endl;
cout << endl;
cout << "최댓값:" << endl;
cout << "int: " << n_int << endl;
cout << "short: " << n_short << endl;
cout << "long: " << n_long << endl;
cout << "long long: " << n_llong << endl << endl;
cout << "int의 최솟값 = " << INT_MIN << endl;
cout << "바이트 당 비트 수 = " << CHAR_BIT << endl;
// cin.get();
return 0;
}
int emus{ 7 }; //emus를 7로 초기화
int rheas = { 12 }; //rheas를 12로 초기화
int rocs = { }; //rocs를 0으로 초기화
int psychics{ }; //psychics를 0으로 초기화
>> 대입연산자(=) 생략 가능하다.
cout.put()
// morechar.cpp -- char형과 int형 비교
#include <iostream>
int main()
{
using namespace std;
char ch = 'M'; // M에 해당하는 ASCII코드를 char형 변수 ch에 대입
int i = ch; // 같은 코드를 int형변수 i에 저장
cout << ch << " 의 ASCII 코드는 " << i << "입니다." << endl;
cout << "이 문자 코드에 1을 더해 보겠습니다." << endl;
ch = ch + 1; // change character code in ch
i = ch; // save new character code in i
cout << ch << " 의 ASCII 코드는 " << i << "입니다." << endl;
// cout.put() 멤버 함수를 사용하여 char형변수 ch를 출력한다.
cout << "cout.put(ch)를 사용하여 char형 변수 ch를 화면에 출력: ";
cout.put(ch);
// using cout.put() to display a char constant
cout.put('!');
cout << endl << "종료" << endl;
// cin.get();
return 0;
}
** 멤버함수란?
- 클래스에 속하고 , 클래스의 데이터를 다루는 방법을 정의한다. 예를 들어, iostream클래스는 문자를 출력하도록 설계된 put()이라는 멤버 함수를 가지고 있다.
- 멤버 함수는 그 클래스의 특정 객체를 통해서만 사용할 수 있다.
** 멤버 연산자(.)란?
- 멤버 함수를 사용하려면 마침표(.)로 객체 이름(cout)과 함수이름(put())을 서로 연결해야한다. 이 마침표(.)를 멤버 연산자 라고 부른다.
- cout.put()이 나타내는 의미는 클래스 객체인 cout을 통해 클래스 멤버 함수인 put()을 사용하겠다는 뜻이다.
** cout.put() 멤버 함수란?
- << 연산자를 사용하여 문자를 출력하는 것에 대한 대안이다.
- cout << ' $ '; 는 $ 문자를 출력하지 않고, ' $ '에 해당하는 ASCII코드 36을 출력하고 cout.put('$');는 문자그대로 ' $ '를 출력했다.
** auto 선언
- 초기화 선언 시 데이터형을 쓰지않고 auto를 사용할 수 있다.
- 자동으로 변수형을 추론
- STL(Standard Template Library)을 사용할 때와 같이 복잡한 변수형을 다룰때 유용하다.
auto n = 100; // n은 int
auto x = 1.5; // x는 double
auto y = 1.3e12L; // y는 long double
int형
배열 초기화 규칙
int cards[4] = {3,6,8,10}; //맞다
int hand[4]; //맞다
hand[4] = {5,6,7,9}; //틀리다
hand = cards; //틀리다
** 배열을 부분적으로 초기화하면, 컴파일러가 나머지 원소들을 모두 0으로 설정한다. 명시적으로 첫 번째 원소만 0으로 초기화하면 된다. 그러면 컴파일러가 나머지 원소들을 모두 0으로 초기화 시켜준다.
** 배열 중괄호에 공백을 추가하여 0으로 초기화 할 수 있다.
float balances [100] { }; // 모든 배열값을 0으로 초기화
** 리스트 초기화시에 narrowing을 방지할 수 있다.
[harrowing] : 데이터 타입이 큰 변수를 데이터 타입이 작은 변수에 담을 경우 생기는 데이터 형변환 문제
문자열 입력
** cin 은 화이트 스페이스가 있으면 그위치에서 문자열 널을 넣어 끝난 것으로 간주한다.
** getline() 은 Enter키에 의해 전달되는 개행 문자를 입력의 끝으로 간주하여 한 행 전체를 읽는다.
** getline() 은 개행 문자를 읽어서 폐기한다.
cin.getline(매개변수 1, 매개변수 2);
ㄴ 매개변수 1 : 입력한 행을 저장할 배열의 이름
ㄴ 매개변수 2 : 입력받을 문자들의 한계이다. (예를 들어, 한계가 20이면 입력받을 문자는 19이다.)
(단, getline() 멤버 함수는 한계에 도달하거나, 한계 이전이라도 개행 문자를 읽으면 읽기를 중단한다.)
// instr2.cpp -- getline() 함수로 한 행을 읽는다.
#include <iostream>
int main()
{
using namespace std;
const int ArSize = 20;
char name[ArSize];
char dessert[ArSize];
cout << "이름을 입력하세요:\n";
cin.getline(name, ArSize); // 개행 문자가 있는 곳까지 읽는다.
cout << "좋아하는 디저트를 입력하세요:\n";
cin.getline(dessert, ArSize);
cout << "맛있는 " << dessert;
cout << " 디저트를 준비하겠습니다. " << name << " 님!\n";
// cin.get();
return 0;
}
- 문자열 name에 저장할 때는 개행문자는 널문자로 대체된다.
** cin.get()을 사용할 때
cin.get(name, ArSize); // 첫 번째 행을 읽는다.
cin.get(); // 개행 문자를 읽는다.
cin.get(dessert, ArSize); // 두 번째 행을 읽는다.
** 두 개의 멤버 함수를 결합하여 사용하는것
cin.get(name, ArSize).get(); // 멤버 함수들을 결합한다.
즉, cin.get(name, ArSize)가 cin 객체로 리턴한다. 리턴 된 cin 객체는 뒤에 결합된 get() 함수를 호출하는 객체로 사용된다.
** 두행의 입력을 연속해서 읽어 name1과 name2 배열에 각각 저장하는 방법
cin.getline(name1, ArSize).getline(name2, ArSize);
String 클래스
- 문자열을 하나의 데이터형으로 나타낸다.
- String 클래스를 사용하려면 프로그램에 string 헤더파일을 포함시켜야 한다.
- String 클래스는 std 이름공간에 속해 있으므로, using 지시자를 사용하거나 std :: string을 사용하여 그 클래스를 참조해 주어야 한다.
// strtype1.cpp -- C++ string 클래스를 사용한다.
#include <iostream>
#include <string> // string 클래스를 사용하기위해 선언힌다.
int main()
{
using namespace std;
char charr1[20]; // 빈 배열을 생성한다.
char charr2[20] = "jaguar"; // 초기화된 배열을 생성한다.
string str1; // 빈 string 객체를 생성한다.
string str2 = "panther"; // 초기화된 string 객체를 생성한다.
cout << "고양이과 동물 한 종을 입력하세요: ";
cin >> charr1;
cout << "고양이과 또 다른 한 종을 입력하세요: ";
cin >> str1; // 입력을 위해 cin을 사용한다.
cout << "아래 동물들은 모두 고양이과 입니다.:\n";
cout << charr1 << " " << charr2 << " "
<< str1 << " " << str2 // 출력을 위해 cout을 사용한다.
<< endl;
cout << charr2 << " 에서 세번째 글자: "
<< charr2[2] << endl;
cout << str2 << " 에서 세번째 글자: "
<< str2[2] << endl; // 배열 표기를 사용한다.
// cin.get();
// cin.get();
return 0;
}
- string str1; => str1 선언은 길이가 0인 string 객체를 생성한다.
- cin >> str1; => 입력을 읽어 str1에 넣을 때 str1의 크기를 자동으로 조절한다.
[string 대입, 결합 , 추가]
string str1;
string str2 = "jaguar";
string str3;
// 객체 대입
str1 = str2;
// 객체 결합
str3 = str1 + str2;
// 객체 추가
str1 += str2; // str1의 끝에 str2를 추가한다.
String 클래스의 조작
// strtype3.cpp -- string 클래스의 기타기능
#include <iostream>
#include <string> // string 클래스를 사용하기 위해서
#include <cstring> // C스타일 문자 라이브러리 사용하기 위해서
int main()
{
using namespace std;
char charr1[20];
char charr2[20] = "jaguar";
string str1;
string str2 = "panther";
// string 객체의 대입과 문자 배열의 대입
str1 = str2; // str2를 str1에 복사
strcpy(charr1, charr2); // charr2를 charr1에 복사
// string 객체의 추가와 문자 배열의 추가
str1 += " paste"; // str1의 끝에 pasete를 추가
strcat(charr1, " juice"); // charr1의 끝에 juice를 추가
// string 객체의 길이 구하기와 C스타일 문자열의 길이 구하기
int len1 = str1.size(); // str1의 길이를 구한다.
int len2 = strlen(charr1); // charr1의 길이를 구한다.
cout << str1 << " 문자열에는 "
<< len1 << " 개의 문자가 들어 있다.\n";
cout << charr1 << " 문자열에는 "
<< len2 << " 개의 문자가 들어 있다.\n";
// cin.get();
return 0;
}
int len1 = str1.size() ;
int len2 = strlen(charr1);
strlen() 함수는 C스타일 문자열을 매개변수로 사용하여 어느 문자열을 사용할 것인지를 나타낸다.
C++의 string 클래스 객체는 객체 이르과 도트 연산자(.)를 사용하여 어느 문자열을 사용할 것인지를 나타낸다.
다른 형태의 문자열 상수
** wchar_t형 , char16_t , char32_t
** 접두어 L,u,U
** C++ 11에서는 UTF-8 유니코드 문자르 위한 인코딩 방법을 지원한다. UTF-8형태의 문자열 상수를 나타내기 위해 "u8"이라는 접두어를 사용한다.
구조체
- C++에서는 구조체 리스트 의 각 항목을 멤버라고 부른다.
- 구조체 태그를 기본 데이터형의 이름처럼 사용할 수 있다.
ex ) 구조체 이름 변수명; //앞에 struct를 안붙인다.
[구조체 초기화]
구조체 이름 : inflatable / 변수명 : duck / 멤버 자료형 : char , float, double
inflatable duck { "Daphne", 0.12, 9.98 }; // '=' 대입 연산자 생략 가능
구조체에 들어있는 멤버에 대하여 각각 0으로 초기화 하는 방법
inflatabel duck { };
구조체의 기타 특성
구조체를 함수에 매개변수로 전달 할 수 있으며, 구조체를 리턴값으로 사용할 수도 있다.
// assgn_st.cpp -- 구조체 대입
#include <iostream>
struct inflatable
{
char name[20];
float volume;
double price;
};
int main()
{
using namespace std;
inflatable bouquet =
{
"sunflowers",
0.20,
12.49
};
inflatable choice;
cout << "bouquet: " << bouquet.name << " for $";
cout << bouquet.price << endl;
choice = bouquet; // 한 구조체를 다른 구조체에 대입
cout << "choice: " << choice.name << " for $";
cout << choice.price << endl;
// cin.get();
return 0;
}
** 구조체 템플릿의 정의와 구조체 변수의 생성을 하나로 결합할 수 있다.
struct perks
{
int key_number;
char car[12];
} mr_smith, ms_jones ; // 두 개의 perks형 변수
// 변수 생성과 동시에 초기화도 같이 처리 가능
struct perks
{
int key_number;
char car[12];
} mr_glitz =
{
7, // mr_glitz.key_number 멤버의 값
"Packard" // mr_glitz.car 멤버의 값
};
** 구조체 안의 비트 필드
구조체 멤버들이 각각 일정의 비트 수를 차지하도록 지정 할 수 있다.
struct torgle_register
{
unsigned int SN : 4; // SN 값 (4비트)
unsigned int : 4; // 사용하지 않음 (4비트)
bool goodIn : l; // 유효한 입력(1비트)
bool goodTorgle : l; // 토클에 성공(1비트)
};
// 이러한 각 멤버를 비트 필드라고 한다.
=> 어떤 하드웨어 장치에 들어 있는 레지스터에 대응하는 데이터 구조를 만들 때 편리하다.
=> 필드형은 정수형이나 열거자여야 한다.
new를 사용한 메모리 대입
프로그램을 실행하는 동안에 int형 값을 저장할 수 있는 이름이 없는 메모리를 대입하고, 포인터를 사용하여 그 메모리에 접근하는 새로운 방법이다.
int *pn = new int;
new int 부분은 int형 데이터를 저장할 새로운 메모리가 필요하다고 프로그램에게 알린다.
new 연산자는 뒤따라는 데이터형을 보고, 몇 바이트가 필요한지를 파악한다.
그리고 나서 적당한 메모리를 찾아 필요한 만큼 블록을 대입하고, 그 주소를 리턴한다. 이제 리턴되는 주소는 int형을 지시하는 포인터로 선언되어 있는 pn에 대입된다.
delete를 사용한 메모리 해제
사용한 메모리를 다시 메모리 풀로 환수 하는 연산자이다.
new로 대입한 변수가 아니면 delete로 해제할 수 없다.
int *ps = new int; // new로 메모리 대입
... // 메모리 사용
delete ps; // delete 로 메모리 해제
동적 배열 생성 과 해제
int *psome = new int[10]; // 10개의 int형 값을 저장할 블록을 대입
new 연산자는 그 블록의 첫 번째 원소의 주소를 리턴한다.
delete [ ] psome; // 동적 배열을 해제
[ ](대괄호)가 사용되었기 때문에 포인터가 지시하는 첫 번째 원소가 해제되는 것이 아니라 배열 전체가 해제된다.
** new를 대괄호를 넣어 사용했으면 delete도 대괄호를 넣어 사용해야 한다.
[delete 사용할 때 규칙]
- new로 대입하지 않은 메모리는 delete로 해제하지 않는다.
- 같은 메모리 블록을 연달아 두 번 delete로 해제하지 않는다.
- new [ ]로 메모리를 대입한 경우에는 delete [ ]로 해제한다.
- 널 포인터에는 delete로 사용하는 것이 안전하다(아무 일도 일어나지 않는다.)
배열의 대안 (Vector 템플릿 클래스)
vector 란?
프로그램이 실행되는 동안에 vecotr 객체의 크기를 세팅할 수 있고, 새로운 데이터를 마지막에 추가하거나 중간에 데이터를 삽입할 수도 있다.
메모리를 관리하기 위해서 new와 delete를 사용하지만, 그 과정은 자동으로 진행된다.
- vector 객체를 사용하기 위해서는 #include <vector> 를 선언해준다.
- vector 식별자는 std 이름 공간의 일부분이기 때문에 using 명령, using 선언 또는 std::vector를 사용할 수 있다.
- 템플릿은 저장된 데이터 형태르 지시하기 위해서 다른 구문을 사용한다.
- vector 클래스는 원소의 개수를 지칭하기 위해서 다른 구문을 사용한다.
#include <vector>
...
using namespace std;
vector<int> vi; // int의 zero 사이즈 배열을 생성하라
int n;
cin >> n;
vector<double> vd(n); // n개의 더블 배열을 생성하라
vi는 vector <int> 형의 객체라고 얘기하고 vd는 <double> vector형의 객체라고 말한다.
vector 객체는 값을 삽입하거나 더할 때 자동으로 크기를 조정하기 때문에 vi가 0의 크기에서부터 시작하는 것은 아무런 문제가 되지 않는다.
array 템플릿 클래스
array 객체는 자유 저장 대신에 고정된 크기와 고정 메모리 대입을 사용하여 내재 배열이 지닌 것과 동일한 수준의 효율성을 지닌다.
[배열, Vector 객체 , Array 객체 비교]
** 배열(arrays), vector 객체, array 객체 간의 공통점과 상이점
// choices.cpp -- 배열 변형
#include <iostream>
#include <vector> // STL C++98
#include <array> // C++0x
int main()
{
using namespace std;
// C, original C++
double a1[4] = {1.2, 2.4, 3.6, 4.8};
// C++98 STL
vector<double> a2(4); // 4개의 요소로 벡터를 생성한다.
// C++98 버전에서는 초기화하는 것이 복잡함
a2[0] = 1.0/3.0;
a2[1] = 1.0/5.0;
a2[2] = 1.0/7.0;
a2[3] = 1.0/9.0;
// C++11 -- array 객체를 생성하고 초기화 하라.
array<double, 4> a3 = {3.14, 2.72, 1.62, 1.41};
array<double, 4> a4;
a4 = a3; // 동일한 크기의 array 객체에 유효하다
// 배열 표시를 사용하라
cout << "a1[2]: " << a1[2] << " at " << &a1[2] << endl;
cout << "a2[2]: " << a2[2] << " at " << &a2[2] << endl;
cout << "a3[2]: " << a3[2] << " at " << &a3[2] << endl;
cout << "a4[2]: " << a4[2] << " at " << &a4[2] << endl;
// 잘못됨
a1[-2] = 20.2;
cout << "a1[-2]: " << a1[-2] <<" at " << &a1[-2] << endl;
cout << "a3[2]: " << a3[2] << " at " << &a3[2] << endl;
cout << "a4[2]: " << a4[2] << " at " << &a4[2] << endl;
// cin.get();
return 0;
}
- 내재 배열, vector 객체, 또는 array 객체를 사용하건 간에, 사용자는 개별 멤버에 접속하기 위해서는 표준 배열 표식을 사용 할 수 있다.
- 주소를 통해서 array 객체가 동일한 지역의 메모리를 사용한다는 것을 알 수 있다.(이 경우에는 stack). 반면 vector 객체는 다른 지역에 저장된다.(자유 저장 또는 heap)
- 하나의 array 객체를 또 다른 array 객체에 대입할 수 있다.
a2[-2] = .5;
불완전한 코드지만 여전히 허용된다.
a2[-2] : 두개의 double요소를 뒤로 이동시킨다.
at( ) 멤버함수를 사용하는것이다.
a2.at(1) = 2.3 ; // 2.3을 a2[1]에 대입함
'LAB > C++' 카테고리의 다른 글
C++ 기초플러스 (13. 클래스의 상속) (1) | 2024.09.27 |
---|---|
C++ 기초플러스 (12. 클래스와 동적메모리 대입) (0) | 2024.09.26 |
C++ 기초플러스 (08. 함수의 활용 - 10. 객체와 클래스) (0) | 2024.09.25 |
C++ 기초플러스 (05. 루프와 관계 표현식 - 07. 함수 - C++의 프로그래밍 모듈) (0) | 2024.09.24 |
C++ / [Ubintu]QT 설치 (0) | 2024.09.23 |