카테고리 없음

java 교육 5일

aonee 2025. 5. 26. 15:50

[교육 1일차]

java 기본 개념 교육 c언어와 비교하며 수업해주셨다.

c언어 실행방법 : gcc test01.c -o a.exe 후 a.exe 

주의사항 ) gcc있어야함. gcc 경로를 못 찾아서 path설정을 해줬다. 환경변수 path에 gcc bin 폴더경로 추가 후 cmd창 닫고 다시 cmd 열면 해결됨

 

java 실행방법 :  javac test02.java 후 java test02

 

test01 .c

#include <studio.h>

int main() {
	int a ; 
	a = 100;
	printf("%d\n", a) ; 
	return 0;
}

test04.java

public class test04 {
	public static void main (String[] args){
		int a;
		a = 10;
		System.out.println(a);
		
		double b = 3.143;
		System.out.println(b);
	}


}

 

test05 .c

#include <stdio.h>

int main(){
int a ;
int *b, *c; 
a=100;
b= &a;
c= b;
printf("%d %d %d", a, *b, *c);

return 0;
}

/*
포인터는 기억공간을 가리킬 수 있는 변수이다 (이름 아님)- 삼각형 기억공간으로 표현
c=b 포인터의 대입은 오른쪽이 가리키는 대상을 왼쪽이 가리키게 된다
*/

test06 .c

#include <stdio.h>

struct ab {
	int a;
	float b;
	
};


int main(){
	struct ab apple;
	struct ab *t;
	
	apple.a = 100;
	apple.b = 3.14;
	
	t= &apple;
	t->b = 0.066;
	
	printf("%d %f\n", apple.a, apple.b);


	return 0;
}

/*
apple이름으로 변수 선언 - struct ab 형태의 공간을 확보한다
a라는int형 변수와 b라는 float형 변수가 함께 있는 복합공간

구조체는 자료형처럼 이해하고 사용하면 됨.
java 클래스는 알고보면 구조체다. 따라서 클래스는 자료형처럼 이해하면 된다.


*/

 

test07.c

#include <stdio.h>


/*
구조체는 자료형처럼 쓸 수 있기에 typedef 를 적용할 수 있다
이러면 마치 AB라는 새로운 자료형을 만든 것처럼 사용이 가능하다

메모리 확보 방법
1. 변수선언 - 자료형 or 구조체, 이름(심볼) 필수
int a ; b=&a; 기억공간에 대한 포인터는 존재한다

2. malloc - 자료형 or 구조체, 이름(심볼) 없음. 이름이 없이 포인터로만 접근 가능하다.

*/
typedef struct ab {
	int a;
	float b;
	
}AB;


int main(){
	AB apple;
	AB *t;
	
	apple.a = 100;
	apple.b = 3.14;
	
	t= &apple;
	t->b = 0.066;
	
	printf("%d %f\n", apple.a, apple.b);


	return 0;
}

/*
apple이름으로 변수 선언 - struct ab 형태의 공간을 확보한다
a라는int형 변수와 b라는 float형 변수가 함께 있는 복합공간

구조체는 자료형처럼 이해하고 사용하면 됨.
java 클래스는 알고보면 구조체다. 따라서 클래스는 자료형처럼 이해하면 된다.


*/

test08.c

#include <stdio.h>

typedef struct ab {
	int a;
	float b;
	
}AB;


int main(){
	AB *t;
	t = (AB*)malloc(sizeof(AB)); // AB형태의 메모리를 확보하여 포인터를 리턴한다
	t->a = 9999;
	t->b = 193.23412345;
	printf("%d %f \n", t->a, t->b);
	free(t); //malloc으로 확보된 기억공간은 free로 소거한다
	// t(삼각형)을 날리는 게 아니라 t가 가리키는 대상(박스)가 날아간다
	return 0;
}

 

test09.java

class AB{
	int a;
	double b;
	
}
public class test09{
	public static void main(String[] args){
		AB t = new AB();
		t.a=100;
		t.b = 3.14;
		System.out.println(t.a + ", "+ t.b);
	}
}

 

test10.c

typedef struct node {
	int data;
	struct node *next; // 가능
	
}Node;


int main(){
	Node* head;
	head= (Node*)malloc(sizeof(Node));

	head->data = 0;
	head->next = (Node*)malloc(sizeof(Node));
	head->next->data = 100;
	
	printf("%d, %d", head->data, head->next->data);
	
	free(head->next); // head포인터가 가리키는 malloc된 대상 안의 next 포인터가 가리키는 대상을 날려라
	free(head);
	
	return 0;
}

 

test11.java

class Node{
	int data;
	Node next;
}

public class test11{
	public static void main(String[] args){
		Node head = new Node();
		head.data = 100;
		head.next = new Node();
		head.next.data = 200;
		
		System.out.println(head.data + ", "+ head.next.data);
	}
}

test15.java

class Node{
	int data;
	Node next;
}


// 클래스(구조체), 인스턴스(malloc), 멤버변수, 참조형변수(포인터) 개념
클래스 안에서 생선한 변수 멤버변수.
멤버변수는 인스턴스를 생성할 때 할당받는다
클래스 이름으로 생성된 변수를 참조형변수라고 한다
인스턴스를 가리키기 위한 용도이다.....................
public class test15{
	public static void main(String[] args){
		Node head ; // 클래스 이름으로 선언한 변수는 참조형변수, new로 할당받은 메모리 공간을 가리키는 용도
		head = new Node(); // new는 malloc과 유사
		// 클래스 안에는 변수를 선언할 수 있다. 이 변수는 new할 때 메모리를 할당받는다.
		// new Node(); 형태로 만들어진 할당받은 메모리 공간을 인스턴스 라고 한다.
	
		// 클래스는 구조체다. 여러번 선언 가능하다. 즉, 여러번 인스턴스 생성 가능하다. 
		// 여러번 인스턴스 만들어질 때마다 새로 변수가 생긴다.
		// 클래스 안에서 선언된 변수를 멤버변수라고 한다.
		// 멤버변수는 인스턴스 생성할 때마다 메모리를 할당받는다
		
		System.out.println(head.data + ", "+ head.next.data);
	}
}

/*
java의 class는 알고보면 구조체다 : 변수 선언이 가능 (대입연산금지)
class이름으로 변수를 선언할 수 있다. 
자료형으로 뭘 할 수 있었지? 변수 선언. 포인터 선언. malloc선언. 가능
구조체로 뭘 할 수 있었지? 변수, 포인터, malloc선언
java는 이 중 변수 선언만 안된다. 이 점이 c와 차이점 !

구조체는 마치 자료형처럼 쓰는구나... typedef
클래스는 변수 선언이 빠진 구조체더라..
*/

 

test16.java

class Node{
	int data;
	Node next;
}

public class test16{
	public static void main(String[] args){
		Node head = new Node();
		Node tail = head;
		
		Node t = new Node();
		t.data = 10;
		t.next = null;
		tail.next = t;
		
		tail = tail.next;
		
		t = new Node();
		t.data = 20;
		t.next = null;
		tail.next = t;
		
		for(t= head.next; t != null ; t = t.next){
			System.out.println(t.data);
		}
			
		
		
	}
}

 

test16.java -> c로 작성

#include <stdio.h>
#include <stdlib.h>

typedef struct node {
	int data;
	struct node *next ;
}Node;

int main(){

	// Node* head, tail, t;
	Node* head = (Node*)malloc(sizeof(Node));
	Node* tail = head;
	
	Node* t = (Node*)malloc(sizeof(Node));
	t->data = 10;
	t->next = Null;
	tail->next = t;
	
	tail = t->next;
	
	Node* t = (Node*)malloc(sizeof(Node));
	t->data = 20;
	t->next = Null;
	tail->next = t;
	
	for(t= head->next; t != Null ; t = t->next){
			printf("%d\n", t->data);
		}
	
	free(head);
	free(tail);
	free(t);
	
	return 0;
}

test17.c

#include <stdio.h>
int add(int i, int j){
	printf("->%d\n", i);
	printf("->%d\n", j);
	return i+j;
}
int main() {
	int r ; 
	r = add(10,20);
	printf("%d ", r);
	return 0;

}

/*
	add(10,20) 이 호출되면??
	1. int i, int j; 선언 - 메모리할당
	2. i = 10; j = 20 ; 대입
	3. 활용
	4. return 값; 값이 함수를 호출한 add(10,20) 부분을 대신한다고 보면 실수가 없다.

*/

 

함수포인터

test20.c

구조체 안에 함수 선언 불가능하다

#include <stdio.h>

typedef struct apple {
	int data;
    //int add(int, int); // error 함수선언 불가능
}Apple;

int add(int i, int j){
	return 100;
}

int add_v2(int i, int j){
	return 200;
}


int main() {
	int (*fp)(int, int);
	fp = add;
	printf("%d ", fp(10,20));
	
	fp = add_v2;
	printf("%d ", fp(10,20));
	
	return 0;

}

/*
	int (*fp)(int, int); 함수포인터
	fp는 포인터 변수다. 기억공간이 아닌 함수를 가리킨다. 매개변수가 int int 이고 리턴타입이 int인
	fp = add; 이 코드는 fp포인터가 add라는 함수를 가리키도록 대입한 코드

	결과값 100 return
	fp(10,20) fp포인터가 가리키는 함수를 호출한다 ..라는 이야기다.
	
	add_v2추가하면?
	결과값 100 200 return
	
	유지보수가 유독 많은 함수에 함수포인터를 이용하면 유지보수성이 좋아진다.
    
    *** 구조체 안에 함수 선언 안된다 !!!!!!!!!!!!!
*/

 

구조체 안에 함수 선언 불가능하지만 !!!!!!!!

함수포인터는 구조체 안에 선언 가능

test21.c

#include <stdio.h>

typedef struct apple {
	int data;
	int (*add)(int, int); // 가능! 함수포인터는 구조체 안에 선언이 가능하다
}Apple;

int Apple_add(int i, int j){
	return 100;
}

int main() {
	Apple* t;
	t = (Apple*)malloc(sizeof(Apple));
	t->data = 0;
	t->add=  Apple_add;
	
	printf("%d %d  \n", t->data, t->add(10,20));
	
	return 0;
}

/*
	t->add(10,20)
	함수 포인터를 이용하면 마치 t가 가리키는 대상 안에 add라는 이름의 함수를 호출하는 것 같은
	모양을 만들 수 있다
	
	java는 class안에 함수 선언이 가능하다. 위와 같은 방법으로 호출할 수 있다.
	t.add(10,20);
*/

 

 

한번 만들어진 메모리 재사용할 때
단순 데이터 재사용하는 것과
이 데이터를 operation할 수 있는 것과
함수 재사용하는 것과 뭐가 더 효율적일까? 2일차 수업에서 계속..

 

[교육 2일차]

클래스
인스턴스
참조형변수
멤버변수
멤버함수
new
this

클래스 안에 올 수 있는 코드? 변수선언가능(멤버변수 / 대입은 불가), 함수선언가능(멤버함수 / 호출은 불가)
=> 클래스는 알고보면 구조체, 함수포인터 이용해서 구조체 안에 함수를 밀어 넣음

클래스로 뭐 할 수 있나? (변수선언 포인터선언 malloc = java에선 변수선언 빠짐)
- 포인터 선언 ( 클래스 이름으로 선언된 변수 - 클래스로 선언된 변수는 100%포인터다. 이를, 참조형변수라 한다.)
- 클래스 이름으로 선언된 변수는 인스턴스를 가리키게 된다

new와 malloc은 유사하다. 선언된 클래스 대로 메모리를 할당받은 실체가 인스턴스

멤버변수는 언제 메모리 할당받나? 인스턴스를 생성할때마다.
멤버변수는 어떻게 호출 ? 인스턴스 생성 + 참조형 변수를 이용 + 이름과 매개변수로 호출, this 사용가능

this는 알고보면 로컬변수이고, 호출 때마다 가리키는 대상이 달라지고, 호출된 함수를 포함하는 인스턴스를 가리키게 된다.

test22.c

#include <stdio.h>

typedef struct ab {
	int a;
	float b;
}AB;


int main(){
	int a;
	int *b;
	
	AB ab;
	AB *p;
	p = (AB*)malloc(sizeof(AB));
	ab.a = 100;
	p->b = 3.14;
	
	b= (int*)malloc(sizeof(int));
	*b = 100; // 변수는 이름 있지만 malloc으로 만든 공간은 이름이 없기에 포인터로 접근해야한다
	a=200;
	a = a + 100;
	
	return 0;
}

/*
변수는 이름 있지만 malloc으로 만든 공간은 이름이 없기에 포인터로 접근해야한다
구조체 : 변수, 포인터, malloc

*/

test23.java

class AB{
	int a;
	double b;
}


public class test23{
	public static void main(String[] args){
		AB p = null
		p = new AB();
	}
}

/*
	클래스: 변수
	모든 포인터에는 null값 대입 가능하다.
	포인터는 인스턴스를 가리킨다
	참조형변수는 클래스 이름으로 선언됐고
*/

test24.java

class Apple{
	int data=  0;
	int add(int i){		
		return 100;
	}
	
}


public class test24{
	public static void main(String[] args){
		Apple t = null;
		t = new Apple();
		
		t.data = 100;
		System.out.println(t.add(10));
	}

}

/*
	클래스 안에 선언된 함수를 호출하려면??
	1. 인스턴스 생성
	2. 참조형 변수로 가리키고
	3. 참조형변수. 함수명(매개변수값); 형태로 호출한다
*/

test25.c

#include <stdio.h>

typedef struct apple{
	int data;
	//int add (int i) {return 10101;} // c언어는 구조체 안에 함수 return 못함 -> 별도 함수로 외부에 작성하고 포인터로 선언해줘야함.
	int (*add)(int);
}Apple;

int Apple_add(int i){
	return 10101;
}

int main(){
	Apple* t; // 포인터 선언
	t = (Apple*)malloc(sizeof(Apple)); // 메모리할당
	
	t->data = 100; //데이터
	t->add = Apple_add;
	
	printf("%d", t->add(100));
	
	
	free(t);
	return 0;
}

test26.java

class Apple{
	int data=  23;
	int add(int i){		
		return (this.data + 10101 );
	}
	
}


public class test26{
	public static void main(String[] args){
		Apple t = null;
		t = new Apple();
		
		t.data = 100;
		System.out.println(t.add(10));
	}

}

/*
	this.data
	this는 변수 아님
	t.data = 100; 과 비교해보면 여기서 this는 Apple형 포인터이어야 한다!!
	
	this.data는 100이면 이 결과가 말이 된다(10201)
	this 포인터는 호출된 함수 포인터를 소유하고 있는 인스턴스를 가리키는 포인터 이어야 한다 !!
	(쉽게 얘기하면 자기 자신에 대한 포인터가 된다)
	
	
	print값이 10124일까 10201일까?
	10201
	t포인터에 data 100으로 값 다시 초기화한 후, add함수 호출한 것이기 때문. this.data는 자기자신의 함수포인터가 되어 Apple클래스를 가리키고 data는 100으로 재호출....
*/

 

test27.c

#include <stdio.h>

typedef struct apple{
	int a;
	int b;
	int c;
	int (*sum)(int, int, int);
}Apple;

int apple_sum(int a, int b, int c){
	return a+b+c;
}

int main(){
	Apple* t; // 포인터 선언
	t = (Apple*)malloc(sizeof(Apple)); // 메모리할당
	
	t->a = 10;
	t->b = 20;
	t->c = 30;
	t->sum = apple_sum;
	
	printf("%d", t->sum(t->a, t->b, t->c));
	
	free(t);
	return 0;
}

/*
	이렇게 함수를 만들면 굳이 구조체로 묶을 필요도 없고, 변수가 추가되면 다시 짜야한다
*/

 

test28.c

#include <stdio.h>

typedef struct apple{
	int a;
	int b;
	int c;
	int x;
	int (*sum)(struct apple*);
}Apple;

int apple_sum(Apple* this){
	return this->a + this->b + this->c + this->x;
}

int main(){
	Apple* t; // 포인터 선언
	t = (Apple*)malloc(sizeof(Apple)); // 메모리할당
	
	t->a = 10;
	t->b = 20;
	t->c = 30;
	t->x = 55;
	t->sum = apple_sum;
	
	printf("%d", t->sum(t));
	
	free(t);
	return 0;
}

/*
	c언어로 객체지향 프로그래밍 할 때,
	구조체 안에서 선언된 모든 함수 포인터의 첫번째 매개변수는 같은 타입의 포인터로 선언한다
	
	t->sum(t) 호출할 때, 사용한 포인터를 같이 넘긴다.
	
	Apple* this = t ; 
	this는 t가 가리키는 대상을 가리킨다.
	
	this 포인터는 sum 함수 포인터가 소속된 인스턴스 안의 모든 함수와 변수에 접근이 가능하다
	
	x변수를 추가한다고 생각하면 유지보수성이 좋아지더라
*/

test29.java

class Apple{
	int data=  23;
	void print(){		
		System.out.println(this.data);
	}
	
}
public class test29{
	public static void main(String[] args){
		Apple a= new Apple();
		a.data = 100;
		a.print();
		
		Apple b= new Apple();
		b.data =200 ;
		b.print();
		
	}

}

/*
	
*/

test30.c

#include <stdio.h>

int main(){
	int a[4];
	int i;
	int temp, max;
	
	// 3 1 4 2
	a[0] = 3;
	a[1] = 1;
	a[2] = 4;
	a[3] = 2;
	
	max = 0;
	if (a[max] < a[1]) { // 3<1
		max = 1; //x
	}
	if (a[max] < a[2]) { // 3<4
		max = 2; // max= 2
	}
	if (a[max] < a[3]) { // 4<2
		max = 3;
	}
	// max = 2
	//printf("1) max a[max] : %d %d", max, a[max]); // 2 4
	
	if(max != 0){
		temp = a[0]; // 3
		a[0] = a[max]; // a[0] = 4
		a[max] = temp; // a[2] = 3
	}

	
	for(i = 0; i < 4; i++){
		printf("%d\n", a[i]);
	} // 4 1 3 2
	return 0;

}

test31.c

#include <stdio.h>
void print(int* t){
	int i;
	for (i = 0; i < 3; i++){
		printf("print() :  %d\n", *(t+i));
	}
	//printf("print() :  %d\n", *t);
}


int main(){
	int a[2];
	int i;
	int *p;
	
	p = a ; // 배열형 변수는 사실은 포인터다
	
	a[0] = 10;
	a[1] = 20;
	a[2] = 30;
	
	printf("%d\n", *p); // 배열형 변수가 대입된 포인터는 배열의 첫번째 요소를 가리킨다
	printf("%d\n", *(p)); //
	printf("%d\n", *(p+0)); // a[0]
	printf("%d\n", *(p+1)); // a[1]
	
	for(i = 0; i < 3; i++){
		printf("%d\n", a[i]);
	} //
	
	print(a);
	return 0;

}

test32.c

#include <stdio.h>


void add(int* t){ // ???
	
	
}
void print(int* t){
	printf("print() :  %d\n", *(t+0));
	printf("print() :  %d\n", *(t+1));
	//int i;
	//for (i = 0; i < 3; i++){
	//	printf("print() :  %d\n", *(t+i));
	//}
	//printf("print() :  %d\n", *t);
}
void sort(int* t){
	int t;
	if (*(t+0) < *(t+1)){ // 동일 코드 : data[0] < data[1]
		t = *(t+0);
		*(t+0) = *(t+1);
		*(t+1) = t
	}
}

int main(){
	int a[2];
	
	add(a, 0, 100);
	add(a, 1, 200);
	
	sort(a);
	
	print(a);
	
	return 0;

}

/*
	이 코드에서
	add 없는 print함수는 의미가 없다
	add 없는 sort도 의미가 없다
	배열 없는 add도 의미 없다
	
	배열 + add + sort + print가 한 덩어리로 묶여서 재사용되는 빈도가 훨씬 많더라
	-> 객체지향적으로 이 부분을 해결해보자
*/

test33.java

public class test33{
	public static void main(String[] args){
		int[] data = new int[2];
		int[] t = data;
		
		data[0] = 100;
		t[1] = 200;
		
		System.out.println(data[1]);
		System.out.println(t[0]);
		
		
	}
}
/*
	int[] data = new int[2];
	
	배열은 인스턴스이다 (new)
	data는 배열을 가리키는 참조형 변수가 된다 (포인터)
	

*/

test34.java

/*
java는 변수와 함수가 독립적으로 존재할 수 없다. 클래스 안에서 선언되어야 한다.
멤버함수 안에서는 this를 쓸 수 있고
t.add(0,100) 형태로 호출됐을 때, add함수 안의 this는 t와 같은 대상을 가리키게 된다.

add, sort, print는 data배열과 뗄레야 뗄 수 없는 관계가 성립된다.
자연스럽게 한 묶음이 되고, 재사용성이 늘어나게 된다.
*/
class Banana{
	int[] data = null;
	
	void add(int idx, int val){
		this.data[idx] = val;
		
	}
	void print(){
		System.out.println(this.data[0] + "," + this.data[1]);
	}
	void sort(){
		if (this.data[0] < this.data[1]){
			int temp = this.data[0];
			this.data[0] = this.data[1];
			this.data[1]= temp;
		}
	}
}

public class test34{
	public static void main(String[] args){
		Banana t = new Banana();
		t.data = new int[2];
		t.add(0,100);
		t.add(1,200);
		t.sort();
		t.print();
		
	}
}

test35.c

#include <stdio.h>

typedef struct banana{
	int *data;
	void (*add)(struct banana*, int, int);
	void (*print)(struct banana*);
}Banana;

int banana_add(Banana* this, int idx, int val){
	//this->data[idx] = val;
	*(this->data+idx)= val;
}

/*
void print(Banana* this){
	pirntf(this.data[0] + "," + this.data[1]);
	
}
*/

Banana* new_Banana(){
	Banana* t;
	t= (Banana*)malloc(sizeof(Banana));
	
	t->add = Banana_add;
	t->data = (int*)malloc(sizeof(int)*2);
	
	return t;
	
}

int main(){
	Banana* b; // 포인터 선언
	t = (Banana*)malloc(sizeof(Banana)); // 메모리할당

	t->add(t, 0, 100);

	free(t);
	return 0;
}

/*
	이렇게 함수를 만들면 굳이 구조체로 묶을 필요도 없고, 변수가 추가되면 다시 짜야한다
	
	c언어로 객체지향스럽게 코드를 짠 예
	
	c언오로 구조체와 함수포인터를 사용하여 객체지향 적으로 개발할 수도 있다
	하지만 애초에 객체지향 프로그래밍을 목적으로 만든 언어를 사용하는 것이 더 적합하다
	
	이코드는 객체지향 언어의 주요개념들(클래스 인스턴스 멤버변수 멤버함수 this new 등)을
	이해하기 위한 목적으로 사용하자
*/

test36.java

class Apple{
	int data; // 멤버변수
	Apple(int i ){ // 생성자함수 : 인스턴스 생성시 호출됨
		System.out.println("Apple " + i);
		this.data = i;
	}
}

public class test36{
	public static void main(String[] args){
		Apple t = null;
		Apple x = new Apple(100);
		Apple y = new Apple(200);
		
		System.out.println(x.data + ", " + y.data);
		
		//x.Apple(0); // 에러. 생성자함수는 멤버함수가 아니어서 포인터로 호출될 수 없다.
	}
}

/*
	클래스 이름과 같고, 리턴타입이 없다 -> 생성자함수 (Constructor)이라고 한다.
	호출될 수 있지만 멤버함수가 아니다. -> 인스턴스 생성시에 호출된다(매번)
	
	생성자 함수에는 매개변수를 선언할 수 있고, 생성자 함수에 값을 전달할 수 있고
	-> "주로(대부분) 멤버변수를 초기화하는 용도로 사용된다."
*/

 

test38.java

class Node{
	int data = 0;
	Node next = null;
	
	/*
	Node(int a){
		this.data=a;
	}*/
	
	Node(int a, Node b){
		this.data=a;
		this.next=b;
	}
}

class LinkedList{
	Node head = null;
	Node tail = null;

	Linkedlist(){
		this.head = new Node(0,null);
		this.tail = this.head;
		
	}
	
	void add(int i){
		this.tail.next = new Node(i, null);
	}
	
	
 

public class test38{
	public static void main(String[] args){
		//Node head = new Node(99);
		//System.out.println(head.data);
		
		//Node head2 = new Node(42, null);
		//System.out.println(head2.data);
		
		LinkedList l = new LinkedList();
		l.add(10);
		l.add(20);
		l.add(30);
		
		
	}
}

/*

*/

test39.c

#include <stdio.h>

int main(){
	int a, *p;
	float b;
	void *vp;
	
	a=10;
	p = &a; // 당연 int* 변수가 int형 공간을 가리킨다
	vp = &a; // void* 형 변수가 int공간을 가리킨다
	
	printf(" %d\n", *p);
	// printf("%d\n", *vp); // 에러. void*형은 반드시 타입 형변환 시킨 후 사용해야함.
	printf(" %d\n", *((int*)vp));
	
	b = 3.14;
	vp = &b; // void*형 변수는 모든 형태의 기억공간을 가리킬 수 있다.
	
	printf("%d\n", *((float*)vp));
	
	printf("%d\n", *((int*)vp));
}

 

 

 

[교육 3일차]

test41.java

class Dog{
	int weight=500;
}

public class test41{
	public static void main(String[] args){
		Dog mary = new Dog();
		mary.weight = mary.weight + 12;
		
		System.out.println(mary.weight);
		
		Dog happy = mary;
		happy.weight = happy.weight + 59;
		System.out.println(happy.weight);
	}
}
/*
	인스턴스가 가진 메모리는
	인스턴스를 가리키는 참조형 변수의 개수가 0이 되는 순간에 회수한다
	(가비지콜렉터 라는 메커니즘이 있고 이것은 자바 실행머신에서 활동한다)
	
	실제로 소거하는 시점은? CPU가 놀 때(할일없음), 메모리가 부족(배고파 죽겠다)
	
	main이 끝나서 mary happy 두 포인터가 자동으로 없어진다 (로컬변수)
	따라서 new Dog()로 생성한 메모리가 밥줄이 끊기고 -> 포획되고 -> 소거된다
	
	없앨 수는 없지만 잡혀가게 할 수는 있다 -> 가리키는 포인터의 개수를 0으로 만들면 된다. 
*/

test42.java

class Node{
	int data = 0;
	Node next = null;
	
	Node(int a, Node b){
		this.data=a;
		this.next=b;
	}
}


public class test42{
	public static void main(String[] args){
		Node head = new Node(0,null);
		Node tail = head;
		
		tail.next = new Node(10,null); 
		tail = tail.next;
		
		tail.next = new Node(20,null); 
		tail = tail.next;
		
		tail.next = new Node(30,null); 
		tail = tail.next;
		
		for(Node t = head.next; t != null ; t = t.next){
			System.out.println(t.data);
		}
		
		Node a = head ; 
		Node b = head.next;
		
		while(a != null){
			a.next = null;
			
			a=b;
			b=b.next;
			
		}
		tail = head;
	}
}
/*
	
*/

test43.c

#include <stdio.h>

typedef struct node {
	int data;
	struct node *next;
}Node;

Node* new_Node(int i, Node* b){
	Node* t;
	t= (Node*)malloc(sizeof(Node));
	
	t->data = i;
	t->next = b;
	
	return t;
	
}

int main(){
	Node *head, *tail, *t;
	Node *a, *b;
	
	head = new_Node(0,Null);
	tail = head;
	
	tail->next = new_Node(10, Null);
	tail = tail->next;
	
	tail->next = new_Node(20, Null);
	tail = tail->next;
	
	tail->next = new_Node(30, Null);
	tail = tail->next;
	
	// 어디에 어떻게 코드를 한 줄 짜면 싹 다 지울 수 있을까?
	a= head;
	b = head->next;
	while (a!=Null){
		a=b;
		b=b->next;
	}
	
	for(t= head->next ; t != Null ; t->next){
		printf("%d\n", t->data);
		
	}
	
	free(head);
	
	return 0;
}

test44.java

class A{
	int data = 100;
	
}
/*
	상속 : 클래스가 가진 멤버변수와 멤버함수를 물려받는 것
*/
class B extends A{
	void print(){
		System.out.println("print");
	}
}

public class test44{
	public static void main(String[] args){
		A a = new A();
		//a.print(); // error
		
		B b = new B();
		System.out.println(b.data);
		b.print();
		
		/*
			조상 클래스형 포인터로 자손 클래스의 인스턴스를 가리킬 수 있다.
			(상속 받은 클래스가 자손, 상속을 준 클래스가 조상)
			
			이때 조상에서 선언된 함수와 변수가 접근 가능하다.
		*/
		A ab = new B();
		// ab.print(); 분명 print 함수 포인터가 있는데도 접근이 안된다
		System.out.println(ab.data);
		
		// B ac = new A(); // error 자손은 조상에게 상속만 받을 수 있음.
		
		
	}
}

test46.c

#include <stdio.h>
#include <stdlib.h>

typedef struct a {
	int data;
}A;

typedef struct b {
	int data; // 상속되어서 물려받은 멤버변수
	void (*print)(void); // 자손에서 추가된 멤버함수
}B;

int main(){
	void* vp;
	A* a;
	B* b;
	
	vp = malloc(sizeof(B));
	a = (A*)vp;
	
	printf("%d\n", a->data);
	//a->print(); // error 조상은 조상까지만 접근가능
	
	b=(B*)vp;
	b->print(); // 자손은 조상+자손 접근가능
	
	return 0;
}

test47.c

#include <stdio.h>
#include <stdlib.h>

typedef struct a {
	int data;
}A;

typedef struct b {
	int data; // 상속되어서 물려받은 멤버변수
	void (*print)(void); // 자손에서 추가된 멤버함수
}B;

void a_print(){
	printf("apple\n");
	
}

void* new_a{
	A* t;
	t = malloc(sizeof(A));
	t->data=100;
	t->print = a.print;
	
	return t;
	
}
int main(){
	A* a;
	a=(A*)new_a();
	printf("%d\n", a->data);
	a->print();
	
	return 0;
}

test48.c

#include <stdio.h>
#include <stdlib.h>

typedef struct a {
	int data;
}A;

// 상속은 골라받을 수 없다. 그대로 순서대로 온 다음 자손에서 추가된 것을 넣어준다.
typedef struct b {
	int data; // 상속되어서 물려받은 멤버변수
	void (*print)(void); // 자손에서 추가된 멤버함수
	void (*print2)(void);
}B;

void a_print(){
	printf("apple\n");
	
}
void b_print(){
	printf("banana\n");
	
}

void* new_a(){
	A* t;
	t = malloc(sizeof(A));
	t->data=100;
	t->print = a.print;
	
	return t;
	
}

void* new_b(){
	B* t;
	t = malloc(sizeof(t));
	t->data=444;
	t->print = a_print;
	t->print = b_print;
	return t;
	
}

int main(){
	A* a;
	B* b;
	
	
	
	a=(A*)new_a();
	printf("\n%d\n", a->data);
	a->print();
	
	printf("\n%d\n", b->data);
	b->print();
	
	b=(B*)new_b();
	printf("\n%d\n", b->data);
	a->print();
	
	return 0;
}

test49.java

class A{
	void print(){
		System.out.println("apple");
	}
	
}

class B extends A{
	void print(){
		System.out.println("banana");
	}
}

public class test49{
	public static void main(String[] args){
		B b = new B();
		b.print(); // banana
	}
}

test50.c

#include <stdio.h>
#include <stdlib.h>

typedef struct a {
	void (*print)(void);
}A;

void a_print(){
	printf("apple\n");
	
}
void b_print(){
	printf("banana\n");
	
}

void* new_a(){
	A* t;
	t= (A*)malloc(sizeof(A));
	t->print = a_print;
	return t;
	
}

typedef struct b {
	void (*print)(void);
}B; // 오버라이딩이 일어난 경우에는 함수포인터를 선언하지 않는다

void* new_b(){
	B* t;
	t= (B*)malloc(sizeof(B));
	t->print = a_print; // 물려받는다
	t->print = b_print; // 오버라이딩의 실체
	// 포인터는 물려받은 거, 가리키는 실체는 자손에서 추가된 것
	return t;
	
}

int main(){
	A* a;
	B* b;

	a=(A*)new_a();
	a->print();
	

	b=(B*)new_b();
	a->print();
	b->print();
	
	return 0;
}

/*
결과
apple
apple
banana
*/

test51.java

class A{
	void print(){
		System.out.println("apple");
	}
	
}

class B extends A{
	void print(){
		System.out.println("banana");
	}
	void print2(){
		System.out.println("orange");
	}
}

public class test51{
	public static void main(String[] args){
	
		A a = new A();
		a.print();
		
		B b = new B();
		b.print(); // banana
		b.print2();
		
		A ab = new B();
		ab.print();
		//ab.print2();//error
	}
}
/*
apple
banana
orange
banana

조상의 포인터로 자손의 인스턴스를 가리킬 수 있다.
조상에서 선언된 멤버변수 멤버함수만 접근 가능하다.
만일 오버라이딩 된 경우에는 오버라이딩 된 함수가 호출된다.
*/

tset52.java

class Node{
	int data = 0;
	Node next = null;
	
	Node(int a, Node b){
		this.data=a;
		this.next=b;
	}
}

class LinkedList{
	Node head = null;
	Node tail = null;
	
	LinkedList(){
		head = new Node(0,null);
		tail=head;
	}
	void add(int a){
		tail.next = new Node(a, null);
		tail = tail.next;
	}
	void print(){
		for (Node t = head.next; t != null; t=t.next){
			System.out.println(t.data);
		}
	}
}

class LinkedList2 extends LinkedList{
	void add(int a){
		head.next = new Node(a, head.next);
	}
}


public class test52{
	public static void main(String[] args){
	
		LinkedList l = new LinkedList();
		l.add(10);
		l.add(20);
		l.add(30);
		l.print();
		
		/*
		10
		20
		30
		*/
		
		LinkedList l2 = new LinkedList2();
		l2.add(10);
		l2.add(20);
		l2.add(30);
		l2.print();
		/*
		30
		20
		10
		*/
	}
}
/*

*/

test53.java

class A{
	A(){
		System.out.println("a");
	}
}

class B extends A{
	B(){
		System.out.println("b");
	}
}

public class test53{
	public static void main(String[] args){
		new B();
	}
}

/*
결과
a
b

생성자함수는 인스턴스를 생성했을 때 (new) 호출된다.
자손의 인스턴스를 생성했다 -> 조상의 생성자 호출되고, 자손의 생성자가 호출된다.

생성자함수: 멤버변수 초기화 용도
-> 조상의 멤버변수는 조상의 생성자에서, 자손의 멤버변수는 자손의 생성자에서 각각 초기화 한다.
*/

test54.java

class A{
	int apple = 1;
	A(int i){
		this.apple = i;
	}
	
}

class B extends A{
	
	int banana = 4;
	B(int i, int j){
		//this.apple = j; // error
		super(j); // 
		this.banana = i;
	}
}

public class test54{
	public static void main(String[] args){
		B b = new B(100,200);
		System.out.println(b.apple);
		System.out.println(b.banana);
	}
}

/*
200
100

조상의 멤버변수는 조상의 생성자에서, 자손의 멤버변수는 자손의 생성자에서 각각 초기화한다.
B는 apple, banana 두개의 멤버변수를 가지고 있다.

자손의 인스턴스를 생성하면 조상의 '디폴트로 매개변수 없는 생성자'가 호출된다
A(){...} 생성자가 선언딘 적이 없다. <- 에러가 났다
*/

조상의 멤버변수는 조상의 생성자에서, 자손의 멤버변수는 자손의 생성자에서 각각 초기화한다.
B는 apple, banana 두개의 멤버변수를 가지고 있다.

자손의 인스턴스를 생성하면 조상의 '디폴트로 매개변수 없는 생성자'가 호출된다
A(){...} 생성자가 선언딘 적이 없다. <- 에러가 났다

조상의 생성자가 먼저 생성됨
즉 자손쪽에서는 먼저 호출되는 조상의 생성자를 선택할 수 있다
선택하게 만드는 것에 super()

test56.c

#include <stdio.h>
#include <stdlib.h>

typedef struct a {
	int apple;
	void (*print)(struct a*);
}A;



void a_print(A* this){
	printf(" a_print(A* this->apple :  %d\n",this->apple);
	
}

void a_constructor(A* this, int val){
	this->apple = val;
}

void* new_a(int val){ 
	A* t;
	t= (A*)malloc(sizeof(A));
	t->print = a_print;
	
	a_constructor(t, val);
	
	return t;
}

typedef struct b {
	int apple;	
	void (*print)(void *);
	
	int banana;
}B; 


void b_print(void* self){
	B *this;
	this = (B*)self;
	
	printf(" b_print(B* this->banana :  %d\n",this->banana);
	
}
void b_constructor(void* self, int val){
	B* this;
	this = (B*)self;
	
	this->banana = val;
}

void* new_b(int i, int j){ 
	B* t;
	t= (B*)malloc(sizeof(B));
	
	t->print = a_print;
	t->print = b_print; 
	
	a_constructor(t,j);
	b_constructor(t,i);
	return t;	
}

int main(){
	
	A *a;
	a=(A*)new_a(200);
	a->print(a);

	
	B *b;
	b=(B*)new_b(100,200);
	b->print(b);
	
	
		
	free(a);
	free(b);
	return 0;
}

test59.java

abstract class A{
	abstract void print();
	void print2(){} //abstarct 하지 않은 함수를 같이 쓰는 건 상관없다
	
}

class B extends A{
	void print(){
		System.out.println("print");
	}
	void sound(){
		
		System.out.println("sound");
	}
}

public class test59{
	public static void main(String[] args){
		B banana = new B();
		banana.print();
		banana.sound();
	}
}
/*
print
sound

void print(); 로 함수 선언을 하려면 반드시 abstract가 앞에 붙어주어야한다
abstract 멤버함수를 하나라도 가지고 있는 클래스는 abstract 해야한다.
abstract class는 인스턴스를 못 만든다

abstarct클래스 :: 추상클래스
인스턴스를 생성할 수 없는 클래스
하나이상의 추상메서드(구현되지 않은 메서드)를 가질 수 있음
자식클래스가 이 클래스를 상속받아 구현을 완성해야함


*/

test60.java

abstract class shoppingmall{
	abstract int db();
	void list(){
		int result = db();
		System.out.println(result);
	}
}

class shoppingmall_mysql extends shoppingmall{
	int db(){
		System.out.println("mysql 연동");
		return 100;
	}
}

class shoppingmall_mariadb extends shoppingmall{
	int db(){
		System.out.println("mariadb 연동");
		return 200;
	}
}

public class test60{
	public static void main(String[] args){
		shoppingmall D1 = new shoppingmall_mysql();
		D1.list();
		shoppingmall D2 = new shoppingmall_mariadb();
		D2.list();
	}
}
/*

*/

현재 상황에서 결정할 수 없거나, 앞으로 변경이 만이 일어날 부분을 abstract로 비워놓고
변경이 적은 부분을 미리 클래스로 만들어놓을 수 있다
쇼핑몰 클래스의 재홀용 빈도가 늘어나게되고 -> 생산성이 향상된다

abstract method의 실체는 구조체 안의 함수포인터에 NULL값이 들어가 있는 꼴이다.
이러한 구조체는 MALLOC하게되면 폭탄이 될 수 있다. -> NULL 값이 들어간
함수포인터는 호출하면 터진다. -> 따라서 이런 구조체는 malloc못하게 해야 한다.
-> 인스턴스를 못 만다는 클래스
mysql 연동
100
mariadb 연동
200

 

[교육 4일차]

test65.java

abstract class Apple{
	abstract int add(int i, int j);
}

class Apple2 extends Apple{
	int add(int i, int j){
		return i+j;
	}
}


public class test65{
	public static void main(String[] args){
		Apple a = new Apple2();
		System.out.println(a.add(1,2));
	}
}
/*

*/

선언되었지만 정의되지 않은 함수 : abstract method
(함수 포인터에 null 값이 대입된 형태와 유사)

함수 포인터에 null값이 대입된 구조체는 존재해서는 안된다. :: 언제 뻗을지 모른다
- 해서 java에서는 인스턴스를 못 만들게 문법으로 박았다 -> abstract class

abstract method 를 상속받으면서 오버라이딩을 하면 abstract 성격이 빠져나간다

t->add = NULL;

test67.java

abstract class Clac {
	abstract int multicas(int i, int j);
	//Addclc(int a) {seed = a;}
	int execute (int i ) {return i + this.seed;}
}

class Mulcalc extends Clac{
	int banana = 0;
	Mulcalc (int a ) {this.banana=  a;}
	int execute (int i ) {return (banana+10)* i;}
}


public class test67{
	public static void main(String[] args){
		
		/*Clac a = new AddCalc(100);
		System.out.println(a.execute(20));*/
		
		Clac b = new MulCalc(100);
		System.out.println(b.execute(20));
	}
}

test68.java

interface IA {
	//void print(){}; // 에러
	void print();
}

class A implements IA {
	void print(){ // 오버라이딩abstract class Clac {
}

public class test68{
	public static void main(String[] args){
		//new IA(); // 에러
		IA t = null;
		System.out.println();
	}
}

/*
*/

interface
- abstract method만 선언이 가능하다
- 앞에 abstract 안 붙여도 자동으로 붙는다.
- 당연히 인스턴스 못만든다 ( 좀 이상한 클래스다)
- 인터페이스를 상속받아 클래스를 만들때는 implements를 이용한다.
  (인터페이스를 상속받아 인터페이스를 만들 때 extends를 사용한다)
- 인터페이스를 상속받아 클래스 선언할 때는 인터페이스의 모든 함수를 오버라이딩 해야한다.

test73.java

class Adam{
	private int redBook = 100;
	public int subHouse = 200;
	protected int map = 300; // 상속자는 접근 가능한데, 포인터로는 접근 불가
	
	void picnic(){
		System.out.println(redBook);
		System.out.println(subHouse);
		}
}

class Brown extends Adam{
	void give(){
		//System.out.println(redBook);//error
		System.out.println(subHouse);
		System.out.println(map);
	}
}

class Jen extends Brown{
	void give2(){
		//System.out.println(redBook);//error
		System.out.println(subHouse);
		System.out.println(map);
	}
}

public class test73{
	public static void main(String[] args){
		Adam a = new Brown();
		//System.out.println(a.redBook); // error // redBook has private access in Adam
		System.out.println(a.subHouse); 
		System.out.println(a.map); 
		//System.out.println(a.give2()); 
		
	}
}
/*


*/

멤버변수와 멤버함수 앞에서 
private : 포인터를 통해 접근이 불가능
protected : 다른 패키지에 속한 클래스는 포인터로 접근 불가능.
public
이 붙어서 접근을 제한할 수 있다

아무것도 없는 경우는 friendly라고 하는데
같은 패키지는 public, 다른 패키지에게는 private로 동작한다

 

 

test74.java

class A{
	public String toString(){
		return "Hello world";
	}
}

public class test74{
	public static void main(String[] args){
		Object t = new A();
		System.out.println(t.toString());
		
		System.out.println((int)(10/3.0));
	}
}

/*
*/

아무 클래스로부터 상속받지 않으면 extends Object가 생략된다

Object는 내장되어 있는 클래스, '모든클래스의 조상이 된다'

toString()은 Object에서 선언되었고, 또한 물려받았다.
java클래스의 모든 인스턴스는 toString()함수를 가지고 잇다 -> Object는 모든 클래스의 조상

toString함수를 오버라이딩 하면 t.toString()호출 시 오버라이딩 된 함수가 호출된다

[JAVA 자료형]

자료형 이름 = 초기값;

정수형 변수 선언에 쓰는 자료형 4가지 : byte(8bit) short(16bit) int(32bit) long(64bit)
일반적으로 40... 이렇게 값을 쓰면 32bit값인데 40L은 64bit 값이 된다

실수형 변수 선언에 쓰는 건 두가지 : float (32bit) double(64bit)
3.14F 32bit가지는 실수 3.14는 64bit값

boolean으로 선언된 변수

char 

UTF-8은 1~4바이트 크기를 가지는 가변 길이 문자 체계이고
이것이 인터넷의 표준 인코딩 방법이 되고 있다

필요한 경우, 8859_1(아스키코드), Unicode, UTF-8을 전환하는 것이 필요할 수 있다


약->강한타입
byte < short < int < long(64bit) < float(32bit) < double(64bit)
long(64bit) < float(32bit) : long이 64인데도 float가 더 쎄다(?) 왜?
약한 타입에서 강한 타입으로는 자동 형변환이 가능하지만
강한 타입에서 약한 타입으로는 강제로만 형 변환이 가능하다 (c언어에서는 없다)

100이 그대로 들어갈까? 아니면 변환시켜 들어갈까? 변환시켜 들어감. double이 강타입으로 자동형변환
변수가 double이고 값이 int면? 변수가 원하는 형태에 맞게 형 변환을 하고 (100.0)으로 바꾸고 대입한다

3.14는 double형이다. double에 int 
약->강타입 : 자동변환 o ex) double b = 100 ; // 100.0
강->약타입 : 자동변환 x ex) int a= 3.14; error // int에 double 못 넣어. 

test80.java

public class test80{
	public static void main(String[] args){
		String t = "helloworld";
		System.out.println(t);
		System.out.println(t.length());
		System.out.println(t.substring(2,5));
		
	}
}

/*
*/

t는 포인터일까요? String은 자료형 아니라 클래스이고, t는 포인터

"Helloworld"는 랎? 인스턴스? -> 인스턴스여야한다

String은 new를 이용하지 않고 인스턴스를 생성하는 유일한 클래스이다.

length()는 문자열 길이를 리턴하는 String의 멤버함수이다.

 

 


[교육 5일차]

test

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

반응형