기본 콘텐츠로 건너뛰기

C언어 - 입력된 정수 홀수와 짝수로 나눠 크기순으로 출력하기



2번째 주 - C언어 문제
길이가 10인 배열을 만들고 그 배열에 10개의 정수를 입력 받는다. 이 때 입력받은 정수가 홀수면 배열의 앞부터 채워나가고 짝수면 배열의 맨 뒤에서부터 채워나가는 프로그램을 만들어라.(정수는 항상 10개를 모두 입력한다고 가정한다.)
실행화면


조건
1. int arr[10], i, num[10];// arr = 짝수 홀수 정리할 배열, num = 숫자 입력 배열\
2.int lennum =() ; // 배열 num의 크기, 배열 입력받을 때 for문에서 10으로 하지말 lennum사용해서 받을 것
int lenarr =(); // 배열 arr의 크기, {1,3,5,7,9,1,8,6,4,2} 형식을 위해 사용
-->hint: sizeof 사용
3.lenarr
출력 포맷을 위 사진과 동일하게 만들기 위해 사용한다. 처음과 끝은 {}를 사용하고 마지막 숫자 뒤에는 콤마가 없어야 한다.
-->hint: if문 사용
 
<풀이>
코드는 총 4부분으로 나뉜다. 입력 받기, 홀수 정리, 짝수 정리, 출력.
 
1. 입력받기

입력 받기 위해 for 문을 사용해서 반복한다. 여기서 조건을 만족시키기 위해 lennum을 구해야 한다. siezof 크기를 알려주는 함수인데 단순히 sizeof(num)을 한다면 10이 나오지 않는다. 40이 나올 것이다. 이는 배열이 가진 인덱스X타입형의 크기 값이 총 배열의 크기이기 때문이다. 따라서 lennum을 구하기 위해서는 다음과 같이 해야 한다.

lennum = sizeof(num) / sizeof(int);

for문 안에서는 scanf를 사용해 입력한 숫자를 num배열에 넣는다.
입력받기 코드

 


2.홀수 정리
 
모든 num배열에 있는 수에 대해서 분류작업을 해야 하기 때문에 for문으로 반복할 수 있게 해 준다.
if-else 문을 통해 홀수와 짝수를 분리한다.
num[i]2로 나눠서 나머지가 남으면 홀수라는 성질을 이용해서 if문의 조건을 적어준다.
if(num[i]%2)
 
이제 홀수를 순서대로 크기순으로 정리해야 한다. 단순히 양 옆에 있는 숫자끼리 비교하는 게 아니라 모든 홀수를 함께 비교해서 arr이란 배열에 순서대로 집어넣어야 한다.
oddcount라는 변수가 나오는데 oddnum[i]arr에 들어갈 인덱스를 의미하고 count는 같은 수가 반복될 경우 얼마나 많이 나왔는지(- 1,1,1,...-->count = 2) 알려주는 변수이다. 이들은 매번 i가 바뀔 때마다 항상 0으로 초기화해줘야 한다.
odd = 0;
count = 0;
 
for문을 통해서 모든 홀수를 하나의 홀수를 나머지 홀수와 비교한다. 만약 자신보다 작은 홀수가 있을 경우 odd1증가시킨다. arr에서 자신의 위치가 한 칸씩 뒤로 밀리는 것이다. 같은 수가 있을 경우에는 count1증가시킨다. for문이 끝나면 홀수 중에서 num[i]보다 작은 홀수의 갯수(odd)와 만약 num[i]와 같은 수가 여러 개라면 자신을 제외하고 얼마나 있는지(count, 하나만 있을 경우에는 0)를 보여준다.
for (j = 0; j < lennum; j ++){
    if ((num[j]%2) && (num[j] < num[i])) odd++;
    if ((i != j) && (num[i] == num[j])) count ++;
}
 
이제 arr에 수를 넣어줘야 한다. 만일 하나만 있는 숫자였다면 arr에 넣기는 쉽다. 그렇지만 반복적으로 들어있던 수를 고려하면 복잡해진다. 일단 if - else문을 사용해 ifnum[i]가 하나만 있을 경우, elsenum[i]가 여러 개있을 경우로 나눈다.
if (count)
else
 
먼저 이해하기 더 쉬운 else 부터 설명하자면 num[i]보다 작은 수가 odd개 있음으로 그냥 arr[odd]에 대입하면 된다. 자신보다 작은 수가 없을 경우는 arr[0]에 들어갈 것이다.
다음은 반복되는 숫자일 경우. while문을 사용해 count0이상일 경우까지 반복한다.(0일 때도 while문을 돌아야하기 때문에 조건에 count+1이라고 적어준다.) num[i]보다 작은 수의 갯수는 k라 하면, arr의 인덱스가 k부터 k+count까지 총 count+1 번 반복한다. countnum[i]를 제외하고 반복되는 수이기 때문에 반복하는 횟수인 count+1num[i]가 실제 num에 존재하는 횟수이다. arr에 대입하고 나서 count1씩 감소시킨다.
if (count) {
    while (count+1){
        arr[odd+count] = num[i];
        count--;
    }
}
else arr[odd] = num[i];
 
홀수 정리 코드

 
 
 
3. 짝수 정리

방법은 홀수와 같다. 다만 인덱스를 정리할 때 작은 숫자가 arr의 끝 인덱스부터 들어간다는 것을 유의하며 구한다.
num[i]보다 작은 수들을 구하고 이를 even, num[i]와 같은 수가 여러 개라면 개수를 count에 대입한다. countevennum[i]가 바뀔 때마다 항상 0으로 초기화해줘야 한다. evenarr에 들어갈 인덱스를 의미하기도 한다. 자신보다 작은 수가 몇 개인지를 계산하여 even1씩 증가시켜 준다. 여기서 count0부터 시작했기 때문에 num[i]가 반복적인 수라면 홀수 때와 마찬가지로 같은 수의 개수-1의 숫자를 가진다.(- 4,4,,... --> 1)
even = 0;
count = 0;
for (j = 0; j < lennum ; j++){
    if (!(num[j]%2) && (num[j] < num[i])) even ++;
    if ((i != j) && (num[i] == num[j])) count ++;
}
 
이제 arrnum[i]를 넣어야 한다. num[i]가 반복적인 수일 경우와 그게 아닐 경우로 나눠 생각한다. if - else문을 사용한다. num[i]가 반복적인 수라면 count가 증가해 0이 아닐 것이다. 이 조건을 if에 사용한다.
if (count)
else
 
먼저 반복이 아닌 경우를 생각해 보자.(else의 경우) 작을수록 인덱스는 9에 가까워져야 한다. (10개의 칸이 있는 배열이기 때문에 마지막 인덱스가 9이다.) 따라서 arr의 인덱스는 9-even이 된다. 가장 작은 짝수일 경우는 자신보다 작은 수가 아무것도 없기때문에 even0이 되어 arr[9](9-0 = 0) 들어간다. 반복일 경우에는 반복인 수만큼 arr에 들어가 있어야 한다. num[i]의 원래 인덱스(9-even)부터 인덱스가 작아지는 방향으로 반복되는 개수만큼 채워져야 한다. 따라서 arr의 인덱스가 [9-even -count]부터 [9-even]까지 넣는 것을 반복해야 한다.
if (count){
    while (count + 1){
        arr[9 - even - count] = num[i];
        count --;
    }
}
else arr[9 - even] = num[i];
 
짝수 전체 코드


 

 
4. 화면에 출력

arr 배열을 처음부터 차근차근 출력하면 된다. 여기서 주의할 점은 괄호({,})와 콤마(,)이다. 배열의 앞쪽은 괄호를 열고, 가장 뒤는 괄호로 닫는다. 출력 시 숫자와 숫자 사이는 콤마로 구분하고 맨 앞 숫자의 앞부분과 맨 뒤 숫자의 뒷부분에선 콤마가 없어야 한다. 이를 위해 배열의 가장 앞, 중간, 뒤로 범위를 나눠 출력하도록 만든다.
배열의 모든 수를 출력해야하기 때문에 for를 이용해 반복문을 만들어준다.
for(i = 0 ; i < lenarr; i++)
 
if - else if - else문을 사용해 범위를 나눈다. i0일 때(가장 앞의 숫자) “출력: ”이라는 글자와 괄호, 그리고 arr[0]와 콤마를 모두 출력한다. else - ifi1 부터 8까지를 출력해준다. 각 숫자 뒤에는 콤마를 함께 출력한다. else문은 i9일 때이다. arr[9]}를 출력한다.
if (i == 0) printf("출력: { %d, ", arr[i]);
else if (i < lenarr - 1) printf("%d, ", arr[i]);
else printf("%d }\n", arr[i]);
 
출력 전체 코드

 
전체 코드

 

 
 


 
**출력하기 변형
if - else if - else를 사용하지 않고 출력하기
printf("출력: {");
for(i = 0 ; i < lenarr; i++){
    printf(" %d,", arr[i]);
}
printf("\b }\n");


댓글

이 블로그의 인기 게시물

C언어 - 입력받은 숫자의 이진수 표현에서 1의 개수를 세는 코드를 짜기

C 언어 문제: 입력받은 숫자의 이진수 표현에서 1의 개수를 세는 코드를 짜기 이 문제를 해결하기 위해서는 시프트 연산자에 대해 알아야 한다. 컴퓨터에서는 숫자를 2진수로 표현하는데 정수는 32비트로 나타낸다. 가장 앞쪽에 있는 비트는 음수와 양수를 구분해 주는 비트이고 이 이하가 숫자를 의미한다. 시프트 연산자는 숫자를 이진수로 표현했을 때 연산을 편리하게 해 주는 연산자이다. 연산자에 대해 자세히 알고 싶으면 ( http://rockykim5581.tistory.com/19 )을 참고하길 바란다. 여기에서는 필요한 부분만 다룰 예정이다. 1. 숫자 입력받기 입력한 숫자를 변수에 대입해야 한다. 2.입력한 숫자의 이진수 표현에서 1의 개수 구하기 이진수에서도 비교 연산자를 사용할 수 있다. AND를 의미하는 &는 두 수가 모두 1일 때만 1(참)을 나타낸다. 이 성징을 이용하면 입력받은 숫자의 이진수를 셀 수 있다. 비트는 1부터 31가지 비교해야 한다.(32비트-사인비트-는 제외) 이 과정을 하기 위해서는 반복문이 필요하다. 여기서는 조건과 초기화, 반복후 실행하는 문이 있어서 for를 사용했다. 비교는 입력은 숫자(이진수 표현)의 n번째(이는 0아니면 1이다)와  n번째가 1인 숫자를 &으로 비교해서 둘 다 모두 1인 경우만 count라는 변수를 하나씩 올려준다. 그러면 입력받은 수의 이진수 표현 1을 셀 수 있게된다. 그러면 n번째가 1이라는 숫자를 어떻게 만들까? 이는 변수(one)를 하나 잡아 반복문의 실행에 따라 1을 시프트 연산자로 이동시킨 수를 대입한다. 예를 들어 처음일 때는 입력받은 수와 1을 옯기지 않은 상태로 비교, 두번째 자리를 비교할 땐 입력받은 수와 1을 한칸 옮긴 상태로 비교하는 식이다. 여기서 주의해야 할 점은 (비교하려는 자리의 수-1)만큼 시프트 연산자로 밀어줘야 한다는 것이다. 1이 한 자리도 차지하기 때문이다. <전체 코드> ...

C언어 - 1~100 사이의 소수 구하기

  C 문제 정수 값을 인자로 받아서 소수인지 판단하는 IsPrime 함수를 정의하고 이 함수를 이용해 1 부터 100 사이의 소수를 모두 구해서 출력하는 프로그램을 작성하시오 .   1.main 함수 만들기 IsPrime 이라는 함수에 인자를 2 부터 99 로 넣어주는 함수를 만들어야 한다 . 반복을 위해 for 함수를 사용한다 . main 함수의 타입이 int 이기 때문에 return 값을 적어줘야 함 .   2.IsPrime 함수 만들기 딱히 반환해야 할 값이 없기 때문에 타입은 void 경우를 2 가지로 나눔 . ①if  인자가 2 일 경우 --> 2 는 소수이기 때문에 2 를 출력함 ②else  인자가 2 가 아닐 경우 --> 2 부터 ( 인자 -1) 까지의 수로 인자를 나눠서 모든 경우에 나머지가 0 이 아니면 소수임 . 즉 어떤 숫자로 나눠 떨어지면 소수가 아니라는 의미로 더이상의 경우를 확인할 필요가 없음 . 따라서 반복하던 for 문을 빠져나옴 . for 문이 끝난 후 인자의 값과 count 의 값이 같다면 count 의 어떠한 숫자로도 인자가 나누어지지 못했다는 의미이다 . 이는 소수라는 뜻과 마찬가지이기 때문에 이 경우에 인자를 출력한다 .   3. 기타 출력한 후 모습을 살펴보는데 IsPrime 에서의 출력이 숫자 끝에 콤마 (,) 가 붙기 때문에 모든 출력이 끝나도 마지막 숫자 뒤에 콤마가 붙어 있다 . 이를 없애기 위해서는 이스케이프 문자 ‘\ b’ 를 사용했다 . 출력 화면이 더 편하게 보이도록 ‘\b\n’ 를 썼으나 이럴 경우 '\b' 의 효과가 사라졌다 . ‘\b\b\n’ 처럼 사용했으나 결과는 역시나 \ n 의 효과만 나타날 뿐 \ b 의 효과는 없었다 . 이를 해결하기 위해 구글링도 했지만 적절한 답을...