개체와 서비스함수로 구별한다면 ?

개별적으로 움직인다면 개체

노을,나무,언덕 - 고정 

추상화 : 개체의 역할이나 행위가 비슷 할때

 

객체 : 보이는것, 실존하는것, 식별이름

개체 : 유형. 적절한 추상화가 필요.개별적으로 움직일 수 있는 유형

  • 비행기 (왼쪽비행기,오른쪽비행기)
  • 자동차(클래식차,SUV,세단)
  • 사람 또는 더 작은 개체로 보면 농부,행인 

class 농부{

  public void쉬다(){

   }

  public void탈곡하다(){

   }

}

산,달,언덕 : 움직임이없어서 고정배경

 

객체분석

객체지향에서의 캡슐화 : 실생활의 내용을 그대로 표현하는 도구

개체가 하는 서비스함수(행위)를 모아둔것 

 

객체지향이란 ?

프로그램을 구성하는 요소로서 객체라는 것을 중심에두고 프로그램을 만드는것.

 

객체지향의 장점 ?

코드의 구조를 실세계내용을 반영해서 인간의 사고에 가깝게 쉽게 표현한다.

 

 

Summary

  • Lotto구조체사용→외부변화에 취약→캡슐화→캡슐도구에 함수를 모음
  • 기존코드는 함수위주의 코딩. 예 : Lotto.sort(lotto);
  • 자바는 함수사용시 무조건 캡슐화를 해야한다. (클래스를 만들고 클래스안에서 함수를 만든다)
  • 반면 자바스크립트는 클래스없이 함수사용가능.
  • 개체: 구조적인 데이터형식
  • 객체: 개체의  실체, 인스턴스 
  • static메소드 :객체사용하지않음, 클래스이름.메소드이름으로 호출, 언제든지 호출가능,매개변수로 작업
  • 인스턴스메소드 : 객체를 생성후 호출, 객체이름.메소드이름으로 호출, 매개변수없음
  • 함수에서 사용하는 변수가 지역변수인지, this의 멤버변수인지, 전역변수(static)인지 구별할것

 

Object Oriented Programming

  • 객체지향 프로그래밍
  • 객체로부터 출발하는 프로그래밍
  • 객체를 중심에 두는 프로그래밍
  • what → how 
  • 주어,목적어가 우선 ( 행위의 주체가 눈에 띄도록한다)
  • 함수는 동사, 행위
  • lotto.gen(); : lotto를 gen()한다.

 

객체지향 적인 표현식으로 바뀐 함수

객체를 사용하는 함수 : Object function / Instance function / method

static과 매개변수를 지운다.

lotto.대신 this를 쓴다.

외부에서는 객체이름.함수이름()으로 호출

내부클래스에서는 this.가 lotto를 대신한다. → this생략가능Summary

Lotto구조체사용→외부변화에 취약→캡슐화→캡슐도구에 함수를 모음

기존코드는 함수위주의 코딩. 예 : Lotto.sort(lotto);

자바는 함수사용시 무조건 캡슐화를 해야한다. (클래스를 만들고 클래스안에서 함수를 만든다)

반면 자바스크립트는 클래스없이 함수사용가능.

 

 

객체지향 적인 표현식으로 바꾸기

객체를 사용하는 함수 : Object function / Instance function / method

static과 매개변수를 지운다.

lotto.대신 this를 쓴다.

외부에서는 객체이름.함수이름()으로 호출

내부클래스에서는 this.가 lotto를 대신한다. → this생략가능 

라디오의 높이, 라디오의 길이를 말하지않고 라디오라고 말하는 것처럼, 그룹핑해서 쓴다. →표현하는 단위가 됨

                                                .

 

this

인스턴스 함수가 넘겨받는 객체를 참조하는 변수

size는 함수내에서 선언되지 않았다.

size를 전역변수라고 잘못 이해하는 경우가 있다.

Lotto클래스의 private int[] nums;와 private int size는 설계도일뿐이다.

this.size에 값이 대입된것이다.

lotto객체외에 lotto1객체를 또 생성하면 

lotto.nums[i] , lotto.size와 lotto1.nums[i], lotto1.size 에 각각 값이 담기게된다.

 

static 메소드 : 객체를 쓰지않는다. 매개변수로만 넘겨받는다. '클래스이름.메서드이름'으로 호출한다.

인스턴스메소드 : 객체를 넘겨받는 메소드, 객체메소드, 실체메소드, 객체생성 후 사용가능.

 

Getter / Setter

사용자입장에서 생각하기.

main()함수가 있는 Program클래스는 외부이다.(사용자입장)

Lotto{}클래스는 데이터와 데이터에 관련된 메서드의 집합, 제공자입장이다.

main()메소드에서 lotto.getSize()를 호출하면 : lotto에 있는 숫자를 불러와줘.

main()메소드에서 lotto.setSize(6)를 호출하면 : size에 6을 넣어줘.

setSize{ this.size = size(지역변수) } this생략하면 지역변수를 지역변수에넣게된다. 

지역변수size를 this.size에 대입한다.

 

캡슐화

기존 캡슐화 : 데이터변화에 영향을 받는것들을 한곳에 모아 둔것

객체지향 캡슐화 : 객체가 갖고있는 서비스들, 즉 객체가 제공해야할 서비스들을 모아둔것

객체를 행위자로 만드는 작업이다.

Print()함수의 재사용

콘솔출력을 위한 클래스를 만들고 Program클래스에서 LottoConsole.print(lotto)를 호출해서 출력하게한다.

static함수로 만들어 언제든지 호출할 수있게한다. 

static함수는 인자를 전달받으므로 public static void print(Lotto lotto)로 매개변수를 넣어준다.

 


생성자(Constructor)

클래스명(){ }

생성자는 함수명이없지만 객체형식을 클래스형식으로 한정한다는 것을 의미.

반환값X, 매개변수O, 오버로드O

생성자를 사용하는 이유 ?

초기화는 단 한번만 실행되어야한다.

초기화는 다른 어떤 로직보다 먼저 실행 되야한다.

 

기존코드의 문제점:

일반함수였을땐느 init()함수가 한번만 실행 되지 않았고, 먼저 실행되도록 하지 못했다.

lotto.gen();을 언제든지 사용할 수있으며, 무조건 먼저 실행되도록 제어할수 없었다.

 

해결:

Lotto lotto = new Lotto();

객체를 생성할때 자동으로 호출되는 '인스턴스 초기화 메서드'.

 

좌: 객체지향 / 우: 언어의 특성

Summary :

  • 캡슐화란 ? 속성에 접근지시자적용, 해당 속성을 사용하는 함수를 같은 클래스내에서 만듦
  • 데이터의 변화가 외부파일에서 오류를 발생 -> 데이터사용하는 함수를 데이터와 같은 클래스에 둔다
  • 캡슐화를 했지만 데이터를 외부에서 쓴다면 ? 캡슐이 깨진다. ->막으려면 ? -> 접근지시자 사용
  • 접근제어자 : 외부에서 데이터를 볼수 없게하는것 
  • print함수를 분리한 이유: Lotto{}에 포함할 경우 콘솔용이 되어버린다.
  • 함수: static / 객체지향에서 사용하는 함수 : 메소드

 

함수는 원래 외부변화에 영향을 받지 않아야한다.

하지만 다른 클래스에서 데이터계층lotto.nums[i]을 사용할때 문제가 발생한다. 

속성을 정의하는 쪽(Ellipse{ })과 사용하는 사람(main메소드())이 다른경우 :

1. 속성을 간접적으로 쓰기위해 속성과 연관된 함수를 호출. 

2. main에서 속성을 따로만들어도 Ellipse{}클래스안에서 만들어달라고 부탁하는것 

 

도형을 담당하는 데이터가 있다고 가정해보자. 다양한 정수를 Ellipse{ }라고 묶어서 데이터를 개념화시킨다. 데이터를 파악하는게 용이하다.

 

Ellipse{ }안의 속성을 마음대로 쓰는것에 주의해야한다.

직접 사용한다면 각 x,y,w,h를 누가, 어느코드에서 ,몇개를 사용하는지 파악하기가 힘들어진다. → 어느코드에서 오류가 발생하는지 파악하기 힘들다.

 

Ellipse{ }안의 속성(int x,y,w,h)을 쓰는것이 모두 Ellipse{ }안에 있다면 속성명이 변경되는 경우 오류의 범위가 Ellipse{ }안으로 한정된다. 외부에서 속성을 직접사용하는것이 없어진다.

 

Ellipse{ } : 데이터구조를 정의하고있는것, 함수를 모아둘 수 있는 울타리역할→클래스

 

캡슐 : 데이터구조와 함수를 하나로 모아둔것

캡슐화 : 캡슐을 만드는 과정 (함수가 외부영향에 받지않도록 최소화) ↔캡슐이 깨지다.(캡슐밖에서 사용되는경우)

데이터 속성과 데이터를 직접쓰는 함수를 묶는것.

 

캡슐을 깨지못하게 하는 도구 : 접근 제어 지시자

외부에서 아예 접근못하도록 막을 수있다.

protected 자식에게만 접근허락.

private int[] nums ; 

캡슐화 실습

  • main()함수에있을때는 lotto.nums에 에러가 발생한다. int[] nums가 private처리되어 다른클래스에서 접근이 불가능하기 때문이다. 
  • main()함수에 있던 gen()와 sort()함수를 Lotto{}클래스 안에 넣었다. lotto.nums[] 오류가 사라진다.
  • 속성에 접근지시자적용, 해당 속성을 사용하는 함수를 같은 클래스내에서 만듦

 

 

 

print()함수를 Lotto{}에 포함하지않은 이유 ? 

사용자에게 보여줄 수 있는 옵션들 : 콘솔출력 / 윈도우 출력 / 웹 출력/ VR

print()함수를 Lotto에 포함하면 콘솔용 프로그램이 된다. 특정UI로 종속되어버린다.

 

Lotto{}클래스에는 입력버퍼가없다. ->데이터입력이 없다.

배열[]인 메모리할당을 한다. 

사용자에게 입력을 받거나 파일에서 읽어들이는 버퍼가 없다.

 

private int[] nums ; 외부접근막았으니 

getNum(Lotto lotto, int i): Lotto클래스의 정수를 하나씩 꺼내줄 수 있는 함수를 만든다.

외부에서는 Lotto.getNum() 함수를 통해 int[] nums에 담긴 값을 불러온다. (클래스명.함수명으로 호출)


Getter함수(값을 얻어오는 함수 Getter, 값을 적용하는 함수Setter)

외부에있는 print()함수에서 int[] nums에있는 숫자를 가져오기위한 함수getNum()를 Lotto클래스에 만든다.

외부클래스에서는 Lotto.getNum()을 통해 숫자를 가져온다.

 

Program 클래스

getNum[]함수는 lotto가 가지고있는 데이터중에서 i번째 숫자를 반환해주는 역할

함수가 해야할 일을 Lotto{}클래스에서 만들어준다.

 

lotto라는 객체,실체,인스턴스를 공유한다

Lotto{}클래스의 nums명을 바꿔도 Lotto클래스안에서만 오류가 발생한다.

int[] nums변수명 변겨시 Lotto클래스에서만 에러발생

초기화함수 static void init()

main()에서 Lotto.init();호출하고 

nums배열 초기화(lotto.nums = new int[6];를)하는 init()메소드를 Lotto클래스에서 만든다.

Pritn()함수가 밖에 있기때문에 size에 직접 접근할 수없고 getSize()함수를 통해 가져온다.

Lotto.getSize()

Program클래스

package ex6.캡슐화.로또;

import java.util.Random;

public class Program {
	
	// 로또를 출력하자
	private static void print(Lotto lotto) {
		//밖에있으니까 캡슐깨지않고 함수를통해얻어야함
		for (int i = 0; i < Lotto.getSize(lotto); i++) {
			System.out.printf("%d", Lotto.getNum(lotto, i));
			if (i < 5)
				System.out.printf(",");
		}
		System.out.println();
	}

	public static void main(String[] args) {// 어플리케이션역할
		//lotto객체를 생성.기존gen()함수에서 분리함 : gen()함수는 숫자만생성하도록
		Lotto lotto = new Lotto();

		//lotto.nums = new int[6];
		Lotto.init(lotto);			
		
		//int[] lotto;

		lotto = Lotto.gen(lotto);//Lotto의 인스턴스(객체,실체)를 만드는 함수

		print(lotto);
		
		Lotto.sort(lotto);

		print(lotto);
		
	}// main메소드 끝

}
package ex6.캡슐화.로또;

import java.util.Random;

//재사용
public class Lotto {
	private int[] nums; // Lotto의 청사진,단순 정의,
	private int size;

	public static int getNum(Lotto lotto, int i) {
		int num = lotto.nums[i];
		return num;
	}
	public static void init(Lotto lotto) {
		lotto.size = 6;
		lotto.nums = new int[lotto.size];
	}

	public static int getSize(Lotto lotto) {
		return lotto.size;
	}

	public int getSize() {
		return size;
	}


	static Lotto gen(Lotto lotto) {
//		Lotto lotto = new Lotto(); // 4바이트
//		lotto.nums = new int[6]; // 배열의 공간생성
		Random rand = new Random();
		for (int i = 0; i < 6; i++) {
			lotto.nums[i] = rand.nextInt(45) + 1;
		}
		// 자판기
		return lotto;
	}// gen()끝

	public static void sort(Lotto lotto) {

		for (int j = 0; j < lotto.size - 1; j++) {
			for (int i = 0; i < lotto.size - 1 - j; i++) {
				int compare;
				if (lotto.nums[i] > lotto.nums[i + 1]) {
					compare = lotto.nums[i];
					lotto.nums[i] = lotto.nums[i + 1];
					lotto.nums[i + 1] = compare;
				}
			}
		}
	}// sort()끝

}

자바는 컴파일하면 바이너리코드가 만들어진다. 다른사람이 만든 컴파일된 결과물을 가져다 쓸 수 있다.

작성한 소스코드를 컴파일하고 jar파일로 압축해 다른곳에서 결과물을 재사용할 수있다.

 

jar파일생성 방법

해당 클래스파일이있는 프로젝트 클릭 → 마우스 오른쪽 →Export→JAR file 선택 후 next

→ 변환하고자하는 파일위치 선택 → 필자의 경우 Lotto.java 선택→저장할경로선택 finish

 

선택한 경로에 들어가면 압축된 jar파일이 확인가능하다.

이때 확장자를 zip파일로 바꾸면 프로젝트폴더안에 해당 저장된 클래스파일을 확인 할 수있다.

 


 

배포된 실행파일 이용하는 방법

배포된 파일을 적용할 프로젝트선택 →마우스 오른쪽클릭 build path Configure Build Path

→Libraries →Add External Jars→해당jar파일을선택 →Apply and Close


 

Confusing things:

개념화된 데이터를 사용하는것

 

코드의 집중화 및 재사용

  • 집중화 : 함수를 생성한 곳만 수정하면 호출한 부분에서는 자동으로 업데이트 된다. (print()메소드를 Program 클래스에서 한번만 적고, 수정하면 호출했던 main클래스의 내역도 자동으로 반영된다. (코드를 줄일 수있다)
  • 재사용: 다양한 프로그램개발에 따른 코드 재사용이 가능하다. 로또 프로그램을 콘솔,웹,앱 등에 맞게 다시 만들 필요없이 Lotto class를 통해 재사용을 할 수있다. (첫번째 사진의 오른쪽)

 

데이터입력과 출력의 분리. 클래스분리

데이터를 만들어내는 부분은 재사용이 가능

다른클래스에있는 함수호출

lotto = Lotto.gen();  Lotto클래스의 gen()함수를 불러와서 lotto에 대입.

성을 붙여서 부르듯이 Lotto.get()로 불러줘야한다.

같은울타리(같은 클래스)에있는 메소드는 메소드이름만으로 호출가능

 

 


실행코드 재사용

새로운 프로젝트 생성 -> Program 클래스생성

함수를 재사용한다는 두가지로 볼 수 있다.

1. 소스코드 재사용 : 소스코드가 모두 오픈되어야 한다.

2. 실행코드 재사용 :컴파일된 결과물을 재사용.(바이너리코드

자바 실행파일 재사용/ jar파일 생성/ 외부 jar파일 추가하기

(소스코드를 컴파일한 결과물.class을 압축하고 재사용 할 예정)

 

jar파일을 libraries에 반영하면 lotto = Lotto.get();하면 정상반영된다.

만약 에러가 뜬다면 기존 jar파일의 메소드가 public으로 설정되어있는지 확인한다. 

gen(), sort()를 직접만들지않고, 컴파일된 압축파일을 이용해 출력이 가능하다.

접근제한자가 걸린메소드를 반영하면 에러가뜬다.
컴파일된 결과물 재사용했을때 정상작동 되는 모습

불러온 gen(), sort()메소드는 소스코드를 확인할 수없다.


구조체 / class 생성 / 데이터를 묶어서 관리

배열을 바로출력 vs 변수로 출력 (구조체)

추가 문제점이 발생한다. int[] 정수배열이 lotto인가 ?

기본형식을 가지는것보다 데이터는 개념화된 데이터가 코드안에 묻어나야한다.

ex, 학생,주문,사원,발주 등 정수배열, 문자배열이겠지만 단위를 묶어서 의미가있는 단위로 쓰는게 바람직하다. (유지보수에도 이점)

개념단위데이터로 표현

Lotto lotto ; 로 자료형을 정의한다.

 

더큰 단위의 개념적인 것을 정의해서 써왔다. (데이터를 묶는것)

다양한 데이터를 Covid로묶은것과 같다

int[] lotto를 Lotto 자료형으로 이용하기위해 main()메소드에서 Lotto lotto; 변수선언한다.

Lotto 클래스안에 담긴것들을 Lotto. 으로 사용할 수 있게된다. 

정수배열 int[]를 담고있는 Lotto라는 개념으로 데이터 단위를 만들어서 한번에 관리한다. 

int[] lotto보다는 Lotto가 바람직하다. 데이터안에 int[]이 다양할 수 있게때문에 혼란이 생길 수있다. 

 

Lotto클래스에 멤버변수가 여러 정수가 있을때 예시

 

객체를 생성해서 호출

 

 

데이터를 묶어서 관리하는 이유

의미를 분명히 할 수있는 자료형으로 해야한다.

각각 String, int를 부르는것보다 stu1식으로 해야 학생데이터인지, 선생님 데이터인지 구분할 수있다.

 

Lotto클래스의 int[]배열을 각각 관리했다면 나중에 유지보수하기 어렵다. 나중에 시간이 지났을때 무슨데이터였는지 기억해내기 힘들다.

Lotto lotto;로 묶어서 사용할것

Lotto라는 자료형을만들어써서 기존의 다른 정수배열과 구분한다. 코드정리

사용자가 원하는 자료형을 명시해서 쓸 수 있다.

하지만 불편함이 두가지 발생한다.

1. 정의하는데 추가 코드발생

2. 계층이 생긴다 lotto.nums[i]로 불러서  써야한다.

 


계층을 두고있는 구조체 사용시 

함수를 흔히 자판기, 블랙박스라고 한다.

우리는 자판기안쪽 구현방식을 알 필요가 없다.

함수구현이 나에게는 몰라도되지만 원하는 기능만 실행하면 된다.

 

함수의 매개변수 이름은 외부에서 사용하는 변수명에 영향을 받지않는다. (지역화,고립화)

계층을 두고있는 구조체를 쓸때 lotto.nums[i]는 지역화가 아니다. Lotto클래스에서 int[] nums;명이 변경된다면 오류가 생긴다.

이름변경에 영향을 받는다
Lotto클래스의 이름을 변경 후 에러발생

외부의 변화에 취약해졌다. 어떻게 해결해야할까 ? -> 캡슐화의 시발점 

함수를 사용 하는 이유 ?

코드를 나눠서 만들기 위해. 코드의 재사용, 집중화, 인터페이스역할(간접적 사용)

 

참조변수사용시 null 발생

변수가 값을 가지고 있는 상태에서 써야한다.

 

 

코드를 작성한 후에 함수로 코드를 나누는 작업 : Bottom -> up

함수로 코드를 작성하고 그것을 구현하는 작업 Top->Dowon

Top : 업무적인 내용, down (알고리즘, 오픈소스)

 

 

데이터를 얻는부분과 출력하는것의 분리

분리전

print메소드는 콘솔출력을 위한것.

데이터를 얻는것과 출력을 함께 두면 콘솔출력으로만 써야한다. ->재사용률이 떨어진다.

결합도를 낮추기 위해 분리시킨다.

 

최대값을 얻는 메소드와 출력하는 메소드를 분리

분리후


load함수 만들기

메소드호출

load안에서 공간을(new String[count][])를 만들어서 rows값을 전달.

메소드의 결과값을 반환해야하므로 rows의 자료형인 String[][]를 메소드상단에 적어준다.

 

함수가 끝나면 함수 안에있는 변수들은 다 사라진다. (지역화된 변수가 사라진다)

사라지면서 반환하기 위해 rows = load(rows,count); rows에 담아준다.

package ex5.fnc;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Scanner;

public class Program3MultiArray4 {


public static void main(String[] args) throws IOException {
      
	int count = 0;
	String[][] rows = null;
	// ---------------------------------------------------------
	// 레코드 개수를 알아내는 코드
	count = getCount();	
	
	// --------------------------------------------------------
	//	rows = new String[count][];
	// 레코드를 로드하는 코드
	rows = load(rows, count); //rows:참조변수 / count:값변수
	
	// ---------------------------------------------------------
	// 레코드를 출력하는 코드
	printCovid19List(rows, count);

	// ---------------------------------------------------------
	// 검사진행자 누적수를 얻는 코드
	int total = getTotal(rows, count);// f3누르면 메소드로이동
	System.out.println(total);
	System.out.println();
	// ---------------------------------------------------------
	// 1.일별 가장 많은 검사진행수는? 몇입니꽈~
	printMax(rows, count);

	// 2.감사진행수가 가장 많았던 날짜는?
	printB(rows, count);
	// ---------------------------------------------------------
	// 확진자 수가 늘어난 일자와 수를 출력하시오.
	printA(rows, count);

	// 확진자 수가 늘어난 일자와 수를 다음 배열에 담아주시오.
	String[][] results;
	int resultCount = 0;
	
	{
		// 확진자 수가 달라질 때마다 resultCount를 증가시킴으로써 증가되는 일자 수를 구하는 코드
		int old = 0; // 현재 확진자 수

		for (int i = 0; i < count; i++) {

			// i 번째 행의 확진자 수
			int current = Integer.parseInt(rows[i][1]);

			// i 번재 확진자(current)와 이전 확진자수(old)가 다르다면
			if (old != current) {
				// 확진자 수가 달라지는 일자의 수를 증가
				resultCount++;

				old = current;
			}
		}

		System.out.println(resultCount);

		results = new String[resultCount][];

		String date = "";
		int diff = 0;

		old = 0; // 현재 확진자 수

		int index = 0;
		for (int i = 0; i < count; i++) {
			int current = Integer.parseInt(rows[i][1]);

			if (old != current) {
				diff = current - old;
				date = rows[i][0];
				// 코로나19 데이터 행을 저장하기 위한 배열
				String[] row = new String[2];
				row[0] = date; // date
				row[1] = String.valueOf(diff); // diff

				results[index++] = row;

				old = current;
			}
		}

		System.out.println("작업완료");

	}

}//main메소드 끝


static void printCovid19List(String[][] rows, int count) {
	System.out.println("// 레코드를 출력하는 코드------------------------");

	for (int j = 0; j < count; j++) {
		for (int i = 0; i < 10; i++) {
			System.out.printf("%s", rows[j][i]);

			if (i < 10 - 1)
				System.out.printf(",");
		}
		System.out.println();
	} // 큰for문끝
}// printCovid19List()끝
	// --------------------------------------------------------

static int getTotal(String[][] rows, int count) {
	int total = 0;

	for (int i = 0; i < count; i++)
		total += Integer.parseInt(rows[i][3]);

	return total;
}

// ---------------------------------------------------------
// 크로스방향으로 단순히 나누기만 한 코드
// 좀 더 개선해 볼 수 있는 여지가 있는가 ?
// 함수의 4가지 특징 중에서 재사용을 생각해보면 ?
static int getMax(String[][] rows, int count) {
	int max = 0;
	int current;

	for (int i = 0; i < count; i++) {
		current = Integer.parseInt(rows[i][3]);
		if (current > max)
			max = current;
	}
	return max;
}

// ---------------------------------------------------------
static void printMax(String[][] rows, int count) {

	int max = getMax(rows, count);// 메소드의 리턴값이 max에 담긴다.

	System.out.printf("max: %d\n", max); // <-콘솔출력을 위한것, 데이터얻는것과 출력을 함께두면 전체적으로 콘솔출력용으로만써야된다.
	System.out.println();

}

// ---------------------------------------------------------
// 확진자 수가 늘어난 일자와 수를 출력하시오.
static void printA(String[][] rows, int count) {

	String date = "";
	int diff = 0;

	int old = 0; // 현재 확진자 수
	int index = 0;
	for (int i = 0; i < count; i++) {
		int current = Integer.parseInt(rows[i][1]);

		if (old != current) {

			diff = current - old;
			date = rows[i][0];

			old = current;
			System.out.printf("일자와 수%d : %s, %d\n", index++ + 1, date, diff);
		}
	}
}

// ---------------------------------------------------------
// 레코드를 로드하는 코드
static String[][] load(String[][] rows, int count) throws IOException {
	rows = new String[count][];

	FileInputStream fis = new FileInputStream("res/corona.csv");
	Scanner fscan = new Scanner(fis);

	String line;

	fscan.nextLine();

	for (int i = 0; i < count; i++) {
		line = fscan.nextLine();
		rows[i] = line.split(",");
	}

	fscan.close();
	fis.close();

	return rows;
}

// ---------------------------------------------------------
// 2.검사진행수가 가장 많았던 날짜는?
static String getDate(String[][] rows, int count) {
	
	String date = "";
	int idx = 0;
	int max = getMax(rows, count);
	
	for (int i = 0; i < count; i++)
		if (max == Integer.parseInt(rows[i][3])) {
			idx = i;
			break;
		}
	date = rows[idx][0];
	return date;
}

// ---------------------------------------------------------
// 2.검사진행수가 가장 많았던 날짜는? 출력
static void printB(String[][] rows, int count) {

	String date = getDate(rows, count);

	System.out.printf("%s", date);
	System.out.println();
}
// ---------------------------------------------------------
static int getCount() throws IOException {
	int count = 0;
	FileInputStream fis = new FileInputStream("res/corona.csv");
	Scanner fscan = new Scanner(fis);

	// while 반복을 하면서 count++ 연산을 한다. 마지막 줄을 만날 때까지
	while (fscan.hasNextLine()) {
		fscan.nextLine();
		count++;
	}

	fscan.close();
	fis.close();

	count--;//반환값필요

	return count;
}

}//class끝

코드정리란 ?

방정리. 개발자를 위한것

물리적으로 다른파일에 둚. 메인함수에서 분리시킴. 재사용가능

 

코드 정리가 어려운 이유는 

필요성을 못느끼고 익숙치 않아서이다.

 

자바의 구조체

클래스, 캡슐화.

객체는 캡슐화된 데이터를 의미

 

구조체와 배열의 차이

1.큰방에 라벨링이 된것 같은 특징으로 가독성이 좋다.

2.다양한 형식을 담을 수있다.

 

함수 와 인터페이스

함수는 능력이 많다.

코드를 자를때도 함수사용.

인터페이스처럼 구현능력을 숨길때도 함수사용

인터페이스가 함수이지만, 함수가 인터페이스는 아니다.

 

함수를 이용하면

  • 코드의 직접사용을 차단, 간접적 사용
  • 코드를 작게 나누어서 만들 수 있다.
  • 코드를 집중화 할 수있다. ( 한 개만 수정하면 나머지 자동수정)
  • 코드를 재사용 할 수 있다.

 

함수 이용해서 코드정리

public class Program{

        메소드생성(자료형 매개변수){ }

 

        public static void main(String[] args){

        메소드호출(참조변수);

        }

 

}

 

 

 

메소드생성
메소드호출


 

메소드생성
메소드호출


메소드생성
메소드호출

 

메소드

static 자료형 메소드이름(매개변수 자료형 매개변수이름){ }

 

 

메소드안 return

 

생성할 메소드명();을 입력 하면 빨간줄이생기고 creat method알림이뜬다. 클릭하면 자동틀완성.

 

 

메소드호출시 순서,갯수,자료형 모두 일치시켜야한다.

 

문제

package ex5.fnc;

public class Program {

	static int power(int x) {
		return (x+3)*(x+3);
	}
	
	static int add(int x,int y) {
		return x+y; //return까지 실행한다.
	}
	static void print(int x) {
		System.out.println(x); 
		//반환하는게없다	
	}
	
	static void printSum(int x,int length) {
		int sum = 0;
		
		if(length <= 0) {
			System.out.println("length에 잘못된 값을 입력함");
			return ;
		}
		
		for(int i=0 ; i< length ; i++)//	
			sum += (x+i);
			
		for(int i=0 ; i< length ; i++) { //출력
			System.out.printf("%d",x+i);
			
			if(i<length-1)
				System.out.print("+");
			
		}
		System.out.print("=");
		System.out.printf("%d\n",sum);
	} 
	


	public static void main(String[] args) {
		
		// power(x) = (x+3)*(x+3)+x;
		//add(x,y) = x+y
		int c = add(3,4);
		
		System.out.println(c);
		System.out.println(add(5,6));
		
		//print(x) = output : x
		print(30);
		
		//printSum(x,length) //x:2 ,length:3->2+3+4

		printSum(3,3);

	}

}

 

 

2차원배열활용
구조체활용

동일한 결과값을 나타내지만 위의 코드보다 아래코드가 이해도가 높다.

배열로만 출력했을땐 어떤 자료들이 더해지는지 알 수 없다.(알기 힘들다)

이 데이터가 어떤 데이터인지, 의미가 더 살아있다.

 

구조체를 이용하는것이 바람직하다.

데이터를 담을때 데이터의 의미를 살리는 변수이름을 만들고,

관련데이터를 그룹핑해서 명명되어있는 이름을 쓰는것이 좋다.

 

변수타입이 서로 다 같더라도 구조체를 사용하는것이 좋다.

모두 정수라도 의미를 살려서 붙이는것이기때문이다.

 

 

 

Confusing things :

  • 객체생성의 기본원리
  • 참조형 배열생성과  객체생성의 차이
  • 객체생성과 초기화의 차이
  • 배열참조변수 list가 null인것과 list[0]이 null인것의 차이

객체생성

객체생성 (객체가 가진 속성을 사용하기위해)
클래스명 변수명; //참조변수선언
변수명 = new 클래스명(); //객체의 주소를 참조변수에 저장

객체사용방법 :
변수명.메서드명();
변수명을 이용해 점뒤에있는 메서드를 이용


배열참조변수 list가 null인것  vs  list[0]이 null인것의 차이

Covid19[] list = new Covid19[3];

list[0].date = "2020";

list는 배열객체가있음(3개짜리만들어짐), null이 아님.

list[0]은 null, NullpointerException발생

 

 

Covid19[] list = null;

list 자체가 null, 배열이아니다.

list사용시 NullpointerException 발생

 

Covid19[] list = new Covid19[10];

list[0].date = "hello";

list는 배열객체만가지고있다.

list[0] 는 가리키는곳이없다. (객체생성이 안되었다)

에러발생한다. 이름에 해당되는 list[0]에 객체생성이안되어있기때문이다.

list[0] = new Covid19(); (list[0]에 Covid19()객체를 대입 해줘야한다.)

list의 자료형이 Covid19()이기 때문이다.

 

 

int a = new int[3];

정수 변수가 3개 만들어짐.

정수를 담을 수있는 공간 3개 생성

a[0], a[1],a[2] 변수가 만들어진다.

 

 

배열의 자료형 : 기본형이 아닌 참조형이라면 ?

Covid19[] covid = new Covid19[3]; 의미

 

Covid19 a;

Covid19 b;

Covid19 c;

Covid19 변수 3개를 한번에 만들어서 사용하기위한것이 Covid19[3] 배열이다.

배열객체만 만들어지는것, Covid19()객체는 만들어지지않았다.

배열생성은 변수3개를 만들뿐 객체를 생성하지않았다.

확진자수, 격리자수 등 저장할 공간은 만들어지지않았다.

기본형이 아닌것들은 heap영역에 공간을 만들어야 값을 넣을 수 있다.

 

Covid19() 객체를 만들려면 new연산자를 통해 객체를 생성해야한다. (변수선언,생성과 비슷하다)

Covid19 a = new Covid19();

Covid19 b = new Covid19();

Covid19 c = new Covid19();

마찬가지로 Covid19 배열도 new연산자를 통해 객체를 생성해야한다.

covid = new Covid19();

 

 

객체생성 후 대입

list[i] = covid; // 담아서 쓰는것

list[i] = Covid19(); 도 되지만, 이미 윗 코드에서 Covid19 covid = new Covid19()를 통해 참조변수를 만들었으므로 참조변수를 사용한다.

초기화가 아니라 객체생성이다.

 

stack : 선언을 통한것만 저장

heap : new연산자를 통해만들어진 객체만

 

 

list[0].date 와 temp.date의 차이

임시변수선언없이 list[0]로 사용하면 매번 list[0].date , list[0].cases, ..로 계속써야한다.

Covid19()클래스에 있는 변수를 쓰기위해 list[0]와 temp모두 사용 할 수있지만 임시변수쓰는것이 복잡도를 낮출 수있다.

변수는 이름을 여러개 가질 수 있다.

 

 

 


 

배열생성후 객체생성을 하지않으면 null 오류가 발생한다.

맨 위의 상단에 Covid19[] list = null; 이라고 선언했기때문에

출력시 list자체가 null이라는 오류가 뜬다.

null 오류

package ex4.struct;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.Scanner;

public class prac1 {

	public static void main(String[] args) throws IOException {

		 int count = 0;
		 Covid19[] list = null;
	      //---------------------------------------------------------
	      // 레코드 개수를 알아내는 코드
	      {
	         FileInputStream fis = new FileInputStream("res/corona.csv");
	         Scanner fscan = new Scanner(fis);
	         
	         // while 반복을 하면서 count++ 연산을 한다. 마지막 줄을 만날 때까지
	         while(fscan.hasNextLine()) {
	            fscan.nextLine();
	            count++;
	         }
	         
	         fscan.close();
	         fis.close();
	         
	         count--;
	      }
	      //--------------------------------------------------------
	      // Covid19를 로드하는 코드
//	      Covid19[] list = new Covid19[count];
	      {
	         FileInputStream fis = new FileInputStream("res/corona.csv");
	         Scanner fscan = new Scanner(fis);
	         
	         String line;
	         
	         fscan.nextLine();
	   
	         for(int i=0; i<count; i++) {
	            line = fscan.nextLine();
	            String[] tokens = line.split(",");
	            Covid19 covid = new Covid19(); //covid는 지역화된 변수라 }만나면 사라지고 반복되면서 다시생긴다

	            covid.date = tokens[0];
	            covid.cases = Integer.parseInt(tokens[1]); //int = String
	            covid.deaths = Integer.parseInt(tokens[2]);
	            covid.tests = Integer.parseInt(tokens[3]);
	            covid.selfIsolation = Integer.parseInt(tokens[4]);
	            covid.release = Integer.parseInt(tokens[5]);
	            covid.recover = Integer.parseInt(tokens[6]);
	            covid.selfQuarantineDomestic = Integer.parseInt(tokens[7]);
	            covid.selfQuarantineImported = Integer.parseInt(tokens[8]);
	            covid.pubDate = tokens[9];
	            
	            list[i] = covid;        
	            
//	            list[i] = covid.date; //covid.date는 String 자료형불일치            
	         }      
	         
	         fscan.close();
	         fis.close();
	      	}

	}

}

 

count만큼 배열을 만들어준다.

Covid19[] list = new Covid19[count];

package ex4.struct;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.Scanner;

public class prac1 {

	public static void main(String[] args) throws IOException {

		 int count = 0;
	      //---------------------------------------------------------
	      // 레코드 개수를 알아내는 코드
	      {
	         FileInputStream fis = new FileInputStream("res/corona.csv");
	         Scanner fscan = new Scanner(fis);
	         
	         // while 반복을 하면서 count++ 연산을 한다. 마지막 줄을 만날 때까지
	         while(fscan.hasNextLine()) {
	            fscan.nextLine();
	            count++;
	         }
	         
	         fscan.close();
	         fis.close();
	         
	         count--;
	      }
	      //--------------------------------------------------------
	      // Covid19를 로드하는 코드
	      Covid19[] list = new Covid19[count];
	      {
	         FileInputStream fis = new FileInputStream("res/corona.csv");
	         Scanner fscan = new Scanner(fis);
	         
	         String line;
	         
	         fscan.nextLine();
	   
	         for(int i=0; i<count; i++) {
	            line = fscan.nextLine();
	            String[] tokens = line.split(",");
	            Covid19 covid = new Covid19(); //covid는 지역화된 변수라 }만나면 사라지고 반복되면서 다시생긴다

	            covid.date = tokens[0];
	            covid.cases = Integer.parseInt(tokens[1]); //int = String
	            covid.deaths = Integer.parseInt(tokens[2]);
	            covid.tests = Integer.parseInt(tokens[3]);
	            covid.selfIsolation = Integer.parseInt(tokens[4]);
	            covid.release = Integer.parseInt(tokens[5]);
	            covid.recover = Integer.parseInt(tokens[6]);
	            covid.selfQuarantineDomestic = Integer.parseInt(tokens[7]);
	            covid.selfQuarantineImported = Integer.parseInt(tokens[8]);
	            covid.pubDate = tokens[9];
	            
	            list[i] = covid;        
	            
//	            list[i] = covid.date; //covid.date는 String 자료형불일치            
	         }      
	         
	         fscan.close();
	         fis.close();
	      	}

	}

}

 

 

 

list 자체는 배열객체만 가리키고있어서 주소의 변화가없다.

list[i]는 Covid19()객체를 가리키고있어서 주소가 바뀐다. for문의 반복으로 객체가 계속 생성되기때문

covid도 Covid19()객체를 가리키기 때문에 list[i]와 주소가 동일하다.

 

코드

1. 프로그래밍을 위한 코드 : 실행을 위한 코드

2. 함수지향 : 구조체 , 함수

3. 객체지향 : 캡슐화, 상속, 다형성

 

코드의 크기가 커지면 ?

가독성이 떨어지고, 코드의 중첩이 생긴다, 데이터수 증가

중복된 코드블럭이 생긴다.

 

다음에도 같은 코드를 또 사용 하고싶다면 ?

나누어서 다시 사용하고싶은 블록을 분리

 

자바는 가장 객체지향적인 언어, 통일감있는 코드가능

스크립트언어(ex, 파이선) 은 메인함수가 없고, 모듈화가없어 바로 사용가능

 

구조체란 ?

다양한 데이터를 담을 수 있는 도구

 

배열의 불편함 :

다 같은형식을 사용해야한다. 결과에 대한 의미가 묻어나지않는다 (ex: row[i][0])

의미론적으로 와닿지않는다.

->배열이 불편함을 구조체가 해결 할 수있다. 

 

메모리공간은 Heap 과 Stack 이있다.

Heap : 비예약석, 동적메모리할당, 연산자(new, = )에 의해서 마련되는 공간

Stack : 예약석, 선언으로 마련되는 공간

 

기본형은 선언만으로 공간할당 stack

참조형은 new연산자를 통해서만 공간할당, 실행 후 메모리가 할당된다 (heap)

String x = new String("hi");

x : main Stack에 공간생김

"hi" : heap 에 공간생김 , heap에 객체담김코드

 

1. 프로그래밍을 위한 코드 : 실행을 위한 코드

 

2. 함수지향 : 구조체 , 함수

 

3. 객체지향 : 캡슐화, 상속, 다형성

 

 

 

데이터를 묶어 그룹을정하는것 구조체 ->계층도만들어짐

 

 

{ String  y = new String("a")};

{}로 지역화처리되어있어서 괄호가 끝나면 사라진다.

y : stack에 블록이 마련된다.

"a" : heap영역에 메모리할당

{}괄호가 닫히면 stack block1이 사라지고, "a"를 가리키던 stack이 사라지면서 heap에있는 "a"는 가비지처리된다.

자바실행환경이 참조가 없는 것들을 찾아 자동으로 처리해준다. (처리시점은 실행상황에따라 달라진다)

 

{int y = 3;}

{}로 지역화되어 stack에 블록이 생긴다 -> 3이 y에 담긴다. ->{}끝나면 사라진다. -> main 스택도 사라진다.

 

 

 

구조체

구조체: Grouping, 의미도 분명히 할 수있고, 묶어서 사용.

자바의 클래스 : 데이터구조, 캡슐화

상: 배열 / 하:구조체


구조체 실습

1.Covid19 클래스생성 후 date, deaths, cases, tests 인스턴스생성한다.

2.Program 클래스에서 Covid19의 객체를 생성 후 Covid19의 인스턴스를 불러와 배열에 연결시킨다.

list[0] = new Covid();

list배열 0번째배열에 Covid19()클래스를 연결시킨것

이중배열은 다른배열을 참조한것 (ex list[][])

구조체는 list이 Covid()객체를 참조한것.

list[0].deaths =12; deaths에 12대입.

 

list[0] = new Covid();를 안한경우

list[0].는 null값이다.

디버깅했을때

list[0] = new Covid(); 객체생성해서 대입 하면

객체 주소값이 연결된다.

 

자바는 나중에 참조를 계속 바꿀수있다. 이름표를 떼었다 붙였다하듯이 사용가능

참조형변수 이름표의 크기는 4바이트

배열의 선언

배열의 공간을 미리 선언할수도 new String[3][4]

나중에 공간을 채울수도있다. new String[3][]

예시는 String이지만, int 등 다양하다.

 

가변배열[n][]

사용자한테 입력을 받을때마다 또는 데이터를 읽을때 공간을 만든다.

공간을 나중에 만들었어서 참조를 나중에바꿔서 아예 다른배열을 가리킬수도있다.

 

자바의 배열

코드사용상 c언어와 똑같아보인다. 자바는 톱니형식. 겉으로보이기엔 그냥배열처럼보이지만 참조배열이라서

자바는 길이를 바꿀 수 있다.

 

 

 

데이터결과물을 다른배열에 담기

1. 확진자수가 증가한 횟수 구하기

      // 확진자 수가 늘어난 일자와 수를 다음 배열에 담아주시오.
      String[][] results;   
      int resultCount = 0;
      
      {
         // 확진자 수가 달라질 때마다 resultCount를 증가시킴으로써 증가되는 일자 수를 구하는 코드
         int old = 0; // 현재 확진자 수
                  
         for(int i=0; i<count; i++) {
            
            // i 번째 행의 확진자 수
            int current = Integer.parseInt(rows[i][1]);
            
            // i 번재 확진자(current)와 이전 확진자수(old)가 다르다면
            if(old != current) {
               // 확진자 수가 달라지는 일자의 수를 증가
               resultCount++;
               
               old = current;   
            }
         }

String[][] results;

전역화해서 나중에 사용할 수 있게한다.

 

if( old != current )

이전확진자수와 i번째확진자 수를 비교한다. 숫자가 다르면 카운트를 더한다.

후에 old = current; i번째 숫자를 이전확진자 수에 대입한다.

 

 

2. 증가한 횟수를 이용해 새로운 2차배열 생성,

 [확진자 증가한 날짜, 증가수] 를 1차원 배열row[]에 넣기.

각 1차원배열을 2차원배열results[][]에 대입

results = new String[resultCount][];
         //이름표: 4바이트, 주소는 4바이트=32비트         
         String date = "";
         int diff = 0;
         
         old = 0; // 위에서 쓰였으므로 초기화시키기
         
         int index = 0;
         for(int i=0; i<count; i++) { //데이터 총 행인 76까지반복
            int current = Integer.parseInt(rows[i][1]); //제주 확진자
            
            if(old != current) {//기존확진자와 현재확진자비교
               
               diff = current - old;//차이 = 현재확진자-기존확진자
               date = rows[i][0]; //차이발생한 날
               old = current; //기존확진자->현재확진자
               
               String[] row = new String[2];
               row[0] = date;       // date
               row[1] = String.valueOf(diff); // 정수->문자열변환
               
               results[index] = row; //index++후 출력하면 인덱스1이 증가되어 다음인덱스가출력됨
               
               System.out.println(Arrays.toString(results[index]));
               
               index++;//results배열인덱스 증가
            }
         }         
         System.out.println("작업완료");

int index = 0;

변수를 쓰는곳 가까이에 선언한다.

 

String[] row = new String[2];

row[0] = date;

row[1] = String.valueof(diff);

if문의 조건이 성립되어 date, diff가 계산이 되고, 계산된 date와 diff를 1차원배열 row[]에 담아준다.

 

results[index++] = row;

1차원배열row[]를 2차원배열results[index]에 연결시킨다.

results[i]를 하게되면 ArrayIndexOutOfBoundsException발생한다. 이유는 i가 for문범위인 count(76)까지 돌게된다.

results[resultsCount][];로 선언했고 resultsCount는 20이므로 범위를 초과하게된다.

i과 상관없이 새로운 변수 index를 선언하고 반복문이 실행되는 동안 증가할수있게 index++를 한다.

자바의 2차원배열은 1차원배열이 여러개가 연결된것.

 

 

 // 확진자 수가 늘어난 일자와 수를 다음 배열에 담아주시오.
      String[][] results;   
      int resultCount = 0;
      
      {
         // 확진자 수가 달라질 때마다 resultCount를 증가시킴으로써 증가되는 일자 수를 구하는 코드
         int old = 0; // 현재 확진자 수
                  
         for(int i=0; i<count; i++) {
            
            // i 번째 행의 확진자 수
            int current = Integer.parseInt(rows[i][1]);
            
            // i 번재 확진자(current)와 이전 확진자수(old)가 다르다면
            if(old != current) {
               // 확진자 수가 달라지는 일자의 수를 증가
               resultCount++;
               
               old = current;   
            }
         }
         
         System.out.println(resultCount);
         
         results = new String[resultCount][];
         //이름표: 4바이트, 주소는 4바이트=32비트         
         String date = "";
         int diff = 0;
         
         old = 0; // 위에서 쓰였으므로 초기화시키기
         
         int index = 0;
         for(int i=0; i<count; i++) { //데이터 총 행인 76까지반복
            int current = Integer.parseInt(rows[i][1]); //제주 확진자
            
            if(old != current) {//기존확진자와 현재확진자비교
               
               diff = current - old;//차이 = 현재확진자-기존확진자
               date = rows[i][0]; //차이발생한 날
               old = current; //기존확진자->현재확진자
               
               String[] row = new String[2];
               row[0] = date;       // date
               row[1] = String.valueOf(diff); // 정수->문자열변환
               
               results[index] = row; //index++후 출력하면 인덱스1이 증가되어 다음인덱스가출력됨
               
               System.out.println(Arrays.toString(results[index]));
               
               index++;//results배열인덱스 증가
            }
         }         
         System.out.println("작업완료");
                  
      }

1. 일별 가장 많은 검사진행 수는 ?

열에서 최대값 찾기

		//일별 가장 많은 검사진행 수는 ? 
		{	
			int max = 0;
			int current;
					
			for(int i =0; i<count;i++) {
				current = Integer.parseInt(rows[i][3]);
				if(current > max) 
					max = current;
				}
			System.out.println(max);
			System.out.println();
		}

 

2.  검사 진행 수가 가장 많았던 날짜는 ? 

해당되는 열의 위치를 찾아 동일한 행,다른열에서 데이터찾기.

		//검사진행수가 가장 많았던 날짜는 ?
		
			String date ="";
			int idx = 0;

			for(int i=0;i<count;i++) {
				if(rows[i][3].equals(String.valueOf(max))) //세미콜론주의
				idx = i;
				}
			date = rows[idx][0];
			System.out.println(date);

 

3. 확진자 수가 늘어난 일자와 수를 출력하시오.

데이터값 변화가있는 열의 위치찾기→데이터변화차이구하기→ 동일한 행,다른열의 데이터찾기(날짜).

			//확진자 수가 늘어난 일자와 수를 출력하시오.		
		{
			String date="";
			int diff = 0;
			
			int current = Integer.parseInt(rows[0][1]);
			int index = 0;
			int next = 0;
			
			for(int i=0;i<count;i++) {
				next = Integer.parseInt(rows[i][1]); //변화할위치
				if(current!=next) {
					diff = next - current;
					date = rows[i][0];
					current = next;
					
					index++;
					
					System.out.printf("%d : %s, %d\n",index,date,diff);
				}
			}		

 

 

 

 

package ex3.array;

import java.io.FileInputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Scanner;

public class Program3MultiArray3 {

	public static void main(String[] args) throws IOException {
		
		int count = 0;
		String[][] rows; 
		//--------------------------------------------------------------
		//레코드 개수를 알아 내는 코드
		{
			FileInputStream fis = new FileInputStream("res/corona.csv");
			Scanner scan = new Scanner(fis);
			
			//while반복을 하면서 count++연산을 한다. 마지막 줄을 만날때까지
			String line;
			while(scan.hasNextLine()) {
				line = scan.nextLine();
				count++;		
			}			
			
			scan.close();
			fis.close();
			count--;
			System.out.println("총 행의 갯수"+count);
		}//충돌방지
		//--------------------------------------------------------------
		//레코드를 로드하는 코드
		{
			rows = new String[count][];
			FileInputStream fis = new FileInputStream("res/corona.csv");
			Scanner scan = new Scanner(fis);
			/*
			 * 0번째방 : {"a", "b", "c"}
			 * 1번째방 : {"d", "e", "f"}
			 * 
			 * */
			String line;
			
			scan.nextLine(); // 담을필요없다.한줄버리기
			for (int i = 0; i < count; i++) { // 한줄 불러오고, 나눠서 배열에넣기
				line = scan.nextLine(); // 한줄불러오기
				rows[i] = line.split(","); // 불러온것 쉼표로 구분
			}
			scan.close();
			fis.close();
		}		
		//--------------------------------------------------------------
		//레코드 출력하는 코드
		for (int j = 0; j < count; j++) { // 행
			for (int i = 0; i < 10; i++) { // 열채우기
				System.out.printf("%s", rows[j][i]);
	
				if (i < 9)
						System.out.printf(",");
			}
			System.out.println();
		}
		//--------------------------------------------------------------	
		//검사진행자 누적수 얻는 코드
		{
			int total = 0;
				
			for(int i=0;i<count;i++)
			total += Integer.parseInt(rows[i][3]);	//문자열을 정수로 형변환
			System.out.println(total);
		} 
		
		//--------------------------------------------------------------	
		//일별 가장 많은 검사진행 수는 ? 
		{	
			int max = 0;
			int current;
					
			for(int i =0; i<count;i++) {
				current = Integer.parseInt(rows[i][3]);
				if(current > max) 
					max = current;
				}
			System.out.println(max);
			System.out.println();
		
		
		//검사진행수가 가장 많았던 날짜는 ?
		
			String date ="";
			int idx = 0;

			for(int i=0;i<count;i++) {
				if(rows[i][3].equals(String.valueOf(max))) //세미콜론주의
				idx = i;
				}
			date = rows[idx][0];
			System.out.println(date);
		}
		//확진자 수가 늘어난 일자와 수를 출력하시오.
		{
			String date = "";
			int diff = 0;
			
			int old = 0; //이전확진자수
			int current = 0; //현재확진자 수
			int index = 0;			
			
			for(int i=1;i<count;i++) {
				current = Integer.parseInt(rows[i][1]);
				
				if(old != current) {
					
					diff = current - old;
					date = rows[i][0];
			
					old = current;
					
					//년 월 일로 출력하기
					date = date.substring(0,4)+"년"+
							date.substring(5,7)+"월"+
							date.substring(8,10)+"일";
					System.out.printf("%d : %s, %d\n",index+++1,date,diff);
					}			
			}
			
		}
		
		
		
		
}
	}

1차원배열과 2차원배열 차이

1차원배열의 반복 -> 2차원

동일한 배열이름 사용(같은코드를 복사,붙여넣기 x)

1차원배열 2차원배열
이름을 각각 지었다.
String[] rows1;
String[] rows2;
이름하나 사용
String[][] rows = String[2][];
rows1 = line.splite();
rows2 = line.splite();
rows[0] = line.splite(); 
배열의 이름을 인덱스로 씀.
인덱스부분에 변수를 넣어 유연하게 쓸 수 있다.
  rows[1] = 3; 불가능
rows[1] = "asds"; 불가능
rows[1][0] = "asds";가능

좌 : 1차원배열                       / 우 : 2차원배열

왼쪽 :1차원을 낱개로 처리 rows1,rows2

오른쪽 :1차원배열의 반복을 일괄적으로 처리.

2차원배열은 대괄호가 두개 사용되어야 값을 넣을 수있다.

rows[0] 1차원배열을 이끄는 참조명 

String[2][]; 2개의 배열을 엮는다.

 

 

 

2차원배열 이용해 코로나 검사진행자 누적수 구하기

  1. FileInputStream, Scanner를 이용해 데이터를 불러온다
  2. 레코드갯수를 알아낸다.
  3. 레코드 로드(데이터불러와서 쉼표로 구분하고 배열에 넣기)
  4. 레코드출력해서 확인
  5. 검사진행자 누적수 얻는 코드작성

1~6 과정 코드

  1. FileInputStream, Scanner를 이용해 데이터를 불러온다
  2. 2. 레코드갯수를 알아낸다.
FileInputStream fis = new FileInputStream("res/corona.csv");
Scanner scan = new Scanner(fis);
			
//while반복을 하면서 count++연산을 한다. 마지막 줄을 만날때까지
String line;
while(scan.hasNextLine()) {
line = scan.nextLine();
count ++;		
}			
			
scan.close();
fis.close();
count--;
System.out.println("총 행의 갯수"+count);

 

3.레코드 로드(데이터불러와서 쉼표로 구분하고 배열에 넣기)

rows = new String[count][];
FileInputStream fis = new FileInputStream("res/corona.csv");
Scanner scan = new Scanner(fis);

String line;

scan.nextLine(); // 담을필요없다.한줄버리기

for (int i = 0; i < count; i++) { // 한줄 불러오고, 나눠서 배열에넣기
	line = scan.nextLine(); // 한줄불러오기
	rows[i] = line.split(","); // 불러온것 쉼표로 구분
	}
			
scan.close();
fis.close();

 

4.레코드출력해서 확인

 

for (int j = 0; j < count; j++) { // 행
	for (int i = 0; i < 10; i++) { // 열채우기
		System.out.printf("%s", rows[j][i]);
	
		if (i < count-1)
			System.out.printf(",");
		}
		System.out.println();
	}

 

5.검사진행자 누적수 얻는 코드작성

int total = 0;
				
for(int i=0;i<count;i++)
total += Integer.parseInt(rows[i][3]);	
System.out.println(total);

 

package ex3.array;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.Scanner;

public class Program3MultiArray3 {

	public static void main(String[] args) throws IOException {
		
		int count = 0;
		String[][] rows; // 배열의 배열 [2][10] 10개짜리2개 [행][열]
		//--------------------------------------------------------------
		//레코드 개수를 알아 내는 코드
		{
			FileInputStream fis = new FileInputStream("res/corona.csv");
			Scanner scan = new Scanner(fis);
			
			//while반복을 하면서 count++연산을 한다. 마지막 줄을 만날때까지
			String line;
			while(scan.hasNextLine()) {
				line = scan.nextLine();
				count ++;		
			}			
			
			scan.close();
			fis.close();
			count--;
			System.out.println("총 행의 갯수"+count);
		}//충돌방지
		//--------------------------------------------------------------
		//레코드를 로드하는 로드
		{
			rows = new String[count][];
			FileInputStream fis = new FileInputStream("res/corona.csv");
			Scanner scan = new Scanner(fis);

			String line;

			scan.nextLine(); // 담을필요없다.한줄버리기

			for (int i = 0; i < count; i++) { // 한줄 불러오고, 나눠서 배열에넣기
				line = scan.nextLine(); // 한줄불러오기
				rows[i] = line.split(","); // 불러온것 쉼표로 구분
			}
			
			scan.close();
			fis.close();
		}		
		//--------------------------------------------------------------
			//레코드 출력하는 코드
			for (int j = 0; j < count; j++) { // 행
				for (int i = 0; i < 10; i++) { // 열채우기
					System.out.printf("%s", rows[j][i]);
	
					if (i < count-1)
						System.out.printf(",");
				}
				System.out.println();
			}
		//--------------------------------------------------------------	
		//검사진행자 누적수 얻는 코드
			{
				int total = 0;
				
				for(int i=0;i<count;i++)
				total += Integer.parseInt(rows[i][3]);	
				System.out.println(total);
			} 
			
	}
}

자바는 포인터가없고 값변수, 참조변수가 있다.

값 변수와 참조변수 :

값변수는 담는 공간을 가지는 변수

참조변수는 담을 공간이 없으며 객체를 가리키는 변수, 객체의 주소를 담고있다. 객체에 이름을 부여.

hailey라는 글자가 주소를 갖고있는게 아닌것처럼, hailey는 참조변수(이름)이다.

String name = "hailey";

자료형 이름     객체(가 공간을가지고있다)

다양한 hailey중 이름을 붙여 구별할수있게한다.


Q. 데이터 4번째 컬럼의 총 합을 구하시오.

데이터 값 출력하기

 

원본데이터

반복해야할 구문 :

1.문자열 한줄을 불러온다.

2.문자열을 쉼표로 구분한다.

3.구분한 문자열을 배열에 넣는다.

4. 인덱스3번의  문자를 숫자로 변환하고 누적값을 구한다.

1~4번을 반복하면 전체 누적수가 나온다.


 

FileInputStream fis = new FileInputStream("파일상대경로");

하드디스크에는 암이라는게있고, 트랙이있다.트랙어딘가에 데이터가있다.

어플리케이션에서 데이터를 사용한다. 어플리케이션은 일정한 버퍼를 통해 데이터를 가져온다.

 

 

Scanner scan = new Scanner(fis);

fis을 사용하는 Scanner의 이름을 scan이라부른다.

데이터를 가져올때 fis.read()를 통해 가져올 수 있다. read는 코드를 하나씩읽어온다.

fis로 Scanner를 이용하면 문자열로 (단어,라인) 읽어올 수 있다.

 

 

String line = scan.nextLine();

nextLine()은 데이터의 일부만 가져오는데, 엔터(13번)까지 가져온다.

line은 "문자열"(scan.nextLine()이 가져온 것)의 이름이다.

문자열 객체인 [기준일자,제주 확진자,제주 사망자,제주 검사진행자수,자가격리중,..]을 가져온다.

line은 [..]을 가리킨다.

 

 

line = scan.nextLine();

line은 첫번째행을 읽어들였는데, 이번엔 두번째 라인을 불러온다.

[2020-10-01,59,0,28,0,0,58,8,230,2020-12-14]을 가져온다.

line은 더이상 위의 scan.nextLine() 을 가르키지않고 현재 scan.nextLine()을 가리킨다.

참조하는게없는 데이터공간을 가비지라고 부른다.

첫번째scan.nextLine()은 메모리누수를 방지하기위해 런타임환경에서 가비지콜렉션이 수거해간다.

즉, 참조하는게없는것은 자바실행환경이 수거해간다.

 

 

String[] cols = line.split(",");

line을 가지고 split이 넣어준 구분자","로 문자열을 쪼갠 후 각각을 문자열로 만든다.

문자열들의 배열이 새로 만들어진다. line.split(",")에 의해 line안에있었던 문자열들이 문자배열이 되었다.

이 문자배열을 참조하기 위해 새로운 String[]배열 이름 cols을 만들어준다.

cols도 line.splite을 가르키는 이름이다.

["2020-10-02","59","0","35","0","0","58","7","230","2020-12-14"]

cols는 공간이아니다. line.split(",");을 참조한다.

 

 

System.out.println(Integer.parseInt([cols[3]);

합계를 구하기위해선 "28" 문자열이기때문에 형변환을 해줘야한다.

 

 

while(scan.hasNextLine())

scan.가 다음라인을 가지고오면 hasNextLIne이 true를 반환한다.

가져올 데이터유무에 따라 true, false값을 반환한다. 이것을  while의 조건으로쓴다.

true를 반환하는동안 while이 반복한다.

끝까지읽고 더이상 읽어올게없으면 false를 반환한다.

 

 

 

추가문제 : 제주 검사진행자수 컬럼의 총합을 구하시오

 

package ex3.array.test2;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Scanner;

public class Jeju {

	public static void main(String[] args) throws IOException {

		FileInputStream fis = new FileInputStream("res/corona.csv"); //파일위치지정
		Scanner scan = new Scanner(fis); //파일불러오기
		String line = scan.nextLine(); // 1행불러온것

		int total = 0;

		// 2020-10-01,59,0,28,0,0,58,8,230,2020-12-14 

		while (scan.hasNextLine()) {// 다음에읽어올게있어?
			line = scan.nextLine();
			String[] cols = line.split(",");		// [2020-10-01,59,0,28,0,0,58,..]
			total += Integer.parseInt(cols[3]);
		}		
		System.out.println(total);

		scan.close();
		fis.close();
		System.out.printf("10월 1일부터 12월14일까지 검사진행자수:%d",total);
	}

}
//10월 1일부터 12월14일까지의 누적검사진행자수
//누적 검사진행수
//첫번째열읽고

 

 

 

 

 

String클래스

new라는 연산자를 통해 객체를 생성해야하지만 생략가능

String은 문자열 개체이다.

아래의 n1은 "hello"문자열을 가지고 있는 도구이다.

n1을 통해 String클래스가 가지고있는 도구들을 사용할 수있다.

String n = new String("hello"); //String클래스 객체를만든것, 문자를 조작할수있는 기능들을갖고있다.
String n1 = "hello"; //객체화됨, 문자열을 담고있는도구 /

 

객체 n1을 통해 indexOf(),substring(),length,toUpperCase(),compareTo 등 메소드들을 사용 할 수있다.

문자열비교

		String n1 = "홍길동";
		String n2 = "홍길동";

		String n3 = new String("홍길동");
		String n4 = new String("홍길동"); //객체비교
		
		System.out.println(n1 == n2); //참 new연산자
		System.out.println(n1.equals(n2)); //참 *자주사용함
		System.out.println(n3 == n4); //거짓
		System.out.println(n3.equals(n4)); //참

n1과 n2는 new를 이용해서 객체를 생성하지 않으면 컴파일러가 해준다. 같은 문자열을 갖고있으면 같은곳에 위치한다.(같은객체참조)

n1==n2비교하면 객체비교,(주소값 비교)이며, 이라고 나온다.

 

n1.equals(n2)는 대상의 내용자체를 비교한다. 결과는 참이다.

 

n3 == n4 는 각각 다른 주소값을 갖으므로 거짓이 나온다.

n3.equals(n4)는 같은 내용을 갖고있으므로 참이 나온다.

equals참조

 

length()

String fileName = "photo.jpg";
String test = fileName.substring(3);//to.jpg
System.out.println(test.length());//6

fileName.substring(3) : fileName의 인덱스3부터 끝까지 문자열을 반환한다. 

test.length() : test의 문자열 길이를 반환한다.

 

 

indexOf() / substring()

		String fileName = "photo.jpg";
		System.out.println(fileName.length()); // 9
		System.out.println(fileName.indexOf(".")); //"."가 포함되었는지? 5
        System.out.println(fileName.indexOf(".",6)); 
        //-1 "."가 6번째부터 포함되어있는지?없다면-1
		System.out.println(fileName.substring(3)); //to.jpg
		System.out.println(fileName.substring(3,2)); // 에러 
		System.out.println(fileName.substring(3,5)); // 인덱스3~4까지 to 

fileName.length() : fileName의 문자열 갯수. 총 9개를 반환한다.

fileName.indexOf(".") : fileName의 문자열 중 "."위치를  찾아준다. "."의 위치 5가 반환된다.

fileName.indexOf(".",5) : fileName의 문자열 중 "."를 인덱스6부터 찾는다.없다면 -1반환한다.

fileName.substring(3,5) : fileName의 인덱스3부터 인덱스4까지 반환 

 

 

String.substring(start,end)

		String fileName = "photo.jpg";
		//위의 파일명에서 .이있는곳까지의 문자열을 출력(단.제외)
		int pos = fileName.indexOf(".");//위치파악
		System.out.println(fileName.substring(0,pos)); //photo
		System.out.println(fileName.substring(pos)); //.jpg

String.substring(start,end): start부터 end전까지 문자열출력

fileName.indexOf(".") : fileName의 특정문자열위치(숫자로 반환)를 갖고있는 객체생성.

fileName.substring(0,pos) : 0부터 pos전까지 문자열출력

fileName.substring(pos) : pos부터 끝까지 문자열출력

 

 

String.compareTo()

		int a = fileName.indexOf(".");//위치파악
		System.out.println(fileName.compareTo("aphoto.jpg")); // 15  결과가0 보다크다면 앞이크다
		System.out.println(fileName.compareTo("photo.jpg")); // 0 문자열 같을때 0을 반환
		System.out.println(fileName.compareTo("qphoto.jpg")); // -1
		System.out.println(fileName.compareTo("rphoto.jpg") > 0); // -2 0보다작으면 괄호

String.compareTo("A") : String의 문자열과 "A"문자열의 순서를 비교

첫번째글자가 같으면 다음 두번째글자를 비교한다. 

String의 문자열이 사전편찬순서상 뒤에있다면 0보다큰 양수 값이 반환된다.(a,b,c,d,...,z순서)

fileName > "aphoto.jpg" 보다 크다면 15가 반환(f가 a보다 순서가 뒤에있으므로 f가 크다)

fileName과 "aphoto.jpg"의 알파벳순서가 같다면 0이 반환

String.compare("A")결과 값이 0이라면 String값이 "A"값보다 더 크다.(조건문의 조건으로사용가능)

fileName > ("aphoto.jpg") 0 보다 크면 fileName이 크다. 음수이면 "aphoto.jpg"이크다.

 

 

문자열배열의 인덱스섞기

		String[] names = new String[] {"강호동","유재석","하하","김지호","김현준","김태희","박민정"};

		Random rand = new Random();
		
		for(int i=0; i<100;i++) {
			int idx1 = rand.nextInt(7); //0~6
			int idx2 = rand.nextInt(7); //0~6
//			System.out.printf("idx1 :%d, idx2:%d\n",idx1,idx2); //랜덤값을 확인한다.
						
			String temp; //데이터형이달라져도 똑같다.
			temp = names[idx1]; //랜덤값끼리 섞어준다
			names[idx1] = names[idx2];
			names[idx2] = temp;			
		}

배열 인덱스 섞기는 자료형이 달라져도 방식은 똑같다.

배열의 인덱스 숫자만큼 랜덤숫자를뽑는다.

임시변수만 String타입으로 선언해준다.

 

 

문자열비교 String.compareTo("A")

		for(int j=0;j<7-1;j++) 		
			for(int i=0;i<7-1-j;i++) 
				if(names[i].compareTo(names[i+1]) > 0){
					String temp;
					temp = names[i];
					names[i] = names[i+1];
					names[i+1] = temp;
					}			
				

String.compareTo()메소드를 통해 두 문자열을 비교할 수있다.

b.compareTo(a) > 0 이라면 b가 a보다 크다. 둘의 위치를 바꾸면 사전편찬순으로 정렬된다.

총7개의 인덱스를 6번반복하면 가장 마지막 문자열 1개가 나오고(작은for문) 이 반복을 6번반복하면 전체정렬이된다.

 

 

String클래스를 통해 만들어진 객체.하면 String클래스에 포함된 메소드들이 뜬다.

 

package ex3.array.test2;

import java.util.Random;

public class Program2 {

	public static void main(String[] args) {
		

		
//		String n = new String("hello"); //String클래스 객체를만든것, 문자를 조작할수있는 기능들을갖고있다.
//		String n1 = "hello"; //객체화됨, 문자열을 담고있는도구 /
		
		
		String n1 = "홍길동";
		String n2 = "홍길동";

		String n3 = new String("홍길동");
		String n4 = new String("홍길동"); //객채비교
		
		System.out.println(n1 == n2); //참 new연산자
		System.out.println(n1.equals(n2)); //참 *자주사용함
		System.out.println(n3 == n4); //거짓
		System.out.println(n3.equals(n4)); //참

		
//		
		String fileName = "photo.jpg";
		System.out.println(fileName.length()); // 9
		System.out.println(fileName.indexOf(".")); //"."가 포함되었는지? 5
		System.out.println(fileName.substring(3)); //to.jpg
//		System.out.println(fileName.substring(3,2)); // 에러 
		System.out.println(fileName.substring(3,5)); // 인덱스3~4까지 to 
//		
		//위의 파일명에서 .이있는곳까지의 문자열을 출력(단.제외)
		int a = fileName.indexOf(".");//위치파악
		System.out.println(fileName.substring(0,a)); //-1이상이면 0부터있다는걸로파악.
		System.out.println(fileName.substring(a,8)); //-1이상이면 0부터있다는걸로파악.

		System.out.println(fileName.compareTo("aphoto.jpg")); // 15 > 0 보다크다면 
		System.out.println(fileName.compareTo("photo.jpg")); // 문자열 같을때 0을 반환
		System.out.println(fileName.compareTo("qphoto.jpg")); // -1
		System.out.println(fileName.compareTo("rphoto.jpg") > 0); // -2 0보다작으면 괄호
		//fileName 이 크면 양수, fileName이 괄호()보다 작으면 음수
		
	
		//"912"(문자열은 1 2 라고읽는다) "9" 문자열의크기 앞글자의 비교
		
		
		String[] names = new String[] {"강호동","유재석","하하","김지호","김현준","김태희","박민정"};

		Random rand = new Random();
		
		for(int i=0; i<100;i++) {
			int idx1 = rand.nextInt(7); //0~6
			int idx2 = rand.nextInt(7); //0~6
//			System.out.printf("idx1 :%d, idx2:%d\n",idx1,idx2); //랜덤값을 확인한다.
						
			String temp; //데이터형이달라져도 똑같다.
			temp = names[idx1]; //랜덤값끼리 섞어준다
			names[idx1] = names[idx2];
			names[idx2] = temp;			
		}
		
		for(int i=0;i<7;i++) {
			System.out.printf("\"%s\"",names[i]);
			if(i<7-1)
				System.out.print(",");		
		}		
		//정렬

						
		for(int j=0;j<7-1;j++) 		
			for(int i=0;i<7-1-j;i++) 
				if(names[i].compareTo(names[i+1]) > 0){
					String temp;
					temp = names[i];
					names[i] = names[i+1];
					names[i+1] = temp;
					}			
			
	}
}


package ex3.array.test2;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Random;
import java.util.Scanner;

public class Program3 {

	public static void main(String[] args) throws IOException {
		
		FileInputStream fis = new FileInputStream("res/names.txt");
		Scanner fscan = new Scanner(fis);

		String line = fscan.nextLine();
		
		String[] names = line.split(",");//쉼표기반으로 잘라줌
		
//		System.out.println(names[1].trim());	//문자열앞뒤빈공백없애줌
		
		String names1 = names[1].trim();
		
		System.out.println(names[1].trim());		
		
				
		fscan.close();
		fis.close();

	}
}

 write(byte [] b, int off, int len) 사용

write(byte[] b) : 

write(byte[] b)를 통해 비트맵파일의 바이트갯수를 한번에 불러와 빠르게 파일을 빠르게 복사했지만,

바이트배열 생성시 1000바이트씩 읽고 1000바이트씩 써서 원본의 크기와 차이가 발생했다.

보통 파일의 값은 1000으로 딱떨어지지않는다.

마지막은 1000개가아니라 454만 출력하도록 해보자.

( 이전글 write(byte[] b) )

 

좌: 원본 / 우 : write(byte[] b) 사용시 

write(byte [] b, int off, int len) 를 이용해 마지막 454바이트까지 불러오게한다.

fos.write(buf,0,size); 넣으면 

0~1000,0~1000,...,0~1000개를 출력하다가 마지막 454개를 출력한다.

 

 

write(byte [] b, int off, int len)

 : b[off] 부터 len 개의 바이트를 출력 스트림으로 보냄.

OutputStream os = new FileOutputStream("파일 경로");

byte[] data = "가나다".getBytes();

os.write(data, 1,2) // "나다"만 출력

package ex3.array;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class CopyProgram {

	public static void main(String[] args) throws IOException {

		FileInputStream fis = new FileInputStream("res/aaa.bmp"); // 이미지파일 불러오기
		FileOutputStream fos = new FileOutputStream("res/img_copy.bmp"); // 이미지파일출력

		// 2. fis를 통해서 1 바이트를 읽어서 byte 변수 b에 담는다.
		// b의 값을 fos로 통해서 출력한다.
		int size = 0;
		
		byte[] buf = new byte[1000];
				
		while ((size = fis.read(buf)) != -1)
			fos.write(buf,0,size);


		fis.close();
		fos.close();

		System.out.println("복사완료");				
	}
}

 

 

hasNextLine()

txt파일(메모장)을 작성후, 메모장내역을 불러와 콘솔에 출력하기

package ex3.array.test2;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Scanner;

public class Program {

	public static void main(String[] args) throws IOException {

	//1.문자열 10개 짜리 names 배열을 생성한다.
		String[] names = new String[10];
		
	//2.파일에서 name들을 읽어와서 names 배열애 대입한다.
		FileInputStream fis = new FileInputStream("res/names.txt");
		Scanner fscan = new Scanner(fis); //문자불러오기
		
		int i =0;
		while(fscan.hasNextLine()) { //참인동안 반복
			String name = fscan.nextLine(); //끝까지 읽었다는 것을 알려줌
			names[i++] = name; // 다음을 증가
			System.out.printf("%s, ",names[i-1]);
			
			if(fscan.hasNextLine()==true) // 거짓이면 중단
				System.out.printf(","); //마지막줄
		}
				
	//3.names 배열의 이름을 다음처럼 콘솔에 출력한다.
	//홍길동,김길동,강호동,유재석
				
		fscan.close();
		fis.close();

		System.out.println("복사완료");	
	}
}

nextLine()줄을 읽어오지만, 끝을 읽었다는걸 알려주거나, 값을가져오는내용이없다. 

fscan.점을찍으면 여러메소드들이 조회된다

hasnextline() : 불리언, 트루, 거짓 값을 반환한다, 다음라인을 가져올수있으면 트루값을가져오도록 한다.

 

if(fscan.hasNextLine() : 불러올 문자가 더 있다면 참
String name = fscan.nextLine(); : 불러온 문자를 변수name에 넣는다.

names[i++] = name; 배열에 담는다.

names[i++] : 다음을 증가, 

 

다음라인이있는지 찾고, 있다면 배열에 담는것을 반복한다-> while로 반복

 

 

 

 

 

1. 정수 10개짜리 nums배열을 생성한다. 

		int[] nums = {1,2,3,4,5,6,7,8,9,10};

 

2. 랜덤값 두개를 뽑아서 100번 섞는다.

정수 두개 변수선언을하고 각각 랜덤함수를 적용해준다.

잘 섞였는지 출력해서 확인

		Random rand = new Random();
		
		for(int i=0;i<100;i++) {
			int idx1 = rand.nextInt(10); //0~9
			int idx2 = rand.nextInt(10); //0~9
			System.out.printf("idx1: %d, idx2:%d\n",idx1,idx2);

 

3. 랜덤으로 뽑은 두 인덱스를 섞는다. (섞기연습)

			int temp;
			temp = nums[idx1];
			nums[idx1] = nums[idx2];
			nums[idx2] = temp;		
			

 

4. 버블정렬을 위해 제일 큰 값을 찾는다.

n번째값보다 n+1번째 값이 크다면 서로 위치를 바꾼다.(if문)

가장 큰값이 마지막에온다.

0번째값이 1번쨰값보다 크다면 두 위치를 값을 바꾼다.

1번쨰값이 2번째값보다 크다면 두 위치의 값을 바꾼다. ~ 8번째값이 9번째값보다 크다면 두 위치의 값을 바꾼다.

		for(int i=0;i<9;i++) // 범위주의 (인덱스갯수-1 : 인덱스가4개일경우 3번이면 모두비교됨)
			if(nums[i]>nums[i+1]) {
				int temp;
				temp = nums[i];
				nums[i] = nums[i+1];
				nums[i+1] = temp;
			}

 

5. 버블정렬로 오름차순(이중 for문)

0,1,2,3,4,5,6,7,8,9의 10개의 수가 섞여있는 배열을 오름차순으로 정렬하기위해서

각 수를 두개씩 묶어서 비교하면 9번만 검사하게된다. (안쪽 for문)

이 반복을 또 9번해야 전체적으로 정렬이된다.(바깥 for문)

 

바깥for (int j=0;j<9-1;j++) : 전체범위 , 9번 반복

안쪽for ( int i=0;i<10-i-1;i++) : 바깥for문이 한번돌면 가장큰 숫자는 맨 오른쪽에위치한다. 확정된 것은 더이상 비교할필요없다.

		for(int j=0;j<10-1;j++) 
			for(int i=0;i<10-1-j;i++) 
				if(nums[i]>nums[i+1]){
				int temp;
					temp = nums[i];
					nums[i] = nums[i+1];
					nums[i+1] = temp;
				}

큰for문의 j가 작은for문안에서 쓰여서 

for(int i=0;i<10-1;i++) : 제일큰 것 찾기, 나머지애들끼리 값을 비교

for(int i=0;i<9-1;i++) : 두번쨰로 큰 것 찾기

for(int i=0;i<8-1;i++) , ... 로 점차좁혀진다. 

for문 범위 변화에 따른 결과값

 

콘솔출력

6. ',' 쉼표찍기

인덱스가 10개이지만 쉼표는 마지막에 빠져야한다. (즉, 9번만 발생)

if문을 사용해서 9번째까지만 찍도록 for문안에 중첩한다. 

for문을 이용해 nums[i]의 값을 순서대로 출력하되, i가 9보다 작다면 ','를 출력한다.

		for(int i=0;i<10;i++) {
			System.out.print(nums[i]);
			
			if(i<9)
				System.out.print(",");
			}

 

5. 전체 오름차순으로 버블정렬

package ex3.array.test2;

import java.util.Random;

public class practice {

	public static void main(String[] args) {
		
		//1.정수 10개짜리 nums배열을 생성한다. 단, 1,2,3,4~10

		int[] nums = {1,2,3,4,5,6,7,8,9,10};
		
		//섞는다.
		//랜덤값을 얻어서
		Random rand = new Random();
		
		for(int i=0;i<100;i++) {
			int idx1 = rand.nextInt(10); //0~9
			int idx2 = rand.nextInt(10); //0~9
			System.out.printf("idx1: %d, idx2:%d\n",idx1,idx2);
			
		//두 인덱스의 위치를 바꿔라.		
			int temp;
			temp = nums[idx1];
			nums[idx1] = nums[idx2];
			nums[idx2] = temp;		
			}
		for(int i=0;i<10;i++) {
			System.out.print(nums[i]);
			
			if(i<9)
				System.out.print(",");
			}System.out.println();
		
		
		//버블정렬 제일큰 값을 찾아서 맨 뒤로 밀어내기
		//배열에서 가장 큰 값찾기		
	    // 범위주의 (인덱스갯수-1 : 인덱스가4개일경우 3번이면 모두비교됨)
		for(int j=0;j<10;j++) {
			for(int i=0;i<(10-j)-1;i++) 
				if(nums[i]>nums[i+1]){
				int temp;
					temp = nums[i];
					nums[i] = nums[i+1];
					nums[i+1] = temp;
				}
		}
				
		
		for(int i=0;i<10;i++) {
			System.out.print(nums[i]);
			
			if(i<9)
				System.out.print(",");
			}
			System.out.println();
		
	}
}

 

+ Recent posts