[정보처리기사/예상문제] - 2023 정보처리기사 실기 예상 문제 모음

JAVA 기출문제 모음

비전공자용 Java 요약 1탄

비전공자용 JAVA 요약 2탄(객체지향, 클래스)

비전공자용 JAVA 요약 3탄(객체 생성, 생성자, 접근제어자)

비전공자용 JAVA 요약 4탄(this, 배열, 상속, super)


목차

1. this 예약어

2. static 변수

3. 배열

4. 상속, super 예약어

5. 오버라이딩(overrriding)

6. 추상클래스


1. this 예약어

앞에서도 맛보기로 살짝 봤듯이 this는 자기자신을 가리키는 예약어이다.

 

science.getTitle("안녕")이렇게 메서드를 호출하면 

public void getTitle(String title){}메서드가 호출되는데

this. title= title은 즉 science.getTitle="안녕"과 동일하고

science.getTitle이라는 자기자신을 this라고 표현하는 것이다

 

english.getTitle("안녕안녕")도 마찬가지로 

this.title=title은 english.getTitle="안녕안녕"을 뜻한다

package test;

class Book {
  private String title;
  public int price;
  public String company;
  public String author;
  
  public String getTitle(){
  return title;
  }
  public void getTitle(String title){
	  this.title= title;
	  }
}

public class Test {
    public static void main(String[] args) {
        Book science = new Book();
        science.getTitle("안녕");
        System.out.println(science.getTitle());
        
        Book english = new Book();
        english.getTitle("안녕안녕");
        System.out.println(english.getTitle());
    }
}

 

 

1-1) 생성자에서 다른 생성자를 호출하는 this

아래와 같이 클래스에 생성자가 여러 개 있을 때 this라는 예약어를 통해 이 클래스의 다른 생성자를 호출할 수 있다

 

Book()생성자에서 this("1번째 책")을 사용해 Book(String title) 생성자를 호출한 것이다

package test;

class Book {
  public String title;
  public int price;
  public String company;
  public String author;
  
  public Book(){
	  this("1번째책");
  }
  public Book(String title){
	  this.title= title;
	  }
}

public class Test {
    public static void main(String[] args) {
        Book science = new Book();
        System.out.println(science.title);
    }
}

 

1-2) 자신의 주소를 반환하는 this도 있는데 이 부분은 생략한다


2. static 변수

static 변수는 C언어에서 봤던 개념과 거의 똑같다.

프로그램이 실행되어 메모리에 올라갔을 때 딱 한번만 메모리 공간이 할당되며 그 값은 모든 인스턴스가 공유한다

 

아래 예문의 결과값을 예상해보자.

package test;

class Book {
  public int a=2;
  static public int b=3;
}

public class Test {
    public static void main(String[] args) {
        Book science = new Book();
        Book english = new Book();
        
       
        english.a++;
        System.out.println(science.a);
        english.b++;
        System.out.println(science.b);
        science.a++;
        System.out.println(english.a);
        science.b++;
        System.out.println(english.b);
        
    }
}
더보기

2

4

3

5

 

static이 아닌 a는 인스턴스마다 새로 초기화가 된다

static인 b는 맨처음 한번 3으로 초기화되고 이 3을 인스턴스끼리 공유한다

 

english.a++; 

System.out.println(science.a); //science.a의 값은 변동이 없어 2가 된다

english.b++; 

System.out.println(science.b); //b가 static변수이므로 1증가된 4가 된다

science.a++;

System.out.println(english.a); //1번증가됐으므로 1증가된 3이 된다

science.b++;

System.out.println(english.b); //b가 static 변수이므로 4에서 1증가된 5가 된다


3. 배열

배열 역시 C언어에서 봤던 개념과 동일하다

클래스가 여러가지 다른 자료형을 설계하는 도구였다면 배열은 여러가지 같은 자료형을 설계하는 도구이다

배열은 같은 자료형을 여러개 한꺼번에 관리할 수 있다

 

배열은 아래와 같은 형태이다

int[] a=new int[10]
int a[]=new int[10]

2가지 형태가 다 가능하다

 

배열 선언과 동시에 초기화

배열은 선언하면 그와 동시에 각 요소의 값이 초기화 되며 아래와 같이 배열 선언과 동시에 특정 값으로 초기화도 가능하다

int[] a=new int[] {1,2,3};
int[] a={1,2,3};

 

자바의 배열은 배열 길이를 나타내는 length 속성을 가지며 a.length하면 3이 출력된다

package test;


public class Test {
    public static void main(String[] args) {

        int[] a= {1,2,3};
        System.out.println(a.length);
        
    }
}

 

배열의 기본적인 것들은 C언어와 동일하므로 생략한다

C언어에서의 배열 개념만 알면 자바에서 배열은 사실 문제만 풀어보면 된다


4. 상속

상속이라는 말은 익힐 들어봤을 것이다.

부모님의 재산을 물려받는 것을 보통 상속이라고 하는데 거의 똑같이 생각해주면 된다.

B 클래스가 A클래스를 상속받으면 B클래스는 A클래스의 객체 변수와 메서드를 사용할 수 있다

 

기본형태는 아래와 같다. Cat이라는 클래스가 Animal이라는 클래스를 상속받았고

그 표현으로 extends라는 표현을 쓴다. 

package test;

class Animal {
	
}

public class Cat extends Animal{
	
}

 

쓸 수 있는 영역을 extends 확장한다는 것이다

상속을 하는 이유를 생각해보자.

고양이 클래스가 있고 개 클래스가 있고 하마 클래스가 있고 이런식으로 여러개의 동물 클래스가 있다고 치자.

고양이, 개, 하마를 묶어서 한꺼번에 동물이라고 표현할 수 있다

고양이, 개, 하마는 모두 동물이므로 만약 따로 따로 클래스를 만들게되면 공통된 요소들이 많아지게 될 것이다

예를 들면 eat(), sleep() 뭐 이런 것들

따로따로 만들면 기능은 똑같은데 굳이 새로 만들어줘야하므로 효율적이지 않다

그래서 상속이라는 개념을 쓴다

 

또한 자바에서 모든 클래스는 Object 클래스의 자식이자 하위 클래스이다.(Object가 제일 상위 클래스)

extends(상속)을 하면 아래의 그림과 같이 확장된다

 

아래와 같은 예문을 보자. Cat cat1=new  Cat()으로 객체를 생성하며 Cat() 생성자를 호출한다. 

출력결과는 무엇일까

package test;

class Animal {
	public Animal(){
		System.out.println("내가 니 부모다");
	}
}

public class Cat extends Animal{
	public Cat(){
	System.out.println("부모님 안녕하세요");
	}
	
	 public static void main(String[] args) {
	  Cat cat1=new Cat(); //cat1 객체 생성
	 }
}
더보기

내가 니 부모다

부모님 안녕하세요

자식 객체를 만들었는데 부모 클래스의 생성자까지 같이 호출되는 것을 확인할 수 있다

즉, 하위 클래스에서 객체가 만들어질 때는 그 객체가 만들어지기 전에 부모가 먼저 만들어지고 그 다음 자식이 만들어진다는 것이다. (생각해보면 부모가 있어야 자식이 있는 것이 당연하다)

상위 클래스의 생성자가 호출된 후 상위 클래스의 객체 변수가 메모리에 생성된다

그 후 하위 클래스의 생성자가 호출된다

 

1) Cat cat1= new Cat(); 실행

2) Object 생성자 호출

3) Animal 생성자 호출

4) Cat 생성자 호출

 

이게 가능한 이유는 원래 super()라는 예약어가 있는데 그게 생략돼있는 것이다.

super()라는 것을 생략해도 컴파일러가 자동으로 넣어준다

super 예약어는 하위 클래스에서 상위 클래스로 접근할 때 사용하며 상위 클래스의 생성자를 호출하는데도 사용한다

 

만약에 매개변수가 있는 상위 클래스의 생성자를 호출해야한다면 super(매개변수); 이런 형태를 쓰면 된다


5. 오버라이딩(overrriding)

 

아래의 출력결과를 예상해보자.

package test;

class Animal {
	
	public void eat() {
		System.out.println("동물이 밥을 먹다");
	}
}

public class Cat extends Animal{
	
	public void eat() {
		System.out.println("고양이가 밥을 먹다");
	}
	
	 public static void main(String[] args) {
	  Cat cat1=new Cat();
	  cat1.eat();
	 }
}

 

더보기

고양이가 밥을 먹다

 

객체를 생성한 후 객체의 메서드를 호출했다. 그런데 아까 배웠듯이 객체가 생성될때 부모의 생성자가 먼저 호출되며 부모가 먼저 만들어진다고 했는데 어떻게 "고양이가 밥을 먹다"가 출력 된 걸까?

이처럼 상위클래스에서 eat()메서드가 이미 정의돼있다.

그런데 상위 클래스에서 정의한 메서드가 하위 클래스에 구현할 내용과 차이가 있을 때는 하위 클래스에서 메서드를 재정의할 수 있는데 이를 메서드 오버라이딩이라고 한다

부모 메서드와 자식 메서드가 동일한 형태로 공존하지만 부모 메서드는 무시되고 자식 메서드만 실행되는 것이다

 

오버라이딩을 하려면 반환형, 메서드 이름, 매개 변수 개수, 매개변수 자료형이 다 같아야 한다

 

 

그렇다면 아래의 출력결과도 예상해보자.

package test;

class Animal {
	
	public void eat() {
		System.out.println("동물이 밥을 먹다");
	}
}

public class Cat extends Animal{
	
	public void eat() {
		System.out.println("고양이가 밥을 먹다");
	}
	
	 public static void main(String[] args) {
	  Animal cat1=new Cat();
	  cat1.eat();
	 }
}
더보기

고양이가 밥을 먹다

 

이번에는 특이하게 객체를 생성하는데 객체를 생성하는 자료형과 생성자가 다르다

Animal cat1= new Cat();

 

객체를 생성하는 자료형은 부모 클래스인 Animal이고 생성자는 자식의 생성자이다.

부모 클래스의 객체를 생성하는 것인데 이렇게 아래 그림처럼 Animal 자료형인 cat1이 Animal만 접근하는 줄 알았는데

부모 클래스는 항상 자식 클래스에서 자신의 메서드를 재정의했는지 확인하기 때문에 Animal 객체를 생성했지만 Animal의 eat()메서드가 아니라 자식의 eat()메서드가 실행된다


 

6. 추상클래스(Abstract class)

 

아래의 예문을 보자.

오버라이딩이 되면서 "동물이 밥을 먹다"는 절대로 실행될 일이 없다

그렇다면 굳이 적을 필요가 있을까?

package test;

class Animal {
	
	public void eat() {
		System.out.println("동물이 밥을 먹다");
	}
}

public class Cat extends Animal{
	
	public void eat() {
		System.out.println("고양이가 밥을 먹다");
	}
	
	 public static void main(String[] args) {
	  Animal cat1=new Cat();
	  cat1.eat();
	 }
}

이런 생각에서 나온 것이 바로 추상 메서드이다.

 

메서드에서 반환타입 메서드 이름등 이런 부분을 선언부라고 하고 안에 중괄호{} 부분을 구현부라고 하는데

아래와 같이 추상메서드는 선언부(메서드 원형)만 존재한다. 

출처  : [Java의 정석]Chapter6.객체지향 프로그래밍(14~17) (velog.io)

 

 

추상메서드는 구현부가 없으므로 반드시 오버라이딩이 된다. 

그리고 구현메서드도 있는데 예를 들어 Animal 클래스를 상속받은 클래스가 고양이, 개 ,하마 정도가 있다고 하면 고양이, 개, 하마는 모두 공통적으로 잠을 자므로 굳이 재정의를 하지 않고 부모 클래스의 sleep()을 그대로 쓴다.

 

이렇게 추상클래스는 추상메서드와 구현메서드가 있고 서로 기능이 비슷한 클래스를 말한다

 

이에 대비되는 개념으로는 서로 기능이 다른 클래스를 인터페이스라고 한다

인터페이스는 구현메서드가 없고 100% 추상메서드로만 구성되어있다 

package test;

abstract class Animal {
	
	public abstract void eat();  //추상메서드
	
	public void sleep() {  //구현메서드
		System.out.println("밤에는 잔다");  
	}
}



public class Cat extends Animal{
	
	public void eat() {
		System.out.println("고양이가 밥을 먹다");
	}
	
	 public static void main(String[] args) {
	  Animal cat1=new Cat();
	  cat1.eat();
	  cat1.sleep();
	 }
}

 

자바는 어렵게 출제가 되지 않으므로 이정도로 마무리하도록 하겠다.

이정도 공부했으면 기출문제를 풀고 개념을 다시 확인해보면 될 것이다


[정보처리기사/예상문제] - 2023 정보처리기사 실기 예상 문제 모음

JAVA 기출문제 모음

비전공자용 Java 요약 1탄

비전공자용 JAVA 요약 2탄(객체지향, 클래스)

비전공자용 JAVA 요약 3탄(객체 생성, 생성자, 접근제어자)

비전공자용 JAVA 요약 4탄(this, 배열, 상속, super)

 

[정보처리기사/예상문제] - 2023 정보처리기사 실기 예상 문제 모음

JAVA 기출문제 모음

비전공자용 Java 요약 1탄

비전공자용 JAVA 요약 2탄(객체지향, 클래스)

비전공자용 JAVA 요약 3탄(객체 생성, 생성자, 접근제어자)

비전공자용 JAVA 요약 4탄(this, 배열, 상속, super)


목차

1. 객체 생성

2. 객체 생성시 메모리 구조(heap 영역)

3. 생성자

4. 접근제어자


*이 게시글에서는 속성=필드=객체변수=인스턴스 변수=멤버변수라고 불리는 것을 객체 변수라고 통일하겠다.

 

1. 객체 생성

앞선 2탄에서 클래스, 객체, 메서드, 메모리 구조에 대해 살펴 보았다. 

클래스는 책을 예를 들어 책이라는 자료형을 만들기 위해 구성요소(제목, 가격, 출판사, 저자등)를 하나로 합쳐놓은 것이다. 

책이라는 객체의 구성요소를 사용하기 위해 책이라는 자료형을 클래스로 만들었다면 그 구성요소를 이용해서 다양한 책(객체)을 만들어야 하지 않겠는가

자바에서는 Book science = new Book(); 이런 형태로 객체를 만들 수 있다.

이렇게 클래스를 이용해서 만든 객체 여기서는 science를 인스턴스라고 한다.

 

클래스는 붕어빵 틀, 객체는 붕어빵1,2 ... 이라고 생각하면 된다

package test;

class Book {
  public String title;
  public int price;
  public String company;
  public String author;
  
  public String getTitle(){
  return title;
  }
}

public class Test {
    public static void main(String[] args) {
        Book science = new Book();
        Book english = new Book();
    }
}

science앞에 붙은 Book은 int, String처럼 Book이라는 자료형이라는 표시이므로

Book자료형 science를 선언한다는 의미이다.

Book science는 int a와 동일한 형태이다

뒤에 붙은 new Book()에서 new는 새로만들어진다는 예약어이고 뒤에 나오는 Book()은 생성자(Constructor)라고 불리는 녀석이다. 

Book science = new Book()은 즉 science라는 책 객체를 만든다는 의미인 것이다.

생성자얘기는 나중에 하고 우선 객체를 생성할 때 메모리에 어떻게 동작되는지 알아보자.


2. 객체 생성시 메모리 구조(heap영역)

살짝 복습하면 static이라고 붙은 메서드를 로딩하는데 거기서 제일 먼저 로딩되는 것이 main메서드이다. 위의 코드를 예를 들어 Test class의 main메서드가 제일 먼저 메모리에 로드돼서 호출된다.

호출되면 stack 영역에 들어가는데 이 메인메서드 안에는 Book science라는 변수가 선언돼있다. 

이때 science라는 변수를 참조변수라고 한다.(참조변수이긴 하지만 동시에 지역변수이기도 하다)

참조변수는 주소값을 저장한다.

C언어의 포인터 생각하면 된다.

출처 : [Java] 참조 타입과 참조 변수 :: 불곰 (tistory.com)

 

 

Book science를 선언하고 new 예약어와 함께 Book()이라는 생성자를 호출하면 Heap영역이라는 메모리 공간에 science라는 객체가 하나 생성된다. 

science라는 참조변수는 Heap 영역에 있는 science객체의 주소를 가리킨다.

 

science 객체 안에는 이런식으로 객체가 만들어져있고 science라는 참조변수는 Book객체(science)의 주소를 가리킨다.

여기서 getTitle()이라는 메서드는 실제 위치는 method 영역에 들어있지만 getName() 메서드의 주소로 메서드 영역의 getTitle()과 연결돼있다.

최종적으로 정리하면 Book science = new Book()이라고 하면 heap영역에 science객체(인스턴스)가 생성되고 science라는 참조변수는 heap영역의 science 객체(인스턴스)의 주소를 가리킨다

 

이렇게 객체를 생성하고 나면 그 객체의 이름인 참조변수를 이용해 객체 변수와 메서드를 사용할 수 있다

 

위의 예문 처럼 science.title 이렇게 도트 연산자를 이용해  각 객체의 객체변수와 메서드에 접근할 수 있게 된다

package test;

class Book {
  public String title;
  public int price;
  public String company;
  public String author;
  
  public String getTitle(){
  return title;
  }
}

public class Test {
    public static void main(String[] args) {
        Book science = new Book();
        Book english = new Book();
        
        science.title="개미와배짱이";
        System.out.println(science.title);  //개미와배짱이 출력
        System.out.println(science.getTitle()); //개미와배짱이 출력
    }
}

 

앞에서 봤던 아래 예문도 객체를 이용하면 hello메서드를 static 예약어 없이 호출가능하다

 

*static 포함한 경우

package test;

public class Test {

	public static void main(String[] args) {
		int a=3;
		System.out.println(hello(a));
		System.out.println(a);
	

	}
	public static int hello(int a) {
		a=7;
		return a;
	}
}

 

*static을 사용하지 않은 경우

package test;

public class Test {

	public static void main(String[] args) {
		int a=3;
		Test test1 = new Test();
		System.out.println(test1.hello(a));
		System.out.println(a);
	

	}
	public int hello(int a) {
		a=7;
		return a;
	}
}

3. 생성자(Constructor)

Book science = new Book();에서

new 예약어 뒤에 붙은 Book()을 생성자라고 한다

 

생성자가 하는 일은 객체(인스턴스)를 heap영역에 생성하고 클래스 안에 Book() 생성자의 {}중괄호를 호출하는 역할을 하는데 객체가 생성될 때 객체 변수 값들을 초기화하는 역할도 한다

즉, science의 title과 english의 title은 다르게 설정된다는 것이다

package test;

class Book {
  public String title;
  public int price;
  public String company;
  public String author;
  
  public String getTitle(){
  return title;
  }
  
  public Book() {} //기본 생성자

public class Test {
    public static void main(String[] args) {
        Book science = new Book();
        Book english = new Book();
        
    }
}

 

생성자는 객체를 생성할 때만 호출되는데 생성자 이름은 클래스 이름과 같고 반환값이 없다

생성자가 없는 클래스는 클래스 파일을 컴파일할 때 자바 컴파일러에서 자동으로 생성자를 만들어주는데 이렇게 자동으로 생성되는 생성자를 기본 생성자(default constructor)이라고 한다

 

개발자가 매개변수가 있는 생성자를 따로 만들면 자동으로 기본 생성자가 생성이 되지 않아 기본생성자를 만들어줘야 한다

아래에 public Book(String title){}이 바로 매개변수가 있는 생성자이다

 

이렇게 클래스에 생성자가 두 개 이상 제공되는 경우를 생성자 오버로딩이라고 한다

 

자바의 한 클래스 내에 이미 사용하려는 이름과 같은 이름을 가진 메소드가 있더라도 매개변수의 개수 또는 타입이 다르면, 같은 이름을 사용해서 메소드를 정의할 수 있는데 이를 오버로딩이라고 한다

 

아래에 나오는 this라는 예약어는 객체 자신을 가리키는 예약어인데 우선 이런게 있다고 알고 넘어가자.

 

아무튼 자바의 한 클래스내에 생성자가 두 개 이상이 있으면 인스턴스를 생성할 때 원하는 생성자를 골라서 만들 수 있다

package test;

class Book {
  public String title;
  public int price;
  public String company;
  public String author;
  
  public String getTitle(){
  return title;
  }
  
  public Book() {} //기본 생성자
  public Book(String title) {
  this.title=title;
  } 

public class Test {
    public static void main(String[] args) {
        Book science = new Book();
        Book english = new Book();
        
    }
}

4. 접근제어자(access modifier)

자바에서는 예약어를 사용해서 클래스 내부의 변수, 메서드, 생성자에 대한 접근 권한을 지정할 수 있다.

이런 예약어를 접근 제어자라고 한다

접근제어자에는 private, protected, default, public 이렇게 4종류가 있다

 

다른 건 그냥 넘어가고 private만 살펴보자

출처  : 19편. 제어자(Modifiers) (hexabrain.net)

 

 

위 코드의 객체 변수 String title에 접근 제어자를 private으로 바꾸면 동일한 클래스를 제외하고는 이 변수에 직접적으로 접근할 수 없다

그래서 이를 접근하기 위해서는 메서드를 만들면 된다.

 

직접적으로 접근을 할 수 없으니 Book 제목을 받아오거나 지정할 수 있도록 메서드를 사용한다. 

package test;

class Book {
  private String title;
  public int price;
  public String company;
  public String author;
  
  public String getTitle(){
  return title;
  }
  public void getTitle(String title){
	  this.title= title;
	  }
}

public class Test {
    public static void main(String[] args) {
        Book science = new Book();
        //science.title="바보"; //오류발생 //접근 불가
        science.getTitle("안녕");
        System.out.println(science.getTitle());
    }
}

 

정보처리기사 실기에서는 어차피 거의 대부분이 동일한 클래스로 나오므로 사실 잘 몰라도 상관없다

위의 코드는 getTitle이라는 메서드가 오버로딩돼있는 것인데

getTitle을 호출할 때 매개변수가 없으면 public String getTitle()을 호출하는 것이고

매개변수가 있으면 public String getTitle(String title)을 호출하는 것이다

 


[정보처리기사/예상문제] - 2023 정보처리기사 실기 예상 문제 모음

JAVA 기출문제 모음

비전공자용 Java 요약 1탄

비전공자용 JAVA 요약 2탄(객체지향, 클래스)

비전공자용 JAVA 요약 3탄(객체 생성, 생성자, 접근제어자)

비전공자용 JAVA 요약 4탄(this, 배열, 상속, super)

[정보처리기사/예상문제] - 2023 정보처리기사 실기 예상 문제 모음

JAVA 기출문제 모음

비전공자용 Java 요약 1탄

비전공자용 JAVA 요약 2탄(객체지향, 클래스)

비전공자용 JAVA 요약 3탄(객체 생성, 생성자, 접근제어자)

비전공자용 JAVA 요약 4탄(this, 배열, 상속, super)


목차

1. 객체지향 프로그래밍

2. 클래스

3. 메서드

4. 자바의 메모리 구조와 변수


1. 객체지향 프로그래밍

자바는 객체지향 언어라고 많이들 들어는 봤을 것이다.

객치지향이라고 하면 절차지향과 대조되는데 절차지향의 대표적인 언어가 C언어이고 객체지향의 대표적인 언어가 Java이다

절차지향은 말 그대로 순서대로 읽어야하는 것이고 객체지향은 그와 반대되는 개념이라 생각하면 된다. 

순서가 절차적으로 진행되는 것이 아니라 그때 그때 필요한 것이 실행되는 것이다.

대충만 생각해봐도 객체지향이 뭔가 더 효율적인 느낌이다

a부터 z까지 진열된 책장이 있다고 생각해보자.

절차지향은 dragon이라는 책을 찾기 위해서 a부터 절차적으로 찾아야한다.

반면에 객체지향은 dragon이라는 책을 바로 검색해서 찾는다.

완벽하진 않지만 대충 생각하면 이렇다.

대충 알았으니 이제 객체지향에 대해 더 알아보자.

우선 객체란 뭘까?

 

1) 객체란?

물리적으로 존재하거나 추상적으로 생각할 수 있는 것 중에서 자신과 다른 것을 식별가능한 것이다.

사람, 자동차, 건물 등의 눈에 보이는 사물은 모두 객체라고 할 수 있으며 눈에 안보이는 주문, 생산, 관리 등 어떤 행동을 나타내는 단어도 객체가 될 수 있다.

출처 : [자바, Java] 객체(Obejct)란? (tistory.com)

 

 

2) 객체지향 프로그래밍

각 요소들을 객체(Object)로 만든 후, 객체들을 조립해서 소프트웨어를 개발하는 기법이다.
쉽게 생각해서 컴퓨터로 예를 들면 컴퓨터의 모든 부품을 적절히 연결하고 조립해서 컴퓨터가 제대로 작동하도록 만드는 것이라고 볼 수 있다. 

"학생이 밥을 먹는다"라는 예문을 생각해보자.
학생이라는 객체와 밥이라는 객체가 협력해서 문장이 구현이 된다.
객체 지향 프로그래밍도 마찬가지로 각 객체가 어떤 기능을 제공하고 객체 간 협력을 어떻게 구현할 것인지 생각해야한다. 

출처 : Do it! 자바 프로그래밍 입문-박은종


2. 클래스

앞서 1탄에서 자바 프로그램은 클래스 단위이기 때문에 자바 프로그램을 만드는 것은 자바 클래스를 만드는 것과 같다고 하였다. 그렇다면 클래스는 뭘까

클래스는 공통된 연산을 갖는 객체의 집합이다

C언어에서 구조체랑 비슷하다.

C언어에서 구조체는 여러가지 자료형을 한번에 관리하기 위해 사용한 것이라면 Java에서 클래스는 여러가지 자료형과 함수(자바에서는 메서드라고 부름)를 한번에 관리하기 위해서 사용한다.

 

간단하게 예를 들어 생각해보자.10이라는 자료를 변수로 저장하고 싶다면 자료형을 뭘로 해야할까?int형 같은 정수형 자료형을 사용하면 될 것이다.그렇다면 책이라는 것을 변수로 저장하려면 자료형을 뭘로 해야할까?그럴때 나오는 개념이 바로 클래스이다.

 

책이라는 객체안에는 제목, 가격, 출판사, 저자등의 다양한 자료들이 들어가 있다. 

자바에서는 아래와 같이 클래스라는 녀석을 이용해서 서로 다른 자료형들과 함수(자바에서는 메서드)를 한꺼번에 담는다.

public class Book{
 public String title;
 public int price;
 public String company;
 public String author;
}

위의 예시에서 title, price, company, author같이 클래스안에 들어있는 변수를 필드 또는 멤버변수 또는 객체변수 또는 속성 또는 인스턴스 변수라고 한다

 

<Book>

String title int price String company String author

위와 같은 느낌으로 생성된다.


3. 메서드

클래스에 포함되는 함수를 메서드라고 한다

일단 함수는 C언어에서도 봤었다.

형태는 거의 동일하다

 

아래 예시에서 

int는 반환값

add는 메서드 이름

int a, int b는 매개변수이다.

int add(int a,int b) {
  return a+b;
}

4. 자바의 메모리 구조와 변수

 

아래 예문의 출력 결과를 예상해보자.

package test;

public class Test {

	public static void main(String[] args) {
		int a=3;
		System.out.println(hello(a));
		System.out.println(a);
	

	}
	public static int hello(int a) {
		a=7;
		return a;
	}
}

C언어때의 예문과 거의 동일하다

 

혹시나 뭔소리인지 모르겠다면 아래 링크에 설명을 보고오는 것이 좋다.

2023 정보처리기사 실기-비전공자용 C언어 요약 3탄(함수, 포인터) :: 잡코딩 정보 블로그 (tistory.com)

 

메서드를 호출함으로써 a의 값이 변경된 줄 알았는데 System.out.println(a)를 보니 a의 값이 바뀌지 않았다. 그 이유는 main메서드의 변수 a와 hello()메서드의 변수 a는 다른 a이기 때문이다. 즉 각기 다른 지역의 지역변수이다.

 

이제 자바의 메모리 구조를 알아보자.

자바에서는 자바 가상 머신(JVM)이라는 녀석이 있는데 이 녀석은 자바 프로그램 실행 환경을 만들어 주는 소프트웨어 이다. 자바 코드를 컴파일하여 자바 가상 머신 환경에서 실행되게 만들어준다.

이 때 컴파일은 0과 1밖에 이해못하는 컴퓨터를 이해시키기 위해 개발자가 만든 소스코드를 기계어로 바꿔주는 작업을 말한다.

JVM이라는 녀석이 위와 같은 예문일 경우 Test라는 이름의 클래스를 찾는다.

그 다음 static 예약어가 붙은 메서드를 메모리에 로딩한다.

C언어에서 배웠다시피 static이 붙으면 지역변수처럼 중간에 소멸되지 않고 프로그램이 종료될 때 까지  계속 메모리에 남아 있다.

 

프로그램이 실행되기 전 Method 영역에 main 메서드와 hello 메서드가 메모리에 로딩되며 제일 우선적으로 main메서드가 호출되면 호출된 정보가 stack 영역으로 들어가서 프로그램이 시작된다.

 

위 예문에서는 hello라는 메서드에 static 예약어가 붙어있기 때문에 main메서드에서 hello 메서드를 사용할 수 있는 것이다

 

아무튼 static이 있으니 프로그램 시작전에 메모리에 로딩돼있고 main부터 실행된다는 것만 알면 된다


[정보처리기사/예상문제] - 2023 정보처리기사 실기 예상 문제 모음

JAVA 기출문제 모음

비전공자용 Java 요약 1탄

비전공자용 JAVA 요약 2탄(객체지향, 클래스)

비전공자용 JAVA 요약 3탄(객체 생성, 생성자, 접근제어자)

비전공자용 JAVA 요약 4탄(this, 배열, 상속, super)

 

[정보처리기사/예상문제] - 2023 정보처리기사 실기 예상 문제 모음

JAVA 기출문제 모음

비전공자용 Java 요약 1탄

비전공자용 JAVA 요약 2탄(객체지향, 클래스)

비전공자용 JAVA 요약 3탄(객체 생성, 생성자, 접근제어자)

비전공자용 JAVA 요약 4탄(this, 배열, 상속, super)

 


 

 

Java 공부하기는 싫고 대충이라도 알아야겠다싶으신분만 보세요

찍먹용이라 아주 간단하게만 적혀져 있습니다

대충 읽어보시고 Java 기출문제 풀어보시면 될 것 같습니다

C언어보다는 난이도가 낮게 출제되므로 시간이 없으시다면 java를 통해 합격전략을 세우시는 것도 좋습니다.

 

기본적인 프로그래밍은 안다고 전제하고 java의 특이한 부분에 대해서 중점적으로 설명할 예정이니 기본적인 프로그래밍도 모르시는 분들은 C언어 요약 먼저 보고오시면 좋습니다

비전공자용 C언어 요약 1탄


목차

1. Java의  기본 구조

2. 변수와 자료형


1. Java의 기본 구조

보통 일반적인 자바 소스코드는 다음과 같은 형태로 만들어진다.
클래스명.java

// 클래스 블록 
public class 클래스명 {

    // 메서드 블록 
    public static void main(String[] args) {
        System.out.println("Hello java");
    }

//public이 접근제어자
//static이 정적메서드와 변수
//void가 리턴자료형
//main은 메서드명
//String[] arg는 메서드의 매개 변수
}

소스코드의 가장 바깥쪽 영역은 클래스 블록이다. 클래스명은 원하는 이름으로 지을 수 있다. 단, 클래스명은 소스파일의 이름(클래스명.java)과 동일하게 사용해야 한다.

 

자바 프로그램은 클래스 단위이기 때문에 자바 프로그램을 만드는 것은 자바 클래스를 만드는 것과 같다.

 

이제 메서드블록을 살펴보자. 

 

1) 접근 제어자

메서드 블록 부분에서 public이라고 되어 있는 부분은 접근제어자라고 하는데 이 자리에는 public, private, protected 또는 아무것도 오지 않을 수 있는데 지금은 이런게 있다고만 알고 넘어가자.

 

2) 정적메서드와 변수

그 다음은 static 키워드가 올수도 있고 오지 않을 수도 있다는 의미이다. static 이라는 키워드가 붙게 되면 static 메서드가 되는데 이것도 일단 이런게 있다고 알고 넘어가자.

 

3) 리턴자료형

그 다음 void는 메서드가 실행된 후 리턴되는 값의 자료형을 의미한다.

리턴값이 있을 경우에는 반드시 리턴 자료형을 표기해야 하며 만약 리턴값이 없는 경우라면 void 로 표기해야 한다. 이 항목은 둘 다 생략할 수는 없고 void 또는 리턴자료형이 반드시 있어야만 한다. 

 

4) 메서드 

메서드는 클래스에 포함되는 함수를 말하며 메서드명은 원하는 이름으로 지을수 있다.

메서드 명 이후의 괄호() 안의 값들은 메서드의 입력 인자를 뜻한다.

입력 인자의 갯수는 제한이 없으며 입력 인자는 "입력자료형"+"매개변수명" 형태로 이루어 진다.

 

String[] args는 메서드의 매개 변수이다. String[]은 배열 자료형이란 의미이고, args는 String[]자료형에 대한 변수명이다. args라는 이름은 인수를 의미하는 arguments의 약어로 관례적인 이름이다. args 대신 다른 이름을 사용해도 상관없다.

 

클래스내에는 이러한 메서드를 여러개 만들수 있다.

 

 

출처  : 02-01 자바 소스코드의 구조 - 점프 투 자바 (wikidocs.net)

 

 

뭔소린지 모르겠으면 일단 넘어가자.

여기서는 일단 자바라는 언어는 코드가 클래스라고 하는 것에 우선 둘러쌓여야하고 C언어와 마찬가지로 역시 main이라고 적혀있는 것을 가장 먼저 실행한다는 것만 알면 된다.

 

그리고 System.out.println은 그냥 C언어 printf와 동일하다고 생각해주면 된다.

괄호안에 있는 것을 출력해주는 역할을 한다.(C언어와 다른 점은 println은 개행이 된다는 점이다)

C언어와 동일하게 개행이 되지 않게 하면 System.out.print("안녕"); 해주면 된다


2. 변수와 자료형

기본적으로 변수는 C언어에서 배웠던 개념과 동일하다

다른게 있다면 자료형이다

 

int, double 이런 것들이 기본 자료형이고 클래스형, 배열형 뭐 이런게 참조 자료형이다

참조 자료형은 쉽게 생각해서 기본 자료형을 사용자의 편의를 위해 입맛대로 변형한 것이라고 생각하면 된다

특히 참조 자료형에는 String이라는 것이 있다.

C언어에서는 문자열을 변수에 저장하고자 할 때 배열이나 포인터를 사용했었다. 하지만 자바에서는 String이라는 자료형이 존재한다. String으로 문자열을 받을 수 있는 것이다.

 

*String은 char의 배열로 구현된 참조 자료형이다.

 

아무튼 여기서는 기본 자료형외에도 참조 자료형이라는게 존재하며 문자열을 string이라는 자료형으로 간편하게 저장받을 수 있다 정도만 알고 넘어가면 될 듯 하다


[정보처리기사/예상문제] - 2023 정보처리기사 실기 예상 문제 모음

JAVA 기출문제 모음

비전공자용 Java 요약 1탄

비전공자용 JAVA 요약 2탄(객체지향, 클래스)

비전공자용 JAVA 요약 3탄(객체 생성, 생성자, 접근제어자)

비전공자용 JAVA 요약 4탄(this, 배열, 상속, super)

[정보처리기사/예상문제] - 2023 정보처리기사 실기 예상 문제 모음
C언어 기출문제 모음
비전공자용 C언어 요약 1탄
비전공자용 C언어 요약 2탄(조건문, 반복문, 배열)
비전공자용 C언어 요약 3탄(함수, 포인터)
비전공자용 C언어 요약 4탄(포인터 심화, 구조체)


목차
1. 포인터와 1차원 배열
2. 포인터와 2차원 배열
3. 포인터와 문자 배열
4. 포인터와 문자열 배열
5. 함수 심화(Call by Value, Call by Reference)
6. 구조체


1. 포인터와 1차원 배열
우선 배열의 이름은 배열의 시작주소이다.
 
아래 예문을 보자.

#include <stdio.h>

int main() {
	int array[3] = { 10,20,30 };
    printf("%x %x %x \n", array, array + 0, &array[0]);  //배열 0번째 요소의 주소 출력
	printf("%d %d %d \n", *array, *(array + 0), *&array[0]);  //배열 0번째 요소의 값 10 출력
}

*array는 array(배열 이름) 주소가 가리키는 값인 10이 출력된다
*(array+0)은 array주소에 0칸 이동한 주소가 가리키는 값인 10이 출력된다
*&가 동시에 있으면 생략이 가능하다.
즉 *&arr[0]=array[0] 따라서 역시 배열의 0번째 인덱스인 10이 출력된다
 
결국 array==array+0==&array[0]이라는 의미이다
 
다만 여기서 주의점은 int형 배열이라 요소 1개의 크기는 4바이트이고 array,array+0, &array[0]으로 출력되는 값은 동일하지만 array만 0번째 요소가 아니라 배열 전체를 가리키기 때문에 12바이트(int형이 3칸있으니 12바이트)가 된다
 
다음과 같이 포인터변수 p에 array(배열이름)으로 배열의 시작주소를 저장하면 포인터변수를 배열처럼 사용할 수 있다
아래 예문은 위의 예문과 결과값이 100% 동일하다

#include <stdio.h>

int main() {
	int array[3] = { 10,20,30 };
	int* p = array; //포인터 변수에 배열의 시작 주소를 저장

	printf("%x %x %x \n",p,p+0,&p[0]); //배열 0번째 요소의 주소 출력
	printf("%d %d %d \n", *p,*(p+0),*&p[0]); //배열 0번째 요소의 값 출력
}

 
다 필요없고 위 같은 경우 포인터변수 p랑 array랑 똑같다고 생각해주면 된다


2. 포인터와 2차원 배열
1차원배열에서는 *(array+i)==array[i]==*&array[i]는 값이라고 배웠는데
2차원 배열에서는  *(array+i)==array[i]==*&array[i]가 주소를 가리킨다
 
int array[2][3] = { 10,20,30,40,50,60 }라는 2차원 배열이 있을 때 테이블 같은 구조를 연상하지만 실제는 일직선으로 나란히 돼있는 것을 일단 상기시키고 가보도록 하자.

2차원배열에서도 1차원배열에서 처럼 &array[0][0] 이런식으로 하면 각 배열의 요소의 주소, *&array[0][0] 하면 각 배열의 요소의 값이 잘 출력된다.
 
그렇다면 아래 예문은 어떤 결과가 나올까? 

#include <stdio.h>

int main() {
	int array[2][3] = { 10,20,30,40,50,60 };

	(1)printf("%x\n", array);  
	(2)printf("%x\n", array[0]);
	(3)printf("%x\n", *(array + 0));
	(4)printf("%x\n", &array[0][0]);
    
	(5)printf("%x\n", array+1);
	(6)printf("%x\n", array[1]);
	(7)printf("%x\n", *(array + 1));
	(8)printf("%x\n", &array[1][0]);
    
    
    (9)printf("%d\n",sizeof(&array[0][0]));  //4 출력(32비트 운영체제의 경우)
    //64비트 운영체제의 경우 8로 출력된다
    
	(10)printf("%d\n", sizeof(array[0]));  //12 출력
    (11)printf("%d\n", sizeof(array));  //24 출력
}

(1)~(4)까지는 array[0][0]의 주소를 출력하고
(5)~(8)까지는 array[1][0]의 주소를 출력한다
 
결과값은 동일하지만 4번과 8번의 경우는 arr[0][0], array[1][0] 처럼 특정한 요소의 주소를 가리키지만 나머지는 아래 그림과 같이 특정행을 가리킨다. 
따라서 (9)는 특정요소를 가리키므로 4가 출력되고 (10)은 행을 가리키므로 12가 출력되고 (11)은 배열 전체를 가리켜서 24가 출력된다 

 
*(array + 0)이 형태만 조금 더 살펴 보자
먼저 array는 배열 전체를 가리키지만 위치는 array[0][0] 시작주소에 가 있다

두번째 *(array+0)는 array에서 +0한 곳의 값을 읽는 것인데 2차원배열에서는 이 값이 행의 주소를 가리킨다
배열에서 특정 행을 가리키지만 위치는 array[0][0] 시작주소에 가 있다

세번째 array[0]+0은 배열에서 특정 행의 특정 요소 가리키지만 역시 위치는 array[0][0] 시작주소에 가 있다
따라서 

모두 출력되는 값은 동일하지만 크기는 다르다
이해한 것을 토대로 아래 출력결과를 예상해보자.

#include <stdio.h>

int main() {
	int array[2][3] = { 10,20,30,40,50,60 };

	(1)printf("%d\n", sizeof(array));
	(2)printf("%d\n", sizeof(array[0]+0));
	(3)printf("%d\n", sizeof(*(array + 0)));
	(4)printf("%d\n", sizeof( & array[0][0])); 
    }
정답보기

(1)은 array가 배열의 전체를 가리키므로 24

(2)는 array[0]이 2차원배열의 0번째 행을 가리키고 0번째 행의 0번째 요소를 가리키므로 4출력

(3)는 array는 배열의 전체를 가리키지만 array+0을 함으로써 0번째 행을 가리키게 돼 12가 출력된다(2차원 배열에서는 배열이름의 주소에 대한 값이 특정행의 주소를 가리키게 된다)

(4)는 0행 0열의 주소를 가리키므로 4가 출력된다

#include <stdio.h>

int main() {
	int array[2][3] = { 10,20,30,40,50,60 };

	printf("%d\n", sizeof(array));  //24출력
	printf("%d\n", sizeof(array[0]+0)); //4출력(32비트 운영체제 기준)
    //64비트 운영체제의 경우 8로 출력된다
    
	printf("%d\n", sizeof(*(array + 0))); //12출력
	printf("%d\n", sizeof( &array[0][0])); //4출력(32비트 운영체제 기준)
    //64비트 운영체제의 경우 8로 출력된다
    }
사진 출처 : C언어본색-박정민

 
하나도 이해가 안된다면 그냥 외우면된다.
1차원 배열에서는 값을 가리켰던 녀석들이 2차원 배열에서는 주소를 가리키는 것이다
 
 
1차원 배열과 동일하게 2차원 배열도 포인터를 써서 똑같이 쓸 수 있지 않을까? 생각할 수있지만 아래처럼 코드를 짜면 에러가 난다. int *p는 1차원 포인터 변수이므로 2차원 배열을 저장해도 1차원처럼 작동되기 때문이다.
따라서 이 경우에 필요한 것이 바로 배열 포인터이다.

#include <stdio.h>

int main() {
	int array[2][3] = { 10,20,30,40,50,60 };
	int* p = array;
	printf("%d\n",p[0][0]);

	return 0;
}

 
2-1.배열 포인터
배열 포인터는 배열을 가리키는 포인터 변수이다.
배열 포인터는 다음과 같이 선언한다.

앞에 int는 자료형이고 (*p)는 배열 포인터 변수 이름이고 [3]은 열 길이이다
이렇게 배열포인터로 선언을 하면 2차원 배열처럼 포인터도 접근할 수 있게 된다

#include <stdio.h>

int main() {
	int array[2][3] = { 10,20,30,40,50,60 };
	int(* p)[3] = array; //포인터 변수에 배열의 시작 주소를 저장
	printf("%d\n", array[0][0]);
	printf("%d\n",p[0][0]);

	return 0;
}

 
2-2 포인터 배열
주소를 저장하는 배열
 
포인터 배열은 다음과 같이 선언한다

앞에 int*는 자료형이고 pointer는 포인터배열 변수 이름이고 [3]은 배열 길이이다

#include <stdio.h>

int main() {
	int a = 10, b = 20, c = 30;
	int* p[3] = {&a,&b,&c};
	printf("%d\n", *p[0]);
	printf("%d\n", *p[1]);
	printf("%d\n", *p[2]);
	printf("%d\n", **(p+0));
	printf("%d\n", **(p+1));
	printf("%d\n", **(p+2));

	return 0;
}

 

정답보기

p[0]에 주소가 들어있으니 *p[0]은 그 주소의 값 따라서 10

나머지도 마찬가지

 

p는 배열의 이름이니 배열의 시작주소인데 +0으로 p의 0번째 요소가 선택되고 0번째요소의 값의 값이니 10이 된다

#include <stdio.h>

int main() {
	int a = 10, b = 20, c = 30;
	int* p[3] = {&a,&b,&c};
	printf("%d\n", *p[0]); //10
	printf("%d\n", *p[1]);  //20
	printf("%d\n", *p[2]);  //30
	printf("%d\n", **(p+0)); //10
	printf("%d\n", **(p+1)); //20
	printf("%d\n", **(p+2));  //30

	return 0;
}

3. 포인터와 문자 배열
문자배열은 그냥 1차원 배열과 포인터 개념과 동일하다
 
아래 예문을 보자.

#include <stdio.h>

int main() {
	char array[3] = { 'A','B','C'};
	char* p = array; //포인터 변수에 배열의 시작 주소를 저장
	printf("%x %x %x \n", array, array + 0, &array[0]);  //배열 0번째 요소의 주소 출력
	printf("%c %c %c \n", *array, *(array + 0), *&array[0]);  //뱌욜 0번째 요소의 값 A 출력

	printf("%x %x %x \n", p, p + 0, &p[0]); //배열 0번째 요소의 주소 출력
	printf("%c %c %c \n", *p, *(p + 0), *&p[0]); //배열 0번째 요소의 값 A 출력
	
}

 
다 필요없고 위 같은 경우 포인터변수 p랑 array랑 똑같다고 생각해주면 된다


 
4. 포인터와 문자열 배열
C언어에서 문자열이란 큰 따옴표 내에 포함된 하나 이상의 문자를 의미하며 문자열의 맨 끝에는 문자열의 끝을 알리는 종료 문자 '\0'이 삽입되어 있으며 이런 종료 문자를 널(Null) 문자라 한다
 
문자열은 문자들이 메모리 공간에 연속적으로 저장되어 있어서 보통 주소로 관리되며 문자열을 출력할 때는 서식 문자 %s를 쓴다문자열은 문자들의 집합이므로 문자의 배열이라고 생각할 수 있다
 
아래 결과를 예상 해보자.

#include <stdio.h>

int main() {
	char array[4] = "ABC";
	printf("%c%c%c\n", array[0], array[1], array[2]);
	printf("%s", array);
	printf("%d %d %d\n", array[0], array[1], array[2]);
	return 0;
}
정답보기

A를 %d로 출력하면 A의 아스키코드인 65가 출력된다

#include <stdio.h>

int main() {
	char array[4] = "ABC";
	printf("%c%c%c\n", array[0], array[1], array[2]); //ABC 출력
	printf("%s\n", array); //ABC 출력
	printf("%d %d %d\n", array[0], array[1], array[2]); //65 66 67 출력
	return 0;
}

 
다음 결과도 예상해보자.

#include <stdio.h>

int main() {
	char array[4] = "ABC";
	printf("%s\n", array);
	printf("%s\n", array+1);
	printf("%s\n", array+2);
	return 0;
}
정답보기

array일때는 전체를 가리켜서 ABC가 출력

array+1일때는 arr[1]번째 시작주소를 가리켜서 BC

array+2일때는 array[2]번째 시작주소를 가리켜서 C

#include <stdio.h>

int main() {
	char array[4] = "ABC";
	printf("%s\n", array);  //ABC 출력
	printf("%s\n", array+1); //BC 출력
	printf("%s\n", array+2);  //C 출력
	return 0;
}

 
이런 문자열을 배열이 아니라 포인터로 바꾸면 아래와 같다

#include <stdio.h>

int main() {
	char array[4] = "ABC"; //배열 방식
	printf("%s\n", array);
	printf("%s\n", array+1);
	printf("%s\n", array+2);

	char* p = "ABC";  //포인터방식
	printf("%s\n", p);
	printf("%s\n", p + 1);
	printf("%s\n", p + 2);
	return 0;
}

5. 함수 심화(Call by Value, Call by Reference)
 
함수에서 이때 까지 사용했던 방식이 Call my Value인데 그것은 값을 복사하는 방식이다.

#include <stdio.h>
int func(int);
int main() {
	int a = 10;
	printf("%d\n",func(a));  //11출력
    printf("%d\n",a);  //10출력
	return 0;
}


int func(int a) {
	a = a + 1;
	return a;
}

 
main 함수에서 변수 a를 선언하면서 초기화 한 후 a변수를 인수로 전달하면서 매개변수 a로 값이 복사된다
값을 복사하는 방식으로 main()함수의 지역변수 a 값 변동에는 영향을 미치지 않는다

다음은 새로 배우게 될 Call by Reference(주소 참조) 방식이다
주소를 인수로 받아서 값을 바꾸기 때문에 main()함수의 지역변수 a에도 영향을 미친다

#include <stdio.h>
int func(int);
int main() {
	int a = 10;
	printf("%d\n",func(&a)); //11 출력
	printf("%d", a);  //11 출력
	return 0;
}


int func(int* a) {
	*a = *a + 1;
	return *a;
}

int func(int* a)인 이유는 주소를 전달받기 때문이다
쉽게 생각해서 포인터변수를 선언할 때 int *p=&a; 이런식으로 선언하는 것을 생각하면 된다
주소를 받기 때문에 함수의 매개변수 형태가 포인터변수가 되는 것이다
 


6. 구조체
하나 이상의 변수를 묶어 그룹화하는 사용자 정의 자료형이다
배열이 같은 자료형만 담을 수 있다면 구조체는 다른 자료형도 담을 수 있다
 
아래와 같은 형식으로 구조체를 정의한다
struct : 구조체 키워드
student : 구조체 이름
 
int score, char name은 구조체 멤버 변수

struct student
{
	int score;
	char name;
};

구조체 정의를 하고 구조체 변수 선언을 동시에 하는 방법은 아래와 같다.

struct student
{
	int score;
	char name;
}p1, p2, p3;

 
따로 선언하는 방식은 아래와 같다.

#include<stdio.h>
struct student
{
	int score;
	char name;
};

int main(){
	struct student p1, p2, p3;


return 0;
}

 
구조체 변수에 .(도트 연산자)를 이용하면 각 변수별 멤버변수에 접근할 수 있다
p1.score이라고 하면 p1의 score에 접근이 가능해지며
p1.score=30; 이라고 하면 p1.score 자리에 30이 저장된다

#include<stdio.h>
struct student
{
	int score;
	char name;
};

int main(){
	struct student p1, p2, p3;
	p1.score = 30;
	printf("%d", p1.score);  //30출력

return 0;
}

 
6-1 구조체와 배열
멤버변수로 배열도 사용 가능하다
 
학생 수가 많아지면 구조체 변수 p1,p2,p3가 무한히 많이 필요할 텐데 이런 문제를 해결하기 위해 구조체 변수를 배열로 사용하면 된다

#include<stdio.h>
struct student {
	char no[10];
	char name[20];
	double math;
	double english;
};

int main(){
	struct student stu[3] = {
		{"12345","Lee",90,90},
		{"12346","KIM",80,70},
		{"12347","Park",50,100}
	};

return 0;
}

 

 
6-2 구조체와 포인터

#include<stdio.h>
struct p {
	int* x;
	int* y;
};

int main(){
	int a = 5;
	int b = 4;
	struct p p1;
	p1.x = &a;
	p1.y = &b;

	printf("%d %d\n", a, b);
	printf("%d %d\n", *p1.x, *p1.y);

return 0;
}

출력결과를 예상해보자

 
 
구초제 변수로 포인터를 사용할 수 도 있다
구조체 변수로 포인터를 사용한다는 것은 구조체 변수에 간접 접근할 수 있다는 의미이다
 
(*p)를 한 이유는 .연산자가 *연산자보다 우선순위가 높아 *p를 먼저 연산하기 위함이다
p는 포인터변수인데 p가 구조체 변수 stu의 주소를 담고 있으므로 *p는 stu의 값을 가리킨다
->연산자는 포인터 변수만으로 구조체의 멤버 변수에 접근할 때 사용한다

#include<stdio.h>
struct student {
	char no[10];
	char name[20];
	double total;
};

int main(){
	struct student stu = {"12345","KIM",20};
	struct student* p = &stu;

	printf("%s %s %lf\n", (*p).no, (*p).name, (*p).total); //12345 KIM 20 출력
	printf("%s %s %lf\n", p->no, p->name, p->total);//12345 KIM 20 출력

return 0;
}

 
 
 
[정보처리기사/예상문제] - 2023 정보처리기사 실기 예상 문제 모음
C언어 기출문제 모음
비전공자용 C언어 요약 1탄
비전공자용 C언어 요약 2탄(조건문, 반복문, 배열)
비전공자용 C언어 요약 3탄(함수, 포인터)
비전공자용 C언어 요약 4탄(포인터 심화, 구조체)

[정보처리기사/예상문제] - 2023 정보처리기사 실기 예상 문제 모음

C언어 기출문제 모음

비전공자용 C언어 요약 1탄

비전공자용 C언어 요약 2탄(조건문, 반복문, 배열)

비전공자용 C언어 요약 3탄(함수, 포인터)

비전공자용 C언어 요약 4탄(포인터 심화, 구조체)

 


목차

1. 함수

2. 변수의 종류

3. 재귀 함수

4. 포인터

 


1. 함수

이처럼 함수는 특정 작업을 수행하는 코드의 집합이라고 생각하면 된다.

예를 들어 a+b라는 식이 있다고 생각하면 a+b가 한번만 나오면 상관없겠지만 엄청 많이 나오면 반복적인 작업임에도 코드가 길어지고 번거로울 수 있다. 그래서 더하기 작업을 수행하는 함수를 만들어 놓는 것이다. 

함수의 기본 구조는 다음과 같다.

사진 출처 : C언어 - 함수의 구조, 함수의 형태 4가지 정리글 (1차 수정) : 네이버 블로그 (naver.com)

 

입력 형태에서 보이는 int x, int y는 매개 변수(Parameter)라고 한다.

함수의 형태는 아래 그림과 같이 4가지가 있다.

출력 형태가 있으면 1, 없으면 0

입력 형태가 있으면 1, 없으면 0

 

return의 의미는 반환하고 함수를 종료라는 의미이므로 출력 형태가 1인 경우에는 반드시 return문이 있어야 한다

사진 출처 : C언어 - 함수의 구조, 함수의 형태 4가지 정리글 (1차 수정) : 네이버 블로그 (naver.com)

 

함수를 배웠으니 변수의 종류에 대해 살펴보자.


2. 변수의 종류

함수에서 사용되는 변수는 지역 변수, 전역 변수, 정적(static) 변수, 외부(extern) 변수, 레지스터(register) 변수가 있다.

이 중에 지역 변수, 전역 변수, 정적(static) 변수만 공부해보도록 하자.

 

1) 지역 변수(Local Variable)

main() 함수, 조건문, 반복문의 중괄호({}) 내부와 함수의 매개 변수(Parameter)로 사용되는 변수를 의미한다

 

아래의 예문 출력결과가 무엇인지 예측 해보자.

#include<stdio.h>
int hello(void);

int main() {
	int k = 20;
	
	printf("%d\n",hello()); 
    printf("%d", k);   
    
	return 0;
}


int hello(void) {
	int k = 100;
	return k;
}
더보기

100

20

#include<stdio.h>
int hello(void);

int main() {
	int k = 20;
	
	printf("%d\n",hello()); //100출력
    printf("%d", k);    //20 출력
    
	return 0;
}


int hello(void) {
	int k = 100;
	return k;
}

위 예문을 보면 int k=20으로 초기화를 시킨후 hello라는 함수를 호출해서 k는 100이라고 바뀐줄 알았는데 그게 아니고 20이 그대로 호출되었다.

즉, main()함수의 k와 hello()함수의 k는 다르다는 것이다.

 

심도있게 알기 위해서는 메모리에 대해 알아야한다. 

지역변수라서 함수가 종료되면 메모리 공간이 소멸된다.

 

2) 전역 변수(Global Variable)

중괄호 외부에 선언되는 변수로 어느 지역에서도 사용이 제한되지 않는 프로그램 어디에서든 접근이 가능한 변수이다

중괄호가 시작되면 메모리가 생성되고 해당 중괄호에서 빠져나오면 메모리가 소멸되는 지역변수와 달리 전역변수는 프로그램이 시작되면 메모리에 생성되고 프로그램이 종료되면 메모리가 소멸된다

 

그래서 전역 변수는 프로그램이 종료되지 않는 한 계속해서 메모리에 존재하고 영역에 제한받지 않으며 사용된다

그리고 전역 변수는 초깃값을 지정해주지 않아도 자동으로 값을 0으로 가진다.

 

전역 변수의 잘못된 사용과 남용은 공유 자원에 대한 잘못된 접근으로 부작용을 낳을 수 있는데 시스템의 변경과 유지 보수를 어렵게 하는 원인이 될 수있으므로 전역 변수의 사용은 최대한 피하는 것이 바람직하다

 

3) 정적 변수(Static)

전역 변수의 단점을 부분적으로 보완한 변수

정적변수는 변수의 자료형 앞에 static 키워드를 넣어서 만든다

static int a;

 

정적 변수는 전역 변수처럼 프로그램이 종료되지 않는 한 메모리가 소멸되지 않고 초깃값을 지정하지 않아도 자동으로 0으로 가지며 또한 정적 변수는 초기화가 단 1회만 수행된다.

 

다음 수행결과가 무엇일지 생각해보자.

#include<stdio.h>
void hello(void);

int main() {
	int k = 20;
	
	hello();
	hello();
	hello();

	return 0;
}


void hello(void) {
	static k = 1;
	int t = 0;
	k++;
	t++;
	printf("%d %d\n", k, t);
}
더보기

2 1

3 1

4 1

static 변수 k는 한번만 초기화되므로 k가 정상적으로 계속 증가하는 것을 볼 수 있지만

지역변수 t는 계속 초기화가 진행이 돼 모든 값이 1임을 확인할 수 있다.


3. 재귀함수(Recursive Function)

함수 내에서 자기 자신을 호출하는 함수

재귀 함수의 경우 계속적인 자기 자신의 함수 호출로 시간과 메모리 공간의 효율이 저하될 수 있다.

 

다음 코드의 결과값을 생각해보자.

#include<stdio.h>
int fact(int);

int main() {
	int a=4;
	printf("%d",fact(a));
	return 0;
}

int fact(int n) {
	if (n <= 1)
		return 1;
	else
		return n * fact(n-1);
}
더보기

24

 

fact(4)=return 4 * fact(3)

fact(3)=return 3* fact(2)

fact(2)=return 2*fact(1)

fact(1)=1

 

fact(4)=4*3*2*1=24

 

따라서 결과는 24

 

위 문제는 재귀함수를 이용한 팩토리얼 예제였다.


4. 포인터

포인터(pointer)란 메모리의 주소값을 저장하는 변수이며, 포인터 변수라고도 부른다.

말 그대로 뭔가를 가리키는 의미를 가지고 있다. (주소값을 가리킴)
char형 변수가 문자를 저장하고, int형 변수가 정수를 저장하는 것처럼 포인터는 주소값을 저장한다.

 

포인터 변수의 선언은 아래와 같이 선언한다. 

사진 출처  : C언어 포인터 사용시 주의점 : 네이버 블로그 (naver.com)

 

포인터 변수의 크기는 주소를 가리키기 때문에 항상 4byte의 동일한 크기를 가진다. (32bit 운영체제 한정)

 

1) 주소 연산자(&)
주소 연산자는 변수의 이름 앞에 사용하여, 해당 변수의 주소값을 반환한다.

 

2) 참조 연산자(*)
참조 연산자는 포인터의 이름이나 주소 앞에 사용하여, 포인터에 가리키는 주소에 저장된 값을 반환한다.

dereference라고 하여 역참조연산자라고도 한다.

 

다 필요없고 포인터는 하나만 알면 된다.

*p는 선언할 때를 제외하고 무조건 값을 가리킨다고 생각하면 되고 &는 주소를 가리킨다고 생각하면 된다.

 

아래는 대충 이해를 돕기위해 만든 표이다. (주소는 그냥 임시로 준 값이다)

#include <stdio.h>

int main() {
  int a=3;
  int b=&a;
  int *c=&a;
  printf("%d\n",a); //그냥 변수 a를 출력
  printf("%d\n",b); //b에 저장된 a의 주소의 값을 출력
  printf("%d\n",c); //포인터 변수 c에 저장된 a의 주소 출력
  printf("%d\n",*c); //포인터 변수 c에 저장된 a의 주소의 값 출력
  return 0;
}

printf("%d",a); //출력 결과 : 3

printf("%d",b); //출력 결과 : 1000K

printf("%d",c); //출력 결과 : 1000K

printf("%d",*c); //출력 결과 : 3

 

b는 a의 주소 값이 b라는 변수에 대입된 것이고

c는 a의 주소 값을 가리킬 수 있게 된 것이다

즉, a와 b는 연결고리가 없는 반면 a와 c는 연결고리가 있다.

 

3) 다차원 포인터

1차원 포인터에는 변수의 주소값이 저장되고 2차원포인터(이중포인터)에서는 1차원 포인터의 주소가 저장된다.

마찬가지로 3차원 포인터는 2차원 포인터의 주소가 저장된다

n차원 포인터는 n-1포인터의 주소를 넣는다.

#include <stdio.h>

int main() {
  int a=3;
  int* b=&a;   //1차원 포인터 : 변수의 주소값 저장
  int** c=&b;  //2차원 보인터 : 1차원 포인터의 주소값 저장
  
  printf("%d\n",b);  //7행과 8행 동일
  printf("%d\n",*c);  // 결과값 : a의 주소
  
  printf("%d\n",*b);  //9행과 10행 동일
  printf("%d\n",**c); //결과값  : 3
  return 0;
}

포인터 변수 b는 a의 주소를 가리키기 때문에 

b는 a의 주소이고

*b는 a의 값이다

 

포인터 변수 c는 b의 주소를 가리키기 때문에

c는 b의 주소이고

*c는 b의 값인데 b의 값이 a의 주소이므로 *c는 a의 주소이다.

*c가 a의 주소이므로 **c는 a의 주소의 값(즉, a의 값)이다 

 

포인터 아무것도 이해 안돼도 좋다. 

정보처리기사 실기는 어차피 결과값 묻는 문제가 대부분인데 포인터는 주소를 가리키는 녀석이다. 컴퓨터마다 메모리 주소가 다 다르므로 주소를 묻는 문제는 나올 수가 없다.

그래서 그냥 포인터변수가 나오면 상수 대입해서 대충 찍어봐라.

대부분 맞다.

아래는 기출문제이다. 한번 생각해보자.

#include <stdio.h>
 
int main(){
int *arr[3];
int a = 12, b = 24, c = 36;
arr[0] = &a;
arr[1] = &b;
arr[2] = &c;
 
printf("%d\n", *arr[1] + **arr + 1);
}
더보기

37

 

야매 풀이

*arr[1] 뭔지 모르겠는데 arr이 배열이니까 왠지 arr[1]=b의 값일 것 같다 =24

**arr 뭔지 모르겠지만 배열인데 아무것도 안적혀있는 거보니 arr[0]을 가리키는 것 같다 그러면 arr[0]+1하면 되지 않을까? =12+1

 

24+13=37

 

진짜 풀이

*arr[1]은 arr[1]의 값인데 arr[1]이 b의 주소를 가리키므로 b의 주소의 값(b의 값) = 24

arr은 배열의 이름이고 arr[0]의 주소와 동일한데 *arr은 a의 주소이고  **은 a의 주소의 값(a의 값) =12

24+12+1=37

(참고로 *가 우선순위 더 높아서 +1보다 먼저 수행된다)

 

4) 주소의 가감산

C언어에서 배우는 자료형은 모두 주소를 가지며 주소의 가감산이 가능하다.

char형 주소에 +1을 하면 1바이트 증가, int는 4바이트 증가, double은 8바이트 증가

 

다음은 기출문제이다. 출력결과를 예상해보자.

#include <stdio.h>

int main() {
	char* p = "KOREA";
	printf("%s\n", p);
	printf("%s\n", p + 3);
	printf("%c\n", *p);
	printf("%c\n", *(p + 3));
	printf("%c\n", *p + 2);
}
더보기

4번째 줄: KOREA라는 문자열의 주소를 포인터변수 p에 저장한다는 의미

5번째줄 :  char이 p라는 주소에서 시작해서 널값 전까지를 전부 출력해서 KOREA

6번째줄 :  char이 1byte이므로 +3하면 3칸이동한것이라고 생각하면 되는데 왼쪽으로 3칸이동해서 널값 전까지 전부 출력해서 EA

7번째줄 :  서식문자가 %c로 바뀌었고 p의 값을 물어보고 있으므로 K

8번째줄 :  서식문자가 %c로 바뀌었고 p+3(p에서 주소를 3칸 이동)의 값이므로 E

9번쨰줄 : 서식문자가 %c로 바뀌었고 p의 값에서 +2한 문자이므로 K,L,M 순이므로 M

 

그냥 p는 p의 제일 첫번째(p+0)를 가리키고 있다고 생각하면 됨

 

 

[정보처리기사/예상문제] - 2023 정보처리기사 실기 예상 문제 모음

C언어 기출문제 모음

비전공자용 C언어 요약 1탄

비전공자용 C언어 요약 2탄(조건문, 반복문, 배열)

비전공자용 C언어 요약 3탄(함수, 포인터)

비전공자용 C언어 요약 4탄(포인터 심화, 구조체)

[정보처리기사/예상문제] - 2023 정보처리기사 실기 예상 문제 모음

C언어 기출문제 모음

비전공자용 C언어 요약 1탄

비전공자용 C언어 요약 2탄(조건문, 반복문, 배열)

비전공자용 C언어 요약 3탄(함수, 포인터)

비전공자용 C언어 요약 4탄(포인터 심화, 구조체)

 


목차

1. 조건문

2. 반복문

3. 배열


1. 조건문

조건에 맞을 경우 해당 실행문장을 처리하고자 할 때 사용한다

조건문에는 if문과 swtich-case문이 있다.

 

먼저 if문

a>b가 참이면 a=a+b;가 실행이 되고 거짓이면 a=a-b;가 실행된다

아래 예문은a=a+b가 실행이 돼 13이 출력 된다

#include<stdio.h>
int main() {
	int a = 8, b = 5;
	if (a > b)
		a = a + b;
	else
		a = a - b;
	printf("%d\n", a);
	return 0;
}

비트연산자에서 봤듯이 조건문에서도 연산자가 있다. &&, ||

&&는 2개의 조건이 모두 참이어야 참(1)을 반환한다

||는 2개의 조건중 하나만 참이어도 참(1)을 반환한다

 

if외에도 또 다른 조건을 추가하고 싶을 때는 else if를 쓰기도 하고 그냥 if를 더 써주기도 하는데 

if-else if-else의 경우에는 조건문중 해당하는 1개만 실행되는 반면

if-if-if의 경우에는 해당 조건에 맞는 모든 조건문이 전부 실행된다.

#include<stdio.h>
int main() {
	int a = 90;
	int count = 0;
	if (a >= 90)
		count++;
	else if (a >= 80)
		count++;
	else if (a >= 70)
		count++;
	else
		count++;
	printf("%d", count);
	return 0;
}
더보기

출력 : 1

#include<stdio.h>
int main() {
	int a = 90;
	int count = 0;
	if (a >= 90)
		count++;
	if (a >= 80)
		count++;
	if (a >= 70)
		count++;
	printf("%d", count);
	return 0;
}
더보기

출력 : 3

 

switch-case문

switch 키워드 다음 괄호안에 들어가는 num이 무슨 값이냐에 따라 그 해당하는 경우를 실행한다.

break는 조건문을 종료하라는 키워드이고

default는 그냥 else라고 생각하면 된다

#include<stdio.h>
int main() {
	int num = 3;
	switch (num) {
	case 1:
		printf("안녕1");
		break;
	case 2:
		printf("안녕2");
		break;
	case 3:
		printf("안녕3");
		break;

	default : 
		printf("안녕안녕");
		break;
	}


		return 0;
}
더보기

출력 : 안녕3

 

break가 없으면 case3부터 아래 모든 조건문이 다 실행된다

#include<stdio.h>
int main() {
	int num = 3;
	switch (num) {
	case 1:
		printf("k");
	case 2:
		printf("o");
	case 3:
		printf("re");

	default : 
		printf("a");
	}


		return 0;
}
더보기

출력 : rea


2. 반복문

반복문에는 for, while, do-while이 있다

먼저 for문이다

 

i=0가 시작값

i<=5가 조건식

i++이 증가감값

 

i가 0부터 시작해서 i가 5가 될때 까지 i가 1씩 증가하면서 반복해라라는 의미이다

#include<stdio.h>
int main() {

	for (int i = 0; i <= 5; i++) {
		printf("%d", i);
	}
	return 0;
}

위 for문은 따라서 012345가 출력이 된다

 

 

다음은 while문이다

while 오른쪽 괄호에 조건식을 넣어준다

i가 5이하일때까지 반복해라

 

그리고 while문은 증감값을 출력문 아래에 적어준다.

출력결과는 012345이다

#include<stdio.h>
int main() {

	int i = 0;
	while (i <= 5){
		printf("%d", i);
	    i++;
	}
	
	return 0;
}

break를 이용해 해당 조건일 경우 while문이 종료되도록 해줄 수도 있다

아래는 0만 출력된다

#include<stdio.h>
int main() {

	int i = 0;
	while (i <= 5){
		if (i %2==1) break; 
		printf("%d", i);
	    i++;
		
	}
	
	return 0;
}

 

또한 continue라는 키워드를 통해 실행문을 실행하지 않고 건너 뛰라고 할 수도 있다

예를 들어 i==1에서 continue를 만났으면 i==1에서 실행될 예정이었던 모든 구문이 건너뛰기 되고 i==2구문이 시작된다

아래처럼 하면 024가 출력이 된다

#include<stdio.h>
int main() {

	int i = 0;
	while (i <= 5) {
		if (i % 2 == 1) {
			i++;
			continue;
		}
		printf("%d", i);
		i++;
	}
	return 0;
}

 

 

for 문은 반복횟수를 알고 있을 때, while 문은 반복 조건위주에 따라 반복할 때 사용된다.

 

 

마지막으로 do-while문이다

조건에 따라 반복을 계속할지를 결정할 때 사용하는 것은 while 문과 동일한데

조건 중괄호 {} 블럭을 한번 실행하고, 조건을 검사하여 반복을 결정한다

#include<stdio.h>
int main() {

	int i = 0;
	do {
		printf("%d", i);
		i++;
	} while (i <= 5);
	
	return 0;
}

출력결과는 012345이다

 

 

 

반복문이 중첩될 수 도 있다

그것을 중첩반복문이라고 한다.

 

간단한 예시를 보겠다. 

아래는 이중 for문이다.

#include<stdio.h>
int main() {
	int k = 1;
	for (int i = 1; i <= 3; i++) {
		
		for (int j = k; j <= k+2; j++) {
			printf("%d ", j);
		}
		printf("\n");
		k += 3;
	}
	return 0;
}

이중for문에 맨 처음for문은 행, 안쪽은 열이라고 생각하면 된다.

i가 1부터 3까지니까 3행이 생기는 것이다.

j도 k부터 k+2까지니까 3열이 생기는 것이다.

 

i=1일때(즉 1행이 만들어졌을 때) j를 k부터 k+2만큼 반복해라(즉 열을 k에서 k+3만큼 만들어라)

i=2일때(즉 1행이 만들어졌을 때) j를 k부터 k+2만큼 반복해라(즉 열을 k에서 k+3만큼 만들어라)

i=3일때(즉 1행이 만들어졌을 때) j를 k부터 k+2만큼 반복해라(즉 열을 k에서 k+3만큼 만들어라)

 

1행 만들어짐-> 3열 만듦

2행 만들어짐-> 3열 만듦

3행 만들어짐->3열 만듦

 

그래서 위에 이중 for문 출력결과를 생각해보자.


3. 배열

배열은 같은 데이터형 변수를 여러개로 묶어놓은 것이다

관련 있는 데이터를 하나의 변수에 할당하여 관리하기 위해 필요하다

아래와 같이 a[]형태가 배열 선언 형태이고 선언과 동시에 {1,2,3,4,5}로 초기화를 했다.

배열의 인덱스는 0부터 시작한다

a[0]=1

a[1]=2

a[2]=3

a[3]=4

a[4]=5

#include<stdio.h>
int main() {
	int a[5] = { 1,2,3,4,5 };
	for(int i=0;i<5;i++){
		printf("%d", a[i]);
	}
	return 0;
}

출력결과가 무엇일지 생각해보자

더보기

12345

 

포인터를 배울 때 얘기하겠지만 배열의 이름은 배열의 주소이다. 

int a=0; 이라는 변수가 있다고 하면 &a를 해야 a변수의 주소를 가리킬 수 있지만 

배열은 a라는 배열 이름만 있어도 변수의 주소를 가리킬 수 있다

 

 

◆배열에서 문자열

'a', 'A'같은 것을 문자라고 하고 문자가 2개이상 결합된 것을 문자열이라고 하는데 배열에 문자열을 저장할 때는 반드시 문자열의 개수+1의 크기로 선언해야한다

문자열의 마지막에는 \0(널 값)이 추가되기 때문이다.

즉, KOREA로 문자가 5개뿐이지만 널값을 포함해야해서 배열길이를 6개로 해줘야한다. 

널 값이 추가되는 이유는 메모리상에서 문자열은 이진 데이터로 저장되기 때문에 문자열의 시작과 끝이 표시되어 있지 않아 구분하기 위해서 존재한다.

#include<stdio.h>
int main() {
	char a[6] = "KOREA";
	printf("%s", a);
	return 0;
}

%s는 문자열을 받는 서식문자로 a나 &a로 사용 가능하다

a로 써도 되는 이유는 a라는 배열의 이름은 배열의 주소를 가리키기 때문이다

 

#include<string.h>를 추가해준 후 strlen이라는 함수로 a라는 배열안에 문자열길이를 구할 수 있다

5가 출력된다

#include<stdio.h>
#include<string.h>
int main() {
	char a[6] = "KOREA";
	
	printf("%d", strlen(a));  //5
	return 0;
}

위 문제를 토대로 문제를 하나 풀어보자.

#include<stdio.h>
#include<string.h>
int main() {
	char a[6] = "KOREA";
	int b = 0;
	b = strlen(a);
	for (int i = 0; i < b; i++) {
		printf("%c", a[i]);
	}
	return 0;
}
더보기

출력결과 : KOREA

 

 

 

◆2차원 배열

2차원 배열은 말그대로 2차원 배열이다.

배열이 이렇게 1차원이였다면 

2차원 배열은 이런식으로 생각하면된다.

아래 처럼 생각하면 된다 x[][] 이런 형태인데

x는 배열의 이름이고 첫번째 []는 행, 두번째 []는 열이라고 생각하면 된다

보기 편해서 이렇게 보는 것이고 실제로 메모리상에는 나란히 이어져있다.

출처 : c언어 2차원 배열 : 메모리 상에 어떻게 저장이 될까요? (tistory.com)

 

 

아래의 출력결과를 생각해보자.

#include<stdio.h>
int a[5][5];
int main() {
	int i, j, k = 1;
	for (i = 0; i < 5; i++) {
		for (j = 4; j >= 0; j--) {
			a[i][j] = k;
			k++;
		}
	}
	for (i = 0; i < 5; i++) {
		for (j = 0; j < 5; j++) {
			printf("%3d", a[i][j]);
		}
		printf("\n");
	}
	return 0;
}

 

 

[정보처리기사/예상문제] - 2023 정보처리기사 실기 예상 문제 모음

C언어 기출문제 모음

비전공자용 C언어 요약 1탄

비전공자용 C언어 요약 2탄(조건문, 반복문, 배열)

비전공자용 C언어 요약 3탄(함수, 포인터)

비전공자용 C언어 요약 4탄(포인터 심화, 구조체)

 

 

 

[정보처리기사/예상문제] - 2023 정보처리기사 실기 예상 문제 모음

C언어 기출문제 모음

비전공자용 C언어 요약 1탄

비전공자용 C언어 요약 2탄(조건문, 반복문, 배열)

비전공자용 C언어 요약 3탄(함수, 포인터)

비전공자용 C언어 요약 4탄(포인터 심화, 구조체)

 

 

C언어 공부하기는 싫고 대충이라도 알아야겠다싶으신분만 보세요

찍먹용이라 아주 간단하게만 적혀져 있습니다

대충 읽어보시고 c언어 기출문제 풀어보시면 될 것 같습니다


목차

1. C언어의 구조

2. 변수와 자료형

3. 서식문자

4. scanf()

5. 사칙연산과 증감연산자

6. 비트연산자


1. C언어의 구조

#include<stdio.h>     
	int main() {
		printf("안녕");
		return 0;
	}

1) #include<stdio.h>는 선행처리기라고 하는데 몰라도 된다.

이 문장이 있어야 printf()함수를 쓸 수가 있다.

 

2) int main()

main() 함수인데 자세한 건 몰라도 된다

그냥 main함수 안에 있는 {   }내용물을 제일 첫번째로 보라는 것이다

 

3) printf()

말그대로 printf() 괄호안에 있는 것을 출력하라는 의미이다

 

4) 맨 뒤 ;(세미콜론)

그냥 "밥을 먹었다."할 때 .(마침표)랑 똑같다고 생각하면 된다

 

5) return 0;

함수가 문제없이 종료됐다는 것을 의미한다

그냥 없다고 생각해도 된다


아래 처럼 코드를 작성하면 어떻게 출력될까?

#include<stdio.h>     
	int main() {
		printf("안녕");
		printf("안녕");
		printf("안녕");
		return 0;
	}

그림1

문장이 다르니까 그림1의 왼쪽 처럼 출력될 것 같지만 줄바꿈기능이 없어 오른쪽처럼 안녕안녕안녕으로 출력된다

 

그렇다면 왼쪽 처럼 출력하려면 어떻게 해야할까 

바로 줄바꿈 기호를 넣어주면 된다

#include<stdio.h>     
	int main() {
		printf("안녕\n");
		printf("안녕\n");
		printf("안녕\n");
		return 0;
	}

줄바꿈기호는 \n(역슬래시 n)인데 보통 엔터키 위에 위치한다.

시험에서 낚시문제로 잘 나오므로 \n있나 없나 잘 봐야 한다


2. 변수와 자료형

변수는 데이터를 저장하는 공간이다

a=1이라고하면 a만 나와도 a안에 1이 있다고 생각하면 된다

 

근데 이때 자료형(데이터 타입)마다 변수를 선언하는 키워드(?)가 다르다

정수형 데이터는 int

실수형 데이터는 double

문자형 데이터는 char

표 출처 :  자료형이란? - 한 눈에 끝내는 C언어 기초 (goorm.io)


3. 서식문자

아래와 같이 출력하면 뭐가 출력이 될까?

#include<stdio.h>     
	int main() {
		int a = 3;
		printf("%d", a);
		return 0;
	}

바로 변수 a의 값인 3이 출력된다.

%d가 출력이 되지 않고 3이라고 출력되는 이유는 %d는 서식문자이기 때문이다.

서식문자는 출력하고자 하는 변수의 출력 형태를 지정하기 위해 사용한다

사진 출처 : [C 언어] 서식문자 (변환문자) 의미 자료형 (tistory.com)

 

 

다음 출력 결과는 어떻게 될까

#include<stdio.h>     
	int main() {
		char a = 'A';
		printf("%d\n", a);
		printf("%c\n", a);

		printf("%d\n", a+1);
		printf("%c\n", a+1);
		return 0;
	}

그림2

출력결과는 그림2처럼 출력된다. char변수로 'A'를 받았는데 서식문자가 %d냐, %c냐에 따라 결과값이 완전 달라지는 것을 볼 수 있다.

A를 정수형으로 출력하면 A의 아스키코드 값인 65가 출력되고

A를 문자형으로 출력하면 A가 그대로 출력된다

 

A를 정수형에서 +1을 하면 아스키코드 값 65+1인 66이 출력되고

A를 문자형에서 +1을 하면 아스키코드 값 66인 문자 B가 출력 된다

 


4. scanf()

scanf()는 변수를 입력받을 수 있도록 해주는 함수이다.

scanf()도 printf()와 마찬가지로 #include<stdio.h>가 있어야 쓸 수 있다. 

 

3을 입력받았다고 할 때 아래의 출력결과는 뭘까?

#include<stdio.h>     
	int main() {
		int a;
		scanf("%d", &a);
		printf("%d", a);
		return 0;
	}

출력결과는 3이다

scanf("%d",&a); 에서

&는  앰퍼샌드(ampersand)라고 읽으며 주소연산자라고도 한다

&a이라고 하면 변수a의 주소를 가리킨다

 

왜 그냥 a가 아니라 &a를 쓸까?

임시공간에 저장됐다가 임시공간에 있는 값을 변수의 주소에 저장하고 그 임시공간을 삭제하므로 변수의 주소가 필요한 것이다.

(이해가 안되면 그냥 넘어가고 scanf가 숫자를 입력받는 함수라는 것만 알고가면 된다)

출처 : [C언어] scanf()함수에서 &(ampersand)를 쓰는 이유 (tistory.com)


5. 사칙연산과 증감연산자

사칙연산 순은 수학에서 배운 것과 동일하다

곱하기(*)와 나누기(/)가 먼저고 그다음이 더하기(+), 빼기(-)이다

여기서 추가로 나머지(%)연산자가 있는데 곱하기, 나누기 우선순위와 동일하다

 

9%2하면 나머지는 1이므로 1이 나온다

 

증감연산자라는 것이 있다. ++a, a++ 이런식으로 표현하는데 -도 동일한 방식이다

증감연산자는 곱하기, 나누기, 나머지보다 먼저 연산된다.

 

다음 출력결과를 맞춰보자

#include<stdio.h>     
	int main() {
		int a = 10;
		int b = 15;
		int c = a++ + --b;
		int d = ++a + b--;
        

		printf("%d\n",a); 
		printf("%d\n", b);  
		printf("%d\n", c); 
		printf("%d", d); 
		return 0;
	}
더보기

12

13

24

26

 

처음보면 살짝 머리터질 수 있는 부분인데

++a는 전치연산이고

a++은 후치연산이다

 

전치연산은 앞에 붙어있어서 바로 계산되고

후치연산은 뒤에 붙어있어서 그 다음 라인부터 계산된다

 

c=a(후치연산)+b(전치연산)=10+14=24

a가 후치연산이라 c에는 a가 10으로 계산되지만

변수c에 값이 저장되는 그 다음부터 바로 a가 11이 된다.

 

d=a(전치연산)+b(후치 연산)=12+14=26

a는 전치연산이라 바로 11에서 1이 더해진 값이 d에 들어가고

b는 후치연산이라 14에서 1만큼 빼진 값이 아니라 그냥 그대로 14가 된다

 

시험에 낚시문제로 많이 출제되니 무조건 이해하고 넘어가자


6. 비트연산자

비트연산자 관련문제는 한번도 출제된 적이 없긴 한데 그래도 쉬우니 보고 넘어가자.

우리가 평소에 사용하는 숫자는 10진수이고 컴퓨터에서는 2진수를 사용한다

2진수는 0과 1로 이루어져있다.

 

3을 2진수로 바꾸면 11이다

2진수를 10진수로 바꾸는 방법은 크게 2가지인데 2번째 방법을 많이 사용한다.

 

일단 빈 백지에 128 64 32 16 8 4 2 1 이렇게 숫자를 적는다.

예를 들어 20을 이진수로 바꿔야한다면 위에 있는 숫자로 20을 만들어야한다

20을 만들려면 16+4면 된다

128 64 32 16 8 4 2 1
0 0 0 1 0 1 0 0

16과 4를 제외한 나머지에는 다 0을 대입해준다.

20의 이진수는 10100이 된다

 

비트연산자에 &, ^ , | 부터 알아본다.

&는 둘다 1일 때만 1반환

^는 두개가 1개는 1, 나머지는 0이어야만 1반환

|는 둘중 1개만 1일 때도 1반환

 

3 & 2 라고 한다면 먼저 3과 2를 이진수로 바꾼다 11과 10이다

11

10

이렇게 봤을 때 둘다 1인 위치만 1이고 나머지는 0이 된다

3 & 2라고 한다면 10으로 2가 된다

3^2라고 한다면 01로 1이 된다

3|2라고 한다면 11로 3이 된다

 

다음은 >>, << 연산자이다

이건 자세한 건 생략하고 푸는 방법만 알려주도록 하겠다.

비트를 이동시키는 연산자인데 

8<<2 라고 하면 8에서 2의 제곱만큼 곱해주면된다

8*4이므로 32가된다

 

8>>2 라고 하면 8에서 2의 제곱만큼 나눠주면 된다

8/4이므로 2가 된다

 

>>1이면 2의 1제곱

>>3이면 2의 3제곱

으로 계산하면 된다

 

[정보처리기사/예상문제] - 2023 정보처리기사 실기 예상 문제 모음

C언어 기출문제 모음

비전공자용 C언어 요약 1탄

비전공자용 C언어 요약 2탄(조건문, 반복문, 배열)

비전공자용 C언어 요약 3탄(함수, 포인터)

비전공자용 C언어 요약 4탄(포인터 심화, 구조체)

+ Recent posts