배열 응용 문제들을 풀어보는 시간이다.
도전 5의 경우 정렬의 기본원리를 설명하고 이에 관한 문제다.
정렬은 다음 Part에서 중요한 내용이므로 꼭 이해하고 넘어가는 것이 좋다.
포인터에 대한 직접적인 문제는 없지만 포인터에 대한 개념적인 이해가 바탕이 되야된다.
길이가 10인 배열을 선언하고 총 10기의 정수를 입력 받아서, 홀수와 짝수를 구분 지어 출력하는 프로그램을 작성해 보자.
일단 홀수부터 출력하고 나서 짝수를 출력하도록 하자.
단, 10개의 정수는 main 함수 내에서 입력 받도록 하고,
배열 내에 존재하는 홀수만 출력하는 함수와 배열 내에 존재하는 짝수만 출력하는 함수를 각각 정의해서 이 두 함수를 호출하는 방식으로 프로그램을 완성하자.
#include <stdio.h>
void odd(int * a, int len)
{
int count = 0;
for (int i = 0; i < len; i++)
if (a[i] % 2 != 0)
count++; // 홀수의 갯수를 센다.
printf("홀수 출력: ");
for (int i = 0; i < len; i++)
if (a[i] % 2 == 1)
{
count--;
printf("%d", a [i]);
if (count != 0)
printf(", ");
}
printf("\n");
}
void even(int * a, int len)
{
int count = 0;
for (int i = 0; i < len; i++)
if (a[i] % == 0)
count++; // 짝수의 갯수를 센다.ㅏ
printf("짝수 출력: ");
for (int i = 0; i < len; i++)
if (a[i] % 2 == 0)
{
count--;
printf("%d", a[i]);
if (count != 0)
printf(", ");
}
}
int main()
{
int a[10];
printf("총 10개의 숫자 입력\n");
for (int i = 0; i < 10; i++)
{
printf("입력: ");
scanf_s("%d", &a[i]);
}
odd(a, sizeof(a)/sizeof(int)); // #include <string.h> 사용한 다음 strlen(a) 사용 가능.
even(a, sizeof(a)/sizeof(int));
return 0;
}
> 출력
총 10개의 숫자 입력
입력: 1
입력: 2
입력: 3
입력: 4
입력: 5
입력: 6
입력: 7
입력: 8
입력: 9
입력: 0
홀수 출력: 1, 3, 5, 7, 9
짝수 출력: 2, 4, 6, 8, 0
-풀이-
사실 마지막 출력에서 숫자 사이에 콤마(,)를 넣으려고 하다보니 count라는 변수가 추가됐다.
콤마 필요 없이 띄어쓰기로만 구분하게 된다면 함수가 아래와 같이 더 간결하게 표현 가능하다.
void odd(int * a, int len)
{
printf("홀수 출력: ");
for (int i = 0; i < len; i++)
{
if (a[i] % 2 == 1)
printf("%d ", a[i]);
}
printf("\n");
}
void odd(int * a, int len)
{
printf("짝수 출력: ");
for (int i = 0; i < len; i++)
{
if (a[i] % 2 == 0)
printf("%d ", a[i]);
}
printf("\n");
}
프로그램 사용자로부터 10진수 형태로 정수를 하나 입력 받은 다음, 이를 2진수로 변환해서 출력하는 프로그램을 작성해 보자.
#include <stdio.h>
int main()
{
int n;
printf("10진수 정수 입력: ");
scanf_s("%d", \n);
int two[100] = { 0 }; // 2진수 자리를 넉넉하게 준비.
int i = 0;
while(n > 0)
{
two[i] = n % 2;
n /= 2;
i++;
}
for (int j = i - 1; j >= 0; i--)
printf("%d", two[i]);
return 0;
}
> 출력
10진수 정수 입력: 12
1100
-풀이-
우선 2진수로 바꾸는 과정을 알아야하는데 모르시는 분, 기억이 가물가물하신 분들은 10진수 2진수 변환 방법 👈 이 블로그를 참고하길 바란다⭐
이번 for문에서는 배열을 역순으로 출력하는 방법이 나왔다.
n을 나눌 수 있을 만큼 나누고, 이에 대한 나머지가 a[0], a[1], ... a[i]순으로 저장된다.
출력될 때에는 a[i], a[i-1], ... a[1]로 역순으로 출력해야한다.
(2진수로 바꾸는 과정에서 큰수 -> 작은수로 가기 때문에 2진수 자릿수가 역순으로 저장되는 것!)
그리고 n을 2로 나누고 다시 n을 초기화 하는 과정에서 정수로 저장되기 때문에 1보다 작아지면 0으로 저장된다. (소수점 자리 수 데이터 소실)
그러므로 while(n>0)
이 무한루프가 아닌 종료 시점이 있을 수 있는 것이다.
길이가 10인 배열을 선언하고 총 10개의 정수를 입력 받는다.
단, 입력 받은 숫자가 홀수이면 배열의 앞에서부터 채워나가고, 짝수이면 뒤에서부터 채워나가는 형식을 취하기로 하자.
따라서 사용자가 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]을 입력했다면, 배열에는 [1, 3, 5, 7, 9, 10, 8, 6, 4, 2]의 순으로 저장이 되어야 한다.
#include <stdio.h>
int main ()
{
int a[10] = { 0 };
int count = 0;
printf("총 10개의 숫자 입력\n");
for (int i = 0; i < 10; i++)
{
int num = 0;
printf("입력: ");
scanf_s("%d", &num);
if (num % 2 == 0)
{
a[9 - count] = num;
count++;
}
else
a [i - count] = num;
}
printf("배열 요소의 출력: %d %d %d %d %d %d %d %d %d %d",
a[0], a[1], a[[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9]);
/* for문으로 출력 가능.
printf("배열 요소의 출력: ");
for (int i = 0; i < 10; i++)
printf("%d ", a[i]);
*/
return 0;
}
> 출력
총 10개의 숫자 입력
입력: 1
입력: 1
입력: 4
입력: 4
입력: 4
입력: 4
입력: 3
입력: 3
입력: 2
입력: 2
배열 요소의 출력: 1 1 3 3 2 2 4 4 4 4
-풀이-
앞에서 풀었던 문제들을 합쳐서 응용하는 문제였다.
입력 받는 숫자가 10개가 아닌 이것마저도 사용자에게 입력받는다면 좀 더 재밌는 문제가 될 것 같다.
회문(Palindrome)은 앞으로 읽으나 뒤로 읽으나 차이가 없는 단어들을 뜻한다.
예를 들어서 level, bob과 같은 단어들은 회문에 속한다.
이에 우리는 인자로 전달되는 영단어가 회문인지 아닌지를 판단해서 그 결과를 출력하는 기능의 함수를 정의하고 이에 적절한 main 함수를 정의해 보고자 한다.
단 구현의 편의를 위해서 대소문자까지 일치해야 회문으로 인정하기로 하겠다.
(이는 어디까지나 구현의 편의를 고려한 제약사항일 뿐이다.)
#include <stdio.h>
int main()
{
char str[101] = { 0 };
printf("문자열 입력: ");
scanf_s("%s", &str, 100);
int len = strlen(str); // strlen == sizeof(str) / sizeof(char)
int count = 0;
for (int i = 0; i < len / 2; i++)
if (str[i] != str[len - 1 - i]) // 회문 확인.
count++; // 아닐 경우 count
if (count == 0) // 회문인 경우
printf("회문 입니다.");
else
printf("회문이 아닙니다.");
}
> 출력
문자열 입력: noon
회문 입니다.
-풀이-
이 문제는 백준에도 있는 알고리즘 문제다.
난 단어 길이를 넉넉하게 100자로 잡았다. (문자열은 마지막 \n
이 들어갈 자리도 고려해서 크기를 잡아야한다.)
그리고 문자열을 입력 받으려고 하면 문자열을 저장할 배열 뒤에 인자로 몇자까지 입력할 수 있는지 정해줘야한다.
(물론, 백준에서 문제를 풀 땐 저게 필요 없다. scanf 함수
도 scanf_s 함수
가 아닌 그냥 scanf 함수
를 사용하면 된다.)
이번에는 정렬 알고리즘을 하나 소개하고, 이것을 이용한 프로그래밍 문제를 제시하고자 한다.
정렬이란 정의된 순서에 의해서 대상을 재배치하는 것을 의미한다.
예를 들어서 길이가 5인 배열에 정수 4, 3, 5, 1, 2가 저장되어 있다고 가정해보자.
이것을 오름차순(ascending order)으로 정렬하면 순서가 1, 2, 3, 4, 5로 재배치 될 것이고, 내림차순(descending order)으로 정렬하면 순서가 5, 4, 3, 2, 1로 재배치될 것이다.
이 문제는 정렬 중에 가장 쉬운 버블 정렬(bubble sort) 알고리즘에 관한 내용이다.
버블 정렬이란? 정렬되는 과정이 마치 거품이 일어나는 모습과 유사하다고 해서 이름이 붙어졌다.
오름차순을 예를 들어 버블 정렬을 설명해보자면,
첫 번째로 해야 할 일은 가장 큰 값을 배열의 마지막으로 보내는 일이다.
이를 위해서는 맨 앞에서부터 비교하여 가장 큰 값을 뒤로 밀어내는 것이다.
두 번째는 가장 큰 수가 배열의 마지막에 위치하였으므로 이것은 더이상 건드리지 않는다. 그 다음으로 큰 수를 배열의 마지막 바로 앞부분으로 이동시킨다.
마지막은 정렬되지 않은 수들을 비교해서 위와 같은 방법들로 정렬해나가는 것이다.
이번 문제는 배열에 저장되어 있는 요소들을 내림차순으로 정렬하는 함수(DesSort라 하자)를 정의하고 이 함수를 호출하는 예제를 작성해보자.
프로그램의 흐름은 길이가 7인 int형 배열을 선언해서 프로그램 사용자로부터 7개의 정수를 입력 받도록 한다.
입력 받은 정수를 내림차순으로 정렬하기 위해서, 배열을 인자로 전달하면서 DesSort 함수를 호출하자.
그리고 마지막으로 제대로 정렬이 되었는지 확인하기 위해서 배열의 요소들을 순서대로 출력해보자.
#include <stdio.h>
void DesSort(int ary[], int len);
int main()
{
int arr[7] = { 0 };
int i;
for (i = 0; i <7; i++)
{
printf("입력: ");
scanf("%d", &arr[i]);
}
DesSort(arr, sizeof(arr) / sizeof(int);
for (i = 0; i < 7; i++)
printf("%d ", arr[i]);
printf("\n");
return 0;
}
void DesSort(int ary[], int len)
{
int i, j;
int temp;
for(i = 0; i < len - 1; i++)
for(j = 0; j < len - 1; j++)
if (ary[j] < ary[j+1])
{
temp = ary[j];
ary[j] = ary[j+1];
ary[j+1] = temp;
}
}
> 출력
입력: 1
입력: 2
입력: 3
입력: 4
입력: 5
입력: 6
입력: 7
7 6 5 4 3 2 1
-풀이-
정렬에 관련해서는 python으로 자료구조를 배운 경험이 있기 때문에 익숙했다.
처음에 이 문제를 풀었을 땐 별 생각 없었는데 버블 정렬을 난 이미 배운적이 있엇구나 생각이 드니 좀 신기했다. ㅋㅋ
(인간의 기억력이란,,,ㅎㅎ)
이 문제를 좀 더 재밌게 한다면 사용자에게 숫자도 입력 받고 이 데이터들을 오름차순으로 정렬할지 내림차순으로 정렬할지 입력 받아 원하는 방식대로 정렬할 수 있게까지 한다면 더 재밌을 것 같다는 생각이 들었다.
// 책에서 알려준 오름차순 방법
void BubbleSort(int ary[], int len)
{
int i, j;
int temp;
for (i = 0; i < len - 1; i++)
for (j = 0; j < (len-i)-1; j++))
if (ary[j] > ary[j+1])
{
temp = ary[j];
ary[j] = ary[j+1];
ary[j+1] = temp;
}
}
<Review>
오늘도 챕터 하나 끝~
재밌다⭐
이번주 술을 4일 내내 마셨더니 머리와 몸이 정상이 아닌거 같았지만
이렇게 공부를 하면 또 머리가 잘 굴러가고 있구나(?), 잘 굴려보자는 느낌이 들어서 좋다👏🏻
내일부터는 오즈 코딩 스쿨 조교로 출근하는 첫날인데 좀 기대가 된다...☆
이전에 고령자들과 다녔던 회사가 아닌 또래들과 다니는 회사란,,,! 둑흔 ㅎㅎ
돈도 벌고 공부도 keep going 해보자~!⭐