본문 바로가기

멋쟁이 사자처럼 BE School

[멋쟁이사자처럼 Back-End School 1기] Day 12. C언어, Java

C언어

💡 scanf 함수를 호출 시 두 번째 인자로 변수의 주소 값을 넘기는 이유
    ● 본인 생각
       - 함수 배개변수가 스택에 새로운 메모리를 차지한다.

       - scanf의 새로운 변수를 스택으로 쌓는 것이 아닌 미리 지정한 변수의 메모리 주소에 넣어줘야 해당 변수의 값을 변경           하는 것.

    ● 강사님 답변

       - scanf : 개발자 대신 키보드의 입력을 관찰하는 역할

       ❗ scanf에 포인터 주소를 넣어주는 이유

           ○ 공간을 빌려줄 수 없다.

           ○ 공간은 주소를 통해서 공유되기만 한다.

           → 대신맨 역할 : 정확한 주소를 알아야 그 주소의 값을 넣어줄 수 있다.

       ❗ C언어에서는 Python의 input()을 사용하지 않는 이유

           ○ Python : 약타입 언어

           ○ C언어 : 강타입 언어 ⇒ 더 세밀하게 조정이 가능하다.

Scanf

Chater 23 문제 1

  • scanf를 사용하여 변수 설정 과 변수의 입력 값 출력
// chapter 23 problem 1
// 문제 : scanf 할때 왜 변수의 주소를 매개변수로 넘겨주는 지 설명해주세요.

#include <stdio.h>

int main(void) {
  int input;

  printf("정수를 입력해주세요. :");
  // 파라미터 2번째 인자에 포인터 사용 이유
  // scanf : 개발자 대신 키보드의 입력을 관찰하는 역할
  // scanf("%d", input); // 배달 시 집주소를 알려주는게 아닌 뭐가 있는지만 알려주는 것
  scanf("%d", &input); // input의 주소에 입력받은 정수 입력

  printf("입력하신 수는 %d 입니다.", input);

  return 0;
}

배열

💡 int arr[2] = {100, 200}

    arr[0] == *arr == *(arr + 0)

    arr[1] == *(arr + 1)

    &arr == arr

    &arr[1] == arr + 1

 

Chapter 23 문제 2

  • 배열 문법을 사용하여 값 넣기
// chapter 23 problem 2
// 문제 : 고객에게 숫자를 10개 입력받아서 배열에 넣기
// 조건 : 변수를 2개만 사용해주세요.
// 조건 : 포인터 문법을 쓸 수 없습니다.

#include <stdio.h>

int main(void) {
  int list[10];

  for (int i = 1; i < 11; i++) {
    printf("%d번째 숫자를 입력해주세요 : ", i);
    scanf("%d", &list[i-1]); // 배열의 주소로 값을 넣음
  }

  for (int i = 1; i < 11; i++) {
    printf("%d번째 입력받은 숫자 : %d\\n", i, list[i-1]); // 배열 문법을 사용해 출력
  }
  return 0;
}

Chapter 23 문제 3

  • 포인터 문법을 사용하여 값 넣기
// chapter 23 problem 3
// 문제 : 고객에게 숫자를 10개 입력받아서 배열에 넣기
// 조건 : 변수를 2개만 사용해주세요.
// 조건 : 배열 문법을 쓸 수 없습니다.

#include <stdio.h>

int main(void) {
  int list[10];

  for (int i = 1; i < 11; i++) {
    printf("%d번째 숫자를 입력해주세요 : ", i);
	  // &arr == arr와 같이 배열의 포인터를 사용하여 해당 주소에 입력
    scanf("%d", list + i - 1); 
  }

  for (int i = 1; i < 11; i++) {
    // &arr == arr와 같이 배열의 포인터를 사용하여 해당 주소의 값 출력
    printf("%d번째 입력받은 숫자 : %d\\n", i, *(list + i - 1));
  }
  return 0;
}

Chapter 23 문제 4

  • 포인터를 사용하여 배열의 값 변경하기
// chapter 23 problem 4
// 문제 : 배열을 훼손하는 change 함수를 만들어주세요.

#include <stdio.h>

// 여기서 change 함수를 구현해주세요.
// 아직 미완성된 상태입니다. 마저 구현해주세요.
void change(int* x) {
  *x = 200;
  *(x + 1) = 400;
}

int main(void) {
  int x[2];
  x[0] = 100;
  x[1] = 200;
  //int x[2] = {100, 200}; // 위 3 줄 코드의 같은 의미이다.

  printf("change 함수를 호출하기 전, x[0] : %d, x[1] : %d\\n", x[0], x[1]);

  // 여기서 change 함수를 실행해주세요.
  change(x);

  printf("change 함수를 호출한 후, x[0] : %d, x[1] : %d\\n", x[0], x[1]);
  // 출력 => change 함수를 호출하기 전, x[0] : 200, x[1] : 400

  return 0;
}

Chapter 23 문제 5

  • 이중 포인터를 사용하여 배열의 값 변경하기

// chapter 23 problem 5
// 문제 : 배열을 훼손하는 change 함수를 만들어주세요.(배열의 포인터)

#include <stdio.h>

void change(int** p) {
  **p = 200;
  *(*p + 1) = 400;
}

int main(void) {
  int x[2] = {100, 200};
  // x : 배열변수
  // x의 값은 자동으로 x[0]의 주소값을 가진다.
  // x == &x[0]
  // x의 타입은 int* 이다.

  printf("change 함수를 호출하기 전, x[0] : %d, x[1] : %d\\n", x[0], x[1]);

  int* p = x;
  change(&p);

  printf("change 함수를 호출하기 전, x[0] : %d, x[1] : %d\\n", x[0], x[1]);
  // 출력 => change 함수를 호출하기 전, x[0] : 200, x[1] : 400

  return 0;
}

Java

💡 미리 알고 있어야 할 내용

  ● 자바에서는 위험하다 판단 시 통과를 시키지 않는다.(프로그램 종료)

     → 개발자의 서명이 필요하다.(수동으로 형변환)

  ● 자바에서는 리모콘의 버튼이 추가되는 것을 극도로 무서워한다.(but, 편리해진다.)

  ● 자바에서는 리모콘의 버튼이 제거되는 것을 늘 안전하다고 판단한다.(but, 불편해진다.)

  ❗컴파일러는 왜 이렇게 멍청할까?

    - 컴파일러는 실행 전 단계에서 검사를 진행한다. 그러므로 컴파일러는 변수의 내용을 볼 수 없다.

Chater 9 문제 6, 7

  • this를 사용하여 이름과 무기를 저장 후 재공격까지
public class Main {
    public static void main(String[] args) {
        Warrior awarrior = new Warrior();
        awarrior.attack("브라이언", "칼");
        // 브라이언이(가) 칼(으)로 공격합니다.

        awarrior.reattack();
        // 브라이언이(가) 칼(으)로 공격합니다.

        awarrior.attack("필립", "창");
        // 필립이(가) 창(으)로 공격합니다.

        awarrior.attack("마크", "지팡이");
        // 마크(가) 지팡이(으)로 공격합니다.

        awarrior.reattack();
        // 마크(가) 지팡이(으)로 공격합니다.

        awarrior.reattack();
        // 마크(가) 지팡이(으)로 공격합니다.
    }
}

class Warrior {
    private String name, weapon;
    public void attack(String name, String weapon) {
        this.name = name; // 마지막으로 정한 이름 저장
        this.weapon = weapon; // 마지막으로 정한 무기 저장

        System.out.println(this.name + "이(가) " + this.weapon + "로 공격합니다.");
    }

    public void reattack() { // 저장된 이름으로 재공격
        System.out.println(this.name + "이(가) " + this.weapon + "로 재공격합니다.");
    }
}

Chapter 10 문제 2

  • 공통 리모콘을 사용해 여러가지 TV를 ON / OFF시키기

💡 추상메소드(abstract method) = 미완성 설계도

  • 자식 클래스에서 반드시 오버라이딩해야만 사용할 수 있는 메소드
  • 버튼을 추가할 수 있는 빈 버튼이라고 생각하면 편하다.

 💡 인터페이스(Interface) = 기본 설계도

  • 인터페이스도 추상클래스처럼 다른 클래스를 작성하는데 도움을 주는 목적
  • 클래스와 다르게 다중상속(구현)이 가능
class Main {
    public static void main(String[] args) {
        Xiaomi xiaomi = new Xiaomi();
        Samsung samsung = new Samsung();
        LG lg = new LG();

        xiaomi.on();
        // 출력 => 샤오미Tv 켜집니다.
        xiaomi.off();
        // 출력 => 샤오미Tv 꺼집니다.
        xiaomi.vr();
        // 출력 => 샤오미Tv vr켜기!

        samsung.on();
        // 출력 => 삼성Tv 켜집니다.
        samsung.off();
        // 출력 => 삼성Tv 꺼집니다.
        samsung.ar();
        // 출력 => 삼성Tv ar켜기!

        lg.on();
        // 출력 => LGTv 켜집니다.
        lg.off();
        // 출력 => LGTv 꺼집니다.
        lg.game();
        // 출력 => LGTv 게임모드전환!

        Tv atv;
        atv = xiaomi;
        atv.on();
        // 출력 => LGTv 켜집니다.
        atv.off();
        // 출력 => LGTv 꺼집니다.

        atv = samsung;
        atv.on();
        // 출력 => LGTv 켜집니다.
        atv.off();
        // 출력 => LGTv 꺼집니다.

        atv = lg;
        atv.on();
        // 출력 => LGTv 켜집니다.
        atv.off();
        // 출력 => LGTv 꺼집니다.

        // LG리모콘으로 형변환 하여 실행!
        LG aLGTv2 = (LG)atv;
        aLGTv2.game();

    }
}

class Tv { // 리모콘을 생성
    // 버튼 전용 메소드, abstract(추상) method
    void on() { // 각각의 버튼

    }

    void off() {

    }
}

class Xiaomi extends Tv {
    void on() {
        System.out.println("샤오미Tv 켜집니다.");
    }

    void off() {
        System.out.println("샤오미Tv 꺼집니다.");
    }

    void vr() {
        System.out.println("샤오미Tv vr켜기!");
    }
}

class Samsung extends Tv {
    void on() {
        System.out.println("삼성Tv 켜집니다.");
    }

    void off() {
        System.out.println("삼성Tv 꺼집니다.");
    }

    void ar() {
        System.out.println("삼성Tv ar켜기!");
    }
}

class LG extends Tv {
    void on() {
        System.out.println("LGTv 켜집니다.");
    }

    void off() {
        System.out.println("LGTv 꺼집니다.");
    }

    void game() {
        System.out.println("LGTv 게임모드전환!");
    }
}

Chapter 10 문제 3

  • 형변환
// chapter 10 problem 3
class Main {
    public static void main(String[] args) {
        사람 a사람 = new 사람();
        원숭이 a원숭이 = new 원숭이();

        // 문제 1 : 아래 줄의 코드가 되는 이유 설명
        // 상속으로 원숭이 is 동물 이란 것을 자바가 인식
        // 동물 리모콘으로 원숭이 객체를 조종해도 괜찮다. -> 자동 형변환
        동물 a동물 = a원숭이;

        원숭이 a원숭이2 = null; // null 은 쓰레기 리모콘이라는 뜻

        // 문제 2 : 아래 줄의 코드가 안되는 이유 설명
        // a원숭이2 변수에는 2개의 리모콘이 필요하다.
        // a동물 변수에는 1개의 버튼이 들어있는 리모콘이 있다.
        // a동물의 리모콘을 복제해서 주려고 했지만 a원숭이2 는 버튼이 2개 필요함
        // but 리모콘에서 버튼을 추가하는 것은 어쩔땐 되지만 어쩔댄 되지 않는다.
        // java에서는 약간이라도 위험 가능성 존재 시 넘어가지 않는다.
        a원숭이2 = a동물;

        // 리모콘 버튼이 빠지는 예시.
        // 리모콘이 버튼이 빠지는 것은 기능적으론 불편하지만, 무조건 안전하다.
        // 자바에서는 안전한 것에 대해서는 자동 형변환
        동물 a동물2 = a원숭이;

        // 문제 3 : 아래 줄의 되는 이유 설명
        // 자바에서는 안전하지 않을 수 있는 것에 대해서는 개발자의 사인이 필요 -> 수동형변환
        a원숭이2 = (원숭이)a동물;

        사람 a사람2 = null;

        // 문제 4 : 아래 줄의 코드가 수동 형변환 까지 했는데도 안되는 이유 설명
        // 자바에서 꼼수를 인정하지 않아 발견 즉시 종료
        // exception이 발생
        // a사람2 = (사람)a동물;
    }
}
abstract class 동물 {
    void 숨쉬다() {
        System.out.println("동물이 숨을 쉽니다.");
    }
}
class 사람 extends 동물 {
    void 말하다() {
        System.out.println("사람이 말을 합니다.");
    }
}
class 원숭이 extends 동물 {
    void 원숭이묘기를하다() {
        System.out.println("원숭이묘기를하다.");
    }
}

Chapter 10 문제 4

  • int와 double의 형변환
// chapter 10 problem 4
// 문제 : 정수 i가 가지고 있는 10을 double 형 변수에 넣고 해당 변수의 값을 다시 i에 넣는 코드를 작성해주세요.

class Main {
    public static void main(String[] args) {
        int i = 10;
        // 자동 형변환 이유
        // double 범위가 int형의 범위보다 크기 때문에 다 담을 수 있다.
        double d = i; // 여기선 자동형변환 허용

        // 수동 형변환 이유
        // double형의 d는 int형의 범위보다 작기 때문에 넘칠 수 있다. 데이터 손실이 있을 수 있기 때문
        i = (int)d; // 여기선 자동형변환 불가능
    }
}

Chapter 10 문제 5

  • 객체의 이동
// chapter 10 problem 5
// 문제 : 자동차 리모콘이 페라리 객체를 가리키게 한 후 해당 리모콘이 가리키고 있는 객체를 다시 페라리 리모콘으로 가리키게(참조하게) 하는 코드를 작성해주세요.

class Main {
    public static void main(String[] args) {
        // 버튼 2개
        자동차 a자동차;

        // 버튼 3개
        페라리 a페라리 = new 페라리();

        // a페라리가 가지고 있는 리모콘의 버튼 중 뚜껑이 열리는 버튼이 뽑혀 a자동차에 저장
        a자동차 = (자동차)a페라리;
        // 리모콘 버튼을 빼는 부분이기 때문에 자동 형변환 가능.
        a자동차 = a페라리;

        // a자동차 변수의 버튼은 2개 이므로 페라리 리모콘을 위해 버튼 1개를 추가해야 하기 때문에
        // 수동으로 형변환을 해야한다.
        페라리 a페라리2 = (페라리)a자동차;
        // 수정가능지역 끝
    }
}
class 자동차 {
    void 달리다() {}
    void 서다() {}
}
class 페라리 extends 자동차 {
    void 뚜껑이_열리다() {}
}

Chater 11 문제 1, 2

  • 실행시키기
class Main {
    public static void main(String[] args) {
        전사 a전사 = new 전사();

        a전사.나이 = 20;
        a전사.a무기 = new 활();
        a전사.a무기 = new 칼();
    }
}

class 전사 {
    int 나이;
    무기 a무기;
}
// 상위 클래스 생성
class 무기 {

}
// 상위 클래스 상속
class 활 extends 무기 {
}
// 상위 클래스 상속
class 칼 extends 무기 {
}

 

후기 : 엄청 어렵다 너무 어렵다 미치도록 어렵다 왜이렇게 어려운지 모르겠다 자바좀 미리 할걸 그랬다 왜 자바를 안했을까 왜 그랬을까 뭘 한걸까 정말 나 스스로가 답답하다 과거로 돌아가고 싶다