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