2019/04/14 - [Android] - 안드로이드 리사이클러뷰(RecyclerView) 사용법 (1)

 

지난 글에 이어서 리사이클러뷰의 아이템부터 알아보겠다.

 

 

/* item.xml */

 


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="100dp"
    android:orientation="horizontal">


    <ImageView
        android:id="@+id/imageView"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        app:srcCompat="@mipmap/ic_launcher" />

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:gravity="center"
        android:paddingLeft="20dp"
        android:paddingRight="20dp"
        android:text="제목" />

    <TextView
        android:id="@+id/textView2"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:gravity="center"
        android:paddingLeft="20dp"
        android:paddingRight="20dp"
        android:text="내용" />
</LinearLayout>

 

- [layout] -> [new] -> [Layout Resource File] 로 .xml 레이아웃 파일을 하나 생성한다.

 

- 아이템은 간단한 예시로 이미지뷰 1개, 텍스트뷰 2개로 구성하였다. 여기서 리스트뷰에 표시할 한 아이템의 레이아웃을 만들면 된다. 

 

 

 

 

 

 

/* RecyclerViewA.java */

 


package com.tistory.godog.test2;

import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

public class RecyclerViewA extends RecyclerView.Adapter<RecyclerViewA.ViewHolder> {

    private String[] title = {"제목1", "제목2", "제목3", "제목4",
            "제목5", "제목6", "제목7", "제목8", "제목9", "제목10", };

    private String[] content = {"내용1", "내용2", "내용3", "내용4",
            "내용5", "내용6", "내용7", "내용8", "내용9", "내용10", };

    public class ViewHolder extends  RecyclerView.ViewHolder {
        public TextView textView;
        public TextView textView2;
        public ImageView imageView;

        public ViewHolder(View view) {
            super(view);
            this.textView = view.findViewById(R.id.textView);
            this.textView2 = view.findViewById(R.id.textView2);
            this.imageView = view.findViewById(R.id.imageView);
        }
    }

    @Override
    public RecyclerViewA.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false);
        RecyclerViewA.ViewHolder viewHolder = new ViewHolder(view);
        return viewHolder;
    }

    @Override
    public void onBindViewHolder(RecyclerViewA.ViewHolder holder, final int position) {
        holder.textView.setText(title[position]);
        holder.textView2.setText(content[position]);

        holder.imageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(v.getContext(), position+"번 째 이미지!", Toast.LENGTH_SHORT).show();
            }
        });

        holder.textView2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(v.getContext(), "Test!", Toast.LENGTH_SHORT).show();
            }
        });

        holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(v.getContext(), position+"번 째!", Toast.LENGTH_SHORT).show();
            }
        });
    }

    @Override
    public int getItemCount() {
        return title.length;
    }
}

 

1. 자바(.java) 파일을 추가합니다.

 

2. RecyclerView.Adapter<RecyclerView.ViewHolder>를 상속 받습니다.

 

3. [Ctrl]+[I] 3개의 메소드를 추가해줍니다.

 

4. 19라인의 RecyclerView.ViewHolder를 상속받은 클래스를 선언한 후 item에서 뷰객체 변수를 선언한 후 연결해 줍니다.

 

5. 2번에서 상속하였던 <RecyclerView.ViewHolder> 부분을 <자바파일명.4번의 선언한 클래스명>으로 수정해줍니다.

 

 

여기까지 진행하였다면 전반적인 구조는 끝이난다.

 

 

onCreateViewHolder() : 이곳은 LayoutManager에 의해 새 아이템을 만들 때 호출하며, 이 아이템뷰의 ViewHolder를 만들어준다.

 

onBindViewHolder() : LayoutManager에 의해 ViewHolder에 position에 맞는 데이터를 이용하여 리스트를 채우게 된다.

 

getItemCount() : 보통 메소드 이름처럼 리사이클러뷰의 표시할 데이터(아이템)의 개수를 리턴 한다.

 

 

 

- holder에서 연결한 item의 뷰 객체들은 onBindViewHolder() 메소드내에서 onClick()등 액션에 대한 실행을 지정할 수 있습니다.

 

아래 이미지는 이미지 뷰, 텍스트 뷰, 아이템에 따라 클릭하였을 때 다른 결과를 확인 할 수 있습니다.

 

이렇듯 리사이클러뷰를 사용하면 간단하게 각 아이템마다 액션을 설정하거나 아이템 내 각각의 뷰마다 액션을 간단히 설정 할 수도 있다.

 

T리사이클러뷰를 이용하여 커스텀 리스트를 만들어 본다.

 

실행 화면

- 리사이클러뷰(RecyclerView)는 기존의 사용하던 리스트뷰(ListView)의 단점들을 보완한 레이아웃이다.

 

- 단점들을 보완하여 만들어진만큼 기존의 커스텀 리스트뷰를 만들 때에 복잡함을 줄여 리스트를 만들 수 있다. ( 데이터를 관리하는 것과 UI를 표현하는 것이 분리가 되어있으므로 번거로운 기존의 수정 방식을 피할 수 있고 에러도 줄일 수 있다.)

 

 

 

 

리사이클러뷰(RecyclerView)

- 이름 그대로 리사이클(재활용)하므로 많은 양의 데이터를 표시하여도 메모리가 부족하게 되어 프로그램이 강제로 종료되는 상황을 막을 수 있다.

(이는 가끔 앱들을 사용하면서 화면을 내릴 때 화면이 버벅거리는 현상들을 발생시킨다.)

 

 

- 재활용이란 위 2개의 이미지를 보면 이해하기 편한데 첫 번째 이미지를 보면 1번 뷰와 같이 스크롤을 내려 보이지 않는 뷰도 메모리를 계속 사용하고 있다.

 

하지만 리사이클 뷰는 두 번째 이미지처럼 지나친 1번 뷰를 다시 아래로 재사용함으로써 메모리 문제를 해결하도록 만들어 준다.

 

 

 

 

 

 

 리사이클뷰를 사용하기 위해서는 우선 라이브러리를 추가해주어야 한다.

 

implementation 'com.android.support:recyclerview-v7:27.1.1'

 

직접 추가해주어도 상관없지만 아래 글을 참조하여 추가해주면 더욱 좋을 것이다.

 

2019/04/03 - [안드로이드] - 안드로이드 스튜디오 라이브러리 추가

 

 

 

 

 

 그러면 먼저 프로젝트 생성 시 만들어지는 메인 레이아웃과 메인 자바 파일을 살펴보겠다.

 

 

 

/* 메인 레이아웃( activity_main.xml ) */

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <RelativeLayout
        android:id="@+id/rel"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <android.support.v7.widget.RecyclerView
            android:id="@+id/recycler_view"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:paddingBottom="40dp">

        </android.support.v7.widget.RecyclerView>

        <Button
            android:id="@+id/button"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignBottom="@+id/recycler_view"
            android:text="hoxy" />
    </RelativeLayout>
</LinearLayout>

 

- android.support.v7.widget.RecyclerView로 리사이클러뷰를 추가하였다. Design 탭의 Palette의 검색하여서 추가할 수도 있다.

 

- 위 코드를 보면 굳이 RelativeLayout 속에 리사이클러뷰와 버튼을 추가하였다. 이는 리사이클러뷰 밑에 버튼 추가 시 보이지 않는 문제를 해결하기 위해서이다.

( 아마도 버튼이 리사이클러뷰 아래로 가서 보이지 않는 것 같다. 버튼을 먼저 삽입하고 리사이클러뷰를 삽입하면 버튼이 보인다.)

 

- 리사이클러뷰에서 paddingBottom을 40dp 준 이유도 마찬가지이다. 이를 한번 빼보고 실행해보는 것도 좋을 것이다.

 

 

 

 

 

 

/* 메인 자바 코드 ( MainActivity.java ) */

package com.tistory.godog.test2;


import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;


public class MainActivity extends AppCompatActivity {

    private RecyclerView recyclerView;
    public RecyclerView.LayoutManager layoutManager;
    private RecyclerView.Adapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        recyclerView = findViewById(R.id.recycler_view);
        recyclerView.setHasFixedSize(true);

        //layoutManager = new GridLayoutManager(this, 1);
        layoutManager = new LinearLayoutManager(this);
     

        recyclerView.setLayoutManager(layoutManager);

        adapter = new RecyclerViewA();
        recyclerView.setAdapter(adapter);
    }
}

 

- 변수 선언 

 12라인 : 리사이클러뷰 변수를 선언

 13라인 : 리사이클러뷰 변수와 연결하여 관리할 레이아웃 매니저 변수 선언

 14라인 : 리사이클러뷰 어뎁터 선언

 

- 설정

 22라인 : .setHasFixedSize(true) 메서드는 리사이클러뷰 안 아이템들의 크기를 가변적으로 바꿀지 아니면 일정한 크기를 사용할지를 지정한다.

 이를 false로 준다면 매번 아이템들의 크기를 계산해야 하므로 성능 저하에 영향을 미칠 수 있다. 그리고 디자인적으로도 크기가 다 같은 것이 좋으니 true를 주는 게 좋다.

 

 

 24/25라인 : 레이아웃 매니저의 타입을 지정해준다. 24라인 주석처리가 된

  new GridLayoutManager(this, 1)는 그리드형으로 보여준다. 그리드형이라고 한다면 쉽게 말해서

  m x n 형태이다. 여기서 2번 째로 주는 인수열의 개수이다.

 

 25라인 : new LinearLayoutManager(this)는 우리가 생각하는 그 리스트형으로 설정에 따라서 가로 혹은 세로로 표시할 수 있다.

 

 

 28라인  : 리사이클러뷰와 레이아웃 매니저를 연결해준다.

 

 

 30라인 : 여기서는 어뎁터 객체를 생성하는데, 이는 추후의 추가할 어뎁터 자바 파일명이다.

 

 31라인 : 리사이클러뷰의 어뎁터를 연결해준다.

 

 

 

 

다음 글에서 이어집니다 

 

2019/04/14 - [Android] - 안드로이드 리사이클러뷰(RecyclerView) (2)

 

 

 

1. 문제

 

Up & down 게임 만들기

 

Up & Down 게임 프로그램을 작성해보자. 게임에 참석하는 사람은 2명이며, 번갈아 가며 다음과 같이 숨겨진 답에 접근해 간다. Up & Down 게임은 전체적으로 UpAndDownGame 클래스로 작성하고 static 멤버로만 구성하라. 선수를 표현하기 위해 Person 클래스를 작성하고 main() 함수는 프로그램을 시작시키는 기능 정도로만 구현하라.

 

 

 

2. 결과

 

 

 

 

3. 코드

 

#include <iostream>
#include <string>
#include <cstdlib>
#include <ctime>
using namespace std;

class Person {
	string s[2];
	int n;
public :
	Person(){ s[0] = "류현진"; s[1] = "손연재"; n=-1; }
	string getName() { 
		n++;
		if( n == 2) {
			n = 0;
			return s[n];
		}
		else return s[n]; }
};

class UpAndDownGame {
	static int result;
	static int low, high;
public :
	UpAndDownGame() { srand( (unsigned)time(0) ); }
	static void Game() ;
};

int UpAndDownGame::high = 99;
int UpAndDownGame::low = 0;
int UpAndDownGame::result = 0;
void UpAndDownGame::Game() {
	int number; Person p;
	cout << "Up & Down 게임을 시작합니다." << endl;
	result = rand() % 100;
	while(1) {
		string name = p.getName();
		cout << "답은 " << low << "과 " << high << "사이에 있습니다." << endl;
		cout << name << ">>";
		cin >> number;

		if( number > result )
			high = number;
		else if( number < result )
			low = number;
		else { 
			cout << name << "이(가) 이겼습니다!!" << endl;
			break;
		}
	}
}

int main() {
	UpAndDownGame gg;
	gg.Game();
}

 

 

4. 설명

 

- Person 클래스는 사람의 이름을 저장하는 클래스 입니다. 

 

-> 생성자에서 이름을 초기화 합니다.

-> getName() 멤버 함수는 저장된 이름들을 호출할 때마다 번갈아가면서 return 합니다.

 

 

- UpAndDownGame 클래스는 게임을 전체적으로 관리하는 클래스입니다.

 

-> static 변수 low, high, result를 선언합니다.

-> static 변수를 이용하기 위하여 game() 멤버 함수도 static으로 선언합니다.

 

-> 입력받은 값이 정답보다 크다면 high값을 수정하고 작다면 low 값을 수정하고 같다면 종료합니다.

 

※ 주의하실 점은 랜덤 한 수( result)는 while문 밖에서 한 번만 구해 저장하여야 합니다. 또한 이름은 while안에서 string 변수 하나의 저장을 해놔야지 나중에 종료 시 누가 이겼는지를 이름을 이용할 수 있습니다.

 

 

 

 

1. 문제

 

8. 디버깅에 필요한 정보를 저장하는 Trace 클래스를 만들어보자. 저자의 경험에 의하면, 멀티태스크 프로그램을 개발하거나 특별한 환경에서 작업할 때, Visual Studio의 디버거와 같은 소스 레벨 디버거를 사용하지 못하는 경우가 더러 있었고, 이때 실행 도중 정보를 저장하기 위해 Trace 클래스를 만들어 사용하였다. Trace 클래스를 활용하는 다음 프로그램과 결과를 참고하여 Trace 클래스를 작성하고 전체 프로그램을 완성하라. 디버깅 정보는 100개로 제한한다.

 

 

 

2. 결과

 

 

 

3. 코드

 

#include <iostream>
#include <string>
using namespace std;

class Trace {
	static string *tag;
	static string *info;
	static int num;
public :
	static void put(string ptag, string pinfo) {
		tag[num] = ptag;
		info[num] = pinfo;
		num++;
	}
	static void print(string ptag="모든") {
		if( ptag == "모든" )
			cout << "----- " << ptag << " Trace 정보를 출력합니다. -----" << endl;
		else
			cout << "----- " << ptag << "태그의 Trace 정보를 출력합니다. -----" << endl;

		for(int i=0; i< num;i++) {
			if( ptag == "모든" )  cout << tag[i] <<":" << info[i] << endl;
			else if( tag[i] == ptag )  cout << tag[i] <<":" << info[i] << endl;
		}
	}
};
int Trace::num = 0;
string *Trace::tag = new string[100];
string *Trace::info = new string[100];

void f() {
	int a, b, c;
	cout << "두 개의 정수를 입력하세요>>";
	cin >> a >> b;
	Trace::put("f()", "정수를 입력 받았음");
	c = a + b;
	Trace::put("f()", "합 계산");
	cout << "합은 " << c << endl;
}

int main() {
	Trace::put("main()", "프로그램 시작합니다");
	f();
	Trace::put("main()", "종료");

	Trace::print("f()");
	Trace::print();
}

 

 

4. 설명

 

 static으로 string*형 변수 tag, info와 int형 num을 선언합니다.

 

- static 변수를 초기화하기 위해서는 클래스 밖에서 "::"를 사용하여서 초기화하여야 합니다. 이러한 이유는 static 변수는 언제든 사용할 수 있어야 하지만 클래스 생성자 안에서 초기화를 한다면 클래스의 객체가 생성되기 전까지는 초기화가 실행되지 않기 때문입니다.

 

-> 디버깅 정보는 100개로 제한하므로 크기가 100인 배열로 초기화 합니다.

-> 마찬가지로 static 변수를 사용하기 위해서는 static 메소드 이어야 합니다.

 

 

 

- print()함수는 매개변수 태그를 하나 입력받아 그의 해당하는 태그를 출력합니다. 여기서 매개변수의 "모든"이라는 디폴트 값을 주어서 매개변수 없을 경우 모든 태그와 정보를 출력하도록 하였습니다.

 

 

 

1. 문제

 

7. 다음과 같은 static 멤버를 가진 Random 클래스를 완성하라(Open Challenge 힌트 참고). 그리고 Random 클래스를 이용하여 다음과 같이 랜덤한 값을 출력하는 main() 함수도 작성하라. main()에서 Random 클래스의 seed() 함수를 활용하라.

 

 

 

2. 결과

 

 

 

3. 코드

 

#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;

class Random {
public :
	static void seed() { srand( (unsigned)time(0) ); }
	static int nextInt(int min=0, int max=32767 ) { 
		int n = min + (rand() % (max-min+1) ); 
		return n; 
	}
	static char nextAlphabet();
	static double nextDouble();
};
char Random::nextAlphabet() {
	int n = rand() % 2;
	if( n == 0) {
		n = 65 + rand() % 26;
		return n;
	}
	else {
		n = 97 + rand() % 26;
		return n;
	}
}
double Random::nextDouble() {
	double n = rand() / (double)(RAND_MAX+1);

	return n;
}

int main() {
	Random::seed();
	int i;

	cout << "1에서 100까지 랜덤한 정수 10개를 출력합니다" << endl;
	for(i=0; i<10; i++) cout << Random::nextInt(1, 100) << ' ';

	cout << endl << "알파벳을 랜덤하게 10개를 출력합니다" << endl;
	for(i=0; i<10; i++) cout << Random::nextAlphabet() << ' ';

	cout << endl << "랜덤한 실수를 10개를 출력합니다" << endl;
	for(i=0; i<5; i++) cout << Random::nextDouble() << ' ';
	cout << endl;
	for(i=0; i<5; i++) cout << Random::nextDouble() << ' ';
	cout << endl;

}

 

 

4. 설명

 

- nextInt()함수는 랜덤한 정수를 구하는 함수 입니다.

 

 이전 글들에서도 설명한적이 있듯이 범위가 min ~ max의 랜덤한 수를 구하기 위해서는

 

int n = min + ( rand() % (max-min+1) );

을 해주셔야 합니다.

=> 이러한 이유는 간단하게 말하자면 rand() % 100 은 rand()가 어떤 랜덤한 수가 와도 나머지이므로 결과는 0~99 사이의 값 입니다. 이 사실을 이해하셨다면 스스로 범위를 잘 조절할 수 있으실 겁니다.

 

 

- nextAlphabet() 함수는 랜덤한 알파벳을 리턴하는 함수입니다.

 

 랜덤한 알파벳인데 소문자인지 대문자인지도 랜덤하게 결정되므로 우선 

 
int n = rand() % 2;

 

를 하여서 0과 1중 랜덤하게 변수 n의 저장합니다.

 

=> 그 다음 0일 경우는 65~90 무작위 대문자를 return 합니다. 또한 1일 경우 97~122 무작위 소문자를 return 합니다.

 

이러한 방법으로 랜덤하게 알파벳을 구할 수 있습니다.

 

 

- nextDouble() 함수는 범위가 0 이상 1미만인 랜덤한 실수를 return하는 함수입니다.

 

double n = rand() / (double)(RAND_MAX+1);

을 하면 0이상 1미만의 무작위 실수를 구할 수 있습니다.

 

=> RAND_MAX는 헤더파일 cstdlib의 정의 되어 있으므로 랜덤 값 중 최대 값 32767을 저장하고 있습니다. 그래서 +1을 해주어서 1미만의 값이 나오도록 합니다.

 

 

1. 문제

 

6. 동일한 크기의 배열을 변환하는 다음 2개의 static 멤버 함수를 가진 ArrayUtility2 클래스를 만들고, 이 클래스를 이용하여 아래 결과와 같이 출력되도록 프로그램을 완성하라.

 

 

2. 결과

 

 

 

3. 코드

 

#include <iostream>
using namespace std;

class ArrayUtility2 {
public :
	static int* concat(int s1[], int s2[], int size){
		int* p = new int[size];
		int n = size/2;
		for(int i=0; i< n; i++) {
			p[i] = s1[i];
			p[i+n] = s2[i];
		}
		return p;
	}
	static int* remove(int s1[], int s2[], int size, int& retSize) {
	
		for(int i=0; i< size; i++) {
			for(int j=0; j< size; j++) {
			 if(s1[i] == s2[j] ) s1[i] =NULL;
			} 
		}
		for(int i=0; i< size ; i++) 
			if(s1[i] !=NULL) retSize++;
		
		int *p = new int [retSize];
		int n=0;
		for(int i=0; i< size; i++)
			if(s1[i] !=NULL ) { p[n] = s1[i]; n++; }

		if(retSize == 0) return NULL;
		else return p;
	}
};

int main() {
	int x[5], y[5], retsize=0, size;

	cout << "정수를 5 개 입력하라. 배열 x에 삽입한다>>";
	cin >> x[0] >> x[1] >> x[2] >> x[3] >> x[4];
	cout << "정수를 5 개 입력하라. 배열 y에 삽입한다>>";
	cin >> y[0] >> y[1] >> y[2] >> y[3] >> y[4];
	cout << "합친 정수 배열을 출력한다." << endl;

	size = sizeof(x)/4 + sizeof(y)/4;
	int *temp = ArrayUtility2::concat( x, y, size );
	for(int i=0; i< size;i++) cout << temp[i] << ' ';
	cout << endl;

	size = sizeof(x)/4;
	temp = ArrayUtility2::remove( x, y, size, retsize );
	cout << "배열 x[]에서 y[]를 뺀 결과를 출력한다. 개수는 " << retsize << endl;
	for(int i=0; i< retsize;i++) cout << temp[i] << ' ';
	cout << endl;
}

 

 

 

4. 설명

 

static int* concat() 함수는 2개의 int형 배열과 size를 입력 받으면, 크기가 size만큼인 int형 배열을 동적으로 생성한 후 2개의 배열을 연결한 배열 하나를 return 합니다.

 

static int* remove() 함수는 2개의 배열과 size 그리고 참조 변수 retSize를 입력 받습니다. 

 

그 후 첫 번째 배열과 두 번째 배열을 비교하여서 첫 번째 배열의 요소 중 두 번째 배열의 요소와 일치하지 않는 것의 수를 구한 후 retSize에 저장합니다. 그리고 이 과정에서 첫 번째 배열에서 일치하는 요소는 NULL값을 삽입합니다.

 

그 후 retSize 크기만큼의 int형 배열을 동적으로 생성한 후 첫 번째 배열의는 첫 번째 배열과 두 번째 배열 중 일치하지 않는 값 빼고는 다 NULL을 삽입하였으므로 NULL이 아니라면 동적 생성했던 배열의 요소로 삽입합니다.

 

 

그리고 이 동적 생성하였던 배열을 return함으로써 일치하지 않는 요소들만 저장되어있는 배열을 생성합니다.

 

 

 

1. 문제

 

5. 동일한 크기로 배열을 변환하는 다음 2개의 static 멤버 함수를 가진 ArrayUtility 클래스를 만들어라.

 

 

2. 결과

 

 

 

3. 코드

 

#include <iostream>
using namespace std;

class ArrayUtility {
public :
	static void IntToDouble(int source[], double dest[], int size) {
		for(int i=0; i< size; i++)
			dest[i] = (double)source[i];
	}
	static void doubleToInt(double source[], int dest[], int size) {
		for(int i=0; i< size; i++)
			dest[i] = (int)source[i];
	}
};

int main() {
	int x[] = {1,2,3,4,5};
	double y[5];
	double z[] = {9.9, 8.8, 7.7, 6.6, 5.6};

	ArrayUtility::IntToDouble(x, y, 5);
	for(int i=0; i<5; i++) cout << y[i] << ' ';
	cout << endl;

	ArrayUtility::doubleToInt(z, x, 5);
	for(int i=0; i<5; i++) cout << x[i] << ' ';
	cout << endl;
}

 

 

4. 설명

 

크기가 size인 int형 배열의 요소들을 double형으로 형변환 한 후 double 배열의 저장하는 IntToDouble()을 강제 형변환을 이용하여서 구현 합니다.

 

double형을 int형으로 바꾸는 doubleToInt() 함수도 마찬가지로 강제형변환을 이용하여서 int형으로 변환하도록 구현 합니다.

 

 

※ double형을 int형으로 강제 형변환하면서 데이터 손실이 발생하였습니다.

 

 

1. 문제

 

4. 다음 클래스에 중복된 생성자를 디폴트 매개 변수를 가진 하나의 생성자로 작성하고 테스트 프로그램을 작성하라.

 

 

2. 결과

 

 

 

 

3. 코드

 

#include <iostream>
using namespace std;

class MyVector {
	int *mem;
	int size;
public :
	MyVector(int n=100, int val=0);
	~MyVector() { delete [] mem; }
	void show() { for(int i=0; i<size;i++) cout << mem[i] << ' '; cout << endl; }
};

MyVector::MyVector(int n, int val) {
	mem = new int [n];
	size =  n;
	for(int i=0; i<size; i++) mem[i] = val;
}

int main() {

	MyVector a, b(4,5);
	
	a.show();
	b.show();
}

 

 

4. 설명

 

주어진 코드의 생성자를 살펴보면 디폴트 매개 값을 가진 MyVector(int n=100, int val=0); 생성자를 생성할 수 있습니다.

 

이 생성자는 크기가 n인 int형 배열을 동적으로 생성한 후 val 값으로 각 원소들을 초기화 하는 기능을 합니다.

 

구현이 잘 되었는지 확인하기 위하여 void show()함수를 생성하여서 결과를 확인 합니다.

 

또한 소멸자에서는 동적으로 생성하였던 int형 배열을 해제 시켜 줍니다.

 

+ Recent posts