본문 바로가기
Language/C++

[C++_제 7장] 1차원 배열과 C-문자열

by 전전긍긍 2021. 12. 6.

본 포스팅은 C++로 시작하는 객체지향 프로그래밍 책을 바탕으로 작성하였습니다.

 

C++로 시작하는 객체지향 프로그래밍

『C++로 시작하는 객체지향 프로그래밍』은 구문보다는 문제 해결에 중점을 두는 문제 구동 방식을 사용한 프로그래밍에 대해 가르치고 있다. 여러 가지 상황에서 문제를 야기한 개념을 사용함

book.naver.com


key point

 

  • 배열(array) : 많은 데이터의 모음을 저장할 수 있다.

7.2 배열의 기초

  • 배열은 같은 유형의 많은 값들을 저장할 때 사용된다. 배열의 요소는 인덱스를 사용하여 접근이 가능하다.

7.2.1 배열 선언

  • 배열의 크기는 상수여야 한다.
//잘못된 것
int size = 4;
double myList[size]

//옳은 것
const int size = 4;
double myList[size]

7.2.2 배열 요소 접근

  • 베열 인덱스는 0부터 시작
  • 배열을 선언할 때 요소의 수를 나타내기 위해서 크기 선언자(size declarator)가 사용된다.
  • 배열 인덱스 -> 배열에서 특정 요소에 접근
  • 범위 초과 오류 주의 (배열의 크기를 넘어서는 인덱스 사용)

7.2.3 배열 초기화

  • 하나의 문장으로 배열을 선언하고 초기화할 수 있다.

- 배열 선언과 초기화는 동시에 해야 한다. 분리는 잘못된 것으로 구문 오류 발생

- 동시에 할 때는 배열의 크기를 생략해도 된다.

double myList[] = {1.9, 2.9, 3.4, 3.5)
//배열의 크기를 생략하면 컴파일러가 자동으로 배열 요소의 수를 지정한다.

- 배열의 일부분만 초기화하는 것도 가능하다.

 

7.2.4 배열 처리

- 배열의 모든 요소는 같은 유형이다. 각 요소에 대해 반복문을 사용하여 동일한 방법으로 처리가 가능하다.

- 배열의 크기를 이미 알고 있으므로 for문을 사용하기에 적당하다.

//다음과 같은 배열을 선언했다고 가정
const int ARRAY_SIZE = 10;
double myList[ARRAY_SIZE];

1. 입력 값으로 배열 초기화

cout << "Enter " << ARRAY_SIZE << " values: ";
	for (int i = 0; i < ARRAY_SIZE; i++)
		cin >> myList[i];

2. 임의의 값으로 배열 초기화

for (int i = 0; i < ARRAY_SIZE; i++)
{
	myList[i] = rand() % 100;
}

3. 배열 출력

for(int i = 0; i < ARRAY_SIZE; i ++)
{
	cout << myList[] << " " << endl;
 }

4. 배열 복사

//myList라는 배열을 list로 옮길려면?

//잘못된 방법
list = myList;

//옳은 방법
for (int i = 0; i < ARRAY_SIZE; i++)
{
	list[i] = myList[i];
}

5. 모든 요소의 합

double total = 0;
for (int i = 0; i < ARRAY_SIZE; i++)
{
	total += myList[i];
}

6. 배열의 최댓값 구하기

double max = myList[0];
for (int i = 0; i < ARRAY_SIZE; i++)
{
	if (mtList[i] > max)
    	max = myList[i];
}

7. 최댓값 요소의 가장 작은 인덱스 구하기

double max = mtList[0]'
int indexOfMax = 0;

for (int i = 0; i < ARRAY_SIZE; i++)
{
	if ( max < myList[i] )
    {
    	max = myList[i];
        indexOfMax = i;
    }
}

8. 요소 임의로 섞기 (무작위로 재배치시켜야 하는 경우 shuffling)

srand(time(0));

for (int i = ARRAY_SIZE; i > 0; i--)
{
	//0 <= j <= i에 대해 무작위로 인덱스 j 생성
	int j = rand() % (i + 1);
    
    //myList[i]와 myList[j] 교환
    double temp = myList[i];
    myList[i] = myList[j];
    myList[j] = temp;
}

9. 요소 시프트 이동

double temp = myList[0];

//오 -> 왼
for (int i = 1; i < ARRAY_SIZE; i++)
{
	myList[i-1] = myList[i];
}
myList[ARRAY_SIZE - 1] = temp;

10. 코드 간략화

string months[] = {"January", "February", ... , "December"};
cout << "Enter a month number(1 to 10) : ";
int monthNumber;
cin >> monthNumber;
cout << "The month is " << months[monthNumber - 1] << endl;

 

7.5 함수로 배열 전달

  • 배열 인수가 함수로 전달될 때 배열의 시작 주소가 함수의 배열 매개변수로 전달된다. 배개변수와 인수 모두 같은 배열을 참조하게 된다. (공유에 의한 전달)
#include <iostream>
using namespace std;

void m(int, int[]);

int main()
{
	int x = 1;
	int y[10];
	y[0] = 1;

	m(x, y);

	cout << "x is " << x << endl;
	cout << "y is " << y[0] << endl;

	return 0;
}

void m(int number, int numbers[])
{
	number = 1001; //number값에 새 값 대임
	numbers[0] = 5555; //numbers[0]에 새 값 대입
}

//x is 1 
//x와 number은 서로 다른 변수라서 1이 출력
//y is 5555
//y와 numbers는 같은 배열을 참조하고 있기 때문에 y[0] = 5555 (별칭으로 작용)

 

7.6 함수에서의 배열 인수 보호

함수의 배열 매개변수 값이 변경되지 않도록 하기 위해 함수에서 const 배열 매개변수를 정의할 수 있다.

#include <iostream>
using namespace std;

void p(const int list[], int arraySize)
{
	//실수로 배열 값을 수정
    list[0] = 100; //컴파일 오류
}

int main()
{
	int number[5] = {1, 4, 3, 6, 8};
    p(number, 5);
    
    return 0;
}

 

7.7 함수로부터 배열 반환

함수에서 배열을 반환하기 위해서는 함수의 매개변수로 전달한다.

#include <iostream>
using namespace std;

void reverse(const int list[], int newList[], int size);

void printArray(const int list[], int size);

int main()
{
    const int SIZE = 6;
    int list[] = { 1, 2, 3, 4, 5, 6 };
    int newList[SIZE];

    reverse(list, newList, SIZE);

    cout << "The original array: ";
    printArray(list, SIZE);
    cout << endl;

    cout << "The reversed array: ";
    printArray(newList, SIZE);
    cout << endl;

    return 0;
}

void reverse(const int list[], int newList[], int size)
{
    for (int i = 0, j = size - 1; i < size; i++, j--)
    {
        newList[j] = list[i];
    }
}

void printArray(const int list[], int size)
{
    for (int i = 0; i < size; i++)
        cout << list[i] << " ";
}

//The original array: 1 2 3 4 5 6
//The reversed array: 6 5 4 3 2 1

 

7.9 배열 탐색

* 배열이 정렬되어 있다면 배열 요소를 찾는 경우 선형 탐색보다 이진 탐색이 더 효율적이다.

* 탐색(searching) : 배열에서 특정 요소를 찾는 작업

 

  • 선형 탐색

주요 요소를 키(key)로 하고, 이 키와 배열 내의 모든 요소를 연속적으로 비교하여 검색하는 방법

*장점 : 배열 크기가 작은 경우나 정렬이 되지 않는 경우 유용

*단점 : 큰 배열에서는 비효율

int linearSeach(const int list[], int key, int arraySize)
{
	for (int i = 0l i < arraySize; i++)
    {
    	if (key == list[i])
        	return i;
    }
    return -1;
}

 

  • 이진탐색

미리 오름차순으로 정렬된 배열을 가정.

배열 중앙 요소와 키(key)를 비교하는 것으로 시작하여 다음 세 경우에 따라 데이터 목록을 검색해 나간다.

- 키가 중앙값보다 작다면, 배열의 앞쪽 절반에서 탐색을 계속한다.

- 키가 중앙값과 같다면 원하는 키 값을 찾은 것이며, 탐색을 끝낸다.

- 키가 중앙값보다 크면, 배열의 뒤쪽 절반에서 탐색을 계속한다.

#include <iostream>
using namespace std;

int binarySearch(const int[], int, int);

int main()
{
    int list[] = { 2, 4, 7, 10, 11, 16, 21, 27, 33, 39, 45, 48, 50, 59, 60, 66, 69, 70, 79, 84 };
    int i = binarySearch(list, 20, 16);  
    int j = binarySearch(list, 20, 9); 
    int k = binarySearch(list, 20, 66); 
    cout << i << " " << j << " " << k << endl;
    return 0;
}

int binarySearch(const int list[], int listSize, int key)
{
    int low = 0;
    int high = listSize - 1;
    int count = 0;

    while (high >= low) 
    {
        count++;
        int mid = (low + high) / 2;
        if (key == list[mid])
        {
            cout << "count: " << count << endl;
            return mid;
        }
        else if (key < list[mid])
            high = mid - 1;
        else
            low = mid + 1;
    }
    cout << "count: " << count << endl;
    return -1;
}

//i = 4

 

7.10 배열 정렬

- 탐색과 마찬가지로 정렬도 컴퓨터 프로그래밍에서 자주 사용되는 기법으로, 많은 정렬 알고리즘이 개발되어 있다.

- 선택 정렬을 사용하여 오름차순으로 목록 정리 : 선택 정렬은 반복적으로 가장 작은 수를 선택하여 남아 있는 목록의 첫 번째 수와 교환한다.

#include <iostream>
using namespace std;

void selectionSort(double list[], int listSize)
{
	for (int i = 0; i < listSize - 1; i++)
	{
		double currentMin = list[i];
		int currentMInIndex = i;

		for (int j = i+1; j < listSize; j++)
		{
        	//내림차순 할꺼면 부등호방향 반대
			if (currentMin > list[j])
			{
				currentMin = list[j];
				currentMInIndex = j;
			}
		}

		//필요하다면 list[i]와 list[currentMinIndex] 교화
		if (currentMInIndex != i)
		{
			list[currentMInIndex] = list[i];
			list[i] = currentMin;
		}
	}

	for (int i = 0; i < listSize; i++)
	{
		cout << list[i] << "  ";
	}
}

int main()
{
	double list[] = { 1, 9, 4.5, 6.6, 5.7, -4.5 };
	selectionSort(list, 6);

	return 0;
}

//-4.5  1  4.5  5.7  6.6  9

 


list

더보기

list 7.1 평균 구하기, 평균보다 큰 값의 개수 구하기

#include <iostream>
using namespace std;

int main()
{
	const int NUMBERS_OF_ELEMENTS = 10;
	double numbers[NUMBERS_OF_ELEMENTS];
	double sum = 0;

	for (int i = 0; i < NUMBERS_OF_ELEMENTS; i++)
	{
		cout << "Enter a new number : ";
		cin >> numbers[i];
		sum += numbers[i];
	}

	double average = sum / NUMBERS_OF_ELEMENTS;

	int count = 0;
	for (int i = 0; i < NUMBERS_OF_ELEMENTS; i++)
	{
		if (numbers[i] > average)
			count++;
	}

	cout << "Average is " << average << endl;
	cout << "Number od elements above the average " << count << endl;

	return 0;
}

/*
Enter a new number : 1
Enter a new number : 2
Enter a new number : 3
Enter a new number : 4
Enter a new number : 5
Enter a new number : 6
Enter a new number : 7
Enter a new number : 8
Enter a new number : 9
Enter a new number : 10
Average is 5.5
Number od elements above the average 5
*/

 

list 7.2 복권번호

#include <iostream>
using namespace std;

int main()
{
	bool isCovered[9];
	int number;

	//1부터 9 false 초기화
	for (int i = 0; i < 9; i++)
	{
		isCovered[i] = false;
	}

	//숫자 입력 받은 것들 true 초기화
	cin >> number;
	while (number != 0)
	{
		isCovered[number - 1] = true;
		cin >> number;
	}

	//모든 숫자가 존재하는지 검사
	bool allCovered = true;
	for (int i = 0; i < 9; i++)
	{
		if (!isCovered[i])
		{
			allCovered = false;
			break;
		}
	}

	//결과출력
	if (allCovered)
		cout << "The tickets cover all numbers." << endl;
	else
		cout << "The tickets don't cover all numbers." << endl;

	return 0;
}
//2 5 6 5 4 3 2 4 2 0
//The tickets don't cover all numbers.

 

list 7.3 DeckOfCards

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

int main()
{
	const int NUMBER_OF_CARDS = 52; //배열 크기 선언
	int deck[NUMBER_OF_CARDS]; //배열 선언

	string suits[] = { "Spades", "Hearts", "Diamonds", "Clubs" };
	string ranks[] = { "Ace", "2", "3", "4","5","6","7","8","9","10","Jack","Queen","king" };

	//카드 초기화
	for (int i = 0; i < NUMBER_OF_CARDS; i++)
	{
		deck[i] = i;
	}

	//카드 섞기
	srand(time(0));
	for (int i = 0; i < NUMBER_OF_CARDS; i++)
	{
		int index = rand() % NUMBER_OF_CARDS;
		int temp = deck[i];
		deck[i] = deck[index];
		deck[index] = temp;
	}

	//앞서부터 4개의 카드 출력
	for (int i = 0; i < 4; i++)
	{
		string suit = suits[deck[i] / 13];
		string rank = ranks[deck[i] % 13];
		cout << "Card number " << deck[i] << " : " << rank << " of " << suit << endl;
	}
	return 0;
}

/*
Card number 6 : 7 of Spades
Card number 16 : 4 of Hearts
Card number 41 : 3 of Clubs
Card number 7 : 8 of Spades
*/

 

list 7.8 각 문자의 발생 빈도 계산

#include <iostream>
#include <ctime> //time함수 사용
using namespace std;

const int NUMBER_OF_LETTERS = 26;
const int NUMBER_OF_RANDOM_LETTERS = 100;
void createArray(char []);
void displayArray(const char[]);
void countLetters(const char[], int[]);
void displayCounts(const int[]);

int main()
{
	//배열 선언와 생성
	char chars[NUMBER_OF_RANDOM_LETTERS];

	//임의의 소문자 배열 초기화
	createArray(chars);

	//배열 출력
	cout << "The lowercase letters are: " << endl;
	displayArray(chars);

	//각 문자의 빈도수 계산
	int counts[NUMBER_OF_LETTERS];

	//각 문자의 빈도수 계산
	countLetters(chars, counts);

	//결과 출력
	cout << "\nThe occurrences od each letter are: " << endl;
	displayCounts(counts);

	return 0;
}

//문자 배열
//임의의 소문자로 배열 초기화
void createArray(char chars[])
{
	srand(time(0));
	for (int i = 0; i < NUMBER_OF_RANDOM_LETTERS; i++)
	{
		chars[i] = static_cast<char>('a' + rand() % ('z' - 'a' + 1));
	}
}

//문자 배열 출력
void displayArray(const char chars[])
{
	for (int i = 0; i < NUMBER_OF_RANDOM_LETTERS; i++)
	{
		if ((i + 1) % 20 == 0)
			cout << chars[i] << " " << endl;
		else
			cout << chars[i] << " ";
	}
}

//각 문자에 대한 빈도수 계산
void countLetters(const char chars[], int counts[])
{
	//배열 초기화
	for (int i = 0; i < NUMBER_OF_LETTERS; i++)
		counts[i] = 0;

	//배열의 각 소문자에 대한 빈도수 계산
	for (int i = 0; i < NUMBER_OF_RANDOM_LETTERS; i++)
	{
		counts[chars[i] - 'a']++;
	}
}

//결과출력
void displayCounts(const int counts[])
{
	for (int i = 0; i < NUMBER_OF_LETTERS; i++)
	{
		if ((i + 1) % 10 == 0)
			cout << counts[i] << " " << static_cast<char>(i + 'a') << endl;
		else
			cout << counts[i] << " " << static_cast<char>(i + 'a') << " ";
	}
}
/*
The lowercase letters are:
f d z i w s p p g u c b o u w z e b s g
u s m m n h r g e o p r u z e m a i c m
n e z m q j z m k g m y z l j n g g p v
u h h u k s t q c n s t p q l a q r y v
m t l v m p b b t q p g z d p c i u a d

The occurrences od each letter are:
3 a 4 b 4 c 3 d 4 e 1 f 7 g 3 h 3 i 2 j
2 k 3 l 9 m 4 n 2 o 8 p 5 q 3 r 5 s 4 t
7 u 3 v 2 w 0 x 2 y 7 z
*/

 

프로그래밍 실습

 

7.2 역순으로 출력

//역순으로 출력_함수사용
#include <iostream>
using namespace std;

void reverse(int list[], int size);

int main()
{
	const int SIZE = 10;
	int list[SIZE];

	cout << "10개의 숫자를 입력하시오 : ";
	for (int i = 0; i < SIZE; i++)
	{
		int num;
		cin >> num;
		list[i] = num;
	}

	cout << "The reverse array: ";
	reverse(list, SIZE);
	cout << endl;

	return 0;
}

void reverse(int list[], int size)
{
	for (int i = 0; i < size / 2; i++)
	{
		int temp = list[i];
		list[i] = list[size - 1 - i];
		list[size - 1 - i] = temp;
	}

	for (int i = 0; i < size; i++)
	{
		cout << list[i] << " ";
	}
}

/*
10개의 숫자를 입력하시오 : 1 2 3 4 5 6 7 8 9 10
The reverse array: 10 9 8 7 6 5 4 3 2 1
*/
#include <iostream>
using namespace std;

int main()
{
	const int SIZE = 10;
	int list[SIZE];

	for (int i = 0; i < SIZE; i++)
	{
		cout << "숫자를 입력해주세요: ";
		cin >> list[i];
	}

	for (int i = SIZE-1; i >= 0; i--)
	{
		cout << list[i] << " ";
	}

	return 0;
}
/*
숫자를 입력해주세요: 1
숫자를 입력해주세요: 2
숫자를 입력해주세요: 3
숫자를 입력해주세요: 4
숫자를 입력해주세요: 5
숫자를 입력해주세요: 6
숫자를 입력해주세요: 7
숫자를 입력해주세요: 8
숫자를 입력해주세요: 9
숫자를 입력해주세요: 10
10 9 8 7 6 5 4 3 2 1
*/

 

7.4 점수 분석

#include <iostream>
using namespace std;

int main()
{
	const int SIZE = 100;
	double score[SIZE];
	double sum = 0;
	int count = 0;

	do
	{
		cout << "Enter a new score : ";
		cin >> score[count];
		if (score[count] >= 0)
			sum += score[count];
	}
	while (score[count++] >= 0);

	double average = sum / (count - 1);

	int up = 0;
	int down = 0;

	for (int i = 0; i < count - 1; i++)
	{
		if (score[i] >= average)
			up++;
		else
			down++;
	}

	cout << "평균값은 " << average << endl;
	cout << "평균과 같거나 큰 점수의 수는 " << up << endl;
	cout << "평균보다 작은 점수의 수는 " << down << endl;
	
	return 0;
}
/*
Enter a new score : 40
Enter a new score : 50
Enter a new score : 60
Enter a new score : -10
평균값은 50
평균과 같거나 큰 점수의 수는 2
평균보다 작은 점수의 수는 1
*/

 

7.8 배열 평균

#include <iostream>
using namespace std;

int average(int array[], int size) //int배열은 int
{
	int total = 0;
	for (int i = 0; i < size; i++)
		total += array[i];

	return (total / size);
}
double average(double array[], int size) //double 배열은 double
{
	int total = 0;
	for (int i = 0; i < size; i++)
		total += array[i];

	return (total / size);
}

int main()
{
	const int SIZE = 10;
	double list[SIZE];
	cout << "10개의 점수를 입력해주세요: ";
	for (int i = 0; i < SIZE; i++)
	{
		cin >> list[i];
	}

	cout << "평균값은 " << average(list, SIZE) << endl;
	return 0;
}

//10개의 점수를 입력해주세요: 1 2 3 4 5 6 7 8 9 10
//평균값은 5

 

7.9 최솟값 찾기

#include <iostream>
using namespace std;

double min(double array[], int size)
{
	double mini = array[0];
	for (int i = 0; i < size; i++)
	{
		if (mini > array[i])
			mini = array[i];
	}

	return mini;
}

int main()
{
	const int SIZE = 10;
	double list[SIZE];
	cout << "Enter ten minutes: ";
	for (int i = 0; i < SIZE; i++)
	{
		cin >> list[i];
	}
	cout << "The minimum number is " << min(list, SIZE) << endl;
	return 0;
}

//Enter ten minutes: 1.9 25. 3.7 2 1.5 6 3 4 5 2
//The minimum number is 1.5

 

7.10 최소값 요소의 인덱스 찾기

#include <iostream>
using namespace std;

//함수 원형
int indexOfSmallestElement(double array[], int size);

//main 함수
int main() {

	//배열 크기 선언하기
	const int x = 10;
	double list[x];

	//배열 초기화
	for (int i = 0; i < x; i++)
	{
		cin >> list[i];
	}

	//출력하기
	cout << "최소값의 인덱스는  " << indexOfSmallestElement(list, x) << endl;

	return 0;
}

//최소값 요소의 인덱스 반환 함수
int indexOfSmallestElement(double array[], int size)
{
	double min = array[0];
	int index = 0;

	for (int i = 0; i < size; i++)
	{
		if (min > array[i])
		{
			min = array[i];
			index = i;
		}
	}
	return index;
}

//22 92 18 48 73 38 18 29 56 98
//최소값의 인덱스는  2

 

7.16 선택 정렬 수정

#include <iostream>
using namespace std;

void selectionSort(double list[], int size)
{
	for (int i = size - 1; i > 0; i--)
	{
		int maxIndex = i;
		double max = list[i];

		for (int j = 0; j < i; j++)
		{
			if (max < list[j])
			{
				max = list[j];
				maxIndex = j;
			}
		}

		if (maxIndex != i)
		{
			list[maxIndex] = list[i];
			list[i] = max;
		}
	}

	for (int i = 0; i < size; i++)
	{
		cout << list[i] << " / ";
	}
}

int main()
{
	const int SIZE = 10;
	double list[SIZE] = { 1, 9, 4.5, 6.6, 5.7 ,-4.5, 2, -1.1, 5.2, -3.7 };

	selectionSort(list, SIZE);
	return 0;
}

//-4.5 / -3.7 / -1.1 / 1 / 2 / 4.5 / 5.2 / 5.7 / 6.6 / 9 /

'Language > C++' 카테고리의 다른 글

[C++_제 17장] 재귀 호출  (0) 2021.12.09
[C++_제 8장] 다차원 배열  (0) 2021.12.09
[C++_제 6장] 함수  (0) 2021.11.23
[C++_백준] if문 ( 1330, 9498, 2753, 14681, 2884 )  (0) 2021.11.08
[C++_제 5장] 반복문  (0) 2021.10.09