(C++) 스마트팩토리 - 15일

내 이름 안찬찬·2023년 2월 6일
0
post-thumbnail

동적 배열과 포인터

동적 배열

  • 지금까지의 배열은 선언할 때 고정된 크기를 지정해야 했다.
  • 배열의 크기를 나중에 정하고 싶을 때 사용되는 것이 동적 배열이다.
  • 단, 동적 배열을 익히기 위해선 포인터의 개념을 먼저 알아야 한다.

포인터 문법

	// ------------- 포인터의 개념 ------------
	// 자료형 뒤에 *을 쓰고
	int* p; //포인터 p라는 변수 생성, n의 메모리 주소를 담을 수 있는 변수 == 포인터 p
	int n = 5;
	int i = 30;
	p = &n; // n의 주소를 p에 선언하겠다.

	std::cout << p << "\n"; //  n이 할당된 주소
	std::cout << &n << "\n";//  n이 가지고 있는 주소
	std::cout << n << "\n"; //  값 5
	std::cout << *p << "\n";//  포인터 p가 바라보고 있던 주소의 값 5
	std::cout << *&n << "\n";// 값 5

	n = 20;
	std::cout << p << "\n"; //  메모리 주소값을 다시 할당하진 않는다.
	std::cout << *p << "\n";//  값 20

	*p = 10;
	std::cout << n << "\n"; //  값 10, 포인터p를 이용하여 n의 값을 바꿀 수 있다.
	std::cout << *p << "\n";//  값 10

	p = &i; //i의 주소값을 바라보게 변경
	std::cout << n << "\n"; //  값 10
	std::cout << *p << "\n";//  값 30

동적 배열 - 선언과 할당

  • 동적 배열을 만들기 위해선 포인터 변수와 new 키워드 사용
	//--------배열에 사용자가 숫자를 입력하고 싶은 경우 = 동적 배열---------
	//int num;
	//std::cin >> num;
	//int num_array[num]; -> 이걸 하고 싶다면!

	int num;
	std::cin >> num;
	int* num_array = new int[num];
	// 동적 메모리를 가리키는 포인터 선언 후
	// new라는 키워드를 사용하여, 동적 배열 할당

	int arr[5] = { 1, 2, 3, 4, 5 };
	std::cout << arr << "\n"; // 주소값
	std::cout << arr[0] << "\n"; // 1

	for (int i = 0; i < num; i++) {
		//*(arr + i) = 1;
		num_array[i] = 1;
	} // 배열의 원소를 전부 1로 초기화

	for (int i = 0; i < num; i++) {
		//std::cout << arr[i] << " ";
		std::cout << num_array[i] << " ";
	}
  • 동적 배열 - 사용과 해제(반납)
int* arr = new int[n2]; // 동적 배열 선언 및 할당

for (int i = 0; i < n2; i++) {
arr[i] = i+1; // 동적 배열 사용
}

delete[] arr; // 동적 배열 해제(반납). 동적 메모리는 사용 후 꼭 해제하기
  • 2차원 동적 배열
int main() {
	//---------2차원 동적 배열---------
	// num을 받아서 num X num 배열
	int num;
	std::cin >> num;
	int** num_arr = new int* [num];//동적 배열 선언 & 할당
	for (int i = 0; i < num; i++) { //배열의 크기 잡기
		num_arr[i] = new int[num];
	}

	for (int i = 0; i < num; i++) { //배열의 값 설정
		for (int j = 0; j < num; j++) {
			num_arr[i][j] = num + i; //동적 배열 사용
			std::cout << num_arr[i][j] << " ";
		}
		std::cout << "\n";
	}

	//-------2차원 배열 반납-----------
	for (int i = 0; i < num; i++) {
		delete[] num_arr[i];
	}
	delete[] num_arr;
}


실습

실습 1

(1) 사용자로부터 x, y 2개의 자연수를 입력 받기
(2) 만약 사용자가 x 와 y 에 0 이나 음수를 입력한다면 에러 메세지를 출력 후 다시
입력 받기.
(3) x y 의 크기를 갖는 이차원 동적 배열 arr 을 선언
(4) arr[0][0] 부터 arr[x][y] 까지 순서대로 1 부터 x
y 저장
(5) arr[0][0] 부터 arr[x][y] 까지 저장된 값 출력

#include <iostream>

int main(){
	int x,y;
	int num = 0;

	while (1) {
		std::cout << "x를 입력하세요: ";
		std::cin >> x;
		std::cout << "y를 입력하세요: ";
		std::cin >> y;
		if (x < 0 || y < 0) {
			std::cout << "x와 y모두 양수를 입력해주세요." << "\n";
		}
		else {
			break;
		}
	}

	int** arr2 = new int* [y];
	for (int i = 0; i < y; i++) {
		arr2[i] = new int[x];
	}

	for (int i = 0; i < y; i++) {
		for (int j = 0; j < x; j++) {
			arr2[i][j] = ++num;
			std::cout << arr2[i][j] << " ";
		}
		std::cout << "\n";
	}

	for (int i = 0; i < x; i++) {
		delete[] arr2[i];
	}
	delete[] arr2;
 }

실습 2

(1) 몇명의 학생 성적 평균을 구할 지 입력 받기
(2) 입력받은 학생 수 만큼 성적을 입력받기
(3) 학생들의 성적 평균 산출하기

  • input
    학생의 수를 입력하세요 : 3
    1번째 학생의 성적을 입력하세요 : 10
    2번째 학생의 성적을 입력하세요 : 20
    3번째 학생의 성적을 입력하세요 : 30

  • output
    평균 : ? ? ? ?

int main() {
	int stu;
	double sum = 0;

	std::cout << "학생의 수를 입력하세요: ";
	std::cin >> stu;

	int* students = new int[stu];
	for (int i = 0; i < stu; i++) {
		std::cout << i+1 << "의 성적: ";
		std::cin >> students[i];
		sum = students[i] + sum;
	}

	std::cout << "\n";
}


vector

#include <iostream>
#include <vector> // 벡터사용시 라이브러리 불러와야함

int main() {
	//std::vector<int> v; //원소의 값(자료형)이 뭐가 될지 적어줘야 함 ex/ std::string등
	//std::vector<int> v(3);//크기가 3인 벡터 배열 생성, 콤마 뒤에 숫자가 없으면 원소를 모두 0으로 초기화
	//std::vector<int> v(3,1); //크기가 3인 벡터 배열 선언, 원소를 모두 1로 초기화
	//std::vector<int> v = { 1,2,3 };//크기가 3인 벡터 배열 선언 및 초기화
	
	std::vector<int> v = { 1, 2, 3, 4, 5 };
	for (int i = 0; i < v.size(); i++) { //.size() = 메서드(변수)의 크기를 알 수 있음
		std::cout << v.at(i) << " ";
		//std::cout << v[i] << " ";
	}

	std::cout << "\n";
	//---------동적 배열------------

	int num;
	std::cin >> num;
	std::vector<int> e;
	e.assign(num, 1); //e가 할당이 된다 num의 크기만큼, 원소는 모두 1로 초기화 

	for (int i = 0; i < e.size(); i++) { 
		std::cout << e.at(i) << " ";
	}

	
	std::cout << "\n";

	std::vector<int> c = { 1,2,3,4,5 };
	// .resize() 크기 지정, 0으로 초기화
	c.resize(6, 6);

	c.push_back(7); //배열의 마지막에 원하는 원소를 추가한다. {1,2,3,4,5,7}

	for (int i = 0; i < c.size(); i++) { 
		std::cout << c.at(i) << " ";
	}



	std::cout << "\n";

	std::vector<int> t = { 1,2,3,4,5 };
	// .resize() 크기 지정, 0으로 초기화
	t.resize(6, 6); // {1,2,3,4,5,6}

	t.push_back(7); //배열의 마지막에 원하는 원소를 추가한다. {1,2,3,4,5,6,7}
	t.pop_back(); //배열의 마지막 원소를 뺀다. {1,2,3,4,5,6}
	for (int i = 0; i < t.size(); i++) {
		std::cout << t.at(i) << " ";
	}

	std::cout << "\n";

	std::cout << t.front() << " "; //가장 앞에있는 원소 출력 {1}
	std::cout << t.back() << " "; //가장 마지막에있는 원소 출력 {6}
	
	std::cout << "\n";

	
	std::vector<int> o = { 1,2,3,4,5 };
	//인덱스 지정 전 .begin (=주소 출력)
	o.insert(o.begin() + 2, 99);//원하는 위치에 원하는 값을 넣을 수 있다. 2번 인덱스에 99 추가
	for (int i = 0; i < o.size(); i++) {
		std::cout << o.at(i) << " ";
	}


	std::cout << "\n";

	std::vector<int> r = { 1,2,3,4,5,6,7 };
	//r.erase(r.begin() + 3); //3번 인덱스 삭제
	r.erase(r.begin() + 2, r.begin()+5); // 2 ~ 4 인덱스 삭제
	for (int i = 0; i < r.size(); i++) {
		std::cout << r.at(i) << " ";
	}


	std::cout << "\n";

	
	std::vector<int> q = { 1,2,3,4,5 };
	q.clear(); // 배열의 모든 원소 삭제. size 0
	for (int i = 0; i < q.size(); i++) {
		std::cout << q.at(i) << " ";
	}

	

	std::cout << "\n";
	for (int rr : r) { //&를 안쓰면 아예 다른 메모리를 가진 변수가 새로 생성되는 것 뿐이다.
		rr = rr + 1; 
	}
	for (int rr : r) {
		std::cout << rr << " ";
	}



	std::cout << "\n";
	for (int &rr : r) {
		rr = rr + 1; // 모든 원자에 +1
	}
	for (int rr : r) {
		std::cout << rr << " ";
	}


	std::cout << "\n";
	// ------------------2차원 벡터 --------------

	std::vector<std::vector<int>> v2; //크기가 지정되어 있지 않음
	v2.assign(3, std::vector<int>(2)); //행의 크기3, 열의크기2 . 0으로 초기화

	for (int i = 0; i < v2.size(); i++) { //v2.size() == 행의 크기 == 3
		for (int j = 0; j < v2.at(i).size(); j++) { //v2.at(i) == v2[i] == 첫 번째 배열의 크기 == 2
			std::cout << v2.at(i).at(j) << " ";
			//std::cout << v2[i][j] << " ";
		}
		std::cout << std::endl;
	}


	std::cout << "\n";

	for (std::vector<int> vv2 : v2) {
		for (int vvv2 : vv2) {
			std::cout << vvv2 << " ";
		}
		std::cout << std::endl;
	}
}

실습

실습 3

  • vector를 이용해 이전 실습 해결하기
    int x, y;

    // x와 y를 입력받는 부분
    while (true) {
        cout << "x를 입력하세요: ";
        cin >> x;
        cout << "y를 입력하세요: ";
        cin >> y;

        // x와 y가 양수인지 확인하는 부분
        if (x > 0 && y > 0) {
            break;
        }
        else {
            cout << "x와 y모두 양수를 입력해주세요" << endl;
        }
    }

    // 2차원 벡터 arr을 x * y 크기로 선언
    vector<vector<int>> arr(x, vector<int>(y, 0));

    // arr[0][0]부터 arr[x-1][y-1]까지 순서대로 1부터 x * y까지 값을 저장
    int cnt = 1;
    for (int i = 0; i < x; i++) {
        for (int j = 0; j < y; j++) {
            arr[i][j] = cnt++;
        }
    }

    // arr[0][0]부터 arr[x-1][y-1]까지 출력
    for (int i = 0; i < x; i++) {
        for (int j = 0; j < y; j++) {
            cout << arr[i][j] << " ";
        }
        cout << endl;
    }

실습 4

(1) 사용자가 입력한 숫자들을 배열에 담고, 그 수의 합 구하기.

	std::cout << "벡터 실습2: 사용자 입력 숫자의 합\n";
	int x = 0;
	int y = 1;
	int sum = 0;
	std::vector<int> v;
	
	while (1) {
		std::cout << "숫자를 입력하세요(0입력시 종료): ";
		std::cin >> y;
		sum = sum + y;
		v.insert(v.begin() + x, sum);
		if (y == 0) {
			break;
		}
	}
	std::cout << v.at(x);


마무리!

그 무섭던 포인터에 대해 배웠다..
사실 그리 깊게 배우지 않은 것 같다는 느낌이 들긴 했다.
활용하는 면에서 보면 굉장히 어렵고 이해하기 쉽지 않은 것은 맞지만
오늘 느낀바로는 벡터가 정말 미친줄 알았다!
특히 2차원 배열 벡터는 아직도 이해가 전혀 되질 않는다 ㅠ
공부를 좀 더 해야할 것 같다.. 뒤쳐지는 느낌이 들어 힘들지만
내가 더 열심히 해서 뒤쳐지지 않아야지 뭐!

내일도 파이팅 해보자!!

profile
스마트팩토리 개발자가 되기 위한 □□ !!

0개의 댓글