■ if명령문
하나의 특정한 행동을 수행할 것인지 말것인지 선택해야 할때는 if명령문을 사용한다. if명령문에는 if와 if else가 있다.
if명령문은 조건을 평가한 결과가 참이면 그 다음에오는 하나의 명령문 또는 명령문 블록을 수행하고,
결과가 거짓이면 그것들을 무시하고 건너 뛴다.
if명령문의 구문은 while명령문의 구문과 비슷하다.
if(test-condition)
   statement

test-condition이 참으로 평가되면 statement를 수행한다. statement는 단일명령문또는 블록이 될수 있다.
test-condition이 거짓으로 평가되면 statement를 무시하고 건너뛴다.


●if else명령문
if명령문은 하나의 특정명령문 또는 블록을 수행할것인지 말것인지를 프로그램이 결정한다.
이에 비해 if else명령문은 두개의 명령문 또는 블록중에서 어느 쪽을 수행할 것인지를 프로그램이 결정한다.
if else명령문은 서로 다른 작업 경로를 선택하게 만드는 유용한 명령문이다.
if else 명령문 구문은 다음과 같다.
if(test-condition)
   statement1
else
   statement2
if else 명령문은 test-condition이 참이면 statement1을 수행하고, test-condition이 거짓이면 statement2를 수행한다.
따라서 프로그램의 코드 단편은 다음과 같이 사용한다.
if(answer == 1492)
   cout<<"정답입니다!"<<endl;
else
   cout<<"1장을 다시 읽는것이 좋겠습니다"<<endl;
answer이면 첫번째 메세지를 출력하고, 그렇지 않으면 두번째 메세지를 출력한다.

●if else if esle 구문
if( ch  == 'A')
  a_grade ++;        //선택1
else if(ch == 'B')
  b_grade++;        //선택2
else
  soso++;           //선택3
ch가 A이면 a_grade 를 ++하고 ch가 B이면 b_grade를 ++하고 A도B도 아니면 else인 soso를 ++함

■논리 표현식
하나 이상의 조건을 검사해야할 경우사용.
 ●논리 OR 연산자(||)
    - 영어에서의 or과 동일하다. 두개의 표현식중에서 적어도 하나가 true이거나 0이 아니면 전체 표현식이 true가 된다.
        5==5 || 5==10  ▶True
        5>8  || 5<10   ▶True
        5>8  || 5>10   ▶False

C++에서 || 연산자는 시퀀스 포인터로 작용한다.
좌변에 지시된 값의 변경은 우변이 평가되기 전에 일어난다.
i++<6  || i==j
처음에 i에 10이 들어있다고 가정한다면, j와 비교가 이뤄질떄는 i는 11로 변해있다. 어느 하나의 표현식이 true이면
전체 논리 표현식이 true가되므로, C++는 좌변의 표현식이 true일 경우에 우변의 표현식은 평가하지도 않는다.



●논리 AND 연산자 (&&)
  &&로 나타내는 논리곱 연산자도 두개의 표현식을 하나로 결합한다. 두개의 표현식이 모두 true일때만 전체 표현식이 true가
  된다.
        5==5 && 5==10  ▶ False
        5>8  &&5<10    ▶False
        5>8  && 5>10   ▶False
        5==5 && 5<10   ▶True


●논리부정 NOT 연산자(!)
!연산자는 뒤따르는 표현식의 값을 반대로 만든다. expression이 true이면 !expression은 false가 된다.
!는 Bang라고 부른다.
if(!(x>5))          //(x<=5)가 더 명확하다.
!연산자를 사용하지않고도 더 명확하게 관계를 표현할수 있다. 그러나 ! 연산자는 true/false값을 리턴하는 함수와 함께
사용한다면 매우 유용하다. strcmp(s1,s2)는 두개의 c스타일 문자열 s1과 s2가 서로 다르면 0이 아닌값(true)를 리턴하고,
같으면 0을 리턴한다. 따라서 !strcmp(s1,s2)는 두 문자열이 같을경우에 true가 된다.


■문자 함수를 위한 cctype 라이브러리
문자 관련 함수들의 원형은 cctype에 정의되어있다. 그 함수들은 어떤 문자가 대문자인지, 숫자인지, 구두점ㅇ 문자인지 등을 판별하는 작업들을 간단하게 처리한다.예를 들어 isalpha(ch) 함수는 ch가 알파벳문자이면 0이 아닌값을, 그렇지 않으면 0을
리턴한다.그리고 ispunct(ch)는 ch가 콤마나 마침표와 같은 구두점 문자이면 참값을 리턴한다.
if((ch>='a' && ch <= 'z') || (ch >= 'A' && ch<= 'Z'))
위함수식을 isalpha()함수를 사용하여 구현하면,
if(isalpha(ch)) 가된다.
cctype계열에 속하는 몇가지 문자 관련 함수중,
알파벳문자인지 판별하는 isalpha(),숫자인지 판별하는 isdigit().개행문자,빈칸문자, 탭문자와 같은 화이트 스페이스인지 판별하는 isspace(),구두점 문자인지 판별하는 ispunct()등이 있다.
 함수이름  리턴값
 isalnum()  전달인자가 영숫자, 알파벳이거나 숫자이면 true
 isalpha()  전달인자가 알파벳이면 true
 isblank()  전달인자가 빈칸문자 또는 수평 탭문자이면 true
 iscntrl()  전달인자가 제어 문자이면 true
 isdigit()  전달인자가 십진숫자이면(0~9) true
 isgraph()  전달인자가 빈칸이 아닌 인쇄할수 있는문자면 true
 islower()  전달인자가 소문자이면 true
 isprint()  전달인자가 빈칸을 포함하여 인쇄할수있는 문자면 true
 ispunct()  전달인자가 구두점 문자이면 true
 isspace()  전달인자가빈칸,개행,캐리지리턴,수평탭,수직탭 문자면true
 isupper()  전달인자가 대문자이면 true
 isxdigit()  전달인자가 16진수이면 true
 tolower()  전달인자가 대문자면 소문자로 바꿔리턴, 그렇지 않으면
전달인자를 변경하지 않고 그대로 리턴한다.
 toupper()  전달인자가 소문자이면 대문자로 바꾸어 리턴,그렇지 않으면
전달인자를 변경하지 않고 그대로 리턴.

■?: 연산자
C++에서는 if else 명령문대신에 사용할수 있는 연산자를 제공한다.
?:로 표기하는 이연산자를 조건 연산자라 부른다. 조건연산자는 C++에서 피연산자를 3개 사용하는 유일한 연산자이다.
일반적인 사용 형식은 다음과 같다.
expression1 ? expression2 : expression3


■switch 명령문
다음 switch 명령문을 사용하는 기본형식이다.
switch(integer-expression)
   case label1: statement(s)
   case label2: statement(s)
    ...
   default    :statement(s)

switch 명령문은 다음에 수행할 명령문이 어느행인지 알려주는 경로 결정기처럼 행동한다. switch 명령문에 도달하면
intger-expression의 값에 해당하는 레이블이 붙어있는 행으로 프로그램이 점프한다.
intger-expression은 그이름이 의미하듯이 하나의 정수값이 될수 있는 표현식이다. 또한 각 레이블은 정수 상수 표현식이다.
대부분의 경우에, 레이블은 1이나 'q'또는 열거자 처럼 단순한 int또는 char형 상수이다. integer-expression에 대응하는
레이블이 없으면 default라는 레이블이 붙어있는 행으로 프로그램이 점프한다. defalut레이블은 생략할수 있다.
default를 사용하지않고 대응되는 레이블도 없을때는 switch명령문은 다음에 오는 명령문으로 프로그램이 점프한다.
각각의 case레이블은 행 레이블로만 작용하고, 선택의 경계로는 작용하지않는다. 따라서, 프로그램이 switch의 특정 행으로 점프하면 명시적으로 흐름을 제어하지않는 한 그 행 이후의 모든 명령문들을 순차적으로 수행한다.
다시말해서, 다음 case가 있는 위치에서 수행을 자동으로 멈추지 않는다. 특정 명령문들을 집합을 처리한후 수행을
멈추게 하려면 특정 명령문들의 집합끝에 break 명령문을 사용한다. break 명령문은 switch명령문 바로 뒤에 오는 명령문
으로 프로그램을 점프시킨다.

●레이블로 열거자 사용하기
   일반적으로 cin은 열거체를 인식하지않는다. 그러므로 프로그램은 사용자가 선택 사항을 입력하면 그것을 int값으로 읽어
   들인다. int값을 switch 명령문이 열거자중의 하나에 대응하는 case 레이블과 비교할때, 열거자가 int형으로 승급된다.
   또한 열거자들은 while루프 조건 검사에서도 int형으로 승급된다.

●switch 와 if else
   if else 는 값의 범위를 다룰수 있다.
if(age > 17 && age <35)
   index=0;
else if(age >= 35 && age<50)
   index=1;
else if(age >=50 && age<65)
   index=2;
else
   index=3;
한편, switch명령문은 값의 범위를 다룰수 없다. switch의 각 case 레이블은 단일 값이어야한다. 또한 그값이 (char형을 포함한)int형이어야 한다. 그래서 switch명령문은 부동 소수점수의 조건 검사 처리를 할수 없다. 그리고 case레이블 의 값도 상수
여야 한다. 따라서 값의 범위를 포함하는 경우나, 부동소수점 수의 조건 검사, 두개의 변수를 비교할때는 if else를 사용해야한다.
그러나 모든 선택 사항들이 정수형 상수로 인식될수 있다면, switch나 if else 를 둘다 사용할수 있다. switch명령문은 바로
이러한 상황을 처리하기 위해 설계된 것이기 때문에, 일반적으로 선택사항의 수가 2개가 아니라면 switch가 코드 크기나
실행속도면에서 if else 보다 훨씬 효율적이다.

■break와 continue명령문
break와 continue 명령문은 프로그램이 코드의 일부를 무시하고 건너뛰게 만든다. break 명령문은 switch 명령문과, 모든
종류의 루프에 사용할수 있다. break는 switch나 루프의 바로 뒤에 오는 명령문을 실행하도록 만든다.
continue 명령문은 루프에만 사용할수 있다. continue는 루프 몸체의 나머지를 무시하고, 새로운 루프 주기를 시작하게 만든다.

■수를 읽어 들이는 루프
int n;
cin>>n;
위경우 사용자가 수를 입력하는 대신에 단어를 입력한다면 네가지 일이 벌어진다.
ⓐn의값은 변하지않는다.
ⓑ입력 큐에 잘못된 입력이 그대로 유지된다.
ⓒcin 객체의 에러 플래그가 설정된다.
ⓓcin메서드 호출이 false(bool형으로 변환된다면)를 리턴한다.
cin메서드가 false를 리턴한다는 사실은, 수를 읽어들이는 루프를 종료시키기 위해 수가 아닌 입력을 사용할수 있다는 것을
의미한다. 또한 수가 아닌 입력이 에러 플래그를 설정한다는 사실은, 프로그램이 다시 입력을 받기 전에 그 에러 플래그를
초기화 해야한다는 것을 의미한다. 파일끝(EOF) 조건을 초기화하는 clear()메서드는 불량입력 플래그도 초기화한다.

*불량입력제거
사용자가 잘못된 데이터를 입력했다는 사실을 프로그램이 알게 된다고 가정하면, 프로그램은 다음과 같은 세단계를 취할 필요
가있다.
ⓐ새로운 입력을 받아 들일수 있도록 cin을 초기화한다.
ⓑ입력 큐에 남아있는 불량 입력을 제거한다.
ⓒ사용자에게 다시 입력할것을 요구한다.
불량입력을 제거하기 전에 프로그램은 먼저 cin을 초기화 해야한다.

■간단한 파일 입/출력
  C++에서는 키보드 입력과 디스플레이 출력에서 배운 기술을 파일 입력과 출력 파일(I/O)에 적용하는것이 간단하다.
  ●텍스트 I/O와 텍스트 파일
    입력을 위해 cin을 사용할때, 프로그램은 그 입력을 연속된 바이트들로 인식한다. 이때 각각의 바이트는 하나의문자
    코드로 해석된다. 목적지 데이터형이 무엇이든지 간에, 그 입력은 문자 데이터, 즉 텍스트 데이터로 시작한다. 그러고나서
    cin객체가 텍스트를 다른 데이터형으로 변환하는 책임을 맡는다. 이것이 어떻게 동작하는지 보기 위하여, 서로다른 코드가
    동일한 입력행을 어떻게 처리하는지 보자. 샘플 입력행은 다음과 같다.
38.5     19.2
cin이 동일한 입력 행을 서로 다른 데이터형에 어떻게 처리하는지 살펴보자.
먼저.char형
char ch;
cin>>ch;
입력 행에 있는 첫문자가 ch에 대입된다. 이경우에, 첫문자는 숫자3이고, 이숫자에 해당하는 문자 코드가(바이너리로)ch에
대입된다. 입력과 목적지가 둘다 문자다. 그래서 따로 변환이 필요없다. (저장되는것이 수치 값 3이 아니라는것에 주의.
그것은 숫자3에 해당하는 문자코드이다) 그입력 명령문이 끝난후에, 입력 큐에있는 다음 문자 숫자는 8이고, 그것이 다음입력
동작이 적용되는 대상이다.
다음에,int형으로 시도해보자.
int n;
cin>>n;
이경우에, cin은 숫자가 아닌 첫문자가 나올때까지 읽는다. 즉, 숫자3과 숫자8을 읽고, 다음에 읽을 문자로 소수점을 입력큐에 남겨둔다. 그러고 나서 cin은 이 두문자가 수치값 38에 해당한다고 계산하고, 38에 해당하는 바이너리 코드를 n에 대입한다.
다음은,double형
double x;
cin>>x;
이경우에, cin은 부동소수점 수의 일부가 아닌 첫문자가 나올때까지 읽는다. 즉, 숫자3,숫자8,소수점(.)문자,숫자5를 읽고,
다음에 읽을 문자로 빈칸을 입력 큐에 남겨둔다. 그러고 나서 cin은 이 네문자가 수치값 38.5에 해당한다고 계산하고,
38.5에해당하는 바이너리코드(부동소수점 형식)를 x에 복사한다.
다음은,char형 배열
char word[50];
cin>>word;
이경우, cin은 빈칸 문자가 나올때까지 읽는다. 즉, 숫자3,숫자8,소수점문자(.), 숫자5를 읽고, 다음에 읽는 문자로 빈칸을 입력 큐에 남겨둔다. 그리고나서 cin은 이 네문자에 해당하는 문자 코드들을 배열 word에 저장하고, 끝에 널문자를 추가한다.변환은 필요없다.
끝으로, char형 배열에 대해 다른 방식의 입력으로 시도해보자.
char word[50];
cin.getline(word,50);
이경우, cin은 개행 문자가 나올때까지 읽는다. 마지막 숫자 2까지의 모든 문자들을 배열 word에 저장하고, 끝에 널 문자를
추가한다. 개행 문자는 폐기한다. 다음 행의 첫문자가 입력큐에서 다음에 읽을 문자가 된다. 변환은 필요없다.

출력에서는 정반대의 변환이일어난다. 즉,정수들이 숫자 문자들의 시퀀스로 변환되고, 부동소수점 수들이 숫자 문자와 기타 문자들의 시퀀스로(예를들면 284,53또는 -1.587E+06)변환된다. 문자데이터는 변환이 필요없다.
여기서 중요한점은, 모든 입력이 텍스트로 시작한다는것이다. 그러므로, 콘솔 입력과 동등한 파일도 텍스트 파일이다.

●텍스트 파일에 쓰기
  -iostream헤더파일을 포함시켜야한다.
  -iostream헤더 파일은 출력을 처리하는 ostream클래스를 정의한다.
  -iostream헤더 파일은 cout이라는 ostream변수 또는 객체를 선언한다.
  -std이름 공간을 지정해야한다. cout과 enld과같은 요소들을 사용하기 위해 using지시자 또는 std::접두사를 사용할수있다.
  -cout을  << 연산자와 함께 사용하여 다양한 유형의 데이터를 출력할수 있다.

파일출력은 이와 매우 비슷한 방식으로 처리된다.
   -fstream헤더 파일을 포함시켜줘야한다.
   -fstream헤더 파일은 출력을 처리하는 ofstream클래스를 정의한다.
   -하나이상의 ofstream변수 또는 객체를 선언할필요가있다. 일반적인 이름짓기 관례를 준수하는 한, 사용자는 원하는이름을
    지정할수 있다.
   -std 이름 공간을 지정해야한다. ofstream과 같은 요소들에 대해 using지시자 또는 std::접두사를 사용할수있다.
   -특정ofstream객체와 특정파일을 연결시킬 필요가있다. 그렇게 하는 한가지 방법은, open()메서드를 사용하는것이다.
   -ofstream 객체를 << 연산자와 함께 사용하여 다양한 유형의 데이터를 출력할수있다.

iostream헤더파일이 cout이라는 미리정의된 ostream객체를 제공할지라도, 사용자 자신의 ofstream객체를 선언하고, 그것에 적당한 이름을 부여하고, 그것을 파일과 연결시켜야 한다는것에 주의해야한다.
ofstream outFile;       //outFile은 ofstream 객체
ofstream foutl           //fout은 ofstream객체

객체를 특정파일에 연결하는 방법은 다음과 같다.
outFile.open("fish.txt");     //fish.txt에 쓰는데 outFile사용
char filename[50];
cin >> filename;              //사용자가 이름을 지정한다.
fout.open(filename);        //지정된 파일을 읽는데 fout사용

open()메서드는 전달인자로 C스타일 문자열을 요구한다. 리터럴 문자열이나 배열에 저장된 문자열을 전달인자로 사용할수 있다. 객체를 사용하는 방법은 다음과 같다.
double wt=125.8;
outFile << wt;          //fish.txt에 하나의 수를 쓴다.
char line[81] = "Objects are closer than they appear.";
fin<<line<<endl;     //한 행의 텍스트를 쓴다.
여기서 중요한 점은, ofstream객체를 선언하고, 그것을 파일에 연결한후에, 그것을 cout과 동일한 방식으로 사용한다는 것이다. cout에 사용할수 있는 <<. endl, setf()과 같은 모든 동작과 메서드들은, 앞의 outFile과 fout과 같은 ostream객체를
사용할수 있다.

파일출력을 사용하는 기본절차는 다음과 같다.
ⓐfstream 헤더 파일을 포함시킨다.
ⓑofstream 객체를 생성한다
ⓒofstream 객체를 파일에 연결한다
ⓓofstream 객체를 cout과 동일한 방식으로 사용한다.

●텍스트 파일 읽기
   -fstream헤더 파일을 포함시켜야한다
   -fstream헤더 파일은 입력을 처리하는 ifstream클래스를 정의한다.
   -하나 이상의 ifstream변수 또는 객체를 선언할 필요가 있다. 일반적인 이름짓기 관례를 준수하는한, 사용자가 원하는
    이름을 지정할수 있다.
   -std이름 공간을 지정해야한다. ifstream과 같은 요소들을 사용하기 위해 using지시자 또는 std::접두사를 사용할수 있다.
   -특정 ifstream 객체와 특정파일을 연결시킬 필요가 있다. 그렇게 하는 한가지 방법은 open()메서드를 사용하는것이다.
   -파일을 다루는 작업이 끝나면, close() 메서드를 사용하여 그 파일을 닫아야한다.
   -ifstream객체를 >>연산자와 함께 사용하여 다양한 유형의 데이터를 읽을수 있다.
   -ifstream객체를 get()메서드와 함께 사용하여, 개별적인 문자들을 읽을수 있다.
    ifstream객체를 getline()메서드와 함께사용하여, 한번에 한행의 문자를 읽어들일수도있다.
   -ifstream객체를 eof()과 fail()과 같은 메서드와 함께 사용하여, 입력시도가 성공했는지 감시할수있다.
   -ifstream객체 자체가 검사조건으로 사용되었을때, 마지막 읽기 시도가 성공이면 bool값 true로 변환,아니면 false

※객체를 선언 하는 방법
ifstream inFile;     //inFile은 ifstream객체
ifstream fin;         //fin은 ifstream객체
※객체를 특정 파일에 연결하는 방법
inFile.open("bowling.txt");    //bowling.txt파일을 읽는데 inFile사용
char filename[50];
cin>>filename;                   //사용자가 이름을 지정
fin.open(filename);             //지정된 파일을 읽는데 fin사용

open()메서드는 전달인자로 C스타일 문자열을 요구한다. 리터럴 문자열이나 배열에 저장된 문자열을 전달인자로 사용할수 있다. 사용방법은 다음과 같다.
double wt;
inFile >> wt;           //bowling.txt에서 하나의 수를 읽는다.
char line[81];
fin.getline(line,81);   //한행의 텍스트를 읽는다.
ifstream객체를 선언하고 그것을 파일에 연결한후에, 그것을 cin과 동일한 방식으로 사용한다. cin에서 사용할수 있는 모든
동작과 메서드들을, inFile과 fin같은 ifstream객체에 사용할수 있다.
어떤파일이 성공적으로 열렸는지 확인하는 방법은 is_open()메서드를 사용하는것이다.
inFile.open("bowling.txt");
if(!inFile.is_open())
{
   exit(EXIT_FAILURE);
}
is_open 메서드는 파일이 성공적으로 열렸으면 true를 리턴한다. 표현식 !inFile.is_open()은 그시도가 실패하면 true를
리턴한다. exit()함수는 cstdlib헤더 파일에 원형이있다. 운영체제와 커뮤니케이션하는데 사용하는 전달인자값으로 EXIT_FAILURE를 정의한다.exit()함수는 프로그램을 종료한다.



================================요   약===============================================
C++에서는 선택을 다루는 도구로 if명령문,if else명령문,switch명령문을 제공한다. if명령문은 단일 명령문이나, 명령문 블록을 조건에 따라 수행하게 만든다. 이것은 특정한 조건이 만족될 떄에만 그 단일 명령문이나 명령문블록을 수행한다는 말이다.
if else명령문은 두개의 단일 명령문이나 명령문 블록 중에서 어느것을 실행할것인지 선택하게 만든다. 여러가지 선택사항중에
선택하게 하려면, 그와 같은 하나의 if else명령문에 원하는 만큼의 if else 를 추가할수 있다. switch명령문은 선택 사항의
목록에서 하나의  특정한 경우를 선택하게 만든다.
if와 if else명령문은 일반적으로 관계 연산자를 사용하여 조건을 검사한다. 논리연산자(&&,||,!)를 사용하여 관계 표현식들을 결합 하거나 수정하여 더욱 정교한 조건검사를 수행할수 있다. 조건 연산자(?:)는 두값중에 하나를 선택하는 간결한 방법을
제공한다. 문자 관련 함수들이 들어있는 cctype라이브러리는 문자 입력을 분석하는 매우 편리하고 강력한 도구를 제공한다.
루프와 선택 명령문은, 콘솔I/O와 매우 유사한 파일 I/O에 유용하게 쓸수 있는 도구다. ifstream과 ofstream객체를 선언하고 그들을 파일과 연결한 후에, 이 객체들을 cin과 cout을 사용하는것과 동일한 방식으로 사용할수 있다.

'C++ > C++ PRIMER PLUS' 카테고리의 다른 글

함수 - C++의 프로그래밍 모듈  (0) 2011.11.09
루프와 관계 표현식  (0) 2011.10.27
복합 데이터형  (0) 2011.10.27
데이터처리  (0) 2011.10.20
C++시작하기  (0) 2011.10.18

C++ for루프, while루프, do while 루프, if 명령문, switch 명령문,과 같은 도구들을 제공한다.
■for 루프
 ●for 루프의 각부분
    for루프를 구성하는 각 부분은 순서대로 다음과 같은 단계를 처리한다.
    ①조건 검사에 사용할 카운터 값을 초기화한다.
    ②루프를 진행할 것인지 조건을 검사한다.
    ③루프 몸체를 수행한다.
    ④카운터 값을 갱신한다.
for루프를 구성하는 각부분들은 각자의 역활이 무엇인지 알기 쉬운 위치에 자리 잡고있다. 초기화, 조건검사,갱신 을 처리하는 for루프의 세 제어 부분은 괄호로 묶여있다. 이들은 각각 하나의 표현식이며, 세미콜로(;)에 의해 분리되어있다. 제어 부분뒤에 오는 명령문을 루프 몸체라고 한다. 루프몸체는 조건 검사가 참일때만 수행된다.
C++는 몸체 안에 여러개 명령문이 사용되었을 경우에도 for루프 전체를 하나의 명령문으로 간주한다.
초기화는 처음에 단한번만 수행한다. 일반적으로 초기화 표현식은 어떤 변수에 시작값을 설정한다.
프로그램은 루프의 주기를 카운트 하는데 그변수를 사용한다.

●갱신 크기 변경
   갱신 표현식으로는 i++대신에 i= i+by라는 표현식을 사용한다.by는  사용자가 지정하는 갱신크기이다.

●for 루프를 사용한  문자열 처리.
string 클래스 객체를  사용한다. string 클래스의 size()메서드가 문자열을 구성하는 문자수를 알아낸다. 그러고 나서 루프의
초기화 표현식에서 i를 그 문자열의 마지막 문자열을 나타내는 첨자로 초기화하기위해 이값을 사용한다. 이떄 널 문자는
계산에 넣지않는다. 문자열을 거꾸로 출력하기 위해 감소연산자(--)를 사용하여 매 루프 주기마다 첨자를 1씩감소한다.

●증가 연산자(++)와 감소연산자(--)
  증가연산자는 루프 카운터를 1씩 증가시키고, 감소 연산자는 루프 카운터를 1씩 감소시킨다. 증가 연산자와 감소연산자들은둘다 접두어 방식과 접미어 방식으로 사용할수 있다. 접두어 방식은 ++x와 같이 피연산자 앞에 연산자를 사용하는것이다.
접미어 방식은 x++와 같이 피연산자 뒤에 연산자를 사용하는것이다. 접두어 방식과 접미어 방식은 피연산자에 가져오는 효과는 동일하지만 연산을 적용하는 시점이다르다.

●부수 효과와 시퀀스 포인트
   부수효과는, 수식을 평가할떄 변수에 저장되어 있는 값과 같은 것이 변경될 때 일어나는 효과를 말한다.
   시퀀스 포인트는, 프로그램의 실행이 다음단계로 넘어가기 전에 모든 부수 효과들이 확실하게 평가되는 포인트이다.
  C++에서 명령문에 있는 세미콜론은 시퀀스 포인트를 표시한다. 그것은 명령문에 대입연산자, 증가 연산자, 감소 연산자에
  의해 일어나는 모든 변화가 프로그램이 다음 명령문으로 넘어가기 전에 반드시 일어나야 한다는 것을 의미한다.

●접두어 방식과 접미어 방식
    x++;   와  ++x;는
   논리적으로, 접두어 방식과 접미어 방식은 차이가 나지 않는다. 수식의 값이 사용되지않는다. 그래서 부수 효과만이 유일한
   효과이다.여기에서 연산자를사용하는 수식들은 완전 수식이다. 프로그램이 다음 단계로 넘어갈 시점에는 x를 증가시키는
  부수효과를 수행되었으리라는 것이 보장된다. 
  접두어 방식과 저미어 방식의 선택이 프로그램의 행동에 영향을 주지 않을지라도 그와 같은 선택이 프로그램의 실행 속도
  에는 작게나마 영향을 줄수 있다.
  접미어 방식은 먼저 값의 복사본을 만들고, 복사본의 값을 증가시키고, 그 복사본을 리턴하는 방식으로 동작하기때문에,
  접두어 방식이 약간더 효율적이다.

●증가/ 감소 연산자와 포인터
   증가 연산자는 기본 변수에 대해서만이 아니라 포인터에도 사용할수 있다. 포인터에 증가 연산자를 사용하면 포인터가
   지시하는 데이터형의 바이트 수만큼 그 값을 증가시킨다. 포인터를 증가시키는것과 감소 시키는 것에는 동일한 규칙이
   적용된다.
double arr[5]= {21.1, 32.8, 23.4, 45.2, 37.4};
double *pt = arr;     //pt는 arr[0],즉 21.1을 지시.
++pt;                     //pt는 arr[1],즉 32.8을 지시.
이 연산자들은 * 연산자와 결합하여 사용함으로써 포인터가 지시하는 값을 변경할수 있다. 하나의 포인터에 * 와 ++ 를 함께
적용하는 것은, 참조되며 증가 되는것은 연산자가 놓여지는 위치와 우선순위에 의해 결정된다.
접두형 증가, 접두형 감소, 내용참조자는 우선 순위가 같고, 오른쪽에서 왼쪽으로 결합된다. 접미형증가,감소 연산자는 우선
순위가 같고, 접두형보다 우선 순위가 높다. 또한 이 두연산자는 왼쪽에서 오른쪽으로 결합된다.
접두형 연산자들에 적용되는 오른쪽 에서 왼쪽으로 결합 규칙은,  *++pt의 경우에 ++가먼저 pt에 적용되고 pt의 새로운 값에
*가 적용된다는것을 의미한다.
*++pt;   //포인터 증가를 한후 값을 취한다. 따라서 arr[2], 즉 23.4
++*pt의 경우에는 pt가 지시하는 값을 먼저구하고, 그값을 증가시킨다는것을 의미한다.
++*pt;  //지시되는값을 증가; 즉 23.4를 24.4로변경

*pt++;  //원래 주소를 참조하고 나서 포인터 증가.
접미형 ++ 연산자가 우선 순위가 더높다는것은, ++연산자가 *pt가 아니라 pt에 적용된다는것을 의미한다.
그래서 포인터는 증가된다. 그러나 접미형 연산자가 사용되었다는 사실은, 참조되는 주소가 새로운 주소가 아니라
원래주소인 &arr[2]라는것을의미한다. 그래서 *pt++의 값은 arr[2]또는 25.4이다.이명령문이 실행되고 난후는
pt의 값은 arr[3]의 주소이다.

●결합 대입 연산자
   += 연산자는 두 피 연산자의 값을 더해서 그 결과를 왼쪽  피연산자에 대입한다. 여기서 왼쪽 피연산자는 변수, 배열원소,
   구조체의 맴버, 포인터에 의해 참조되는 데이터와 같이 실제로 값을 대입할수 있어야한다.

 연산자  효과(L은 왼쪽 피연산자,R은 오른쪽피연산자)
 += L+R을 L에 대입한다.
 -= L-R을 L에 대입한다.
 *- L*R을 L에 대입한다. 
 /= L/R을 L에 대입한다.
 %= L%R을 L에 대입한다. 

■While 루프
While루프는 for루프에서 초기화 부분과 갱신부분을 없애고 , 루프 몸체와 조건 검사부분만 남겨놓은것이다.
while(test-expression)
{
   body
}
프로그램은 먼저 괄호 안의 조건검사 표현식을 평가한다, 표현식이 true로 판명되면 루프 몸체이있는 명령문을 실행한다. for
루프와 마찬가지로 루프 몸체는 하나의 명령문 또는 한 쌍의 중괄호로 묶은 블록이다. 조건 검사 표현식이 여전히 true이면
루프 몸체를 다시 실행한다. 조건 검사 표현식을 평가하고 루프 몸체를 실행하는 이와 같은 루프 주기는 조건 검사표현식이
false가 될때까지 반복된다.

●시간 지연 루프
   while루프로는 간단하게 효과를 만들어낼수 있다.
long wait =0;
while(wait<100000)
   wait++;       //수를 카운터한다.
이방법의 문제점은 컴퓨터 프로세서(cpu)성능에 따라 카운트 수의 한계를 변경해주어야한다는것이다.
좋은 시스템에서는 빨리 카운트가 될것이고, 성능이 좋지 않은 시스템에서는 늦게 카운트가 될것이다.
이 문제점을 해결하기 위해서는 clock()이라는 함수가있다.
이함수는 프로그램이 실행된 순간부터 이 함수가 호출 된 순간까지경과 한 시스템시간을 리턴한다.  그렇지만 이 함수를
사용하는데  두가지 제약이있다. 첫째, clock()함수가 리턴하는 값은 초단위 시간이 아니다.
둘째, 이 함수가 리턴하는 데이터 형은 어떤 시스템에서 는 long형, 다른 시스템에서는 unsigned long형, 또다른 시스템에서
는 다른 데이터 형일수 있다.

그러나 ctime헤더 파일이 이 문제에 대한 해결책을 제공한다. 첫째, 이해더 파일은 초당 시스템 시간 단위 수를 알려주는
CLOCKS_PER_SEC라는 기호 상수를 정의한다. clock()함수가 리턴하는 시스템 시간을 이상수로 나누면 초 단위의 시간을
얻을수 있다. 둘쨰, cltim은 clock()함수가 리턴하는 데이터형의 대용 이름으로 clock_t형을 정의한다.
이것은 변수를 clock_t형으로 선언할수 있다는 것을 의미한다. 컴파일러는 그것을 적당히 맞는 데이터형으로 변환하여 준다.

■do while 루프
do while루프는 for루프나 while루프와 달리, 탈출조건 루프이다. 몸체를 먼저 실행하고, 조건을 나중에 검사한다.
검사하는 조거닝 false로 평가 되면 루프가 종료된다. 검사하는 조건이 true로 평가 되면 새로운 루프 주기와 조건 검사가 시작된다. 그러므로 do while루프는 조건을 평가하기 전에 루프 몸체를 적어도 한번은 실행한다.
do
  body
while(test-expression);
루프 몸체 부분은 단일 명령문 또는 중괄호로 둘러 싸인 블록이다.

■루프와 텍스트 입력
파일이나 키보드로 부터 문자를 하나씩 읽어 들이는방법이다.
C++의 while루프가 C의 while 루프와 같다고는 해도, C와 C++의 I/O기능은 다르다. 그렇기 때문에 C++의 루프는 C의 루프와
약간달라보인다. 실제로 cin객체는 단일 문자 입력에서 세가지 서로 다른 모드를 사용한다. 이들은 사용자 인터페이스가
제각각 다르다.
 ●cin을 이용한 입력

●cin.get(char)를 이용한 입력
일반적으로 문자 단위로 입력을 읽어 들이는 프로그램은 빈칸문자, 탭문자, 개행 문자까지 포함하여 모든 문자를 읽어 들여야한다. cin이 속해 있는 istream클래스 는 이런 요구를 만족시키는 맴버 함수들을 가지고있다. 특별히 cin.get(ch)맴버 함수는 빈칸 문자까지도 입력받아 ch변수에 저장한다.

●파일의 끝 (End-Of-File)조건
 파일로 부터 정보를 읽어들이는 것은 cin이나 키보드 입력과 관계가 없는것처럼 보이지만 두가지 연관성이 있다.
첫번째, 많은 운영체제가 리디렉션 기능을 제공하므로 키보드 입력을 파일로 대체 할수 있다.
두번째, 많은 운영 체제들이 EOF조건을 키보드 입력을 통해 시뮬레이션하고 있다.
cin은 EOF를 탐지했을때 두개의 비트를 1로 설정한다. eof()라는 맴버 함수를 사용하면 eofbit가 설정되었는지 알수있다.
cin.eof()의 호출은 EOF가 탐지되었으면 bool값 ture를 리턴하고, 아니면 false를 리턴한다.
fail()맴버 함수는 eofbit또는 failbit가 1로 설정되어 있으면 true를 리턴하고 아니면 false를 리턴한다.
eof()가 fail()메서드는 가장 최근에 읽은 결과를 보고한다.



●입력을 끝내는 EOF
 cin 메서드가 EOF를 발견하면, cin 객체에서 EOF 조건을 나타내는 플래그가 설정된다. 이플래그가 설정되면, cin은 더이상 입력을 받아들이지 않는다. 파일 입력인 경우에 파일의 끝을 지나쳐서 읽으면 당연히 안되기 떄문에 이것은 이치에 맞는다.
그러나 키보드 입력인 경우에, 루프를 끝내기 위해 시뮬레이션 EOF를 사용한 후에도 다른 입력을 더 읽기를 원할수 있다.
이때 cin.clear()메서드는 EOF플래그를 지우고, 다시 입력이 진행될수 있도록 허용한다.
이다만 어떤 시스템에서 Ctrl+Z를 누르면 입력과 출력이 완전히 종료되며, 이경우에는 cin.clear()로 입출가능상태를 다시 복원할수 없다.

■문자 입력에 자주 쓰는 구문
EOF가 나타날때까지 텍스트를 한번에 한문자 씩 읽는 루프는 다음과 같다.
cin.get(ch);                                //문자하나를 읽는다.
while(cin.fail() == false)              //EOF인지 검사한다.
{
   ....                                        //일을 처리한다.
  cin.get(ch);                            //다음문자를 읽는다.
}
!연산자를 사용하면 while(cin.fail() == false)구문을 다음과 같이 고칠수 있다.
while(!cin.fail())                     //입력이 실패하지 않았으므로 루프 실행.
cin.get(char)메서드가 리턴하는 값은 cin 객체이다. 그러나 istream클래스는 cin과 같은 istream객체를 bool값으로 변환하는
함수를 제공한다. while루프의 조건 검사와 같이 bool값이 필요한 곳에 cin이 나올때 이변환 함수가 호출된다.
또한 bool값으로 변환된 결과는 마지막으로 시도한 읽기가 성공이면 true이고, 실패이면 false이다. 따라서 앞에나온
while조건 검사를 다음과 같이 고쳐쓸수도있다.
while(cin)             //입력이 성공했으면 루프실행
이것은 디스크 고장과 같은 다른 결함까지도 탐지하기 때문에 !cin.fail()이나 !cin.eof()보다 좀더 일반적으로 사용된다.
마지막으로 cin.get(char)의 리턴값이 cin이므로 while루프를 다음과 같이 줄일수 있다.
while(cin.get(ch))   //입력이 성공했으면 루프 실행
{
   ....                     //일을 처리한다.
}
여기서, cin.get(char)는 두번 이 아니라 검사 조건에서 한번만 호출된다.
루프 조건을 검사하기 위해, 프로그램은 먼저 cin.get(ch)를 호출하고, 입력이 성공적이면 ch에 값을 넣는다.
그러고 나서 프로그램은 함수 호출의 리턴값으로 cin을 얻는다. 이렇게 얻어진 cin에 bool변환을 적용하는데,
입력이 성공이면 true로 변환, 그렇지않으면 false로 변환한다.

●cin.get()의 또 다른 버전
전달인자가 없는 cin.get()맴버 함수는 입력으로 부터 그 다음 문자를 읽어 리턴한다. 즉, 다음과 같이 사용할수 있다.
ch=cin.get();
이함수는 C의 getchar()함수와 유사하게 동작한다. 즉, 문자 코드를 int형 값으로 리턴한다. 마찬가지로 cout.put()함수를
문자 출력하는데 사용할수 있다.
cout.put(ch);
이함수 호출은 전달인자가 int형이 아니라 char형이라는 것을 제외하고는 c의 putchar()와 유사하게 동작한다.

cin.get()을 성공적으로 사용하려면, 이함수가 EOF조건을 어떻게 다루는지 알아야한다. 이 함수가 EOF에 도달했을때는
더이상 리턴할 문자가 남아있지 않다. 그대신에 cin.get()은 기호 상수 EOF로 나타내는 특별한 값을 리턴한다.
이 기호 상수는 iostream헤더 파일에 정의되어있다. 프로그램이 정규문자의 값과 EOF값을 혼동하지 않도록 EOF는 정규 문자
와 다른 값을 가져야한다.
ASCII코드로 -1을 갖는 정규문자는 없으므로, 일반적으로 EOF를 -1로 정의 하고있다.
char ch;
cin.get(ch);
while(cin.fail() == false)    //EOF검사
{
   cout<<ch;
   ++count;
   cin.get(ch);
}
int ch를 사용하고, cin.get(ch)를 cin.get()으로 대체 하고, cout을 cout.put()으로 대체 하고, cin.fail()검사를 EOF검사로
대체 할수 있다.
int ch;                         //EOF값 호환을 위해 사용
ch= cin.get();
while(ch != EOF)
{
   cout.put(ch);
   ++count;
   ch=cin.get();
}
ch가 문자이면 루프는 그것을 출력, ch EOF이면 루프가 종료.

어떤 C++ 시스템에서 char형은 부호가 없다. 그래서 값이 -1 인 EOF를 char형 변수로 처리 할수 없다.
이러한 이유때문에 cin.get()을 사용하여 EOF검를 하려면, cin.get()의 리턴값을 char형 대신 int형에 대입해야한다.
또한 ch를 char형이 아닌 int형으로 만들면, ch를 출력할때 다시 char형으로 데이터 형변환을 해주어야한다.
                    특     성                     cin.get(ch)                    ch=cin.get()
 입력문자 전달방법 전달인자 ch에 대입   함수의 리턴값을 ch에 대입
 문자가 입력되었을때 함수 리턴값  istream클래스의 객체(bool값->true)  int형으로 된 문자코드
 EOF에서 함수 리턴값  istream클래스의 객체(bool값->false)                          EOF 

■중첩 루프와 2차원 배열
2차원 배열은 행과 열을 모두 가지고있는 표를 연상하면된다.
C++은 2차원 배열을 나타내는 데이터형을 따로 제공하지않는다. 그대신에 배열의 배열, 즉 다른 배열을 원소로 사용하는 배열을 만들수 있다. 예를들어 5개 도시의 지난 4년 동안의 연중 최고 온도를 저장하는 2차우너 배열을 만들고 싶다면 다음과 같이
선언한다.
int maxtemps[4][5];
 maxtemps[0][0]   maxtemps[0][1]  maxtemps[0][2]   maxtemps[0][3]   maxtemps[0][4] 
 maxtemps[1][0]   maxtemps[1][1]   maxtemps[1][2]   maxtemps[1][3]   maxtemps[1][4] 
 maxtemps[2][0]   maxtemps[2][1]   maxtemps[2][2]   maxtemps[2][3]   maxtemps[2][4] 
 maxtemps[3][0]    maxtemps[3][1]  maxtemps[3][2]   maxtemps[3][3]   maxtemps[3][4] 

maxtemps[0]은 maxtemps배열의 첫번째 원소로서 그자체가 5개의 int값을 갖는 1차원 배열이다.
maxtemps[0]의 첫번째 원소는 maxtemps[0][0]으로서 하나의 int형 변수이다.그 int형 원소에 접근하려면 첨자는 2개를
사용해야한다. 첫번째 첨자는 행을 나타내고 두번째 첨자는 열을 나타낸다.

maxtemps배열에 들어있는 모든 내용을 출력하고 싶다면, 이중for문을 사용하면 된다.
for(int row=0; row<4;row++)
{
   for(int col=0; col<5; ++col)
   {
      cout<<maxtemps[row][col]<<"\t";
      cout<<endl;
   }
}

========================================요    약==================================================
C++에서 for,while,do while이라는 세종류의 루프를 제공한다. 루프는 조건 검사 표현식이 true또는 0이 아닌 값으로 평가되는
동안 동일한 명령문들의 집합을 반복하여 수행한다. 조건 검사 표현식이 false또는 0으로 평가되면 루프를 종료한다.
for 루프와 while 루프는 루프 몸체에 있는 명령문들을 실행하기 전에 먼저 조건을 평가하는 진입 조건 루프이다. 반면에
do while루프는 루프 몸체의 명령문들을 먼저 실행한 후에 조건 검사 표현식을 평가한다.
루프는 단일 명령문으로 인식되는 루프 몸체를 요구한다. 루프 몸체는 여러개의 명령문을 중괄호로 묶은 복합 명령문 또는
블록이 될수 있다.
루프의 조건 검사표현식으로 두개의 값을 비교하는 관계 표현식이 자주사용된다.
관계 표현식은 6개의 관계 연산자 <.<=,==,>=,>,!= 중에 어느 하나를 사용한다. 관계 표현식은 bool값 ture또는 false로 평가
된다. 많은 프로그램들이 텍스트 입력이나 텍스트 파일로부터 문자 단위로 입력을 읽어 들인다. istream 클래스는 이작업을 할수 있는 몇가지 방법을 제공한다. ch가 char형 변수 일때, 다음과 같은 명령문은
cin>>ch;
입력 문자를 ch에 저장한다. 그러나 이명령문은 빈칸 문자나 탭문자, 개행문자들은 무시하고 건너뛴다. 다음과 같은 맴버 함수호출은,
cin.get(ch);
입력 문자를 읽어 들여 그값이 무엇이든간에 ch에 저장한다. cin.get()맴버함수의 호출은 빈칸 문자나 개행문자, 탭문자도
포함하여 입력받은 문자를 리턴한다. 이것의 사용 예는 다음과 같다.
ch=cin.get();
cin.get(char)맴버 함수의 호출은 EOF를 만나면 bool값으로 변환한 false를 리턴한다. 그러나 cin.get()맴버 함수의 호출은 EOF를 만나면 iostream파일에 정의되어있는 EOF를 리턴한다.
중첩 루프란 루프안에 다른 루프가 들어있는것이다. 중첩 루프는 2차원 배열을 자연스럽게 처리할수 있다.

'C++ > C++ PRIMER PLUS' 카테고리의 다른 글

함수 - C++의 프로그래밍 모듈  (0) 2011.11.09
분기 명령문과 논리 연산자.  (0) 2011.11.07
복합 데이터형  (0) 2011.10.27
데이터처리  (0) 2011.10.20
C++시작하기  (0) 2011.10.18

■배열
 - 배열이란 데이터형이 같은 여러개의 값을 연속적으로 저장할수 있는 데이터 구조이다.
    배열은 선언 명령문을 사용하여 생성한다. 배열 선언 명령문에서는 다음과 같은 세가지를 선언한다.
   ●각 원소에 저장될 값의 데이터형
   ●배열의 이름
   ●배열 원소의 개수

배열원소의 개수를 대괄호안에 넣어서 선언한다.
short months[12];       //12개의 short형 값을 넣을수 있는 배열 생성
배열의 이름이 months이고, 12개의 원소를 가지며, 각 원소에 short 형 값을 저장할수있다는것을 나타낸다.

배열의 일반적인 형식
typeName arrayName[arraySize];

원소개수를 나타내는 arraySize는 값 10 또는 const기호 상수와 같은 정수 상수이거나, 또는 컴파일 할때 값이 결정되는 8*sizeof(int)
와 같은 상수 수식이어야한다.
배열이 여러가지 용도로 유용한 것은 각각의 배열 원소에 개별적으로 접근할수 있기때문이다.
개별적인 접근을 허용하기 위해 첨자또는 인덱스를 사용하여 배열 원소에 차례로 번호가 매겨진다.
C++의 배열 첨자는 항상 0부터 시작한다. 그리고 C++는 대괄호 안에 첨자를 넣어 배열원소를 지정한다. 예를들어, months[0]은 months 배열의첫번재 원소를 나타낸다. months[11]은 months 배열의 마지막 원소를 나타낸다. 배열의 마지막 원소를 나타내는 첨자는 배열의 크기보다 항상 1만큼 작다.

■배열 초기화 규칙
초기화 형식은 배열을 정의하는 곳에서만 사용할수 있다. 초기화를 나중에 할수는 없다.
그러나 첨자를 사용하여 배열 원소에 개별적으로 값을 대입하는 것은 언제든지 가능하다. 배열을 초기화 할때, 초기화 값의 개수를 배열원소의 개수보다 모자라게 제공할수도있다.
float hotelTips[5] = {5.0,2.5};
배열을 부분적으로 초기화하면, 컴파일러가 나머지 원소들을 모두 0으로 설정한다. 따라서 배열의 모든 원소를 0으로 초기화하는일은 매우 쉽다.
 명시적으로 첫번째 원소만 0으로 초기화 하면 된다. 그러면 컴파일러가 나머지 원소들을 모두 0으로 초기화 시켜준다.
long totals[500]={0};

{0}대신에 {1}로 초기화한다면 첫번째원소를 1로 설정하고, 나머지들은 여전히 0으로 설정한다.
배열을 초기화할때 대괄호([])속을 비워두면, 컴파일러가 초기화 값의 개수를 헤아려 배열원소의 개수를 결정한다.
short things[] = {1,5,3,8};

배열원소의 개수가 4개인 short형의 배열 things 를 생성한다.

■문자열
문자열 이란 메모리에 바이트 단위로 연속적으로 저장되어있는 문자들을 말한다. C++는 두가지 방법으로 문자열을 처리한다.
첫번째 방법은 C로부터 유래한 C스타일의 문자열 처리방법.
두번째 방법은 string클래스 라이브러리에 기반을둔 또다른 문자처리 방법.

문자들이 메모리에 바이트 단위로 연속적으로저장된다는것은, 문자열을 char형의 배열에 저장할수 있다는것을 의미한다.
이때 문자열을 구성하는 각문자들은 배열의 원소에 하나씩 저장된다.
char dog[5] = {'b','e','a','u','x'};
char cat[5] = {'f','a','t','s','\0'};

두배열이 모두 char형의 배열이다. 그러나 두번째 배열만이 문자열이다. 널 문자는 C스타일의 문자열에서 중요한 역할을 한다.
C++는 cout이 사용하는 함수들도 포함하여, 많은 문자열 처리 함수를 가지고있다. 이 함수들은 널 문자를 만날때까지 문자 단위로 문자열을 처리한다. cat문자열을 cout으로 출력하면 , 4개의 문자를 출력하고 나서 널문자를 만나면 출력을 중단한다.
그러나 dog를 cout으로 출력하면, 배열에 들어있는 5개의 문자를 모두 출력한뒤에도 그이후 메모리 내용을 한 바이트 씩 문자로 간주하여 계속해서 출력한다. 출력은 우연히 널 문자를 만날때까지 이어진다.
문자열에 들어있는 각문자들은 일일이 작은 따옴표로 묶어 콤마로 구분하고, 끝에 널 문자를 넣어야 한다.
그러나 이보다 좋은방법은 char형의 배열을 문자열로 초기화 하는 것이다.
다음과 같이 큰 따옴표 안에 문자열을 넣기만 하면 된다. 이렇게 큰 따옴표로 묶인 문자열을 문자상수라고한다.
char bird[10] ="Mr. Cheeps";    // \0을저장한다.
char fish[] ="Bubbles";            //컴파일러가 알아서 처리한다.

큰따옴표로 묶인 문자열은 끝내기 널 문자를 암시적으로 가지고 있다.
키보드 입력에서 문자열을 읽어 char형의 배열에 저장하는 C++의 다양한 입력 기능들은 끝내기 널 문자를 자동으로 추가한다.
문자열을 저장할 char형의 배열은, 그 크기가 끝내기 널 문자까지 포함하여 그문자열에 들어이 있는 모든 문자들을 다 넣을수 있을만큼 충분히 커야한다. char형의 배열을 문자열 상수로 초기화하면 컴파일러가 배열 원소의 개수를 대신 헤아려 주므로 더 안전할 수 있다. 이방법은 전혀 문제를 일으키지않는다. 오히려 배열의 크기를 크게 잡는 바람에 메모리를 낭비하는 일을 막아준다.
C++는 문자열의 길이에 제한을 두지않는다.
(큰따옴표를 사용하는) 문자열 상수와 (작은따옴표를 사용하는) 문자 상수는 서로 바꾸어 쓸수 없다.

■배열에 문자열 사용
배열에 문자열을 넣는 가장 일반적인 방법은 두가지이다.
배열을 문자열 상수로 초기화 하는 방법과 , 키보드 입력이나 파일 입력을 배열에 저장하는 방법이다.
문자열의 길이를 알아내기위한 표준 라이브러리 함수에는 strlen()을 사용하고 cstring표준 헤더파일을 include해준다.

■문자열 입력

 

디저트르르 입력하라는 프롬프트에 응답할 기회도 주지않고 넘어가버린다.
이렇게 되는 이유는 cin이 문자열의 끝을 인식하는 방법 때문이다. 키보드로는 끝내기 널 문자를 입력할수 없기 떄문에,cin에게 문자열의 끝을 알려주는 다른 수단이 필요하다. 그렇기 때문에 cin은 빈칸, 탭,캐리지 리턴과 같은 화이트 스페이스가 있으면 그위치에서문자열이 끝난것으로 간주한다. 즉, char형의 배열에 저장하기 위해 키보드로 부터 입력을 받을때 cin은 하나의 단어만 읽어 그것을 배열에 저장하고 널 문자를 끝에 추가한다.

■한번에 한 행의 문자열 입력읽기
istream 클래스가 행 단위로 문자열을 입력하는 클래스 맴버함수인 getline()과 get()을 제공한다. 둘다 전체 입력 행을 읽는다.
즉, 개행문자가 나올때까지 읽는다. 그러나 getline()은 개행문자를 읽어서 폐기하는 반면에 get()은 입력 큐에 개행문자를 남겨둔다.

 ●getline()을 이용한 행 단위 입력
    getline() 함수는 Enter 키에 의해 전달되는 개행 문자를 입력의 끝으로 간주하여 한 행 전체를 읽는다. cin.getline()을 함수 호출로 
   사용함으로써 이 메서드를 호출할수 있다. 이함수는 두개의 전달인자를 사용한다.
   첫번째 전달인자는 입력한 행을 저장할 배열의 이름이다.
   두번째 전달인자는 입력받을 문자들의 한계이다.
   
   getline()함수로 이름을 읽어 20개의 원소를 가진 name배열에 저장하고 싶다면 다음과 같은 호출을 사용할수 있다.
cin.getline(name,20);
이 명령문은 한행 전체를 읽어 name배열에 저장한다. 이때 그행에 있는 문자들의 개수는 최대 19개 또는 그보다 적어야한다.
getline()함수는 편리하게 한행을 한번에 읽는다. 이함수는 행의 끝을 표시하는 개행문자까지 읽는다.
그러나 개행 문자는 저장하지않는다. 문자열을 배열에 저장할 때 개행문자는 널 문자로 대체된다.

  ●get()을 이용한 행 단위 입력
    istream클래스는 또다른 맴버 함수 get()을 제공한다. 이함수는 여러 변종이있다. 그중의 하나가 getline()처럼 동작한다.
    같은 전달인자를 사용하고, 전달인자를 같은 방식으로 해석하며, 행의 끝까지 읽는다. 그러나 이 함수는 개행문자를
    읽어서 버리지 않고 입력큐에 그대로 남겨둔다. get()을 연달아 두번 호출한다면 문제가 생길것이다.
    첫번째 호출이 입력 큐에 개행문자를 그대로 남겨두기 때문에, 두번째 호출은 그 개행문자를 첫문자로 만나게된다.
    그래서  get()은 읽을 것도 없이 곧바로 행의 끝에 도달했다고 결론을 내린다. 
  
    위와같은 문제는 cin.get()호출로 해결할수 있다. cin.get()호출은 그것이 개행문자이든 아니면 다른 무엇이든 간에 무조건
    하나의  문자로 읽는다. cin.get()을 사용하면 개행 문자를 읽어서 처리하고, 다음 행의 입력으로 넘어가게 할수 있다.
cin.get(name,ArSize);        //첫번째 행을 읽는다.
cin.get();                          // 개행문자를 읽는다.
cin.get(dessert,ArSize);     //두번째행을 읽는다.
get()을 사용하는 또한가지 방법은 두개의 클래스 맴버 함수를 결합하여 사용하는것이다.
cin.get(name,ArSize).get();    //맴버함수들을 결합한다.
이와같이 사용하면 cin.get(name,ArSize)가 cin객체를 리턴한다.
이와 비슷한원리로
cin.getline(name1.ArSize).getline(name2,ArSize);
두행의 입력을 연속해서 읽어 name1과 name2 배열에 각각 저장한다. 이것은 getline()를 2번호출하는것과 같다.
-getline()대신에 get()을사용한 이유는
 첫째, 구식 C++에는 getline()이 없다.
 두번째,get()이 사용자를 다소 신중하게 만들기때문.

●빈행과 문제점
  get()이 빈행을 읽으면 failbit라는것이 설정된다. 이행동이 뜻하는것은 계속되는 입력을막고, 입력을 복원하려면 다음과 같은 명령을
  실행해야한다는것이다.
  cin.clear();
  잠재적으로 발생할수 있는 또 하나의 문제는 입력 문자열이 할당된 공간보다 더 길수 있다는 것이다.
  입력 행이 지정된 문자 수보다 길면, getline()과 get()은 failbit를 설정하고 더이상 입력을 받지않는다.

 ●문자열과 수치의 혼합 입력

cin이 입주 연도를 읽어 들이고, Enter키가 만들어내는 개행문자 를 입력 큐에 남겨두기 때문에 이프로그램은 주소를 입력할 기회를
주지않는다.
cin.getline()은 입력큐에 남겨진 개행문자를 빈행으로 읽어들이고, address배열에 널문자열을 대입한다. 이문제를 해결하는 방법은
주소를 읽기전에 개행문자를 읽어 버리는것이다. 전달인자를 사용하지않는 get()이나, 하나의 char형 전달인자를 사용하는 get()을
호출하는 것을 포함하여, 여러가지 방법으로 이문제를 해결할수 있다.
cin>>year;
cin.get();                 //또는 cin.get(ch);

또는 cin>>year가 cin객체를 리턴한다는 사실을 이용하여, cin>>year에 결합하여 사용할수도있다.
(cin>>year).get();           //또는 (cin>>year).get(ch);

■string 클래스
문자열을 저장하는데 문자 배열을 사용하는 대신, string형 변수를 사용할수 있다.
string클래스를 사용하려면, 프로그램에 string 헤더파일을 포함시켜야한다.
string클래스는 std이름 공간에 속해있으므로, using지시자를 사용하거나 std::string를 사용하여 그 클래스를 참조해야한다.
string객체를 문자 배열과 동일한 방식으로 사용할수 있다.
-C스타일 문자열로 string객체를 초기화 할수 있다.
-cin을 사용하여 string객체에 키보드 입력을 저장할수 있다.
-cout을 사용하여 string 객체를 디스플레이 할수 있다.
-배열 표기를 사용하여 string 객체에 저장되어있는 개별적인 문자들에 접근할수 있다.
string객체를 사용하는것이 배열을 사용하는것보다 편리하고 안전하다. 개념적으로, char형의 배열은 char형 저장 단위의 집합체라고 생각할수 있고, string 클래스 변수는 문자열을 나타내는 하나의 실체라고 생각할수 있다.

 ●대입,결합,추가
char charr1[20];                       //빈배열 생성
char charr2[20]= "jaguar";          //초기화된 배열생성
string str1;                               //빈string객체 생성
string str2="panther";                 //초기화된 string객체생성
charr1=charr2;                         //틀리다. 배열대입 x
str1=str2;                                //맞다. 객체 대입 o

string 클래스는 문자열 결합을 간단하게 처리한다. +연산자를 사용하여 두개의 string객체를 하나로 결합할수도있고, +=연산자를 사용하여 기존의 string객체의 끝에 또 다른 string객체를 덧붙일수있다.

 ●string 클래스의 조작
   cstring 헤더 파일에 strcpy()함수를 사용하여 문자열을 문자 배열에 복사할수있고, strcat()함수를 사용하여 문자열
   문자 배열에  추가할수있다.
strcpy(charr1, charr2);      //charr2를 charr1에 복사한다.
strcat(charr1,charr2);        //charr2의 내용을 charr1에 추가한다.

■구조체
  구조체는 사용자가 정의할수 있는 데이터 형이다. 데이터 형의 특성을 정의하는 구조체 선언이 필요하다. 데이터형을 정의한후에는
  그 데이터형의 변수를 생성할수 있다.
struct inflatable      //구조체선언
{
   char name[20];
   float volume;
   double price;
};

여기서 키워드 struct는 이코드가 구조체 서술을 정의하고 있다는것을 나타낸다. 태그라고도 부르는 식별자 inflatable은 새로
만들어지는 데이터형의 이름으로 사용된다. 중괄호 { } 안에는 이 구조체를 구성하는 데이터형들의 리스트를 넣는다.
이 리스트의 각항목을 맴버라고 부른다. 이 예제에는 문자열을 저장하는 적당한 하나의 char형 배열, 하나의 float형,
하나의 double형을 사용한다.
hat가 inflatable형이라면 , 맴버연산자(.)을 사용하여 그 구조체의 개별적인 맴버에 접근할수 있다.
예를 들어 hat.volume은 hat변수의 volume맴버를나타낸다.
쉽게 말해서, 배열 첨자를 이용하여 배열 원소에 접근할수 있듯이, 맴버 이름을 사용하여 구조체의 맴버에 접근할수 있다.

 

- 초기화 과정에서
inflatable guest=
{
  "Glorious Gloria",       //name값
  1.88,                         //volume값
  29.99,                       //price값
};

배열과 마찬가지로, 한쌍의 중괄호 { } 안에 초기화 값들이 콤마로 구분되는 초기화 리스트를 넣는다. 반드시 초기화 값들은 콤마로 구분해야 한다. 구조체의 각 맴버는 자신의 데이터형에 맞는 값으로 초기화 할수 있다.
name맴버는 char의 배열이므로 , 문자열로 초기화 가능.

  ●구조체의 기타 특성
    사용자가 정의한 데이터형을 내장 데이터형과 동일한 방식으로 다룰수있다. 구조체를 함수에 전달인자로 전달할수 있으며,
    구조체를 리턴값으로 사용할 수도 있다. 대입 연산자(=)를 사용하여 하나의 구조체를 같은 데이터형의 다른 구조체로
    대입할수도 있다. 이때 에는 한 구조체의 맴버값들이 상대방 구조체의 해당 맴버에 각각 대입된다. 
    데이터형 이름이 없는 구조체를 생성할수도 있다. 이것은 태그 이름을 생략하고 템플릿과 변수를 동시에 생성하는 것이다.
 
struct            //태그가없음.
{
   int x;          //두개의 맴버
   int y;
}position;      //구조체변수

이것은 position이라는 구조체 변수를 생성한다. position.x와 같이 맴버 연산자를 사용하여 맴버에 접근할수 있지만,
데이터형 이름이 없기 때문에 이후에 같은 형의 다른 변수를 생성할수 없다.


  ●구조체의 배열
    inflatable 구조체는 배열을 맴버로 포함하고 있다. 또한 원소가 구조체인 배열을 생성할수도 있다. 구조체의 배열을 만드는
    방법은  기본 데이터형의 배열을 만드는것과 같다.
inflatable gifts[100];         //inflatable 형 구조체 100개생성.

구조체의 배열을 초기화 하는 방법은 (각 맴버의 값의 리스트를 콤마로 분리하고 중괄호로 묶는) 구조체 초기화 규칙과
(각원소 값의 리스트를 콤마로 분리하고 중괄호 로 묶는), 배열원소의 각 값의 리스트를 콤마로 다시 분리하고 중괄호로 묶는다.
inflatable guests[2]=                     //구조체 배열을 초기화
 {
    {"Bambi",0.5,21.99},                 //첫번째 배열 원소인 구조체
    {"Godzilla",2000,565.99}            //두번째 배열 원소인 구조체
};
 ●구조체 안의 비트 필드
   구조체 맴버들이 각각 일정 비트수를 차지하도록 지정할수 있다. 이것은 어떤 하드웨어 장치에 들어있는 레지스터에 대응하는  데이터 구조를 만들때 매우 편리하다. 사용할 비트수는 콜론을 찍고 그뒤에 적는다. 이름이 없는 필드를 사용하여 간격을
 줄일수도 있다. 이러한 각 맴버를 비트 필드라 한다.
struct  torgle_register
{
   unsigned int SN:4;     //SN값(4비트)
   unsigned int  :4;        //사용하지않음(4비트)
   bool goodIn:1;          //유효한 입력(1비트)
   bool goodTorgle:1;    //토클에 성공(1비트)
};

■공용체
 공용체는 서로 다른 데이터형을 한번에 한가지만 보관할수 있는 데이터 형식이다. 즉, 구조체는 int형과 long형과 double형을
 한꺼번에 보관할수 있지만, 공용체는 int형이나 long형이나 double형 중에서 한번에 어느 하나만 보관할수 있다.
 구문은 구조체와 같지만 의미가 조금 다르다.
union one4all
{
   int int_val;
   long long_val;
  double double_val;
};

one4all 변수는 int형이나 long형이나 double형을 보관할수 있지만, 어느 한 시점에 어느 한가지만 보관할수 있다.
one4all pail;
pail.int_val =15;       //int형 저장
cout<<pail.int_val;
pail.double_val = 1.38;   //double형을 저장, int형 값은 소실
cout<<pail.double_val;

pail은 어떤 경우에는 int형 변수처럼, 또어떤경우에는 double형 변수처럼 행동.
pail이 어떤 데이터형의 변수로 행동하는지는 맴버이름을 보면 알수 있음.
공용체는 한번에 하나의 값만 보관할수 있으므로, 가장 큰 멤버를 보관할수 있을만큼의 공간이 필요하다. 따라서 공용체의 크기는
가장 큰 맴버의 크기가 된다.
여러가지 데이터형을 사용할수는 있지만 이들을 동시에 사용할수 없을때 공용체를 사용하면 메모리를 절약할수 있다.
struct widget
{
   char brand[20];
   int type;
   union id                               //데이터 형이 부품 종류에 따라 다름
   {
      long id_num;                     //1번 형식의 부품
      char id_char[20];               //다른 형식의 부품
   }id_val;
};
......
widget prize;
......
if(prize.type ==1)
  cin>>prize.id_val.id_num;      //맴버이름으로 모드를 나타낸다.
else
  cin>>prize.id_val.id_char;
익명공용체는 이름이 없다. 본질적으로 익명 공용체의 맴버들은 동일한 주소를 공유하는 변수들이다.
당연히 한번에 한 맴버만 사용할수 있다.
struct widget
{
   char brand[20];
   int type;
   union                        //익명공용체
   {
      long id_num;          //1번형식 부품
      char id_char[20];   //다른 형식의 부품
   };
};
....
widget prize;
....
if(prize.type == 1)
   cin>> prize.id_num;
else
   cin>>prize.id_char;
익명 공용체이므로 id_num과 id_char는 동일한 주소를 공유하는 prize의 두맴버로 취급된다.
따라서 이경우에는 중간에 개입하는 식별자 id_val이 필요하다.

■열거체
 C++의 enum기능은 const를 사용하여 기호 상수를 만드는 것에 대한 또 다른 방편을 제공한다. 그것은 제한적이기는 하지만 새로운 데이터 형을 정의 할수 있게 해준다. enum을 사용하는 구문은 구조체 구문과 비슷하다.
enum spectrum{red,orange,yellow,green,blue,violet,indigo,ultraviolet};
이명령문은 두가지 일을 수행한다.
①spectrum을 새로운 데이터형의 이름으로 만든다. struct형 변수를 구조체라 부르듯이, enum형 변수를 열거체 라 부른다.
②red,orange,yellow...등을 0에서 7까지의 정수 값을 각각 나타내는 기호 상수로 만든다. 이 상수들은 열거자라고 부른다.

기본적으로 첫번째 열거자에는 0이 대입되고, 두번째 열거자에는 1이 대입되는 방식으로 정수값들이 차례로 대입된다. 그러나 열거자에 정수값을 명시적으로 대입하면 이 기본값을 무시할수있다.

spectrum band;  로 선언했을경우 열거체 변수에는 그데이터형을 정의하는데 사용된 열거자 값들만 대입할수 있다.
즉 band = red;, band=blue; 는 사용 할수 있지만 band=200; 은 사용할수 없다.
그리고 열거체는 대입연산자만 사용할수 있고 산술연산자는 사용되지않는다. 예) ++band;  band = red+blue;  (X)
일부 C++에서는 제한을 시키지않는경우도있다. band가 ultraviolet또는 7을 값으로 가지고있다면, ++band를 8로증가시킨다.
그런데 8은 spectrum값이 아니다. 이식성을 최대한 높이기 위해서는 이제한을 지키는것이 좋다.
열거체에 적용 되는 규칙은 매우 제한적이다. 실제로 열거체는 새로운 데이터형을 정의하는 수단이 아니라, 상호 관련이있는 기호 상수들을 정의하는 용도로 주로 사용된다. 예로들면, switch문에 사용할 기호 상수들을 정의하기 위해 열거체를 사용한다.
단지 상수만을 사용할 계획이고 열거체변수를 만들생각이 없다면, 열거체이름을 생략할수도있다.
enum{red,orange,yellow,green,blue,violet,indigo,ultraviolet};

■포인터와 자유저장
포인터는 값자체가 아니라 값의 주소를저장하는 변수이다.
주소연산자(&) 를 변수 앞에 붙이면 그 변수의 주소를 알아낼수 있다.주소 연산자(&)를 변수 앞에 붙이면 그 변수의 주소를 알아낼수있다.
16진수 표기가 메모리를 나타내는 가장 일반적인 방법이기 때문에, 주소값을 출력할때 16진수 표기를 사용한다.
포인터란, 포인터라는 특변한 데이터형의 변수에 어떤값의 주소를 저장한다.
즉, 포인터의 이름이 주소를 나타낸다. 간접값 연산자또는 간접참조연산자라고 부르는 *를 포인터 이름앞에 붙이면 그 주소에
저장되어있는 값이 된다.
예를들어 manly가 포인터라고 가정하였을때, manly는 주소를 나타내고, *manly는 그주소에 저장되어있는 값을 나타낸다.
*manly는 보통의 int형 변수와 동등하게 취급된다.

int형 변수 updates와 포인터 변수 p_updates는 동전의 양면과도 같다. updates변수는 값을 우선적으로 나타내고,
여기에 &연산자를 적용하여 주소를 알아낸다. p_updates 포인터 변수는 주소를 우선적으로 나타내고, 여기에 *연산자를
적용하여 값을 알아낸다. p_updates는 updates를 지시하기때문에 *p_updates와 updates는 완전히 동등하다.
그러므로 *p_updates를 int형 변수처럼 사용할수 있다.

●포인터의 위험
포인터를 생성하면서 컴퓨터는 주소를 저장하기 위한 메모리를 할당한다. 이것은 그포인터가 지시하는 데이터를 저장하기 위한 메모리를 할당하는것이아니다. 데이터를 저장하기 위한 메모리를 할당하는 것은 이와 전혀 다른단계이다.
long *fellow;            //long형을 지시하는 포인터 생성
*fellow =223323;       //어딘지 알수 없는 곳에 값을 저장
여기서 fellow는 포인터다. 그런데 이포인터가 어디를 지시하고 있는지는 알수가 없다. fellow에 주소를 대입하는 단계를
빠트렸기 때문이다.

●포인터와 수
 일반적으로 컴퓨터가 주소를 정수로 다루고 있지만, 포인터는 정수형이아니다.
포인터는 개념적으로 정수형과 다른 데이터형이다. 수행할 수 있는 연산의 관점에서 포인터와 정수형은 서로 다르다.
결론적으로 말해서, 포인터에 정수를 직접 대입할수 없다.
int *pt;
pt = 0xB8000000;    //데이터형 불일치
여기서 좌변은 int형을 지시하는 포인터다. 따라서 주소를 대입할수 있다. 그러나 우변은 단순한 정수이다.
우변의 정수 0xB8000000은 실제로는 세그먼트와 오프셋이 결합된 비디오 메모리의 주소이다.
하지만 이것이 주소라는 것을 알려주는 것이 전혀 없다.
데이터형이 일치하지않을경우 컴파일러는 에러메시지를 내보낸다. 따라서 어떤 주소로 사용하려면 데이터형 변환자를
사용하여 적당한 주소형으로 반드시 변환해주어야한다.
int *pt;
pt = (int *) 0xB8000000;   //데이터형일치
이제 대입 명령문의 좌변과 우변이 모두 정수의 주소를 나타낸다. 따라서 이대입 명령문은 올바른것이다.
int형의 값을 가지고 있다해서 pt를 int형이라고 생각해서는 안된다.

●new를사용한 메모리 할당
C에서는 malloc()이라는 라이브러리 함수를 사용하여 이름이 없는 메모리를 할당하였다.
C++에서도 여전히 그렇게 사용할수 있다. 그러나 C++에서는 new연산자를 사용하는 더좋은 방법을 제공한다.
프로그램을 실행하는 동안 int 형 값을 저장할수 있는 이름이 없는 메모리를 할당하고, 포인터를 사용하여 그메모리의 접근하는 새로운방법에는 new연산자가 중요한 역할을 한다.
어떤 데이터형의 메모리를 원하는지 new연산자에게 알려주면, new연산자는 그에 알맞은 크기의 메모리 블록을 찾아내고,
그블록의 주소를 리턴한다. 이주소를 포인터에 대입하면된다.
int *pn =new int;
new int 부분은 int형 데이터를 저장할 새로운 메모리가 필요하다고 프로그램에게 알린다.
new연산자는 뒤따르는 데이터형을 보고, 몇바이트가 필요한지 파악한다.
그러고나서 적당한 메모리를 찾아 필요한만큼 블록을 할당하고, 그주소를 리턴한다.
리턴되는 주소는 int형을 지시하는 포인터로 선언되어있는 pn에 대입된다. 여기서 pn은 주소이고, *pn은 그주소에 저장되는 값이다.
int higgens;
int *pt =&higgens;
두방식 모두 int형의 주소포인터(pn과 pt)에 대입된다. 두번째 방식에서는 pt를 통하지않고 변수 이름higgens를 통하여 int형
값에 접근할수 있다. 그러나 첫번째 방식에서 포인터pn이 int형 값에 접근할수 있는 유일한 통로이다.
pn은 데이터 객체를 지시하고있기때문에 메모리의 이름이 없어도 접근이 가능하다.
기본데이터형일 수도있는 어떤 단일 데이터 객체를 저장하기 위해 메모리를 확보하고, 그 주소를 포인터에 대입하는 일반적인
형식은 다음과 같다.
typeName *pointer_name = new typeName;
여기서는 데이터형을 두번 사용한다. 한번은 요구하는 메모리의 종류를 지정하기 위해 사용하고,
다른한번은 적당한 포인터를 선언하기 위해 사용한다.
적당한 데이터형을 지시하는 포인터가 이미 선언되어있는 경우에는 포인터를 새로 선언할 필요없이 그 포인터를 사용한다.

●delete 를 사용한 메모리 해제
new로 할당된 메모리는 delete를 사용하여 다시 메모리 풀로 환수해야한다.
이것은 메모리를 가장 효율적으로 사용하기 위한 중요한 절차이다.
delete는 new로 할당한 메모리 블록을 지시하는 포인터와 함께 사용한다.
int *ps = new int;     //new로 메모리할당
....
delete ps;              //delete로 메모리 해제
이렇게 하면 ps가 지시하는 메모리가 해제된다.
그러나 ps자체가 없어지는 것은 아니다. ps는 새로 할당한 메모리를 지시하는데 다시 사용할수 있다. new를 사용한후에는
반드시 delete를 사용해야한다. 그러지않는다면 메모리 누설이 발생할수 있다.
int *ps = new int;         //메모리를 할당하고 첫번째 포인터로 지시
int *pq = ps;                //같은 메모리를 지시하는 두번째 포인터 설정
delete pq;                   //두번째 포인터에 delete사용

●new 를 사용한 동적 배열의 생성
배열, 문자열, 구조체와 같은 커다란 데이터를 다룰 때에는 new를 사용하는것이 훨씬 효율적이다.
선언에 의해 배열을 생성하면, 프로그램이 컴파일 될때 배열을 위한 메모리가 할당된다. 프로그램이 실행될때 이배열은
실행이 되든 안되든 항상 메모리를 차지한다. 이방식을 정적 바인딩이라고 한다. 이것은 배열이 컴파일 시간에
생성된다는것을 뜻한다. 그러나 new를 사용하면 배열 실행 시간에 생성할수 있고, 필요없으면 생성하지 않을수도있다.
또는 프로그램을 실행하는 동안에 배열의 크기를 결정할수있다. 이방식을 동적바인딩이라고 한다.
   ◈new를 사용한 동적 배열의 생성
      10개의 int형 원소를 갖는 배열이 필요하다면, 대괄호 안에 원소의 개수를 넣어 다음과 같은 형식으로 동적배열을 생성.
     
int *psome = new int[10];    //10개의 int형 값을 저장할 블록을 할당.
new 연산자는 그블록의 첫번째 원소의 주소를 리턴한다.포인터 psome에 그주소가 대입된다.
new를 사용하여 생성된 메모리 블록은 , 프로그램이 사용을 끝낸 후에 반드시 delete로 해제해주어야한다.
new를 사용하여 생성된 배열을 해제할때는,
delete [] posme;      //동적 배열을 해제
대괄호 [] 가 사용되었기 때문에 포인터가 지시하는 첫번째 원소가 해제되는것이 아니라 배열 전체가 해제된다. 대괄호는
delete와 포인터사이에 사용된다. new를 대괄호 없이 사용했다면 delete도 대괄호를 넣어 사용해야한다.
▣new와 delete를 사용할때는 다음과 같은 규칙을 지켜야한다.
  ▶new로 할당하지않은 메모리는 delete로 해제하지않는다.
  ▶같은 메모리 블록을 연달아 두번 delete로 해제하지않는다.
  ▶new[]로 메모리를 할당한 경우에는 delete[]로 해제한다.
  ▶new를 대괄호 없이 사용했으면 delete도 대괄호 없이 사용한다.
  ▶널 포인터에는 delete를 사용하는 것이 안전하다.(아무일도 일어나지않음)
동적배열을 위한 메모리를 할당하고, 그 배열의 시작 주소를 포인터에 대입하는 형식은 다음과 같다.
type_name *pointer_name = new type_name[num_elements];


첫번째원소는 p3[0]  즉 0.2이지만
p3= p3+1;
을 만나고 나서 p3[0]이 배열의 두번째 원소를 지시하게 된다. p3에서 다시 1을 빼면 포인터는 원래의
첫번째 원소를 지시하게 된다. 따라서 delete[]로 배열에 할당된 메모리를 정확하게 해제 할수 있다.

■포인터, 배열, 포인터 연산
 정수형 변수에 1을 더하면 값이 1만큼 증가한다. 그러나 포인터 변수에 1을 더하면 값이 그 포인터가 지시하는 데이터형의
바이트 수만큼 증가한다. double형이 8바이트인 시스템에서,double형을 지시하는 포인터에 1을 더하는것은 그 포인터의
수치값에 8을 더하는것과 같다. short형이 2바이트인 시스템에서 short형을 지시하는 포인터에 1을 더하는것은 그포인터의 값에 2를 더하는 것과 같다.

◈포인터에 관한 요약
   ★포인터 선언
      -특정 데이터형을 지시하는 포인터를 선언하려면 다음과 같은 형식을 사용한다.
typeName *pointerName;
ex) double *pn;      //pn은 double형 값을 지시할수 있다.
      char *pc;        //pc는 char형 값을 지시할수 있다.
     ★포인터에 값 대입
        - 포인터에는 메모리 주소를 대입해야 한다. 변수 이름에  &연산자를 적용하면 이름이 있는 메모리의 주소를 얻을수 
           있다. new연산자는 이름이 없는 메모리의 주소를 리턴한다.

     ★포인터의 간접참조
        -포인터의 간접 참조는 포인터가 지시하는 주소에 저장되어 있는 값을 참조한다는 뜻이다. 간접값 연산자 또는
         간접참조 연산자라 부르는 *연산자를 포인터에 적용하면, 그 포인터가 지시하는 주소에 저장되어있는 값을 참조할수
         있다. 배열표기는 포인터를 사용하여 값을 간접적으로 참조하는 또 다른 방법이다. pn[0]은 *pn과 같다. 포인터를 
         적당한 주소로 초기화하지 않은 상태에서 간접 참조에 사용하면 안된다.

    ★포인터와 참조값 구별
      -pt가 int형을 지시하는 포인터라면, *pt는 int형을 지시하는 포인터가 아니라 int형 변수와 완전히 동등한 것이다.

    ★배열이름
      -대부분의 경우에는 C++는 배열 이름을 그 배열의 첫번째 원소의 주소와 동일하게 취급한다.
       한가지예외는 배열 이름에 sizeof연산자를 적용할떄에는 배열의 첫번쨰 원소의 크기가 아니라 배열의 전체 크기가
       바이트 단위로 리턴된다.

   ★포인터연산
     -C++에서는 포인터에 정수를 더할수 있습니다. 포인터에 1을 더하는것은 원래의 주소 값에 그포인터가 지시하는 데이터
       객체의 크기를 더하는 것과 같다. 반대로 포인터에서 정수를 뺄수도있다. 두포인터의 차를 구하는 연산은 두 포인터가
       같은 배열을 지시하고 있을때에만 의미가 있다.
   
   ★배열의 동적 바인딩과 정적바인딩
     -정적 바인딩으로 배열 크기가 고정된 배열을 생성할 때에는 배열 선언 명령문을 사용할수 있다.
      동적 바인딩으로 동적 배열을 생성할 때에는 new연산자를 사용한다. 동적 바인딩에서는 프로그램이 실행될때 배열의
      크기가 정해지고 메모리를 할당받는다. 배열을 사용하는 작업이 끝나면 delete[]로 메모리를 해제해야한다.

    ★배열 표기와 포인터 표기
     -대괄호를 사용하는 배열 표기는 포인터를 사용하는 간접 참조와 의미상 동등하다. 
       tacos[0]은 *tacos와 동등하다. 이들은 tacos주소에 있는 값을 의미한다.
       tacos[3]은 *(tacos +3)과 동등하다. 이들은 tacos+3주소에 있는 값을 의미한다.

■포인터와 문자열
char flower[10] ="rose";
cout<<flower<<" s are red\n";
배열이름은 첫번째 원소의 주소이다. 여기서 cout명령문에 있는 flower는 문자 r이 들어있는 char형 원소의 주소이다.
cout객체는 그 주소를 문자열의 주소라고 간주하여 그 주소에 있는 문자를 출력한후, 널문자(\0)를 만날때까지 계속해서
문자들을 출력한다. 다시 말해, cout에 문자의 주소를 넘겨주면, 그 문자부터 시작해서 널 문자를 만날떄까지 계속해서
출력한다.

●new를 사용한 동적 구조체의 생성
 new연산자를 사용하여 동적 구조체를 생성할수 있다. "동적"이라는 말은 컴파일 시간이 아닌 실행 시간에 메모리를 할당
받는다는것을 뜻한다. new를 구조체에 사용할 떄에는 두가지를 알아야한다.
하나는 구조체를 생성하는것, 또다른 하나는 구조체의 맴버에 접근하는것이다.
구조체를 생성할면 구조체형 앞에다 new를 붙인다.
inflatable *ps =new inflatable;
inflatable형의 구조체를 저장할수 있는 새로운 메모리 블럭을 확보하고, 그것의 주소를 포인터 ps에 대입한다.
맴버에 접근하는 방식은 동적구조체에는 도트(.) 맴버연산자를 사용할수 없다. 그이ㅇ는 구조체에는 이름이없기
때문이다. 우리는 동적 구조체의 주소만 알수있다. 이 문제를 해결하기 위해서는 화살표 맴버 연산자(->)를 제공한다.
화살표 맴버연산자는 하이픈(-)에'보다큰(<)'연산자를 결합한것이다.
도트 맴버 연산자는 구조체이름과 함께 사용하고, 화살표 맴버 연산자는 구조체를 지시하는 포인터와 함께 사용한다.
ps가 inflatable형 구조체를 지시하는 포인터라면 ps->price 는 ps가 지시하는 구조체의 price맴버이다.
또하나의 방법은 ps가 구조체를 지시하는 포인터이면, *ps는 그포인터 지시하는값, 즉 구조체가 된다. *ps가 구조체이기
때문에 (*ps).price는 그 구조체의 price맴버이다.

● new와 delete를 사용하는 예제

포인터를 리턴하는 getname()함수를 정의한다. 이함수는 입력 문자열을 일단 큰 임시배열에 읽어 들인다음, 적당한 크기를
가지고 new[]를 사용하여 그 입력문자열의 길이에 꼭 맞는 크기의 메모리 블록을 할당한다. 그리고 나서, 그 메모리 블록을 지시하는 포인터를 리턴한다. 이러한 접근은 많은 개수의 문자열을 읽어 들여야하는 프로그램에서 메모리를 크게 절약한다.

char형을 지시하는 1000개의 포인터를 원소로 가지는 배열을 만든는것이다. 그런다음, 문자열마다 new를 사용하여 각
문자열의 크기에 맞는 메모리 블록을 할당하고, 각 블록의 주소를 포인터 배열의 각 원소에 대입한다. 이렇게 하면 적어도
수만 바이트를 절약할 수 있다. 문자열 마다 하나씩 커다란 배열을 사용하는 대신에 이방법은 입력 문자열의 크기에 꼭 맞게 메모리를 할당할수있다.

 ●C++에서는 데이터를 저장해두기 위한 메모리를, 할당하는 방법에 따라 자동 공간,정적공간, 동적공간으로 구분한다. 동적 공간은  자유공간 또는 힙이라고 불른다.
   ▶자동공간(Automatic storage)
     자동 공간을 사용하는 함수 안에서 정의되는 보통의 변수들 을 자동변수 라고 한다.
     위의 예제에서 임시배열 temp는 getname()함수가 작동하는 동안에만 존재한다. 프로그램의 제어가 main()으로 다시 
     넘어가면 , temp가 사용하던 메모리는 자동으로 해제된다. 만약에 getname()이 temp의 주소를 리턴했다면, main()
     에있는 name포인터는 곧 다른용도로 사용될 운명을 지닌 메모리 위치를 지시하는꼴이 되었을것이다.
     getname()에서 new를 사용하는것은 바로 그이유때문이다.
     자동변수는 자신들을 포함하고있는 블록안에서만 유효하다(지역변수).블록이란 중괄호로 묶여진 코드의 일정부분을
     말한다.블록들중의 어느 하나 안에서 변수를 선언하면, 그변수는 프로그램이 그 블록안에 있는 명령문들을 실행되는
     동안에만 존재한다.
▶정적공간(Static storage)
     정적 공간은 프로그램이 실행되는 동안에 지속적으로 존재하는 공간이다. 변수를 정적으로 만드는 방법은 두가지이다.
     하나는 외부에서 변수를 정의하는 것이고, 다른하나는 변수를 선언할때 static이라는 키워드를 붙이는것이다.
static double fee= 56.50;
정적변수는 프로그램이 실행되는 동안에 지속적으로 존재하고, 자동 변수는 특정함수나 블록이 실행되는 동안에만 존재한다.

▶동적 공간(Heep)
   new와 delete 연산자는 보다 융통성 있는 방법을 제공한다. 이들은 자유공간이라 부르는 메모리 풀을 관리한다. 이풀은 
   자동변수 와 정적 변수가 사용하는 메모리와 분리되어 있다. new와 delete는 어떤함수에서 메모리를 할당하고, 다른 함수
   에서 그것을 해제할수 있도록 해준다. 따라서 데이터의 수명은 프로그램의 수명이나 함수의 수명에 얽매이지 않는다.
   new와 delete를 함께 사용하면 일반 변수를 사용할 때 보다 메모리에 대한 더 강력한 제어권을 가질수 있다.

================================요약============================================
배열,구조체,포인터는 C++의 세가지 복합 데이터형이다. 배열은 동일한 데이터형의 여러개 값을 하나의 데이터 객체 안에
저장할수 있으며, 첨자를 사용하여 배열 내의 각 원소에 접근할수 있다.
구조체는 데이터형이 다른 여러개의 값을 하나의 데이터 객체 안에 저장한다. 도트(.) 맴버 연산자를 사용하여 개별적인 맴버
에 접근한다. 구조체를 사용하려면 먼저 구조체 템플릿을 생성해야 한다. 구조체 템플릿은 구조체 안에 어떤 맴버를 넣을
것인지 정의한 것이다. 템플릿 이름 또는 태그는 새로운 데이터형을 나타내는 식별자로서, 그 데이터형의 구조체 변수를 생성
할수 있다.
공용체는 여러 가지 데이터형을 저장할수 있으나 오직 하나의 값만 저장한다. 어떤 데이터형이 사용되고 있는지 멤버 이름
으로 판별해야한다.
포인터는 주소를 저장하도록 설계된 변수이다. 포인터는 자신이 저장하고 있는 주소를 지시하고 있다. 포인터를 선언할 때에는 반드시 그 포인터가 어떤 데이터형의 객체를 지시하는지 함께 지정해야한다. 포인터에 간접 참조 연산자(*)를 적용 하면
포인터가 지시하는 주소에 저장되어있는 값을 얻을수 있다.
문자열은 널문자로 끝나는 연속된 문자들이다. 문자열은 큰따옴표로 묶어서 문자열 상수로 나타낼수 있다.이때 끝내기 널문자는 내부적으로 처리 된다. 문자열은 charq배열에 저장할수 있다. 또한 문자열은 char형을 지시하는 포인터를 가지고 나타낼
수도있다. 이때 char형을 지시하는 포인터는 그 문자열의 첫번째 문자의 주소를 지시하도록 초기화 된다. strlen()함수는 널 문자를 빼고 문자열 의 길이를 리턴한다. strcpy()함수는 한위치에서 다른 위치로 문자열을 복사한다. 이러한 문자열 함수들을 사용하려면 cstring또는 string.h 헤더파일을 포함해야한다.
string헤더 파일이 지원하는 C++ string클래스는,문자열을 다루는 좀더 친근한 수단을 대안으로 제공한다. 특별히,string객체들은 문자열을 저장하는데 꼭 알맞은 크기로 자동으로 조절된다. 그리고 대입 연산자를 사용하여 문자열을 복사 할수 있다.
프로그램이 실행되는 동안에 new연산자를 사용하여 데이터 객체를 저장할 수 있는 메모리를 할당할수 있다. new연산자는
할당한 메모리의 주소를 리턴한다. 리턴되는 주소를 포인터에 대입할수 있다. 포인터를 사용하는 것이 그 메모리에 접근할수 있는 유일한 방법이다. 데이터 객체가 간단한 변수라면 간접 참조 연산자를 사용하여 포인터가 지시하는 값을 나타낼수 있다. 데이터 객체가 가 배열인 경우 포인터를 마치 배열이름처럼 사용하여 배열의 원소에 접근할수 있다. 데이터 객체가 구조체일
경우에는 화살표 맴버연산자(->)를 포인터와 함께 사용하여 구조체의 맴버에 접근할수 있다.
포인터와 배열은 가까운 관계이다. ar가 배열이름일때, ar[i]는 *(ar+i)로 해석된다. 이때 배열이름은 그 배열의 첫번째 원소의
주소로 해석된다. 그래서배열 이름은 포인터와 같은 역할을 한다. 반대로 포인터 이름을 배열 표기화 함께 사용하여 new로
할당된 동적 배열의 원소에 접근할수 있다.
new 연산자를 사용하여 데이터 객체를 위한 메모리를 할당하고, delete연산자를 사용하여 할당한 메모리를 해제하여 메모리 풀에 반환하는것을 명시적으로 제어할수 있다. 함수 안에서 선언하는 자동 변수와, 함수 밖에서 선언하거나 static이라는
키워드를 사용하여 선언하는 정적 변수는 융통성이 적다. 자동 변수는 자신이 정의되어있는 블록이나 함수가 실행되는
동안에만 존재한다. 정적변수는 프로그램이 실행되는 동안에 지속적으로 존재한다.

'C++ > C++ PRIMER PLUS' 카테고리의 다른 글

함수 - C++의 프로그래밍 모듈  (0) 2011.11.09
분기 명령문과 논리 연산자.  (0) 2011.11.07
루프와 관계 표현식  (0) 2011.10.27
데이터처리  (0) 2011.10.20
C++시작하기  (0) 2011.10.18
데이터처리 C++/C++ PRIMER PLUS 2011. 10. 20. 18:38

■간단한 변수
int braincount;
braincount=5;
이 명령문은 하나의 정수를 저장할것이며, braincount라는 이름이 그 정수의 값, 즉 5를 나타낸다고 프로그램에게 알려준다.
이명령문만 보고는 그값이 메모리의 어디에 저장되는지는 알수 없다 그러나 프로그램은 그위치를 추적할수 있다.
사용자도 &연산자를 사용하면 braincount의 메모리 주소를 알아낼수 있다.

■변수 이름
C++에서 변수 이름을 지을때에는 다음과 같은 간단한 규칙에 따라야한다.
ⓐ변수 이름에는 영문자, 숫자, 밑줄(_) 문자만을 사용할수 있다.
ⓑ숫자를 변수 이름의 첫문자로 사용할수 없다.
ⓒ변수 이름에서 대문자와 소문자는 구별된다.
ⓓC++ 키워드는 변수 이름으로 사용할 수 없다.
ⓔ두개의 밑줄친 문자로 시작하는 이름이나, 밑줄 문자와 대문자로 시작하는 이름은, 그것을 사용하는 컴파일러와 리소스가
   사용하기로 예약되어있다. 하나의 밑줄 문자로 시작하는 이름은, 그것을 사용하는 컴파일러와 리소스가 전역 식별자로 사용하기로
   예약되어있다.
ⓕ변수 이름의 길이는 제한이 없으며, 변수이름에 쓰인 모든 문자들이 유효하다.

- 두개 이상의 단어를 결합하여 변수이름을 지을때는, my_onions와 같이 밑줄로 단어를 구분하거나, myEyeTooth와 같이 첫단어를 제외하고 각단어들의 첫문자를 대문자로 쓰는것이 관례이다.

■ 정수형
C++은 여러가지 정수형을 제공한다.
이것은 프로그램이 요구하는 특정상황에 가장 알맞은 정수형을 골라서 사용할수 있도록 하기 위해서이다.
C++의 여러 정수형들은 서로 다른 크기의 메모리를 사용하여 정수를 저장한다.
메모리 블록이 클수록 나타낼수 있는 정수값의 범위가 크다. signed데이터 형은 양수값과 음수값을 모두 나타낼수 있으나, unsigned데이터형은 양수값만 나타낼수있다. 정수를 저장하는 데 사용되는 메모리 크기를 폭(width)라 한다. 메모리 크기가 클수록 폭이 넓다. C++의 기본 정수형을 크기 순서로 나열하면 char,short,int,long순이다. 이 기본형들에 대해 signed형과 unsigned형이 각각 따로
존재한다.

■short,int,long 정수형
컴퓨터의 메모리는 비트(bit) 단위로 이루어진다.
C++에서 short,int,long은 정수를 저장하는데 사용하는 비트수가 다르다.
C++는 이 데이터형들의 최소 크기만을 정하여 보다 융통성있는 표준을 제공한다.
 ●short형은 최소한 16비트 폭을 가진다.
 ●int형은 최소한 short만큼 크다.
 ●long형은 최소한 32비트 폭을가지며, 최소한 int만큼은 크다.

C++들이 short형을 16bit로 , long형을 32bit로 사용하는 최소 보증 표준을 따르고있다. 그러나 int형에 대해서는 폭이 16,24,32가 될수있다.
일반적으로  IBM용 구식 C++에서는 int형이 16비트이다. windows 98,XP,NT,OSX등에서는 C++의 int형이 32bit이다.

다른 데이터형들의 변수도 int형 변수처럼 선언할수 있다.
short score;              //short형의 정수형 변수를 만든다.
int temperature;        //int형의 정수형 변수를 만든다.
long position;          //long형의 정수형 변수를 만든다.

int,short,long 세가지 데이터형은 부호가 있는 데이터형으로서, 나타낼수 있는 양의 정수값과 음의 정수값 범위가 거의 같다.

C++ 시스템의 정수크기가 얼마인지 알고 싶으면, 데이터 크기를 알아내는 C++도구를 사용할수 있다.
첫번째 방법은 sizeof연산자를 사용하는 것이다. sizeof연산자는 변수나 데이터형의 크기를 바이트 단위로 리턴한다.
'바이트'의 의미는 컴파일러에 따라 다르므로 2바이트 int형이 어떤 C++에서는 16비트인반면, 어떤컴퓨터에서는 32비트가 될수도있다.

두번째 방법은 여러가지 정수 형들의 범위에 대한 정보가 있는 climite헤더파일을 열어보는것이다.

 


▣climits에 정의 되어있는 기호 상수들
 기호상수  의미
 CHAR_BIT  char형의 비트수
 CHAR_MAX char형의 최대값 
 CHAR_MIN char형의 최소값 
 SCHAR_MAX signed char형의 최대값
 SCHAR_MIN signed char형의 최소값
 UCHAR_MAX unsigned char의 최대값
 SHRT_MAX short 형의 최대값
 SHRT_MIN short형의 최소값
 USHRT_MAX  unsigned short형의 최대값.
 INT_MAX  int의 최대값
 INT_MIN  int의 최소값
 UINT_MAX  unsigned int 의 최대값
 LONG_MAX  longt의 최대값
 LONG_MIN  long의 최소값
 ULONG_MAX  unsinged long형의 최대값

■unsigned형
- unsigned형을 사용하면 그변수에 저장할수 있는 최대값을 늘릴수 있다. 예를들어 short형이 -32768에서 +32767까지의 범위를
  갖는다면, unsigned short는 0부터 65535까지의 범위를 갖는다. 물론 unsigned형은 인구수,낱알수, 웃는 얼굴 표정수와 같이 결코
음수가 될수 없는 양을 나타낼 때만 사용해야한다.

 


■정수형 상수
 정수형 상수는 212,1776과 같이 프로그램에 직접 써넣는 정수를 말한다.
 정수형상수에는 세가지 방법이있다. 일상생활에서는 사용하는 10진수, 구식 Unix가 사용하던 8진수, 하드웨어 전문가가 좋아하는
16진수.
C++에서는 상수의 처음하나의 숫자 또는 처음 두개의 문자가 진수를 의미한다.
처음 숫자가 1~9이면 그수는 10진수이다. 처음 숫자가 0이고 두번째 숫자가 1에서7이면 그수는 8진수이다.
따라서 042는 8진 정수형 상수이며, 10진수로는 34이다. 그리고 처음 두개의 문자가 0x또는 0X이면 16진수를 나타낸다.
0x42는 16진 정수형 상수이며 10진수로 66이다. 그런데 16진 정수형 상수를 나타내는데쓰이는 A~F까지의 문자는 10진수로 각각 10에서 15까지 해당하는 16진수 숫자이다. 그러므로 0xF는 10진수로 15이고 0xA5는 10진수로 10x16+5,즉 165이다.


 


■C++가 상수의 데이터형을 결정하는 방법
cout<<"Year ="<<1492<<endl;
-프로그램은 149를 int로 저장할까 long형으로 저장할까 아니면 다른형으로 저장할까?
  C++에서는 특별한 이유가 없다면 정수형상수를 모두 int형으로 저장한다.
  그러나 특정 데이터형을 의미하는 접미어를 상수에 붙였을때와 , 값이 너무커서 int형으로 저장할수 없을때에는 그렇지않다.

 접미어에 대해 알아보자.
 접미어는 상수 끝에 붙는 문자로서 그 상수의데이터형을 나타낸다. l이나Ldms long형을 의미하고 u나U는 unsigned int형을 의미.
 ul은 unsigned long형을 의미,(ul의 l은 숫자1과 혼동하기 쉬으므로 대문자L로 사용한다.)

 16비트 int형과 32비트 long형을 사용하는 시스템에서, 22022는 16비트 int형으로 저장되고 , 22022L은 32비트 long형으로 저장된다.
 그리고 22022LU와 22022UL은 unsigned long형으로 저장된다.

 C++는 16진수 정수나 8진 정수에 적용하는 규칙과는 약간 다른 규칙을 10진수 정수에 적용하고있다.
 접미어가 없는 10진 정수는 int,long,unsigned long형중에 크기가 가장작은것으로 나타낸다.
 예를들면, 16비트 int형과 32비트 long형을 사용하는 시스템에서, 20000은 int형으로, 40000은 long형으로  300000000은 unsigned 
 long형으로 나타낸다. 또한 접미어가 없는 16진 정수나 8진 정수는 int,unsigned int , long, unsigned long형 중에 크기가 가장작은
 것으로 나타낸다. 그이유는 성질상 부호가 없는 메모리 주소를 일반적으로 16진수로 나타내기 때문이다.
 그래서 16비트 주소를 나타내는데는 long형보다 unsigned int형이 적당하다.


■char형: 문자와 작은 정수
 char형은 이름에서 알수 있듯이, 문자와 숫자를 저장하기 위한것이다.
 char형은 실제로 또 하나의 정수형이다. 컴퓨터 시스템에서 사용하는 문자와 숫자, 구두점과 같은 기본적인 기호들을 모두 char형
 으로 나타낼수있다. 대부분의 컴퓨터 시스템들은256개 보다 적은 개수의 문자들을 지원한다.
 이러한 문자들은 1바이트만으로 충분히 나타낼수 있다. 그러므로 char형은 문자들을 처리하는 데 사용할수 있고, short형보다 작은  범위의 정수를 나타내는데 사용할수 있다.
 예를들어 65는 문자 A에 해당하는 코드이고, 77은 문자M에 해당하는 코드이다.
 ASCII나 EBCIDC은 국제적인 요구를 모두 수용하지 못한다. 그래서 C++는 보다 넓은 범위의 값을 수용하는 Unicode국제 문자 세트
 를 사용할수 있는 확장 문자형을 지원한다 그러한 데이터형을 wchar_t형이다.



char형 A에 해당하는 숫자는 65이다.


 

 


-cout.put()란?
 cout.put()은 C++객체 지향 프로그래밍에서 중요한 개념인 맴버함수를 설명할수 있다.
클래스는 데이터 형식과 그 데이터를 다루는 방법을정의 해놓은 것이다.
맴버 함수는 클래스에 속하고, 클래스의 데이터를 다루는 방법을 정의한다.
예를들어, ostream클래스는 문자를 출력하도록 설계된 put()이라는 맴버함수를 가지고있다.

맴버함수는 그 클래스의 특정 객체를 통해서만 사용할수 있다. cout객체를 통해 put()이라는 맴버함수를 사용한다. cout과 같은
객체를 통해 멤버함수를 사용하려면 마침표(.)로 객체이름(cout)과 함수이름(put())을 서로연결해야한다.
이마침표를 멤버연산자라고 부른다. cout.put()이 나타내는 의미는 클래스 객체인 cout을 통해 클래스 멤버함수인 put()을 사용하겠다는 뜻이다.

cout.put 맴버함수는 << 연산자를 사용하여 문자를 출력하는 것에 대한 대안이다.
그런데 여기서 cout.put()이 왜 필요한가?
 그것은 C++ Release 2.0 이전에 cout은 문자 변수들을 문자로 출력했지만, 'M'이나 'N'과 같은 문자 상수들은 수로 출력했다. 이문제는  C와 C++초기 버전들이 문자 상수를 int형으로 저장하는데서 비롯되었다.
즉, 문자상수'M'에 해당하는 코드 77이 16비트 또는 32비트로 저장되었다. 그러나 cahr형 변수는 8비트만 차지했다.그래서 다음과 같은 명령문은

char ch='M';
 문자상수 'M'으로 부터 char형 변수 ch로 8비트만복사했다.
이것은 문자상수'M'과 char 변수 ch가 동일한 값을 가지고 있더라도 cout에게는 서도 다르게 보였다는것을 의미한다.

그래서 다음과 같은 명령문은
cout<<'$';

문자$를 출력하지않고. '$'에 해당하는 ASCII코드 36을 출력했다. 그러나 다음 과 같은 명령문은

cout.put('$');

원하는 대로 문자 $를 출력했다. C++ Release2.0 이후에 모든 C++들은 문자상수를 int형이 아닌 char형으로 저장한다.
그래서 이제는 cout이 문자상수를 바르게 처리할수 있게되었다.

■만국 문자 이름
- C++는 특정 키보드와 무관한 국제 문자들을 표현하는 메커니즘도 가지고있다. 그것을 만국문자이름(Universal character names)
   라고 한다.

●signed char형과 unsigned char형
-int 형과는 달리, char형은 signed형이나 unsigned형으로 미리 정해져있지않다. 이것은 개발자가 하드웨어 특성에 맞추어 알맞은
 char형을 정할수 있도록 하기위한 배려이다. 그러나 char형이 어느 특별한 한가지 행동만을 보여야한다면, signed char형 또는
 unsigned char형을 사용하여 그행동을 명시적으로 제한할수 있다.

char fodo;              //signed형 또는 unsigned형
unsigned char bar;     //unsigned형 char
signed char snark;    //signed형 char
이러한 구별은 char형으로 수를 나타내고자할때 중요하다.
unsigned char형은 0에서 255까지의 범위를 나타낼수 있고, signed char형은 -128부터 127까지의 범위를 나타낼수있다.
예를들어,200정도 되는 값을 char형 변수에 저장한다고 하면 이것은 어떤 시스템에서는 동작하지만 다른 어떤 시스템에서는 동작하지 않을것이다.  같은 값을 unsigned char형에 저장한다면 어느 시스템에서나 무리없이 동작할것이다. 그러나 표준ASCII문자를 char형
변수에 저장할때에는 signed형이나 unsigned형이나 상관없으므로 간단히 char이라고 쓰면 된다.

●확장 char형: wchar_t
-프로그램이 1바이트(8bit)로 표현할수 없는 문자세트(일본어,중국어,한글등)를 처리 해야할때에쓰인다.
 C++에서는 두가지 방법으로 처리 한다.
 첫번째, 확장 문자 세트가 시스템의 기본 문자 세트이면, 컴파일러 개발업체가 char형 을 처음부터 2바이트(16bit)또는 그이상으로
 만드는것.
 두번째, 기본문자 세트와 확장 문자세트를 동시에 지원하느것이다. 즉, 보통의 8비트 char형 으로 기본 문자세트를 나타내고,
 wchar_t형으로 확장 문자세트를 나타내는것이다.
 wchar_t형은 시스템에서 사용되는 가장 큰 확장 문자 세트를 나타낼수 있을만큼 충분한 비트 폭을 가진 정수형이다.
 wchar_t형은 기초데이터형 이라고 부르는 정수형과 동일한 크기와 부호 속성을 가진다. 기초 데이터형은 시스템에 따라 다른데,
 어떤 시스템에서는 unsigned short형일수도있고, 다른시스템에서는 int형이 될수도있다.

 확장문자상수나 확장 문자 문자열은 그앞에 L을 붙여서 나타낸다. 다음과 같은 코드는 변수 bob에 문자 P의 wchar_t형버전을
 저장하고, 단어 tall의 wchar_t형 버전을 디스플레이한다.

wchar_t bob=L'P';          //확장 문자 상수
wcout <<L"tall"<<endl;   //확장 문자 문자열의 출력

2바이트 wchar_t 형을 사용하는 시스템에서, 이코드는 각문자에 2바이트씩 할당하여 메모리에 저장한다.

●bool형
-bool형 변수는 참이나 거짓 어느 한가지 값만 가질수 있다. On / Off 스위치라 생각하면 쉽다.
 C++는 0이 아닌값들을 참으로, 0인값을 거짓으로 해석한다.

bool usready = true;

int ans = true;               //ans 에 1이되입된다.
int promise = false;      //promise에 0이 대입된다.

어떠한 수치 값이나 포인터 값도 하나의  bool값으로 묵시적으로 변환될수 있다.
bool start =-100;       //start에 true가 대입
bool stop = 0;          //stop에 false가 대입

■const 제한자
- #define문보다 쉽게 기호 상수를 다루는 방법은 const키워드를 사용하여 변수를 선언하고 초기화 하는 것이다.
  1년의 달수를 기호 상수로 나타내고 싶다면
const int MONTH =12;   //MONTHS는 12를 나타내는 기호 상수

MONTH와 같은 상수는 한번 초기화 되면 그값이 '고정' 된다. 컴파일러는 이후 MONTH의 값을 변경하려는 어떠한 시도도  허용하지
않는다.
키워드 const는 선언의 의미를 제한하므로 제한자라고 부른다.
일반적으로 관행은,MONTHS가 상수라는 것을 금방알수있도록 이름을 모두 대문자로 쓰거나,또다른 관행은 상수이름의 첫문자만
대문자로 쓴다던지, kmonth처럼 앞에다가 k를 넣는것이다.

상수를 만드는 일반적인 형식은 다음과 같다.

const  데이터형 상수이름 = 값;
const 상수는 선언할 때 초기화해야 하며, 다음과 같이 하는것은 좋지않다
---
const int toes;      //toes값은 미확정
toes= 10;

const상수는 선언할때 값으로 초기화 하지 않으면 변경할수 없는 미확정값으로 남겨진다.
#define보다 const를 사용하는게 좋은이유는
첫번째, 데이터형을 명시적으로 지정할수 있다는점.
두번째, C++의 활동범위 규칙에 의해 그 정의를 특정함수나 파일에만 사용할수 있도록 제한할수있다는점.
세번재, 배열이나 구조체 와 같은 복잡한 데이터 형에도 const를 사용할수 있기때문.

■연산자 우선순위
===C++연산자 우선순위와 결합 규칙====
              연   산   자             결 합 규 칙                 의   미
              우선 순위 그룹1               
 ::    사용 범위 결정 연산자
             우선 순위 그룹 2                  
 (expression)    괄호묶기
 ()                     L-R  함수호출
 ()    값생성, 즉 type(expr)
 []    배열 첨자
 ->    간접 맴버 연산자
 .    직접 맴버 연산자
 const cast    특수화된 데이터형 변환
 dymic cast    특수화된 데이터형 변환
 reinterpret cast    특수화된 데이터형 변환
 static cast    특수화된 데이터형 변환
 typeid    데이터형 인식
 ++    증가 연산자, 접미어
 --    감소 연산자, 접미어
              우선순위 3그룹(단항)            
 !                   R-L  논리부정
 ~    비트 부정
 +    단항 플러스(양수부호)
 -    단항 마이너스(음수부호)
 ++    증가 연산자, 접두어
 --    감소 연산자, 접두어
 &    주소
 *    내용 참조(간접 값)
 ()    데이터형 변환(type) expr
 sizeof    바이트 단위의크기
 new    동적으로 메모리할당
 new[]    동적으로 배열 할당
 delete    동적으로 할당된 메모리해제
 delete[]    동적으로 할당된 배열 해제
                 우선순위 4그룹  
 .*                    L-R  맴버내용 참조
 ->*    간접 맴버내용 참조
              우선순위 5그룹(2항)  
 *                   L-R  곱셉
 /    나눗셈
 %    나머지
              우선순위 6그룹(2항)  
 +                    L-R  덧셈
 -    뺄셈
                 우선순위 7그룹  
 <<                     L-R  비트들을 왼쪽으로 시프트
 >>    비트들을 오른쪽으로 시프트
                우선순위 8그룹  
 <                 보다 작다
 <=    보다 작거나 같다
 >=    보다 크거나 같다
 >    보다 크다
                 우선순위9그룹  
 ==                    L-R  같다
 !=    같지않다
     
                우선순위10그룹(이항)  
 &                     L-R  비트 AND
                우선순위 11그룹  
 ^                     L-R  비트 XOR
               우선순위  12그룹  
 |                     L-R  비트 OR
                우선순위 13그룹  
 &&                     L-R  논리AND
                우선순위 14그룹  
 ||                   L-R  논리OR
                우선순위 15그룹  
?:                    R-L  조건식
                우선순위 16그룹  
 =                   R-L  단순대입
 *=    곱셈후대입
                우선순위 17그룹  
 /=                 나눗셈후 대입
 %=    나머지셈 후 대입
 +=    덧셈후 대입
 -=    뺄셈후 대입
 &=    비트 AND후 대입
 ^=    비트 XOR후 대입
 |=    비트 OR후 대입
 <<=    왼쪽으로 시프트후 대입
 >>=    오른쪽으로 시프트후 대입
                 우선순위 18그룹  
 throw                     L-R  예외발생
                 우선순위 19그룹  
 ,                      L-R  두 수식을 하나로 결합


■데이터형 변환
C++는 데이터형의 불일치를 해결하기 위해 다음과 같은 상황일때자동으로 데이터 형 변환을 수행한다.
 ●특정 데이터형의 변수에 다른 데이터형의 값을 대입했을때
 ●수식에 데이터형을 혼합하여 사용했을때
 ●함수에 전달인자를 전달했을때.

◎대입명령문에서 데이터형변환
  -범위가 작은 데이터형의 값을 범위가 큰 데이터형에 대입하는것은 문제가 되지않는다. 하지만 short형 값을 long형 변수에
   대입하면 값은 변하지 않고 의미없는 여분의 바이트만 추가된다. 그러나 21112222333과 같은 큰 long형 값을 float형변수에
   대입하면 정밀도가 손실된다.
   데이터형변환에서 일어날수있는 잠재적문제는 다음과 같다.

                             데이터  형변환                                   잠재적   문제점      
 double→float와 같이 큰부동 소수점형을
 작은 부동 소수점형으로
 정밀도(유효숫자)가 손실된다. 원래의 값이 변환 데이터의 범위
를 벗어날경우, 결과를 예측할수없다.
 부동 소수점형을 정수형으로  소수부를 잃어버린다. 원래값이 변환 데이터형의 범위를 벗어날
경우, 결과를 예측할수없다.
 long→ short와 같이 큰정수형을
 작은 정수형으로
 원래 값이 변환 데이터형의 범위를 벗어날경우,
대개 하위 바이트들만 복사된다


■ 수식에서의 데이터형 변환
- 일반적으로 컴파일러는 산술식에 어떤ㅌ 데이터형 변환이 이루어져야하는지를 검사한다.
  이를 위해 컴파일러가 검사하는 목록은 순서대로 다음과 같다.
ⓐ한쪽 피연산자가 long double형이면, 상대편 피연산자를 long double형으로 변환한다.
ⓑ그렇지않고 한쪽 피연산자가 double형이면, 상대편 피연산자를 double형으로 변환한다.
ⓒ그렇지않고 한쪽 피연산자가 float형이면, 상대편 피연산자를 float형으로 변환한다.
ⓓ그렇지않다면 피연산자들이 정수형이므로 정수승급이일어난다.
ⓔ이경우에, 한쪽 피연산자가 unsigned long형이면, 상대편 피연산자를 unsigned long형으로 변환한다.
ⓕ그렇지않고 한쪽 피연산자가 long int 형이고 상대편 피연산자가 unsigned int형이면, 두데이터형의 상대적인 크기에 따라 변환이
   결정된다. long형이 unsigned int값을 나타낼수 있으면, unsigned int형이 long형으로 변환된다.
ⓖ그렇지않으면 두 피연산자가 모두 unsigned long 형으로 변환된다
ⓗ그렇지않고 한쪽 피연산자가 long형이면, 상대편 피연산자를 long형으로 변환한다.
ⓘ그렇지않고 한쪽 피연산자가 unsigned int형이면, 상대편 피연산자를 unsigned int 형으로 변환한다.
ⓙ컴파일러가 이 지점까지 도달한다면, 두 피연산자는 int형이다.

■데이터형 변환자
C++에서는 데이터형 변환자를 사용하여 강제로 데이터형을 변환시킬수있다.
데이터형 변환자는 두가지 형태로 사용된다.
(long) thorn      //thorn의 long형 변환을 리턴한다.
long (thorn)      //thorn의 long형 변환을 리턴한다.

데이터형 변환자는 thron변수 자체는 변경하지않는다.
그대신에 지시된 데이터 형의 새로운 값을 만든다.

(typeName) value       // value를 typeName형으로 강제 형변환한다.
typeName (value)       // value를 typeName형으로 강제 변환한다.
첫번째 형태는 C에서 사용하던 방법이다.
두번째형태는 C++에서만 사용하는 형태이다.
이것은 내장 데이터형에 대한 데이터형 변환을 마치 사용자 정의 클래스를 위해 설계할 수 있는 데이터 형
변환처럼 보이게한다.
satic_cast<>연산자는 어떤 수치 데이터형을 다른 수치 데이터형으로 변환하는데 사용할수 있다.
예를 들어, 다음과 같이 thorn을 long형 값으로 변환하는 데 사용할수 있다.
static_cast<long> (thorn)     //thorn의 long형 변환을 리턴한다.

일반적으로 다음과 같이 할수 있다.
static_cast<typeName>(value) // value를 typeName형으로 변환한다.


 


======================================요약=============================================
C++의 기본 데이터형은 두그룹으로 나뉜다. 한 그룹은 정수형으로 저장되는값들로 이루어진다. 다른 한 그룹은 부동 소수점형으로
저장되는 값들로 이루어진다. 값을 저장하는데 사용되는 메모리 크기와 그것이 signed냐 unsigned냐에 따라 정수형은 다시 여러가지
형으로 세분된다. C++의 정수형을 크기가 작은것부터 순서대로 나열하면 bool,char,signed char,unsigned char, short , unsigned shore, int , unsigned int, long, unsigned long형의 순이다.
wchar_t라는 정수형이 하나더있다. 앞의 크기 순서에서 wchar_t가 들어갈 위치는 시스템에따라 다르다. char형은 그시스템의
기본문자세트에 속하는 어떠한 문자도 저장할수있을만큼 커야한다. wchar_t형은 시스템의 확장문자 세트에 속하는 어떠한 문자도
저장할수 있을만큼 커야한다. short형은 최소 16비트이다. int형은 최소한 short형만큼 커야한다. long형은 최소 32비트이고, 최소한 int형만큼 커야한다. 각 데이터형의 정확한 크기는 C++시스템에 따라 다르다.
문자들은 그에 해당하는 수치 코드로 나타낸다. 그수치코드를 문자로 해석할것인지 수로 해석할 것인지는 입출력(I/O) 시스템이
결정한다.
부동 소수점형은 소수부가 있는 값을 나타낼수 있다. 또한 정수보다 훨씬 큰값을 나타낼수있다. 부동소수점형은 float, double, long double형 세가지가 있다. long double형은 최소한 double형 만큼은 커야한다. double형은 최소한 float형만큼은 커야한다.
일반적으로 float형은 32비트, double형은 64비트, long double형은 80에서 128비트의 메모리를 사용한다.

C++는 크기가 다른 다양한 데이터형과, 그들의 signed,unsigned 변형까지 제공하므로 특정 데이터에 적합한 데이터형을 골라서
사용할수 있다.

C++는 수치 데이터형에 대해 산술 연산(덧셈, 뺄셈, 곱셈, 나눗셈, 나머지셈) 을 수행하는 연산자를 제공한다. 두 연산자가 하나의 피연산자에 걸려있을때에는 우선 순위 규칙과 결합 방향 규칙을 적용하여 어느 연ㅅ간을 먼저 수행할 것인지를 결정한다.

변수에 값을 대입할때, 수식에 서로 다른 데이터형을 혼합하여 사용할때, 데이터 형 변환자를 사용하여 강제로 데이터형을 변환
시킬때, 이러한 경우에 C++에서는 한 데이터형을 다른 데이터형으로 변환한다. 데이터형 변환에서 데이터의 실제값은 대부분 그대로
유지된다. 예를 들어, int형 값을 long형으로 변환하는 것은 전혀 문제를 일으키지 않는다. 그러나 부동 소수점형을 정수형으로
변환할때에는 약간의 주의가 필요하다.

다양한 데이터형 변환 규칙을 고려 해 볼때, C++의 기본 데이터 형이 이렇게 많을 필요가 있을까 의문이 들수도있다.
그러나 기본데이터형들 중의 어느 하나가 상황에 꼭 맞는 경우를 언젠가는 만나기때문에 그럴 걱정은 필요없다.

'C++ > C++ PRIMER PLUS' 카테고리의 다른 글

함수 - C++의 프로그래밍 모듈  (0) 2011.11.09
분기 명령문과 논리 연산자.  (0) 2011.11.07
루프와 관계 표현식  (0) 2011.10.27
복합 데이터형  (0) 2011.10.27
C++시작하기  (0) 2011.10.18
C++시작하기 C++/C++ PRIMER PLUS 2011. 10. 18. 23:53

main() 함수내의 기본구조
 //  주석문
 #include  전처리 지시자
 int main()  함수머리
 using namespace  지시지
 { } 범위내에는 함수의 몸체
 cout  메시지를 출력하는 명령문
 return main()함수를 종료 

●main()함수
--------------------------------------------------------------
int main()
{
   명령문들
   return 0
;
}

첫번쨰행에 있는 int main()이라는 부분이 함수머리(function head)
중괄호 { } 로 묶여있는 부분이 몸체(function body)
- 함수머리는 프로그램을 다른 부분과 연결하는 고리역활, 함수몸체는 그함수가 처리하는 동작을 컴퓨터에게 지시.

컴퓨터에게 내리는 지시를 명령문이라 한다. C++에서 모든 명령문은 세미콜론(;)으로 끝나야 한다.
main() 함수의 끝에 있는 명령문은 return 명령문 - 함수를 종료하는 역활을 함.

함수머리는 호출함수와 피호출 함수의 인터페이스를 나타냄. 함수이름의 앞부분을 함수 리턴형이라한다. 이것은 피호출 함수가 호출함수로 다시 넘겨주는 정보의 흐름을 나타냄.

함수이름뒤에 있는 괄호부분의 안의 부분을 전달인자 리스트 또는 매겨변수리스트라고 함.

int main() 함수머리는
main()함수가 자신을 호출한 함수로 부터 어떠한 정보도 전달받지 않지만, 그함수에게 정수값을 리턴한다는것을 나타냄.

main()   //클래식 C의 함수 머리 스타일
- 리턴형을 생략하는 것은 그함수가 INT형이라고 말하는것과 같다

C++ 에서는
int main(void) // 명시적인 스타일
-괄호안에 키워드 void를 사용하는 것은 그함수가 다른함수로부터 어떠한 정보도 전달받지않는다는 것을 명시적으로 밝힘.
  C++에서 괄호안을 비워두는 것은 괄호안에 void 가 있는것과 같다.

void main()

-void리턴형이, 함수가 값을 리턴하지 않는다는것을 뜻함.

main()의 끝에 리턴명령어를 두어야함. 컴파일러가 리턴명령을 만나지 못한채 main()문의 끝에 도달한다면
main()문을 끝내는것과 동일한효과를 낸다.
  
   return 0;

- 암시적 리턴은 다른함수들에는 해당되지않고 오로지 main()함수에만 특별히 허용된다.

이름이 반드시 main()이어야하는 이유

C++프로그램에는 main()함수가 반드시 하나가 있어야함.(대/소문자가 틀리거나 철자가 틀리면안됨)
프로그램에 main()함수가 없으면 완전한 프로그램이 아님. 이러한경우 컴파일러에서 main()함수를 정의하지 않았다고 지적.

-예외도있음. Windows프로그래밍에 동적 링크 라이브러리(DLL)모듈을 작성할때. DLL모듈은 다른 Windows프로그램들이 사용할수 있는 코드 로서, 독립된 프로그램이 아니므로 main()이 필요없다.

일반적인 독립형 프로그램에튼 반드시 main()이 필요함.

■C++ 주석문

더블슬러쉬(//) 뒤에는 항상 주석문.
주석문은 프로그램안에 기록해두는 메모의 일종. 프로그램의 구역을 구분하거나 코드의 어떤부분이 어떤 역활을 하는것인지 표시하는데사용.

주석문에는  //   를 사용하여 한줄 주석을 할수도있고, /*  (주석시작)      */(주석의끝) 과같은 부호를 사용하여 원하는 만큼주석처리가능.

전처리기와 iostream 파일

#include <iostream>
//전처리 지시자
이지시자는 전처리기에 iostream 파일의 내용을 프로그램에 추가하라고 지시. 컴파일이 되기전에 원시코드에 텍스트를 추가하거나 텍스트를 대체 하는것이 전처리기가 수행하는 기본역활.
iostream 의 i는 (input) 입력  o 는 (out)출력 을 나타냄.
프로그램에서 cout과 cin의 기능을 사용할려면 iostream을 정의해야함.

namespace

iostream.h대신에 iostream 을 사용할시에 프로그램이 iostream의 정의를 사용할수 있게 하려면 다음과 같은 이름공간지시자를사용.

  using namespace std;
-using지시자라고함.

using 지시자는 std이름 공간에 들어있는 모든 이름을 사용할수 있게 해준다.

using std::cout;
using std::cin;
using std::endl;

매번 using std:: 를 쓰지 않기 위해선  using namespace std 지시자를 사용하면
std::를 붙이지않고  cin  , cout을 사용가능.

cout을 이용한 C++출력
 
   cout<<"C++의 세계에 오십시오.";

큰따옴표안에 있는것은 출력할 메세지이다. c++에서 큰따옴표안에 들어있는 연속된 문자들을 문자열이라고한다.
<<표시는 명령문이 그문자열을 cout에 전달한다는 것을 뜻함. <<표시가 나타내는 방향이 정보의 흐름을 상징.
cout은 문자열(string),수(number),문자(character)들을 포함한 여러가지 다양한 정보를 출력하는 방법을 알고 있는 미리정의된 객체이다.


조정자 endl

cout<<endl;

endl은 새로운 행이 시작된다는 중요한 개념을 나타내는 특별한 C++표기이다. endl을 출력 스트림에 삽입하면 화면 커서가 다음행의 시작위치로 간다. cout에게 특수한 의미를 가지는 endl과 같은 특별한 표기들을 조정자(manipulator)라고 부른다.
cout과 마찬가지로,endl도 iostream 헤더파일에 정의되어있고, std 이름공간에 속한다.

cout은 문자열을 출력하고 나서 다음행의 시작위치로 커서를 자동으로 넘겨주지 않는다. 그러므로 넘겨주기 위해서는 cout을 사용한다.

■개행문자(\n)
c표기 방법은 \n 은 개행문자(newline character)라고 부르는 하나의 문자를 나타내는것으로 간주된다.
문자열을 출력하고자 할떄, 꼬리표처럼 뒤에 endl을 매다는것보다 문자열의 일부로 개행 문자를 포함시키는 것이 타이핑의 수고가 적기 때문에 사용한다.  개행문자는 "이스케이프 시퀀스"라고 하는 특별한 키스트로크결합의 한예이다.


■토큰과 화이트스페이스
한행의 코드에서 더이상 분리할수 없는 기본요소를 "토큰" 이라고 한다.
일반적으로 하나의 토큰은 빈칸,탭,캐리지 리턴 에 의하여 다음 토큰과 분리된다.  빈칸, 탭, 캐리지 리턴을 집합적으로
화이트스페이스 라고 부른다. 괄호나 콤마와 같은 일부 단일 문자들은 화이트 스페이스로 분리하지 않아도 되는 토큰이다.


■C++원시 코드 스타일

●한행에 하나의 명령문을 사용한다.
●함수를 여는 중괄호 { 와 닫는 중괄호 } 에 각각 한행을 할애한다.
●함수안에 들어갈 명령문들은 중괄호에서 약간 오른쪽으로 들어간 위치에서 시작한다.
●함수 이름과 괄호 사이에는 어떠한 화이트 스페이스도 넣지않는다.

■C++명령문
-변수를 선언하는 선언명령문, 변수에 값을 대입하는 명령문
int carrots;     //정수 변수를 선언
carrots =25;   // 변수에 값을대입

선언명령문과 변수
   int carrots;
 -이명령문은 하나의 정수를 저장할수 있는 한 기억공간을 할당하고, 그위치가 어딘지 말해주는 꼬리표를 붙이는 작업을 수행.
   int :  소수부가 없는 정수형을 말하며 양의 정수와 음의 정수가 있다. int형의 크기는 사용하는 시스템에따라 다르다.

선언명령문은 데이터형을 선언하는것뿐만아니라, 앞으로 프로그램에서 그기억공간에 저장되어있는 값을 carrots라는 이름으로 사용하겠다고 선언하는것이다.
이와같은 carrots를 변수(variable)라고 부른다. 변수라는 이름은 값이 변하기때문에 붙여진 이름이다.

int carrots ;←세미콜론은 명령문의 끝을 나타냄.
↑    ↑
|   변수이름.
저장될데이터형.

선언명령문을 정의 선언 명령문, 또는 정의라고 부른다. 정의가있으면 컴파일러는 그변수를 위해 메모리공간을 할당한다.

C++의 기타 명령문
 ●cin 사용법
cin>>carrots;

입력은 바깥 세상에서 프로그램 안으로 흘러들어가는 문자들의 스트림이다. cin은 iostream 파일에 입력스트림을 나타내는 객체로정의되어있다. 출력을 할때는 cout이 <<연산자를 사용하여 문자들을 출력스트림에 삽입하고 , 입력할때는 cin이 >>연산자를 사용하여 입력스트림에서 문자들을 가져온다.
가져온 정보를 저장할 변수는 >> 연산자의 오른쪽에 적는다.

■함수
  C++함수는 두가지 유형이있다. 리턴값이있는것과 리턴값이 없는 것.
  표준라이브러리에 있는 함수를 사용할수도있고, 사용자가 직접만들어서 사용할수도있다.

리턴값이있는함수.
  -리턴값이있는 함수는 변수에 대입할수있는 하나의 값을 만들어낸다.예를들어 C/C++표준라이브러리에는 어떤 수의 제곱근을
   리턴 하는 sqrt()라는 함수가있다. 제곱근을 구하여 변수 x에대입하여야한다고 가정할때, 다음과 같은 코드가 작성된다.
x=sqrt(6.25);   //값2.5를 리턴하여 x에 대입한다.

   괄호안에있는값은 함수에 전달되는 정보이다

x= sqrt(6.25) --->피함수호출 sqrt()코드 -> x에 값을 리턴한다.

  x= sqrt(6.25);  
  ↑   ↑     ↑_함수에 전달되는인자
 | 함수이름
 함수 리턴값이 x에 대입된다.

-전달인자는 함수에 전달되는 정보이고, 리턴값은 함수가 돌려주는값이다.
다만, 함수를 사용하기전에 C++컴파일러는 그함수가 어떤 종류의 전달인자를 사용할것이며, 어떤 종류의 리턴값을 리턴하는지 미리 알고 있어야한다. 즉, 리턴값이 정수인지, 문자인지,소수부가있는수인지 알고있어야한다는것이다. 이런정보가 없다면 컴파일러는 그리턴값을 어떻게 처리할지 판단할수가없다.
C++은 함수원형 명령문을 사용하여 이런 정보를 컴파일러에게 전달한다.

C++라이브러리에는 sqrt()함수가 소수부가 있는수 를 전달인자로 전달받으며, 전달받은것과 동일한 데이터형의 값을 리턴한다고 정의 되어있다.

소수부가 있는 실수는 double형으로 나타내며, sqrt()의  함수 원형은 다음과 같다.

double sqrt(double); //함수원형
 
앞에있는 double는 sqrt()함수가 double형의 값을 리턴한다는뜻.
뒤에있는 double는 sqrt()함수가 double형의 전달인자를 전달받는다는뜻이다.

sqrt()함수를 사용하려면 함수원형을 제공해야하는데 함수원형을 제공하는 방법은 두가지가있다.
●함수 원형을 원시코드 파일에 직접 입력한다.
●함수원형이 들어있는cmath헤더 파일을 포함시킨다.


■변이함수
어떤함수는 하나이상의 정보를 요구한다. 그러한 함수는 여러개의 전달인자를 콤마(,)로 구부한다. pow()는 전달인자를 2개요구한다.
이함수는 첫번째 전달인자를 두번째 전달인자의 횟수만큼 거듭제곱하여 그결과값을 리턴한다.
  double pow(double, double); //2개의 전달인자를 가진 함수 원형

예를들어 5의 8제곱근을 구한다면
  double pow(5.0,8.0);  //전달인자 리스트가 있는 함수호출.

전달인자를 사용하지않는 함수도있다. C라이브러리에는 전달인자는 사용하지않지만 임의의 정수를 리턴하는 rand()라는 함수가있다.
이함수의 원형은
int rand(void);   //전달인자가 없는 함수원형.
키워드 void는 전달인자를 사용하지않는다는것을 명시적으로 밝히는것이다.

■함수의 모양
 
함수정의의 모양을 다음과 같이 일반화 가능.
type functionname(argumentlist)
{
   statements
}


=====================================================================================================================
※요약
C++프로그램은 함수라고 부르는 하나또는 그이상의 모듈들로 이루어진다.
프로그램은 main()이라는 함수부터 실행이 된다. 그러므로 어떤 프로그램이든지간에 main()함수가 반드시 하나 있어야한다.
함수는 함수머리와 함수몸체로 이루어진다. 함수 머리는 그함수가(리턴값이 있는경우) 어떤 데이터형의 값을 리턴하고, 어떤 종류의 정보를 전달인자로 받는지 나타낸다. 함수몸체는 중괄호{ }로 둘러싸인 C++명령문들로 이루어진다.
C++명령문들의 유형은 다음과같다.

●선언명령문: 함수에 사용되는 변수의 이름과 데이터형을 선언한다.
●대입명령문: 대입연산자(=)를 사용하여 변수에 값을 대입한다.
●메시지명령문: 객체에 메시지를 전달하여 활동을 시작하게한다.
●함수호출: 함수를 동작시킨다. 피호출 함수가 종료되면, 프로그램은 호출 함수의 함수 호출 바로 뒤에 있는 명령문으로 복귀한다.
●함수의 원형: 함수가 기대하는 전달인자의 개수, 전달인자의 데이터형, 함수의 리턴형을 선언한다.
●return 명령문: 피호출 함수가 리턴하는 값을 호출 함수에 전달한다.

클래스는 사용자가 정의하는 데이터 형식이다. 클래스에는 정보를 어떻게 표현할것이며, 그정보를 대상으로 수행할수 있는 동작은 무엇인지가 함께 정의 된다. 데이터형을 사용하여 간단한 변수를 생성하는것과 마찬가지로, 객체는 클래스의 속성을 사용하여 실제로 생성하는 구체물이다.
 C++에서는 입력과 출력을 위해 cin과 cout이라는 두개의 미리정의된 객체를 사용한다. 이들은 각각 istream과 ostream클래스의속성
으로 생성된 객체이다. istream과 ostream 클래스는 iostream파일에 정의되어있다. 이클래스들은 입력과 출력을 연속된 문자들의 스트림이라고 간주한다. 삽입 연산자(<<)는 ostream 클래스에 정의되어있으며, 데이터를 출력 스트림에 삽입한다. 추출 연산자(>>)
는 istream 클래스에 정의되어있으며 스트림으로 부터 정보를 추출한다. cin과 cout은 잘짜여진 영리한 객체이기때문에 프로그램의 문맥에 따라 한 형식을 다른 형식으로 자동변환할수 있다.

C++는 방대한 양의 C라이브러리 함수를 사용할수 있다. 라이브러리 함수를 사용 하려면 함수 원형을 제공하는 헤더파일을 프로그램에포함시켜야한다.

'C++ > C++ PRIMER PLUS' 카테고리의 다른 글

함수 - C++의 프로그래밍 모듈  (0) 2011.11.09
분기 명령문과 논리 연산자.  (0) 2011.11.07
루프와 관계 표현식  (0) 2011.10.27
복합 데이터형  (0) 2011.10.27
데이터처리  (0) 2011.10.20

1. 객체지향의 개념
    - 어떤문제를 해결하기 위한 과정을 순차적으로 설계하는것 ▶절차적 방법론
       절차적언어: Pascal , Fortran, C, C++등..

2. 객체 클래스와 상속
    - 유사한 특징을 지닌 객체를 묶어서 그룹지은것이 객체클래스(Object Class)
    - 인스턴시에이션(Instantiation): 추상적 개념으로 부터 구체적 실례 하나를 만드는것.
    - 같은 클래스에 속한 모든 객체는 동일한 메세지에 대하여 동일하게 반응함. 즉,동일한 메소드를 사용.
    - 클래스를 바라보면 클래스간의 계층구조가 존재하는것을 알수 있음. 즉,어떤 클레스(Child Class,
       sub Class, Derived Class)는 더높은 일반적인클래스(Parent Class, Super Class, Base Class)에 
       속하고, 그 클래스는 다시 더높고 포괄적인 클래스에 속한다.
    - 객체지향 언어에서 클래스간 계층구조를 선언하는것은 상위클래스의 속성(Attribute)을
       상속(Inheritance) 받기위함.

 객체지향 설계과정  
 1단계  문제를 풀기위해 필요한 객체설정
 2단계  객체간의 유사한 속성파악
 3단계  유사한 속성을 지닌객체를 모아 기본클래스 선언
 4단계  기본 클래스로부터 특수한 속성을 지닌 하위 클래스  정의

   - 상위 클래스에서 메소드를 선언하였을때, 어떤 클래스가 그하위 클래스라고 선언하기만 하면 자동으로  
      상위메소드를 상속받게된다. 자신의 소속을 밝힘으로써, 자신이 속한 단체의 재산 을 가져오는 행위.

3. C++객체지향
   -프로그램의 단위성(Modularity)이 높음.
   -큰문제 전체를 하나로 놓고 한꺼번에 모든 세부사항을 처리하는것보다 그문제를 잘라서
     작은단위(Module)로 분할한 다음 이들을 개별, 단위별로 구현하는것이 훨씬 수훨한방법이다.
   -객체단위로 잘라놓으면 나중에 다른문제를 해결할때에도 필요한 객체만 가져다가 조합함으로써
     재사용성(Reusablity)을 높일수 있다.
  ①인터페이스 파일
    -클래스의 선언은 Public 섹션과 Private색션  두부분으로 구성.
      Public은 '공유'라는뜻으로, 내부에서 선언된 메세지를 외부사용자가 공유할수 있다는 의미이다.
      따라서, 외부사용자는 여기에서 선언된 메세지를 사용하여, 이클래스의 객체에게 일을 시킬수 있다.
    -객체지향 개념에서의 메세지를 C++에서는 맴버함수라고 부른다.
      클래스 선언은 인터페이스의 역활만 하면 충분함으로 맴버함수의 구체적인 구현 내용은 나타나지않고
      함수명(Function Prototype)만표시한다. 객체를 불러서 사용하는 외부에서는 구체적인 외부내용은 볼
      필요가 없기때문이다. 외부에서 이파일만 보고 메세지를 던져야 하는사람을 위해서 메세지가
      구체적으로 무엇을 해주는 것인지 쉬벡 알아볼수 있도록하여야함(주석처리)
    -맴버함수중 클래스명과 동일한 함수명을 사용하되 리턴타입을 선언하지않는 함수가
      "생성자(Constructor)"함수이다.
      이함수는 문자 그대로 새로운 객체를 만드는 함수로써, 객체의 선언시 자동으로 불려져온다.
      반면,객체를 없애고 그객체가 사용하던 메모리 공간을 운영체제에게 반납하기 위한 함수가
      "소멸자(Destruct)"함수이다.
     소멸자 함수는 클래스명앞에 물결(Tilde,~)표시로 구분하며, 생성자 함수와 마찬가지로 리턴타입을 
     선언하지 않음.
   -C++클래스 선언의 두번째 섹션은 Private 라는 키워드로 시작, 이부분은 사적인것으로 외부사용자와 
     공유하는 부분은 아니다.
     즉,이섹션에 선언된 변수나 함수를 읽고 쓰려고 외부에서 직접접근을 할수없다.
     이부분을 접근할수 있는 자격을 가진것은 자체클래스 맴버함수 뿐이다.
     일반적으로 Private섹션에 나타내는것은 맴버함수를 수행하는데 필요한 객체의 내부 저장공간.
     즉, 변수들로써 이를 C++에서는 맴버데이터라고 부른다. 객체자신의 변화상태를 나타내는 변수라는
     의미에서 객체지향에서는 이를 "상태변수:라고도한다.
  ②구현파일 
   -구현함수에서는 클래스명을 먼저쓰고, 콜론(:) 두개를 붙인다음. 이어서 메세지명을 써야한다
     ex) Card::card()
     이렇게 함으로써, 어느클래스에 속한 함수인지 나타낼수 있다.
     같은 이름의 메세지라 할지라도, 클래스에따라서 처리방식이 달라질수있기 때문이다.
  ③메세지전달요령
    -어떤클래스에 속한 객체를 선언하려면 클래스명다음에 객체를 선언.
     ex)Card MyCard;
     Card는 클래스 MyCard는 해당클래스에 속한 객체명.
    -C++에서 메세지전달은 메세지를 받을 객체 다음에 점을 찍고 메세지명을대면된다.
     ex) MyCard.Flip();
      필요하다면 괄호안의 파라미터를 같이넣어 전달하면됨. 객체의 맴버데이터를 지정할때에도 객체명 
      다음에 점을찍고 변수명을 지정한다.
      맴버함수 다음에는 파라미터가 없어도 빈괄호를 넣는것이 상례. 
      ※ 괄호가 없을시 그것이 맴버함수인지,맴버데이터인지  헷갈릴수가있다.
  ④상속과 다형성
   
Class triangle: Public Shape{
   Public:
       Triangle();
        ~Triangle();
       void Draw();
       float Area();
       float GetBase();
   Private:
       float Base();
       float Height();
};

    -클래스의 속성은 맴버함수와 맴버데이터 모든것을 일컷는다. 따라서, 하위클래스가 상위클래스의 속성을
      이어받는것은 맴버함수와 맴버데이터 모두를 이어받는것.
    -EX)1-1의 경우 triangle.T;라고 선언하고 T.Rotate(); 명령을 내릴수도있다. 맴버함수가 없음에도 이러한
      명령을 내릴수있는것은 상위클래스인 Class Shape에 Rotate라는 맴버함수가 정의되고 구현되어있기
      때문. 즉, 상속에 의한것임.
    -T.Rotate();라고한다면 T클래스인 triangle 클래스에 해당함수가 있는지 먼저 검색함. 만약 해당함수가
      있다면, triangle클래스에 선언된 함수가 직접실행. 그곳에 없을때에 한해서만 그 상위 클래인 Shape
      클래스로 올라가서 , 가장먼저선언된것이 사용된다. 실행시 일어난다는 의미에서 "동적연결"이라함.
    -연산자 오버로딩 ▶ 동일연산자에 두개이상의 의미를 부여하는것.

4.절차적설계와비교

   
-절차적 설계에는 어떤작업을 함수로 정의하고 이를 반복해서, 호출함으로써 재사용성을 높임.
       반면 객체 지향설계는 모든 함수를 수행할수 있는 객체를 우선시한다. 어떤객체를 설정하여 그객체가 
       할수있는 모든 기능을 한군대 모아놓는 접근방법이 재사용 면에서는 더욱유리하다.
       객체지향에서 무엇보다 중요한것은 인터페이스와 구현의분리이다.
       외부에서 객체를 사용하는 사람의 입장엣서는 인터페이스만 알면된다. 객체 내부가 구체적으로 어떻게
       구현되는지 몰라도된다. 이처럼 내부가 외부에 공개되지않도록 "외부와 벽을 쌓고있다"라는 의미에서
       이를 "인캡슐레이션"이라고한다.
   
 
Const C++/열혈강의C++ 2011. 8. 23. 17:29

'C++ > 열혈강의C++' 카테고리의 다른 글

NameSpace  (0) 2011.08.17
인라인 함수  (0) 2011.08.17
매크로 함수  (0) 2011.08.17
함수 오버로딩  (0) 2011.08.17
NameSpace C++/열혈강의C++ 2011. 8. 17. 17:28




#include<iostream>
  namespace A.COM
  {
    void function(void)
     {
       std::cout <<"A.COM에서 정의한 함수"<<std::endl;
      }
    }

   namespace B.COM
   {
     void function(void)
    {
      std::cout<<"B.COM에서 정의한 함수"<<std::endl;
     }

'C++ > 열혈강의C++' 카테고리의 다른 글

Const  (0) 2011.08.23
인라인 함수  (0) 2011.08.17
매크로 함수  (0) 2011.08.17
함수 오버로딩  (0) 2011.08.17

'C++ > 열혈강의C++' 카테고리의 다른 글

Const  (0) 2011.08.23
NameSpace  (0) 2011.08.17
매크로 함수  (0) 2011.08.17
함수 오버로딩  (0) 2011.08.17

#define Squar((x)*(x))

'C++ > 열혈강의C++' 카테고리의 다른 글

Const  (0) 2011.08.23
NameSpace  (0) 2011.08.17
인라인 함수  (0) 2011.08.17
함수 오버로딩  (0) 2011.08.17