1. 메소드의 정의 및 용법
: 동일한 내용의 코드가 여러차례 반복하여 쓰여질 경우, 그러한 코드를 하나의 이름으로 묶어서 관리할수 있도록 해주는 그룹이라고 정의할수 있겠다. 다음의 예제를 보자.
1//    public class Exam07_01 {
2//        public static void main(String[] args) {
3//           System.out.println("*****");
4//           System.out.println("연습삼아 쳐봤어요.");
5//           System.out.println("*****");
6//           System.out.println("*****");
7//           System.out.println("그만 할께요");
8//           System.out.println("*****");
9//        }
10//    }
위에서 3, 5, 6, 8번째 줄은 반복되는 코드들이다. 이러한 코드들이 간단한 줄일 경우에는 문제가 되지는 않으나, 만약 코드가 10줄, 100줄이 넘어갈 경우에는, 이러한 코드들을 일일이 다 쳐줄수는 없는 일이다.

그렇기 때문에 동일한 소스코드를 하나의 그룹으로 묶어서, 필요할 때마다 그 그룹을 불러오게 되는데, 그 그룹을 바로 메소드라고 할수가 있다.

메소드는 다음과 같은 형식으로 작성을 한다.
접근제한자 지정예약어 결과형리턴값 메소드명 (매개변수들) throws 예외클래스들 {
    내용정의부;
}
이렇게 풀어적어서 적어 놓으니까, 뭐라고 하는지 하나도 모르겠다. 다음과 같은 형식으로 바꿔서 설명하겠다.
1//    public static void view_star() {
2//        System.out.println('*****");
3//    }
1번째 라인에 있는 구문중 public 이라고 적혀 있다. 이것이 바로 접근 제한자라고 부르는데, 여기에는 private, protected, public, package 라는 제한자가 올수가 있다.

그다음에 오는 static 이라는 항목이 지정예약어라고 불리우는 예약어인데, 여기에는 static, final, abstract, synchronized 등이 온다.

이제 다음에 나오는 것이 void 인데, 이게 바로 결과형 리턴값이며, void 는 일반적으로 아무것도 돌려줄 값이 없는 경우에 사용되는 값인데, 메소드에서 어떠한 동작을 수핸한 후에, 되돌려줄 값이 있을 경우, 그 값의 형태를 알려주는 부분이다.

view_star 는 당연히 메소드 명이며, 지금 1번째 라인의 () 안에는 아무것도 없지만, 매개변수들이 들어가는 경우가 생길수가 있다.

그리고 마지막 throws 예외클래스들은 사용이 할때도 있고 안할때도 있으니, 그건 나중에 설명하기로 한다.

그럼 위의 첫번째 예제를 메소드를 사용하여 고쳐 보도록 하자.
1//    public class Exam07_01 {
2//        public static void view_star() {
3//            System.out.println("*****");
4//        }

5//        public static void main(String[] args) {
6//            view_star();
7//            System.out.println("연습삼아 쳐봤어요.");
8//            view_star();
9//            view_star();
10//           System.out.println("그만 할께요");
11//           view_star();
12//        }
13//    }
여기서 중요할 점은, class 밖에다가는, import, package, 또다른 class 이외에는 다른 코드를 사용할수가 없다는 점이다.

즉, 메소드가 단독적으로 class 밖에서 사용할수는 없다는 이야기이다.

2번째 라인 ~ 4번째 라인에서 사용된 메소드를 이용하여, 6, 8, 9, 11번째 라인에서, 메소드명으로 해당 메소드를 호출하여 결과값이 수정전 코드와 똑같게 출력되게 만들어 주었다.


2. 메소드의 종류
메소드의 종류에는 총 3가지가 있으나, 이 파트에서는 2가지만 다루도록 한다.
(1) call by name
: 메소드의 이름에 의해 호출되는 메소드로 특정 매개변수 없이 실행가능하다. 하지만, 다른 방식의 메소드 호출에 비해 기능이 상당히 제한적이다. 이 방식은 이미 결정된 결과를 출력하거나, 고정된 실행을 요구하는 것외에는 사용 할수가 없다.

위에 예제를 든 메소드가 이에 해당한다.

(2) call by value
: 메소드를 이름으로 호출할 때 특정 매개변수를 전달하여 그 값을 기초로 실행하는 방식인데 각 매개변수는 그 개수에 있어서 제한도 없고 자료형에도 제약이 없다. 클래스 형이 사용될수도 있다. 이 경우에는 상당히 동적이라고 말할 수가 있다.

예를 들어 보자.
1//    public class Exam07_02 {
2//        public static void view_star(int y, int x) {
3//           for(int j = 0; j < y; ++j) {
4//               for(int i = 0; i < x; ++i) {
5//                  System.out.print("*");
6//               }
7//               System.out.println();
8//           }
9//           // x = 75;
10//        }    // 행렬 형식의 출력 메소드

11//        public static void main(String[] ar) {
12//           view_star(2, 5);
13//           System.out.println("출력하자");
14//           view_star(3, 3);
15//           view_star(2, 10);
16//           System.out.println("출력된다");
17//           System.out.println("출력되었다");
18//           view_star(4, 7);
19//        }
20//    }
이렇게 매겨변수를 받아, 그 매개변수로 동적으로 실행시킬때 사용할수 있는 방식이 바로 call by value 방식이다.

여기서 생각해야 할 것 하나. 만약, 9번째 라인에 있는 주석을 제거하여 x = 75 라는 코드를 살려두었다고 하여도, 12, 14, 15, 18번째 라인에 있는 매개변수 x 에 해당되는 값들에 영향을 미치지는 않는다.

위의 메소드 영역과, 아래 main 영역은 전혀 차별화된 공간이며 서로 다른 영역이기 때문에 서로간의 값이 영향을 받지 않는다. 이렇게 원본 값이 변하지 않는 것이 call by value 이며, 훗날 배우게 될 call by reference 에서는 원본 값이 변하게 되는데, 이것은 나중에 설명하기로 한다.

(3) call by reference
: 메소드 호출시 매개변수로 사용되는 값이 특정 위치를 참조하는 reference 변수, 차후 설명


3. 결과형 리턴값
메소드를 실행한 후 결과로 되돌려 주는 값을 지칭하며, 이때는 return 예약어를 사용해야 한다.

하지만, 지금까지의 코드들은 대부분 되돌려주는 값이 없었다. 그렇기에 return 이라는 예약어가 생략 가능했었다.

이러한 것에는 여러 종류가 있는데, 이를 살펴보면...
void : 실행 후 돌려줄 결과가 없을 때
원시 타입 자료형 : 8대 자료형
클래스형 : 모든 클래스나 인터페이스 형
위의 예문을 본다면, 2번째 라인에서 void 가 사용되었는데, 이는 되돌려주는 값이 없다는 뜻이며, 이로 인해 return 이 생략이 되었던 것이다. 하지만, 9번째 라인의 주석을 치우고, return; 라는 구문을 추가할수도 있으며, return 이후에 나오는 값을, 되돌려 준다.
public class Exam07_03 {
    public static boolean aaa() {
       return false;
    }

    public static int bbb() {
       return 34;
    }

    public static int ccc(int x, int y) {
       int z = x + y;
       return z;
    }

    public static void main(String[] ar) {
       boolean a = aaa();
       System.out.println("a = " + a);
       int b = bbb();
       System.out.println("b = " + b);
       inc c = ccc(10, 20);
       System.out.println("c = " + c);
    }
}

여기에서는 3가지의 메소드가 사용되어졌다. 첫번째 메소드 aaa() 는 논리형인 boolean 값을 되돌려 주었고, 두번째 메소드 bbb() 에서는 정수형인 int 값을 되돌려 주었다. 세번째 메소드 ccc() 에서는 매개변수 int x, int y 를 받아서, 덧셈을 한후, 그 결과값을 되돌려 주는 기능을 수행한다.

이렇게, 메소드 안에서 어떠한 기능을 수행한후 되돌려 주고픈 값이 있을때, 그때 사용되는게 바로 이 return 이라는 예약어이다.


p.s 위의 글들은, 김승현 강사님열혈강의 Java Programming 의 Round 7-1, 2, 3, 동영상 강좌에 기초한 내용입니다.
:
1. 두개의 수와 배수 n을 입력받아 두 수 사이의 n 배수의 합을 구하는 프로그램을 작성해보자.
1//    import java.io.*;

2//    public class SumTwoMulti {
3//        public static void main(String[] args) throws IOException {
4//           BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

5//           int first = 0, second = 0, mul = 0, sum = 0, temp = 0;

6//           System.out.print("Input the Frist Number : ");
7//           first = Integer.parseInt(in.readLine());

8//           Ststem.out.print("Input the Second Number : ");
9//           second = Integer.parseInt(in.readLine());

10//           System.out.print("Input the Multiple : ");
11//           mul = Integer.parseInt(in.readLIne());

12//           if(first >= second) {
13//              temp = second;
14//              second = first;
15//              first = temp;
16//           }

17//           for(int i = 1; mul * i <= second; ++i) {
18//              if(mul * i < first) continue;

19//              sum += mul * i;
20//           }

21//            // for(int i = first; i <= second; ++i) {
22//            //    if(i % mul == 0) {
23//            //         sum += i;
24//            //    }
25//            // }

26//           System.out.println();
27//           System.out.println("The Sum of Multiple from " + first + " to " + second + " is " + sum);
28//        }
29//    }
첫 번째로 할일은 규칙을 찾는 일일 것이다. 얼마전 해봤던 두수의 크기 비교를 약간 응용한 문제였기 때문에, 그 부분까지는 문제가 되지 않았으나(16번째 라인까지), 문제는, 어떻게 하면 입력받은 두수안에서, 입력한 배수를 구하고, 그것의 합을 구하느냐였다.

오랜만에 수학적인 문제를 생각하려니, 머리가 회전되지 않는게 가장 큰 문제였으나, 가장 무식하게, 연습장에다가 써보면서 문제를 차근차근 풀어가기로 마음먹었다.

예를 들어, 10부터 20까지의 수중, 4의 배수를 구하는 문제를 대입해 보았다.

4의 배수를 처음부터, second 에 입력될 20까지 차례 대로 나열하면 다음과 같다.
4 * 1 = 4
4 * 2 = 8
4 * 3 = 12
4 * 4 = 16
4 * 5 = 20
4 * 6 = 24
이에 관한 for 문이 바로 17번째 라인에 있는 for문이다.

이제 문제는 여기서, 어떻게 하면, 범위내의 배수를 빼내느냐, 즉, 10부터 20이라는 숫자 사이의 있는 4의 배수를 어떻게 빼내오느냐의 문제가 발생한다.
4 * 1 = 4 (X)
4 * 2 = 8 (X)
4 * 3 = 12 (O)
4 * 4 = 16 (O)
4 * 5 = 20 (O)
4 * 6 = 24 (X)
20 이후의 문제는, 17번째 라인의 for 문에서 20이 될때까지 반복 실행하라고 하였으니, 20 이후의 문제는 없지만, 10 이전의 문제는, 어떻게 하면 풀수 있을까?

그때 생각난 것이 continue 예약어였다. 만약 4의 배수가 10보다 작으면, 아무 수행도 하지 않고, 다음 반복할 작업으로 바로 넘어가도록 만드는 것인데, 거기에 continue 가 가장 제격이었다.

그렇게, 하고, 마지막에는, 배수들의 합을 sum 에 저장하는 것으로 마무리 했다.

이렇게 다 풀고 나서, 풀이를 보니....

이...이렇게 간단하게 풀줄이야..... -0- 여전히... 돌머리임에는.. 틀림없다....


2. 문자 하나를 입력받아 대문자인지 소문자인지 구별하는 프로그램을 작성.
import java.io.*;

public class Capital {
    public static void main(String[] args) throws IOException {
       char ch;

       System.out.print("Input the One Character : ");
       ch = (char)System.in.read();

       if(ch >= 'a' && ch <= 'z') {
          System.out.println(ch + " is a small letter.");
       } else if(ch >= 'A' && ch <= 'Z') {
          System.out.println(ch + " is a capital letter.");
       } else
          System.out.println(ch + " is not the Alphabet.");
    }
}
이 문제는 굳이 설명할 필요가 있을까... 그래서 패스..


3. 연도를 입력받아 윤년인지 아닌지를 구별하는 프로그램.(윤년은 일반적으로 4년에 한번씩 돌아오는데, 그중 100으로 나누어 떨어지는 해는 윤년이 아니다. 그러나 100으로 나누어 떨어지는 해 중에서도 400으로 나누어 떨어지는 해는 윤년이다.)
1//    import java.io.*;

2//    public class LeapYear {
3//        public static void main(String[] args) throws IOException {
4//           BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
      
5//           int ly = 0;

6//           System.out.print("Input the year : ");
7//           ly = Integer.parseInt(in.readLine());

8//           if(ly % 4 == 0) {
9//              if(ly % 100 == 0) {
10//                 if(ly % 400 == 0) {
11//                    System.out.println(ly + " is a leap year.");
12//                 } else {
13//                    System.out.println(ly + " is not a leap year.");
14//                 }
15//              } else {
16//                 System.out.println(ly + " is a leap year.");
17//              }
18//           } else {
19//              System.out.println(ly + " is not a leap year.");
20//           }
21//        }
22//    }
if ~ else 문이라는 구문에 대해서 약간 헷걸렸던 문제다. 가끔가다, 수박을 보고, 수박이라는 단어가 문득 생소하다는 것을 느끼듯, 이 문제도 if ~ else 문에서, 잠시 사용법에서 약간의 혼돈이 와서.... 역시, 프로그래밍은 자주 사용해야 한다니까.... -0-

총 3단계의 검색을 거친다고 볼수가 있는데, 처음, 입력한 년도가 4로 나누어지는지를 검사한다. 만약, 나누어 지지 않는다면, 19번째 라인이 실행되어, 윤년이 아니라는 메세지가 출력된다.

4로 나누어지는 지를 통과하면, 100으로 나누어지는 지를 확인한다. 만약, 나누어지지 않는다면, 16번째 라인이 실행, 윤년이라는 메시지가 출력된다.

100으로 나누어지면, 400으로 나누어지는 지를 마지막으로 검사한다. 만약, 400으로 나누어지면 윤년이라는 메시지를, 아니라면 윤년이 아니라는 메시지를 출력하게 되어있다.

문제는 예상외로 쉬우나, 나같이 돌머리를 소유한 자라면, 예상외로 힘들게 풀지도... 아무튼, if ~ else 문에 대해서 착각하지 않는다면, 쉽게 풀릴 문제.


4. 주민등록번호 8번째 자리를 입력받아 출생지를 알아보는 프로그램을 작성.(인터넷 검색을 이용하여 각 숫자가 나타내는 지역을 알아보자. 예를 들면 123456-7891234에서 8이라는 숫자가 적혀있는 자리는 출생지를 나타낸다. 그 숫자가 0이면 '서울' 이런 식인데 인터넷에서 검색하여 알아보자.)
import java.io.*;

public class ID8 {
    public static void main(String[] args) {
       int id8 = 0;

       System.out.print("Input the 8th number of your ID : ");
       id8 = System.in.read() - 48;

       switch(id8) {
             case 0 : System.out.println("You were born in Seoul."); break;
             case 1 : System.out.println("You were born in Kyoung Gi, In Cheon."); break;
             case 2 : System.out.println("You were born in Kang Won."); break;
             case 3 : System.out.println("You were born in Chung Book."); break;
             case 4 : System.out.println("You were born in Cung Nam, Dae Jeon."); break;
             case 5 : System.out.println("You were born in Jeon Book."); break;
             case 6 : System.out.println("You were born in Jeon Nam, Gwang Ju."); break;
             case 7 : System.out.println("You were born in Kyoung Book, Dae Gu."); break;
             case 8 : System.out.println("You were born in Kyoung Nam, Pusan."); break;
             case 9 : System.out.println("You were born in Jeju."); break;

             default : System.out.println("Who are you...???");
       }
    }
}
설명...필요한가????


5. 구구단을 출력하는 프로그램을 작성해 보자.
import java.io.*;

public class Gugu {
    public static void main(String[] args) throws IOException {
       int gugu = 0;
      
       System.out.print("Input the Multiplication number : ");
       gugu = System.in.read() - 48;

       System.out.println();
       System.out.println("========= " + gugu + " =========");

       for(int i = 1; i <= 9; ++i) {
          System.out.println(gugu + " * " + i + " = " + (gugu * i);
       }
    }
}
이것역시..설명이 필요한가???


6. 앞서 배운 계산기 프로그램을 만들어서 한번 계산을 한 후 다시 게산을 할 것인지 물어 보고 수행을 계속할 것인지를 결정하는 프로그램을 만들어 보자.
import java.io.*;

public class Calc {
    public static void main(String[] args) throws IOException {
       BufferedReader in = new BufferdReader(new InputStreamReader(System.in));

       int x = 0, y = 0;
       char op = 0, yn = 0;

       while(true) {
    // 첫번째 숫자를 입력 받아서 변수 x에 저장
             System.out.print("Input the First Number : ");
             x = Integer.parseInt(in.readLIne());

    // 연산자를 입력하는 부분. 출력된 +, -, *, /, % 외에 문자를 입력하면, 다시 입력할수 있도록
    // 반복실행 시켜준다.

             do{
                 System.out.print("Pick the Operators(+, -, *, /, %) : ");
                 op = (char)System.in.read();
                 System.in.read();
                 System.in.read();
             } while(op != '+' && op != '-' && op != '*' && op != '/' && op != '%');

    // 두번째 숫자를 입력받아 변수 y에 저장
             System.out.print("Input the Second Number : ");
             y = Integer.parseInt(in.readLine());

    // 입력받은 연산자에 따라, 해당 위치로, 이동, 출력.
             switch(op) {
                case '+' : System.out.println(x + " " + op + " " + y + " = " + (x+y)); break;
                case '-' : System.out.println(x + " " + op + " " + y + " = " + (x-y)); break;
                case '*' : System.out.println(x + " " + op + " " + y + " = " + (x*y)); break;
                case '/' : System.out.println(x + " " + op + " " + y + " = " + (x/y)); break;
                case '%' : System.out.println(x + " " + op + " " + y + " = " + (x%y)); break;
             }

    // 다시 한번 계산을 할것인지를 물음.
             System.out.print("One more? ");
             yn = (char)System.in.read();
             System.in.read();
             System.in.read();

    // 위의 질문에서 n이나 N 을 입력시 while 문을 탈출.
             if(yn == 'N' || yn == 'n') break;
       }
    }
}
설명은 주석문으로 대체.


7. 연도와 월을 입력받아 달력을 출력하는 프로그램을 작성(윤년도 확인해야 하고 요일도 나타나야 한다.) 참고 : 배열 없이 프로그램 작성
import java.io.*;

class Cal {
    public static void main(String[] args) throws IOException {
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
       
        // yr : 입력 받을 년도를 저장, mth = 입력 받을 월을 저장,
        // mth_day = 입력 받은 월에 해당하는 일수를 저장, day : 출력하게 될 날짜들을 저장,
        // date : 입력받은 월의 전월까지의 총 일수를 저장
        // ch_mon : 입력 받은 월에 해당되는 영어를 저장,   
        // blank : 달력 출력시, 시작되는 날짜와 요일에 따른 선행 빈 공간 출력

        int yr = 0, mth = 0, mth_day = 0, day = 0, date = 0;
        String ch_mon = "";
        String blank1 = "", blank2 = "\t", blank3 = "\t\t", blank4 = "\t\t\t", blank5 = "\t\t\t\t", blank6 = "\t\t\t\t\t", blank7 = "\t\t\t\t\t\t";

        // 년도 입력, 저장
        System.out.print("Input the year by 4 units(EX : 2004) => ");
        yr = Integer.parseInt(in.readLine());

        // 월을 입력, 저장
        // 입력받은 월에 해당되는 영어를 변수에 저장하며,
        // 입력받은 월에 해당되는 일수를 저장한다.
        // 또한 전월까지의 총 일수를 저장하며,
        // 이 모든 과정을 평년과 윤년에 따라 수행되도록 한다.
        do
        {
            System.out.print("Input the month(EX : 6) =? ");
            mth = Integer.parseInt(in.readLine());

            switch(mth) {
                case 1 : ch_mon = "January"; mth_day = 31; break;
                case 2 : ch_mon = "February";
                    if(yr % 4 == 0 && yr % 100 != 0 || yr % 400 == 0) {
                        mth_day = 29;            // 윤년
                    } else {
                        mth_day = 28;            // 평년
                    }
                    date = 31; break;           
                    // 전월까지의 일수를 합해서 저장. 1월까지의 일수를 저장
                case 3 : ch_mon = "March"; mth_day = 31;
                    if(yr % 4 == 0 && yr % 100 != 0 || yr % 400 == 0) {
                        date = 31 + 29; break;   
                // 윤년시, 전월까지의 일수를 합해서 저장, 1월과 2월까지의 일수를 합산, 저장.
                    } else {
                        date = 31 + 28; break;   
                // 평년시, 전월까지의 일수를 합해서 저장, 1월과 2월까지의 일수를 합산, 저장.
                    }
                case 4 : ch_mon = "April"; mth_day = 30;
                    if(yr % 4 == 0 && yr % 100 != 0 || yr % 400 == 0) {
                        date = 31 + 29 + 31; break;
                    } else {
                        date = 31 + 28 + 31; break;
                    }
                case 5 : ch_mon = "May"; mth_day = 31;
                    if(yr % 4 == 0 && yr % 100 != 0 || yr % 400 == 0) {
                        date = 31 + 29 + 31 + 30; break;
                    } else {
                        date = 31 + 28 + 31 + 30; break;
                    }
                case 6 : ch_mon = "June"; mth_day = 30;
                    if(yr % 4 == 0 && yr % 100 != 0 || yr % 400 == 0) {
                        date = 31 + 29 + 31 + 30 + 31; break;
                    } else {
                        date = 31 + 28 + 31 + 30 + 31; break;
                    }
                case 7 : ch_mon = "July"; mth_day = 31;
                    if(yr % 4 == 0 && yr % 100 != 0 || yr % 400 == 0) {
                        date = 31 + 29 + 31 + 30 + 31 + 30; break;
                    } else {
                        date = 31 + 28 + 31 + 30 + 31 + 30; break;
                    }
                case 8 : ch_mon = "August"; mth_day = 31;
                    if(yr % 4 == 0 && yr % 100 != 0 || yr % 400 == 0) {
                        date = 31 + 29 + 31 + 30 + 31 + 30 + 31; break;
                    } else {
                        date = 31 + 28 + 31 + 30 + 31 + 30 + 31; break;
                    }
                case 9 : ch_mon = "September"; mth_day = 30;
                    if(yr % 4 == 0 && yr % 100 != 0 || yr % 400 == 0) {
                        date = 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31; break;
                    } else {
                        date = 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31; break;
                    }
                case 10 : ch_mon = "October"; mth_day = 31;
                    if(yr % 4 == 0 && yr % 100 != 0 || yr % 400 == 0) {
                        date = 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30; break;
                    } else {
                        date = 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30; break;
                    }
                case 11 : ch_mon = "November"; mth_day = 30;
                    if(yr % 4 == 0 && yr % 100 != 0 || yr % 400 == 0) {
                        date = 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31; break;
                    } else {
                        date = 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31; break;
                    }
                case 12 : ch_mon = "December"; mth_day = 31;
                    if(yr % 4 == 0 && yr % 100 != 0 || yr % 400 == 0) {
                        date = 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30; break;
                    } else {
                        date = 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30; break;
                    }

                default : System.out.println("Please Input Again.");
            }


        }while (mth != 1 && mth != 2 && mth != 3 && mth != 4 && mth != 5 && mth != 6 && mth != 7 && mth != 8 && mth != 9 && mth != 10 && mth != 11 && mth != 12);

        System.out.println(" ============== " + "<< " + yr + ", " + ch_mon + " >>" + " ============== ");
        System.out.println();
        System.out.println(" Sun\tMon\tTue\tWed\tThu\tFri\tSat ");

// 출력시, 시작일수와 요일에 따른 빈 공간을 출력하기 위한 부분, 하지만 이해안되는 식
// yr-1은 무얼까??

        int extra = ((yr-1) + (yr-1)/4 - (yr-1)/100 + (yr-1)/400 + date + 1 ) % 7;

        switch(extra) {
            case 0 : System.out.print(blank1); break;
            case 1 : System.out.print(blank2); break;
            case 2 : System.out.print(blank3); break;
            case 3 : System.out.print(blank4); break;
            case 4 : System.out.print(blank5); break;
            case 5 : System.out.print(blank6); break;
            case 6 : System.out.print(blank7); break;
        }

        for(int i = 1; i <= mth_day; i++) {
            day = i;

//    이해안되는 식
//    (yr-1)/4 - (yr-1)/100 + (yr-1)/400 : 윤년횟수
//    date : 전월까지의 일수를 총 합산한 일수
//    day : 해당 날짜, 1일, 2일, 3일, ....
//    yr-1 은 무얼까... -0-

            int total = ((yr-1) + (yr-1)/4 - (yr-1)/100 + (yr-1)/400 + date + day ) % 7;

//    6보다 작으면 그대로 출력, 그렇지 않으면, 한줄 내려 출력
            if(total % 7 < 6) {
// 10보다 작으면, 한자릿수라는 이야기 이므로, 한자릿수 앞에 0을 붙여 출력, 그렇지 않으면,
// 두자릿수라는 이야기로 0을 제외한 채 출력
                if(day < 10) {
                    System.out.print(" 0" + day + "\t");
                } else {
                    System.out.print(" " + day + "\t");
                }
            } else {
                if(day < 10) {
                    System.out.println(" 0" + day + "\t");
                } else {
                    System.out.println(" " + day + "\t");
                }
            }
        }
    }
}
솔직히 풀다가 막힌 부분이 생겨, 다른 소스를 보고 약간의 편집을 통해 완성시킨 소스.

그래서 이해가 안가는 부분이 몇가지가 있었는데, total 이라는 변수와, 달력을 출력시 틀에 맞춰 출력시키기 위한 코딩부분에서 이해가 안가는 부분이 몇가지 있었다.

특히 위의 yr-1 부분은 여전히 이해가 안가는 부분이다.

이 문제는 일단, 여기서 종료.
:
1. for문에서
: 두개의 for문을 사용시, 바깥쪽 for문은 몇번 실행될지를 나타내고, 안쪽 for문은 실제로 출력되는 부분을 나타내주는 부분이다.

2. while문에서
: for 문이 수치에 의한 제어이고, while 문이 행위에 의한 제어라고 말한 것에 대한 의미는, 이 의미는, 무언가를 입력받거나, 혹은, 무언가의 행위가 있을 경우(화면보호기를 예로 들어서), 이러한 행위에 대해서 제어가 되는 경우를 뜻하며, 그렇다고 해서 while 문이 수치에 의한 제어를 할수 없지는 않다. 제어를 할수 있지만 수치에 의한 제어는 for문이 좀더 효율적이기에 while 문을 사용하지는 않는다.

주로 무한 반복 실행에 사용되며, 벗어나기 위해 break 예약어와 if문을 함께 사용한다.

출처 : "열혈강의 JAVA Programming / 김승현 저"
:
3. while문
while 문 역시, 반복문의 일종으로 일정한 행위를 반복시키기 위한 구문 이다. 말로는 행위에 의해서 제어한다라고 하지만, 그렇게 말해봤자, 더 헷갈리고.. 아무튼... 예제를 살펴보자.
1//    import java.io.*;

2//    class Exam06_08 [
3//        public static void main(String[] args) {

4//           while(true) {
5//              System.out.print("Input a Character : ");
6//              char ch = (char)System.in.read();
7//              System.in.read();                        // Enter 키부분중 \r 부분 해제
8//              System.in.read();                        // Enter 키부분중 \n 부분 해제
9//              System.out.println(ch + " = " + (int)ch);

10//              System.out.print("One More?(Y/N)");

11//              char c = (char)System.in.read();
12//              System.in.read();
13//              System.in.read();

14//              if(c == 'N' || c == 'n') break;      // if 문을 제외한 가장 가까운 블록 탈출
15//           }
16//        }
17//    }
while 문은 처음 논리조건문을 확인을 한다. 그 논리 조건문이 true 라면, while 안에 있는 구문을 실행을 시키게 되는데, 만약, 구문이 false 라면, while 구문을 탈출하게 된다.

여기서 등장한 예제는, if 문을 함께 사용하고, 논리 조건문에 true 를 집어넣어, 반 무한루프를 돌리게 만든 프로그램이다.

4번째 라인에서, while 문의 논리조건문으로 true 가 직접적으로 사용되었으나, 이 외에도 다른 논리 조건문이 올수 있다. 논리 조건문이 true 니까, 일단 한번은 반드시 실행이 되어야 한다.

5 번째 라인에서 입력받은 값을, 6번째 라인에서 변수 ch에 char형으로 저장을 하고, 7번째와 8번째 라인에서는 5번째 라인에서 입력받았던 enter 키 값을 없애주는 작업을 해준후, 9번째 라인에서, 변수 ch와 ch를 int 형으로 변환시켜준 값을 출력한다.

10번째 라인에서는, 또다시 실행시킬것인가를 묻는데, 11번째 라인에서 변수 c에 char 형으로 저장된, 10번째 라인에서 입력한 문자는, 14번째 라인에서, N 이나 n 을 입력했는지를 판별해주는데, 만약 입력을 했다면, break; 문에 의해 if 문을 제외한 가장 가까운 블록인 while 문을 탈출하게 된다.

12번째 라인과 13번째 라인은, 7번째 라인과 8번째 라인이 해주었던 역할을 똑같이 해주는 역할을 해주고 있다.

이렇듯, 한번 실행후, 계속 실행을 원할경우, 이렇게 if문과 혼용되어 사용하기도 한다.

while 문에서는 변형된 형태가 하나 있는데, 그것이 바로 do~while 문이다. do~while 문은 번역을 해봐도 알수 있듯이, 일단은, 까고 보는 것이다. 즉, 일단 한번 실행해주고, 그다음, 반복할 것인지 마는 것인지를 결정한다고 할수 있다.

보통 while 문은 조건이 true 이면, 실행이 되면서 false 가 될때까지 반복이 되는데 반해, do~while 문은, 일단 무조건 적으로 한번은 실행시키고, 그다음, 반복실행시킬 것인지를 판단한다.

다음은, 그 예제이다.
1//    import java.io.*;

2//    class Exam06_09 {
3//        public static void main(String[] args) {
4//           BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

5//              int kor = 0, eng = 0, math = 0, sum = 0;
6//              float avg = 0.0f;

7//              do{
8//                  System.out.print("Korean Score : ");
9//                  kor = Integer.parseInt(in.readLine());
10//             } while(kor < 0 || kor > 100);

11//            do {
12//               System.out.print("English Score : ");
13//               eng = Integer.parseInt(in.readLine());
14//             } while(eng < 0 || eng > 100);

15//            do {
16//               System.out.print("Math Score : ");
17//               math = Integer.parseInt(in.readLine());
18//             } while(math < 0 || math > 100);

19//            sum = kor + eng + math;
20//            avg = sum / 3.0f;                  // 혹은 casting 변환

21//            System.out.println();
22//            System.out.println("Total Score : " + sum + "Point");
23//            System.out.println("Average Score : " + avg + "Point");
24//            // System.out.printf("Average Score : " + avg + "Point");
25//        }
26//    }
지금까지 사용된 제어문을 살펴보면, 조건식을 넣으면 그만이었지만, 이번 do~while 문에서는 while 이 끝난후, ; 으로서 마무리를 짓고 있다. 그러한 모습을 보여주는 게 10, 14, 18번째 라인이다. do~while 의 마지막 문장은 ; 으로서 끝나고 있다.

do~while 문은 처음 한번은 무조건 실행을 하게 된다. 그렇게 실행된 문장은, 마지막 while 에서 조건을 한번 검색한후, 만약, 그 조건이 true 이면, 다시 do 부분으로 이동시켜, 계속 실행시키고, 그렇지 않으면, do~while 문을 탈출하는 루틴을 보여주고 있다.

20번째 라인에서는, 형 변환을 보여주고 있다. 변수 avg 는 float 형으로 선언이 되었으며, 변수 sum 은, 다른 int 형 변수, kor, eng, math 의 값의 합을 저장하기위해, int 형으로 선언이 되었었다. 만약, 20번째 라인에서, int 형 sum 과, 3 이라는 정수형으로 계산을 시도하면, 정수 / 정수 가 되어, 몫만 출력되고, 소수점 이하는 생략이 되버린다.

그렇기에, 3 대신에 3.0f 라는 float 형으로 사용해주어서, 실수영역으로 변환을 시켜주었다. 이러한 상황은 다음과 같은 식으로 바꿔써줄수가 있다.
avg = (float) sum / 3;
바로 casting 변환이다. 결과값은, 똑같다.

24번째 라인에서 사용된 방식은, 자바 1.5 에서부터 지원이 되는 내용으로, C언어를 사용하던 프로그래머들을 배려하여, 지원하게 된, 메소드이다. printf 문 형식으로, 사용방법은, c언어와 비슷하다.

다음은 간단한 사칙연산이 가능한 계산기 소스코드이다.
1//    import java.io.*;

2//    class Exam06_11 {
3//        public static void main(String[] args) {
4//           BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

5//              int su1 = 0, su2 = 0, sum = 0;
6//              char yon = 0;

7//              System.out.print("Input the first number : ");
8//              su1 = Integer.parseInt(in.readLine());

9//              do {
10//                  System.out.print("Input the operator(+, -, *, /) :" );
11//                  yon = (char) System.in.read();
12//                  System.in.read();
13//                  System.in.read();
14//              } while(yon != '+' && yon != '-' && yon != '*' && yon != '/');

15//             do {
16//                  System.out.print("Input the second number : ");
17//                  su2 = Integer.parseInt(in.readLine());
18//              } while(yon == '/' && su2 == 0)

19//             switch(yon) {
20//                  case '+' : sum = su1 + su2; break;
21//                  case '-' : sum = su1 - su2; break;
22//                  case '*' : sum = su1 * su2; break;
23//                  case '/' : sum = su1 / su2; break;
24//              }

25//               System.out.println();
26//               System.out.println(su1 + " " + yon + " " + su2 + " = " + sum);
27//        }
28//    }
만약, 위의 do~while 문에서 while 문 뒤에 있는 조건식을 적지 않는다면, 에러가 발생할 것이고, false 를 적어놓는다면, 에러대신, 몇가지 논리적 오류가 발생하게 된다.

연산자 부분에, 사칙 연산자를 제외한 다른 문자를 집어넣어도, 계산은 실행된다. 다만, 제대로 된 계산은 실행되지 않는다.

두 번째는, 나눗셈에서, 0을 집어넣으면 에러가 발생하게 되는데, 이는 su1과 su2 과 정수형인 int 형으로 선언되었고, 정수형 / 정수형 에서 0으로 나누는 행위는 일어날 수가 없기 때문에, 에러가 발생하게 되는 것이다. 그래서, 위의 방식대로 조건식으로 첨가시켜주어, 사칙연산을 제외한 다른 값을 넣으면, 다시 값을 넣으라는 문장이 출력되며, 나눗셈을 입력한 상태에서 0이 입력되면, 역시 다시 값을 넣으라는 문장이 출력되게 된다.

다음 이야기할 부분은 26번째 라인이다.

여 기서는 " " 부분이 고의적으로 삽입되었다. 물론, 빈칸을 주기위한 기본적인 의도가 있으나, 만약 "" 를 사용하지 않게 된다면 char 형으로 선언된 변수 yon 도 아스키 코드 값으로 인식, 계산이 가능해져 변수 su1 과 변수 su2와 값이 더해지게 된다. 그것을 방지하고자 " " 부분이 고의적으로 삽입된 것이다.


p.s 위의 글들은, 김승현 강사님열혈강의 Java Programming 의 Round 6-5, 6, 동영상 강좌에 기초한 내용입니다.
:
3. for문
for은 반복문이라고 하여, 일정한 행위를 반복시키기 위한 구문이다. 이러한 반복은 수치에 의해 제어가 되는데, 이러한 방식은 다음과 같다
for(초기화영역;논리조건식영역;증감식영역){
반복실행될 구문 영역;
}
이러한 for 문의 사용법은 다음과 같이 여러방식으로 사용이 가능하다.
class Exam06_04 [
    public static void main(String[] args) {

       for(int i = 100; i <= 1000; i += 100) {          // ①
          ....
       }

       int i = 0;                                              // ②
       for(i = 100; i <= 1000; i += 100) {
          ....
       }

       int i = 100;                                           // ③
       for(; i <= 1000; i += 100) {
          ...
       }

       for(int i = 100, j = 200; i <= 1000; i += 100) {       // ④
          ...
       }

       for(int i = 100; ; i += 100) {                   // ⑤
          ...
       }

       for(int i = 100; true; i += 100) {             // ⑥
          ...
       }

       for(;;) {                                        // ⑦
          ...
       }
    }
}
① 번 방식
: 아주 기본적인 방식이다. 초기화를 100으로 잡아주고, 100이 100씩 커지면서 1000이 될때까지 반복하는 구문으로, for 문안에 ;로 구분한 3 영역이 모두 존재하는 방식

② 번 방식
: 역시, 기본적인 방식으로, 저레벨 렙업한 경우(-.-) 이다. 변수선언을 밖에서 해주었지만, for문 안에서 초기화 값을 잡아주며, ①번 방식과 동일해졌다.

③ 번 방식
: 초기화를 for문 밖에서 잡아주는 방식으로, for문 안에서 초기화를 잡아주는 영역을 공란으로 표시했다. 이때 주의할 점은, 공란 이후에 ; 를 꼭 집어넣어줘야 한다는 점. 그리고, 밖에서 변수 선언 및 초기화를 해주었기 때문에, 이는 for문에만 국한 된 것이 아닌 프로그램 전체에 국한이 되어 사용되어 진다는 점이다.

④ 번 방식
: 초기화 부분에, 두가지 변수를 동시에 초기화 시켜줄수 있다. 단, 초기화 시킬 자료형은 동일해야 하며, 여기서는 int 형으로 동일시해주었다.

⑤ 번 방식
: for문의 가운데 해당되는 부분은 논리 조건식 영역으로, 이 부분이 항상 참이면, for문은 항상 실행을 하게 될 것이다. 이를 우리는 무한 루프라고 부르는데, 가운데 논리 조건식 영역을 비워버리면, 이 for문은 항상 true 라는 값을 가지게 되고, 이는 이 for 문을 무한루프로 만들어 버리는 결정적인 역할을 부여해준다.

⑥ 번 방식
: ⑤번 방식과 마찬가지인데, 여기서는, 가운데, 논리 조건식 영역에, true 라는 값을, 아예 박아 놓아, 이 for 문을 무한 루프 시켜버리고 있다.

⑦ 번 방식
: 이 방식은, 아무것도 설정을 해놓지 않는 방법으로, 이 역시 무한 루프를 돌리는 또 다른 방법이다. 아무것도 설정을 해놓지는 않았지만, ;; 는 꼭 써놓아야 한다.

다음은 for 문에서 사용되는 break; 와 continue; 의 예시이다.

1//    class Exam06_05 {
2//        public static void main(String[] args) {
3//           for(int i = 1; i < 5; ++i) {
4//              if(i == 2) {
5//                 break;
6//                 // continue;
7//              }
8//                   System.out.println("*");
9//           }
10//        }
11//    }

5번째 라인
: break; 는 switch 문에서도 잠깐 살펴봤지만, if문을 제외한 가장 가까운 블록을 탈출시키라는 의미를 가지고 있다고 했었다. 즉, 여기서는, i값이 1일때 *를 한번 찍고, 2로 올라가면서 for문을 빠져나가도록 하는 역할을 해주고 있는게 여기서 break; 가 하고 있는 역할이다.

6번째 라인
: continue; 는 if 문을 제외한 가장 가까운 블록 끝으로 이동시키라는 의미를 가지고 있다. 여기서는, i 값이 1일때 *를 한번 찍어주고, 2일때는, if 문을 제외한 for문의 끝 블록 } 으로 이동, 8번째 라인의 *표를 찍는 구문을 실행시키지 않고, 3일때와 4일때, 다시 *표를 찍어주라는 이야기가 된다. 총 3개의 *가 찍히게 된다.

switch 를 제외한 다른 제어문과 마찬가지로, 이 for 문도 여러번 사용될수가 있으며, 이를 다중 for 문이라고 한다.
다음은 다중 for문의 예제이다.
1//    class Exam06_06 {
2//        public static void main(String[] args) {
3//           for(char a ='A'; a <= 'Z'; ++a) {
4//              System.out.print(a + " : ");
      
5//              for(char b = 'A'; b < a; ++b) {
6//                 System.out.print(" ");
7//              }
         
8//              for(char c = a; c <= 'Z' - (a - 65); ++c) {             // ①
9//              // for(char c = a; c <= 'Z'; ++c) {                       // ②
10//              // for(char c = 'A'; c <= 'Z' - (a - 65); ++c) {      // ③
11//              // for(char c = 'A'; c <= 'Z'; ++c) {                    // ④
12//                 System.out.print(c);
13//              }
14//                 System.out.println();
15//           }
16//        }
17//    }
위의 예제는 다중 for문을 사용함으로써 나타낼수 있는 여러가지 형태를 보여주고 있다. 이러한 다중 for문은, 행렬에 빗대어 생각할수가 있는데, 첫번쨰 for 문이 사용된 3번째라인은, 행에 해당되는 부분이며, 그 안에 사용된 for문들을 열에 해당된다고 할수가 있다.

8번째 라인 ~ 11번째 라인
: 여기는 가능한 여러 형태의 for문으로 보여주고 있다. 8번째 라인 대신, 9번째 라인이, 혹은 10번째 라인이, 혹은 11번째 라인의 for문을 작성할수가 있는데, 먼저, 8번째 라인의 for문을 사용하면 어떻게 되는지 보면 다음과 같다.
사용자 삽입 이미지

9번째 라인의 for 문을 보자.

사용자 삽입 이미지

10번째 라인의 for문은 이렇다.

사용자 삽입 이미지

11번째의 for문은 이렇다.

사용자 삽입 이미지

8번째 라인의 for문을 사용해서 모래시계 형태로 알파벳을 출력시키는게 가능하다.
1//    class SandClock {
2//        public static void main(String[] args)    {
3//           for(char a = 'A'; a <= 'M'; ++a) {
4//              System.out.print(a + " : ");
      
5//              for(char b = 'A'; b < a; ++b) {
6//                 System.out.print(" ");
7//              }
      
8//              for(char c = a; c <= 'Z' - (a - 65); ++c) {
9//                 System.out.print(c);
10//              }

11//              System.out.println();
12//           }

13//           for(char d = 'N'; a <= 'Z'; ++d) {
14//              System.out.print(d + " : ");

15//              for(char e = 'N'; e > d; --e) {
16//                 System.out.print(" ");
17//              }

18//              for(char f = d; f >= 'Z' - (d-65); --f) {
19//                 System.out.print(f);
20//              }

21//              System.out.println();
22//           }
23//        }
24//    }
3번째 라인 ~ 12번째 라인
: 이 부분은, 역 삼각형 모양이 된다. 만약 첫번째 for 문이 없다면, 각 출력문장마다 붙는 A :, B : 이런 부분을 없앨수 있지만, 걍, 놔두었다.

첫번째 for 문에서, 반복을 'M' 이 될때까지만 실행되도록 설정을 해놓았고, 이 지점은, 역삼각형이 완료되는 바로 그 지점이 된다.

13번째 라인 ~ 21번째 라인
: 이 부분은, 역 삼각형 모양이 끝나는 지점부터, 정 삼각형 모양을 출력하는 소스코드이다. 반복을 M에서 끝나게 했으니, N부분에서부터 반복을 다시 시작하게 해주었으며, 역삼각형으로 출력할때는, 역삼각형에서 시작부분부터, 끝부분까지, 양쪽으로 감소시키며 들어갔으나, 이 부분에서는, 정삼각형으로 출력하면서, 정삼각형 시작부분부터, 끝부분까지 양쪽으로 증가시키며 출력을 해나간다.

고로, 역삼각형 코딩부분의 5번째 라인 ~ 7번째 라인, 8번째 라인 ~ 10번째 라인이, 정삼각형 코딩부분의 15번째 라인 ~ 17번째 라인, 18번째 라인 ~ 20번째 라인에서 원칙적으로 반대로 작성이 된다. 증감영역에서 증가를 시켜주었던 것이, 감소를 시켜주는 방향으로, 작을때까지가 클때까지로등으로, 구문이 작성이 되어야 한다.(무슨 말인지 원통....어차피 나혼자만 알아들으면 되니까.. -0-)

이상을 출력하면 다음과 같이 된다.

사용자 삽입 이미지

반복문중에는 Label 이라는 구문을 사용하는 문장도 있다. 다음과 같은 문장에서 말이다.
1//    class Exam06_07 {
2//        public static void main(String[] args) {
3//          aaa : for(int i = 0; i < 5; ++i) {
4//                      bbb : for(int j = 0; j < 5; ++j) {
5//                                  if(j == 2)
6//                                     break;
7//                                     continue;
8//                                     break aaa;
9//                                     continue aaa;
10//                                  {
11//                                      break;                  // 에러
12//                                      System.out.print("*");
13//                                  }
14//                               }
15//                      System.out.println();
16//                   }
17//        }
18//    }
여기서 몇가지 처음보는 구문들이 있을 것이다.

바로 3번째 라인 과 4번째 라인일텐데, 여기서 사용된 것들이 바로 Label 이라는 기능이다.

3번째 라인 ~ 4번째 라인
: 첫번째 for문에 Label aaa 를 붙여 주었다. 이것은 첫번째 for 문을 aaa 라는 이름으로 지정해주겠다는 의미이다. 4번째 라인도 마찬가지다. 두번째 for 문을 bbb 라는 이름으로 지정해주겠다는 의미이다.

6번째 라인 ~ 9번째 라인
: 여기서 사용된 4줄의 문장을 모두 작성한다면, 이 프로그램은 에러가 발생한다. 즉, 4문장중, 한문장만 상황에 맞게 사용하라는 이야기다.

6 번째 라인에서 break; 를 사용하였기에, 이것은, if 를 제외한 가장 가까운 블록을 벗어나라는 이야기이다. 즉, 두번째 for문에 의해 j가 0일때 * 하나, 1일때 * 하나 찍어주고, 2일때는, 가장 가까운 블록에 해당되는 문장, 즉 두번쨰 for 문을 벗어나서, 첫번째 for 문을 실행시키라는 의미이다. 이는 다음과 같이 찍히게 된다.
**
**
**
**
**
7 번째 라인에서는 continue 문이 사용되었다. continue; 는 if문을 제외한 가장 가까운 마지막 블록 } 로 이동하라는 의미이다. 즉, 여기서는, j가 0일때 * 찍고, 1일때 * 찍고, 2일때는, if 문을 제외한 가장 가까운 마지막 블록, 즉 두번째 for문의 끝 블록 } 으로 이동하고, 다시 j가 3일때 * 찍고, 4일때 *를 찍어주게 된다. 이는 다음과 같이 찍히게 된다.
****
****
****
****
****
8 번째 라인에서, 사용된 break aaa; 는 aaa 라는 Label 을 가진 블록, 즉 첫번째 for 문을 탈출하라는 의미이다. 여기서는, j가 0일때 *, 1일때 * 찍고, 2일때는 aaa 라는 Label 을 가진 블록, 즉 첫번째 for문을 탈출하고, 바로 종료가 되어버리는 프로그램이다.
**
9번째 라인에서, 사용된 continue aaa; 는 aaa라는 Label 을 가진 블록, 즉 첫번째 for 문의 마지막 블록 } 으로 돌아가라는 의미가 된다. 즉, 두번쨰 for 문에서 j가 0일때 *, 1일때 * 찍고, 2일때는, aaa라는 Label 을 가진 블록, 즉 첫번째 for 문의 마지막 블록 } 으로 넘어가서, i 값을 하나 증가 시키고, 두번째 for문을 또 실행시킨다. 이렇게 되면, 결국 15번째 라인의 System.out.println(); 이 실행될수 없게 된다.
**********
11 번째 라인에서도, break; 문을 작성해주었는데, 이렇게 작성이 되면 에러가 발생하게 된다. 이유는 if문의 {} 안에서, 그것도 처음으로 사용이 되어졌기 때문이다. 그래서, if 안의 실행문인, System.out.print("*"); 부분을 실행시킬수 없다며, 에러가 발생한다.

Label 은 제어문에게 이름을 주고, 그 이름을 이용하여, 직접 이동시켜 실행시켜주는 역할을 하고 있으며, 루프문에서 주로 사용되지만, 그렇게 많이 사용되지는 않는듯싶다.


p.s 위의 글들은, 김승현 강사님열혈강의 Java Programming 의 Round 6-3, 4, 동영상 강좌에 기초한 내용입니다.
:
1. if 문
모든 제어문 중 가장 기초가 되는 제어문. 보통 3가지 형식이 있는데, 대부분이 거기서 거기인지라, 다만, 한가지 중요한 점은, 영어 if 가 갖는 의미에서 처럼, 만약 이라는 가정하에 벌어질수 있는 상황을 제어하는 문장이라는 것이다.

3가지 형식은, 1) if문만 쓰이는 경우, 2) if~else 가 사용되는 경우, 3) if~else if~else 가 사용되는 경우이다.

기본적으로 다, 똑같은 역할을 해줄 뿐 다를 것은 그다지 없다. 아래는 if 문의 간단한 소스
1//    import java.io.*;

2//    public class Exam06_01 {
3//        public static void main(String[] args) throws IOException {
4//           BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
5//           int su1 = 0, su2 = 0, su3 =0;

6//           System.out.print("첫번째 수를 입력하시오 : ");
7//           su1 = Integer.parseInt(in.readLine());

8//           System.out.print("두번째 수를 입력하시오 : ");
9//           su2 = Integer.parseInt(in.readLine());

10//           System.out.print("세번째 수를 입력하시오 : ");
11//           su3 = Integer.parseInt(in.readLine());

12//           if(su2 >= su1 && su2 >= su3) {
13//              int imsi = su1;
14//              su1 = su2;
15//              su2 = imsi;
16//            }
17//           else if(su3 >= su1 && su3 >= su2) {
18//              int imsi = su1;
19//              su1 = su3;
20//              su3 = imsi;
21//           }

22//           if(su3 > su2) {
23//              int imsi = su2;
24//              su2 = su3;
25//              su3 = imsi;
26//           }

27//             System.out.println(su1+ " >= " + su2 + " >= " + su3);
28//        }
29//    }

이 프로그램은 3가지 수를 받아서, 그 수를 큰수부터, 차례대로 나열하는 프로그램이다. if문의 간단한 예제인데, if 문의 조건에는 논리 조건문이 들어간다. 즉, true 나 false 라는 값이 들어가고, 그 조건을 만족하면, 해당 영역이 실행이 되고, 그렇지 않으면, 그 다음 영역이 실행되는 것이다.

여기서 중요한 부분은 5번째 라인의 변수를 초기화 시켜주는 부분인데, 초기화 시켜줄때, 위와 같은 방식은 괜찮으나, 다음과 같은 방식은 안된다.

int su1, su2, su3 = 0;

c 언어에서는 되었던 것 같은데;;; -0- 쿨럭


2. swich ~ case ~ break 문
switch 문, 역시 다 알테니... -0-, 이 제어문은 특정 수나 문자를 입력받아, 그에 해당되는 곳으로 이동, 해당되는 구문등을 실행시키도록 제어해주는 제어문이다. 수치나 문자에 따른 이동의 처리가, 아무래도 if문 보다는 빠르며, 컴파일 시에 위치가 정해진다.

다음은 switch 문의 예제이다.
1//    import java.io.*;

2//    class Exam06_02 {
3//           public static void main(String[] args) throws IOException [
4//           int city = 0;
5//           /*
6//           char city = 0;         // char 형태로 사용하고 싶을 경우, 사용
7//           */

8//           System.out.println("0 : Seoul");
9//           System.out.println("1 : InCheon, KyoungGi");
10//           System.out.println("2 : GangWon");
11//           System.out.println("3 : ChungBook");
12//           System.out.println("4 : DaeJeon, ChungNam");
13//           System.out.println("5 : JeonBook");
14//           System.out.println("6 : GwangJu, JeonNam");
15//           System.out.println("7 : DaeGu, KyoungBook");
16//           System.out.println("8 : PuSan, KyoungNam");
17//           System.out.println("9 : JeJu");

18//           System.out.print("Put the number above which you are from : ");
19//           city = System.in.read() - 48;
20//           /*
21//            city = (char)System.in.read();         // char 형태로 사용하고 싶을 경우 사용
22//           */

23//           switch(city) {
24//              case 0 : System.out.println("You are from Seoul"); break;
25//              case 1 : System.out.println("You are from InCheon, KyoungGi"); break;
26//              case 2 : System.out.println("KangWon"); break;
27//              case 3 : System.out.println("ChungBook"); break;
28//              case 4 : System.out.println("DaeJeon, ChungNam"); break;
29//              case 5 : System.out.println("JeonBook"); break;
30//              case 6 : System.out.println("GwangJu, JeonNam"); break;
31//              case 7 : System.out.println("DaeGu, KyoungBook"); break;
32//              case 8 : System.out.println("PuSan, KyoungNam"); break;
33//              case 9 : System.out.println("JeJu"); break;

34//              default : System.out.println("Who.....who are you?");
35//           }
36//        }
37//    }
18번째 줄에서 입력받은 값을, 19번째 줄에서, city 라는 변수안에 저장하고, 23번째 줄에 switch 문으로 넘겨서 입력받은 값을 판단한다.

입력받은 값이 0이면, 24번째 줄에, case 0으로, 넘어가, 프로그램이 실행되며, 입력받은 값이 5이면, case 5로 넘어가 프로그램이 실행된다. 하지만, case 몇번으로 넘어가든지, switch 문에서 프로그램은, 넘어간 곳에서부터 프로그램을 순차적으로 실행시키는데, 예를 들어, 위에서 4를 입력하면, case 4로 넘어가고, case4 에 해당되는 부분이 실행이 되고, 이후, 순차적으로, case 5, case 6, case 7 ... 등이 실행이 된다. 그렇게 되면, 자기가 원치 않는 부분까지도 실행이 되기 때문에 이를 막기 위해, break; 라는 문을 case 문 다음에 작성하여, 해당 case 구문이 실행된후 바로, 탈출할수 있도록 해준다.

break; 는 if 문을 제외하고, 가장 가까이 있는 블록하나를 탈출시키는 구문으로, 주로 loop 문에서 사용되며, 또한, switch 문에서, 해당 구문을 실행시키고 바로 빠져나오도록 할때 사용하기도 한다.

위에는 숫자 형태로 받아서 사용하는 방법으로, 19번째 줄에서 보듯이 숫자 형태로 받아 처리하기 위해 System.in.read()-48; 이라는 구문을 집어넣었다. 문자형태인, char 형으로 받아서 처리하기 위해서는, 4번째와 19번째 라인을 6번째 라인과 21번째 라인처럼 바꿔주고, 문자형이라는 것을 알려주기 위해서 case '0' 이라는 식으로 작은 따옴표 '' 를 붙여주어야 한다.

default 값은, 말그대로, 기본값으로, 만약, 입력받은 값이, case 문에 해당되지 않으면, 출력되어지는 부분이다.

아래는 또다른 예제이다.

1//    import java.io.*;

2//    class Exam06_03 {
3//        public static void main(String[] args) throws IOException {
4//           int id7 = 0, year = 0;
5//           String gen = "":
      
6//           System.out.print("Input the 7th number in your ID :");
7//           id7 = System.in.read() - 48;

8//           switch(id7) {
9//              case 9 : case 0 : year = 1800; break;
10//              case 1 : case 2 : year = 1900; break;
11//              case 3 : case 4 : year = 2000; break;

12//              default : year = -1;
13//           }

14//           switch(su % 2) {
15//              case 0 : gen = "Woman"; break;
16//              case 1 : gen = "Man";
17//           }

18//           if(year == -1) {
19//              System.out.println("When...were you born?")
20//           }
21//           else {
22//              System.out.println("You were born in " + year + "'s and a " + gen);
23//           }
24//        }
25//    }


8번째 라인 ~ 11번째 라인
: 가끔 case 문에 아무 구문도 없는 경우가 있는데, 바로 위와 같은 경우이다. 9번째 라인에서, 실질적으로 case 9 과 case 0의 구문이 동일하다. 그렇기에, 앞서 실행되는 case 9 의 구문을 없애주면, 9라는 숫자가 switch 문에 들어왔을때, case 9 를 실행하는데, 막상 case 9 에 해당되는 구문이 없으니까, 바로 case 0 으로 넘어가고, 거기서 year = 1800; 이라는 구문이 실행된다. 그후, break; 를 만나, switch 문을 탈출한다.

앞 서 설명했듯이, case 문으로 이동한 후에는, 해당 case 문 이후의 문장은 모두 실행에 버리는 switch 문의 특성상, 프로그래머가 언제, switch 문을 종료할것인지를 break; 를 사용하여, 적절히 조절해주어야 하겠다.

p.s 위의 글들은, 김승현 강사님열혈강의 Java Programming 의 Round 6-1, 2, 동영상 강좌에 기초한 내용입니다.
:
1. 숫자 하나를 입력받아 그 수가 1이면 "남성", 2이면 "여성' 이라는 글자를 출력하는 프로그램을 만들어 보자.

예시 :
성별을 입력하세요.(남성 : 1, 여성 : 2) : 1
당신은 남성입니다.

풀이과정
-> 이러한 문제들을 보면, 상당히 애매모호한게, 과연 진도상에서 배우지 않은 것을 사용해도 되는가라는 문제이다. 이 문제를 예로 들면, if 문을 사용해도 가능한지가 궁금했었던 문제인데, 문제 자체는 어려울 것이 없지만, 진도상에서 보면, 아직 if 문이라는 진도가 나오지 않았고, 삼항 연산자만 등장했기에, 문제의도가 삼항 연산자만을 가지고 풀라는 이야기로 해석해서, 삼항 연산자로만 풀었지만 이렇게 되면, 문제가 되는 것이, 과연 1이나 2를 제외한 나머지 키 값을 입력하면??

if 문을 사용한다면, 금방 풀리겠지만, if 문을 사용하지 않는다면... 흠.... 내 머릿속으로는 불가능... if 문을 사용하지 않고, 또한, 위의 문제가 발생하는 프로그램 소스 코드는 다음과 같다.

소스코드
import java.io.*;

class Sex {
    public static void main(String[] args) throws IOException {
        BufferedRead in = new BufferedReader(new InputStreamReader(System.in));

        String str = "";      
        System.out.print("성별을 입력하세요.(남성 : 1, 여성 : 2) :");
        int sex = Integer.parseInt(in.readLine());
        // in.readLine() 은 문자열을 위한 것이지, 정수형이나, 실수형을 위한 것은 아니다.
        // 문자열을, 숫자형태인, 정수형으로 바꿔서, 다음 삼항 연산자를 이용하여 연산을 하였다.

        str = sex == 1 ? "남성" : "여성";

        System.out.print("당신은 " + str + "입니다.");     
    }
}
위의 문제는 아까도 말했듯이, 그렇다면, 1과 2를 제외한 나머지 키를 입력했을 경우에는??? if 문을 사용하는 수밖에... -0-


2. 문자 하나를 입력받아 그 문자가 산술 연산자인지 아닌지를 판단하는 프로그램을 만들어 보자.

예시 :
산술 연산자를 입력하세요.('+', '-'. '*', '/', '%') : +
'+'는 산술 연산자 입니다.

산술 연산자를 입력하세요.('+', '-'. '*', '/', '%') : a
'a'는 산술 연산자가 아닙니다.

풀이과정
-> 여기서 막혔던 문제는 in.readLine() 이라는 메소드와, System.in.read() 라는 메소드의 몇가지 잘못된 이해에서 비롯되었다.

알 다시피 System.in.read() 는 문자 하나의 값만을 가질수 있으며, 엔터키를 입력하면, 엔터키에 대한 처리까지 해주어야 되는 번거로움이 있다. 그래서 나는 in.readLine() 이 더 편리한 것인줄 알고, in.readLine() 을 사용하여, 문제를 처리하려고 했다.

여기서, 아직 이해 못한 부분이 하나 등장하는데,

삼항연산자에서는 조건식에 문자열을 사용하냐 못하냐가 바로 그것이다. 나는 사용할수 있다고 생각을 하고, 다음 같은 소스 코드를 짜버렸다.

소스코드 // 실행은 되나, 오류 발생
import java.io.*;

class Operating {
    public static void main(String[] args) throws IOException {
       BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

       String str, op = "";
      
       System.out.print("산술 연산자를 입력하세요. ('+', '-', '/', '*', '%') : ");
       op = in.readLine();

       str = op == "+" || op == "-" || op == "/" || op == "*" || op == "%" ? "는 산술 연산자 입니다." : "는 산술 연산자가 아닙니다.";
      
       System.out.println("'" + op + "'" + str);
    }
}
하 지만, 여기서 발생하는 오류는, 무엇을 집어넣던지 간에, 삼항 연산자는, 조건식에서 false 라고 인식, 항상, false 부분에 있는 항을 실행시킨다. 결국, in.readLine() 사용을 포기하고, 문자열이 아닌, 문자값 하나만을 받는, System.in.read() 를 사용했다.

소스코드 // 문자 값을 사용하여 처리
import java.io.*;

class Operating {
    public static void main(String[] args) throws IOException {
       String str = "";

       System.out.print("산술 연산자를 입력하세요 ('+', '-'. '*'. '/', '%') : ");

       char op = (char)System.in.read();

       str = op == "+" || op == "-" || op == "*" || op == "/" || op == "%" ? "는 산술 연산자입니다." : "는 산술 연산자가 아닙니다.";

       System.out.println("'" + op + "'" + str);
    }
}
오류없이, 실행 성공, 이는 다음과 같이, 아스키 코드값을 이용하여 작성할수도 있지만, 모든 문자의 아스키 코드값을 외울수도 없는 노릇이고....

소스코드 // 아스키 코드 값을 사용하여 처리
import java.io.*;

class Operating {
    public static void main(String[] args) throws IOException {
       String str = "";

       System.out.print("산술 연산자를 입력하세요. ('+', '-', '/', '*', '%') : ");
       int op = System.in.read();

       str = op == 43 || op == 37 || op == 42 || op == 45 || op == 47 ? "는 산술 연산자입니다." : "는 산술 연산자가 아닙니다.";

       System.out.println("'" + op "'" + str);
    }
}
이상... 이며 아직, 해결 못한 부분은 다시 한번 알아봐야 하겠다.
:
7. 삼항 연산자
이는 3개의 항이 있는 연산자로 (조건항 ? 항 1 : 항 2) 로 표현이 되며, 조건항이 true 면 항 1이, false 면 항 2가 실행이 되는 연산자이다. 쉬운 연산자니까 패스.

8. 배정 대입 연산자
이 연산자는 주로 이런 식으로 표현된 연산자이다. =, *=, /=, %=, +=, -=, <<=, >>=, >>>= 등이다.
1//    class Exam05_08{
2//        public static void main(String[] args) {
3//           byte a = 10;
4//           a= a + 1;          // 에러
5//           a += 1;
6//
7//           byte b = 15;
8//           byte c = 58;
9//           b = b + c;         // 에러
10//           b += c;
11//
12//           System.out.println("B = " + b);
13//        }
14//    }
4번째 라인과 9번째 라인은 에러가 발생한다. 4번째 라인과 9번째 라인을 대신해서 작성한 라인이 5번째 라인과 10번째 라인이다.

4번째 라인과 9번째 라인은, 과거 "[JAVA를 "잡아라"] 연산자의 우선 순위(2)" 에서 설명한 것과 같이 int 형보다 작은 byte 형으로 변수를 선언하고, 계산을 시도 하였고, 이를 자바에서는 int 형으로 변환, 저장을 하려고 시도하다, int 형 변수가 없어서, 에러가 발생하는 것이다.

그렇다면, 이 배정 대입 연산자가 어디에 쓰이는지 용도가 바로 나온다. 즉, 이렇게 int 형보다 작은 자료형이라도, 그 작은 자료형으로 연산을 시도, 저장하기 위한 목적으로 사용한다고 할 수 있겠다.


p.s 위의 글들은, 김승현 강사님열혈강의 Java Programming 의 Round 5-5, 동영상 강좌에 기초한 내용입니다.
:
5. 관계 연산자
관계 연산자는 <, >, >=, <=, ==, != 같은 것들이다. 역시 몇가지는 수학공식에서 숱하게 보는 것이니 설명은 생략. 다만, 이 관계 연산자를 통해 갖게 되는 값은 항상 true 나 false 같은, 논리 값들이며, 이러한 값들이 변수에 저장이 된다.
1//    class Exam05_06 {
2//        public static void main(String[] args) {
3//           boolean a = 5 < 3;
4//           boolean b = 10 == 10;
5//
6//           System.out.println("A = " + a);
7//           System.out.println("B = " + b);
8//
9//           boolean c = a!=b;
10//           boolean d = a=!b;
11/
12//           System.out.println("C = " + c);
13//           System.out.println("D = " + d);
14//        }
15//    }
여기서는 몇가지 관계 연산자를 사용하였다.

4번째 라인
: == 이것은, 우리가 흔히 수학에서 사용하는 공식 = 와 같은 개념이다. 하지만, 자바에서의 = 는 수학공식에서의 = 와는 약간은 다른 개념이다. 자바에서의 = 는 대입 연산자로 대입의 의미가 강하며, == 는 관계 연산자로, 두 식이 같다를 의미하고 있다.

9번째 라인 ~ 13번째 라인
: 9번째 라인에서는 a!=b , 10번째 라인에서는 a=!b 가 사용되었는데, 이 둘은 다른 의미를 가지고 있다. 9번째 라인에서 a 라는 변수와 b 라는 변수가 다르다는 것을 나타내 주고 있다. 10번째 라인에서는 b 를 논리 부정 연산자인 ! 를 사용하여 먼저 변수b 를 부정한다음, 이를 a 에 대입하고, 최후로, 변수 d 에 대입하라는 이야기이다.

논리 부정 연산자가 대입 연산자보다 우선순위가 먼저이기 때문에 논리 부정 연산자가 먼저 실행이 되는 것이다. a의 값은 false 가, b의 값은 true 가, c의 값은 true가, d의 값은 false 가 저장, 출력된다.


6. 비트, 논리 연산자
비트 연산자는 비트로 변환시켜 연산하는 연산자로, &, |, ^ 등이 있고, 논리 연산자는 참, 거짓이라는 논리 값으로 연산하는 연산자로, &&, || 등이 있다..
1//    class Exam05_07 {
2//        public static boolean aaa() {               
3//           System.out.println("AAA");
4//           return false;
5//        }
6//  
7//        public static boolean bbb() {
8//           System.out.println("BBB");
8//           return true;
10//        }
11//
12//        public static void main(String[] args) {
13//           int a = 4;
14//           int b = 7;
15//
16//           System.out.println("& = " + (a & b));
17//           System.out.println("| = " + (a | b));
18//           System.out.println("^ = " + (a ^ b));
19//
20//           boolean c = 8 < 5 && 15 > 8;
21//           boolean d = 10 != 28 || 7 <= 5;
22//
23//           System.out.println("C = " + c);
24//           System.out.println("D = " + d);
25//
26//           boolean e = aaa() & bbb();    // 비트 연산자가 논리 연산자처럼 사용
27//           System.out.println("E = " + e);
28//        }
29//    }
위의 소스 코드는, 비트 연산자와 논리 연산자를 함께 설명하고 있다.


13번째 라인 ~ 18번째 라인
: & 연산은 두개의 값을 비트로 변환 시켜서, 비트끼리의 연산을 실행한다. 그래서 만약 두 비트가 모두 참이면 참을 출력한다. 비트안에서의 참은 1이고, 거짓은 0이다.
| 연산은 두개의 값이 모두 거짓이면, 거짓을 출력한다.
^ 연산은, 두 비트가 다르면, 참을 출력하고, 같으면 거짓을 출력한다.

13번째 라인과 14번째 라인에서 사용된 변수를 놓고 보자면, 다음과 같다.
0100          // 4
0111          // 7

& 연산         ☞        0100          // 둘다 참이면 참, 그외는 거짓
| 연산         ☞        0111         // 둘다 거짓이면 거짓, 그외는 참
^ 연산         ☞        0011         // 두 비트가 틀리면 참, 그외는 거짓
출력되는 값은 차례로, 4, 7, 3 이다.

20번째 라인 ~ 24번째 라인
: && 연산은 두개의 식을 비교해서, 두 식이 모두 참이면, 참을 출력한다. 반대로 || 는 두개의 식을 비교해서 두 식이 모두 거짓이면 거짓을 출력한다.

이  둘은 논리 연산자로서, 논리 단위인 true 나 false 값으로 연산한다. 이 연산자에게는 한 가지 특징이 있다. 만약 && 연산을 취한다면, 두개의 식을 비교하고, 첫 식이 거짓이라고 판단되면, 다음 식을 판단 하나, 안하나, 전체의 값은 거짓으로 결과가 나온다. || 연산 역시, 앞의 식이 참이라면, 다음 식을 검사 하나, 안하나, 전체의 식은 참이라는 결과가 나온다. 이러한 특성은, 불필요한 계산을 무시, 프로그램의 속도를 좀더 원활히 해주는 장점이 있다. 하지만 다음과 같은 단점이 생긴다.


2번째 라인 ~ 10번째 라인, 26번째 라인 ~ 27번째 라인
: 만약 26번째 라인에서 & 연산 대신, && 연산을 시켜버리면 어떻게 될까? 2번째 라인 ~ 5번째 라인의 aaa() 라는 메소드의 실행이 먼저 되고, 이 값이 false 를 반환하면서, 26번째 라인은 bbb() 라는 메소드를 무시하고, 바로 false 라는 값이 변수 e에게 저장이 된다.

이런 경우, 가끔가다, 두개의 메소드를 모두 실행시켜주는 경우가 발생한다. 하지만, && 연산이나, || 연산은, 앞의 식만을 판별해서, 뒤의 식을 무시하게 될수도 있다. 이러한 현상을 보완하고자, 앞에서 설명한 비트 연산자가, 논리 연산자처럼 사용되는 경우가 있다.

이렇게 비트 연산자가 논리 연산자처럼 사용되는 경우에는, 두개의 식을, 무조건, 모두 실행 시키고, 값을 출력해 주게 된다. 즉, 위의 경우에서는, aaa() 라는 메소드를 실행 시키고, false 를 반환받고, false 라는 값을 반환 받았음에도 불구하고, 뒤에 bbb() 라는 메소드를 실행시킨 후 true 라는 값을 반환받는다. false 와 true 를 & 으로 연산해서, false 라는 값이 변수 e에 저장이 되고, 27번째 라인에서 출력이 되게 된다.


p.s 위의 글들은, 김승현 강사님열혈강의 Java Programming 의 Round 5-4, 동영상 강좌에 기초한 내용입니다.
:
3. 산술연산자
산술연산자는 말그대로, 산술하는 연산자로, 우리가 수학에서 흔히 쓰는, +, -, /, %, * 등이 이에 해당한다.
1//    class Exam05_04 {
2//        public static void main(String[] args) {
3//           byte a = 10;
4//           byte b = 20;
5//           byte c = a + b;         // 에러
6//           short d = a + b;         // 에러
7//           int e = a + b;
8//
9//           long f = 10L;
10//           int g = 10;
11//           int h = f + g;         // 에러
12//           long i = f + g;
13//
14//           float j = 10.3f;
15//           long k = 10L;
16//           float l = j + k;
17//        }
18//    }
위 의 코드는 몇가지 산술 연산을 적용시킨 코드이다. 뎃셈이나, 뺄셈, 혹은 곱셈, 나눗셈 등의 연산을 모르는 이도, 없고, 나머지 구하는 것도 모르는 이가 없으니, 이에 대한 설명은 넘기고, 그것보다도 자료형이라는 것에서 오는 약간은 헷갈리는 몇가지가 있다.

3번째 라인 ~ 7번째 라인
: 3번째 라인과 4번째 라인은, byte 형으로 변수를 선언, 값을 저장시켰다. 그런데, byte 형으로 저장된 값을, 서로 산술연산을 시키면 어떻게 될까? 그에 대한 해답은, 5번째 라인에서 보듯이 에러가 발생하게 된다.

기본적으로 자바에서는 int 라는 자료형보다 낮은 자료형이 산술 연산을 할때는, 자동적으로 int 형으로 변환되어 연산이 되고, 따라서, 값은, int 형으로 저장이 되어야 한다. short 라는 자료형도, int 형이라는 자료형보다는, 낮은 자료형이기에, 6번째 라인도 에러가 발생하며, 이렇기에, 7번째 라인처럼, int 형의 연산값을 저장할 변수를 선언, 저장해주어야 한다.

9번째 라인 ~ 12번째 라인
: 그렇다면, 이 반대의 상황은 어떨까? int 형보다 큰 자료형과 int 형의 산술 연산은, 당연히, 큰 자료형을 따라가 연산이 되고, 그렇기에, 저장될 변수도, 큰 자료형으로 선언을 해주어야 한다. 11번째 라인은, int 형과 long형의 연산을 int형에다가 저장하려고 하니까 에러가 발생했다. 12번째 라인처럼, long 형으로 변수를 선언, 저장시켜야 한다.

14번째 라인 ~ 16번째 라인
: 실수형과 정수형의 계산도 마찬가지다. 실수형이 무조건, 정수형보다 크기때문에, 실수형과 정수형의 연산에서, 실수형으로 변수를 선언, 저장해주어야 한다. 16번째 라인이, 그렇게 한 경우이다.


4. 쉬프트 연산자
쉬프트 연산자를 비트를 이용한 연산으로, 값을 비트로 변환하여, 계산한후, 다시 값으로 변환시켜주는 과정을 지니고 있다. <<, >>, >>> 등이 있다.

1//    class Exam05_05 {
2//        public static void main(String[] args) {
3//           int i = 1 << 3;
4//           int j = 8 >> 3;
5//
6//           System.out.println("I = " + i);
7//           System.out.println("J = " + j);
8//
9//           int k = -9 >>> 3;
10//           System.out.println("K = " + k);
11//        }
12//    }

위 코드는 쉬프트 연산자를 사용한 코드이다. << 의 의미는 연산할 2진 비트를 왼쪽으로 해당 비트만큼 이동시키라는 이야기다. >> 의 의미는 오른쪽으로 이동시키라는 이야기며, >>> 역시, 오른쪽으로 이동시키라는 의미를 기본적으로 가지고 있다.

3번째 라인
: 1 바이트만으로 놓고 봤을때(실제로 위의 예제는 4바이트), 3번째 라인에서, 1에 해당하는 2진 비트는 다음과 같다.
0000 0001
이 비트를 왼쪽으로 3비트 만큼 이동시키라는 의미가 << 에 들어 있으며, 이렇게 되면 다음과 같이 비트가 변하게 된다.
0000 1XXX
이동한 후에는, 1뒤에 남은 자리가 존재하게 되는데, 이곳에다가는, 0이라는 비트를 채워주게 되고, 이렇게 되면, 다음과 같은 결과가 된다.
0000 1000
이는 결국 8이 되고, 6번째 라인에서의 출력은 8이 된다. 여기에 해당되는 공식은 다음과 같다.
연산할 값 * (2의 이동시킬 비트 수제곱)
3번째 라인을 예로 들면, 1*2의 3제곱 = 1 * 8 = 8 이 된다.

4번째 라인
: 역시 1 바이트만으로 놓고 봤을때, 8에 해당되는 2진 비트는 다음과 같다.
0000 1000
여기서 >> 에 의해, 오른쪽으로 3비트를 이동시키면, 다음과 같다.
XXX0 0001
이동한 후, 여기에서도, 남는 자리가 존재하게 되는데, 이때는 3번째 라인과는 달리, XXX 라는 자리는 원래의 수가 가지는 비트중 최상위 비트에 따라 달라지게 되어있다.
0000 1000   // 최상위 비트가 0   ☞   0000 0001 // 이런식으로 변환

1000 1000   // 최상위 비트가 1   ☞   1111 0001 // 이런식으로 최상위 비트에 따라 달라진다.
여기서 착각하지 말아야 할 부분은, 지금 예로 든 것이 1바이트 안에서 예를 든 것이지, 실제 int 형은 4바이트이므로, 실제 확인을 할때는 이 점을 고려해야 한다. 아무튼 여기서도 공식이 존재한다.
연산할 값 * (1 / 2의 이동 시킬 비트 수제곱)
4번째 라인을 예로 들면, 8 * 1 / 2의 3제곱 = 8 * 1/8 = 1 이 된다.

고로, 7번째 라인은 1이 출력된다.

9번째 라인
: 여기서 사용된 >>> 는 >> 과 마찬가지로 우측으로 비트를 이동하는 것인데, 다만 차이점은, 최상위 비트에 의해 좌우가 되없던 남은 자리의 비트가, 여기서는 그런것에 상관없이 무조건 0으로 집어넣는다.

9번째 라인은, int 형 4바이트의 음수 이므로 다음과 같이 표현이 된다.
1111 1111 1111 1111 1111 1111 1111 0111
여기서 3비트를 >>> 연산 시키면 다음과 같이 바뀌게 된다.
0001 1111 1111 1111 1111 1111 1111 1110
답은,  536870910 (ㅡ.ㅡ)이 된다. >>> 연산은 따로 공식이 존재하지 않으므로, 이런 부분이 나온다면, 계산기를 두들겨야 하...는 건가.. -0-

참고로, 이러한 쉬프트 연산자 역시, 산술 연산자처럼 int 형보다 작은 자료형으로 연산시에는 int 형으로 변환되어 연산이 되어, 저장이 되므로, 저장 역시, int 형 변수로 선언해주어야 한다.


p.s 위의 글들은, 김승현 강사님열혈강의 Java Programming 의 Round 5-3, 동영상 강좌에 기초한 내용입니다.
:

BLOG main image
아무거나 공부하자!!! by Young79

공지사항

카테고리

분류 전체보기 (79)
Programing (29)
English (31)
Graphic (4)
Saying on T"We"tter (15)

최근에 올라온 글

최근에 달린 댓글

글 보관함

달력

«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Total :
Today : Yesterday :