정보처리기사 실기 코딩 알고리즘 C언어 최신 문제 정리 해설 - 24년 대비
공부를 하며 정보처리기사 실기 코딩 알고리즘 문제 중 긴가 민가했던 부분만 개인 확인용으로 정리하였습니다. 혹시 보시는 분이 있을지는 모르겠지만 문제가 있을 경우도 있어 꼭 믿지 않으셨으면 좋겠습니다.
C언어 문제 1년간 비중
20년 : 4문제
21년 : 5문제
22년 : 7문제
23년 : 15문제
20년도 문제
1회 14번
#include <stdio.h>
main() {
int c=1;
switch(3){
case 1:c+=3;
case 2:c++;
case 3:c=0;
case 4:c+=3;
case 5:c-=10;
default : c--;
}
printf("%d",c);
}
저는 순간 break; 가 없다는 걸 생각없이 풀었습니다.
이 코드에서 switch 문은 3과 매치됩니다. 그러나 case 문에서 break 문이 없으므로, case 3부터 default까지의 모든 문이 실행됩니다. 따라서 c의 값은 다음과 같이 계산됩니다.
1. case 3: c는 0이 됩니다.
2. case 4: c에 3이 더해져서 c는 3이 됩니다.
3. case 5: c에서 10을 빼서 c는 -7이 됩니다.
default: c에서 1을 빼서 c는 -8이 됩니다.
그 결과로 printf 함수가 호출될 때 c의 값은 -8이 되어 -8이 출력됩니
1회 20번
#include <stdio.h>
void align(int a[]){
int temp;
for(int i=0;i<4;i++)
for(int j=0;j<4-i;j++)
if(a[j]>a[j+1]){
temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
}
}
main() {
int a[]={85, 75, 50, 100, 95};
align(a);
for(int i=0;i<5;i++)
printf("%d",a[i]);
}
이 문제는 답을 작성시 붙여 쓰는게 맞는거 같은데 먼가 이상한데? 라는 생각을 가저 작성하였습니다.
버블 정렬을 사용하므로 배열이 오름차순으로 정렬됩니다. 따라서 정렬된 배열의 출력은 50758595100
4회 10번
#include <stdio.h>
main() {
char *p="KOREA";
printf("%s\n",p);
printf("%s\n",p+3);
printf("%c\n",*p);
printf("%c\n",*(p+3));
printf("%c\n",*p+2);
}
순간 예전에 printf("%s\n", *p) 가사용이 가능한지 혼동이 온적이 있어 정리하게 되었습니다.
%s는 문자열을 출력하기 위한 서식 지정자이며, 포인터 연산의 결과는 문자열이 아니라 단일 문자나 다른 유형의 데이터입니다.
이 코드는 포인터를 사용하여 문자열을 다루고 출력하는 예제입니다. 여기서 %s는 문자열을 출력하기 위한 서식 지정자이고, %c는 단일 문자를 출력하기 위한 서식 지정자입니다.
1. printf("%s\n", p);: p 포인터가 가리키는 문자열 "KOREA"를 출력합니다. 따라서 출력은 "KOREA"가 됩니다.
2. printf("%s\n", p+3);: p 포인터가 가리키는 위치에서 3칸 뒤에 있는 문자열을 출력합니다. 즉, "KOREA"에서 세 번째 문자 'E'부터 끝까지인 "EA"가 출력됩니다.
3. printf("%c\n", *p);: p 포인터가 가리키는 위치에 있는 문자를 출력합니다. *p는 포인터가 가리키는 위치의 첫 번째 문자인 'K'를 나타냅니다. 따라서 출력은 'K'가 됩니다.
4. printf("%c\n", *(p+3));: p 포인터가 가리키는 위치에서 3칸 뒤에 있는 문자를 출력합니다. *(p+3)은 "KOREA"에서 네 번째 문자 'E'를 나타냅니다. 따라서 출력은 'E'가 됩니다.
5. printf("%c\n", *p+2);: *p는 포인터가 가리키는 위치의 첫 번째 문자 'K'를 나타냅니다. 여기에 2를 더하면 'K'에 ASCII 값 2를 더한 값이 됩니다. 'K'의 ASCII 값은 75이므로, 75에 2를 더한 값은 77입니다. 따라서 출력은 'M'이 됩니다.
21년도 문제
1회 15번
#include <stdio.h>
void main(){
struct insa {
char name[10];
int age;
}a[] = {"Kim",28,"Lee",38,"Park",42,"Choi",31};
struct insa *p;
p = a;
p++;
printf("%s\n", p-> name);
printf("%d\n", p-> age);
}
이 코드는 구조체 배열을 선언하고, 포인터를 사용하여 배열의 요소에 접근하는 예제입니다. 코드를 실행하면 배열의 두 번째 요소인 "Lee"와 그에 해당하는 나이 38이 출력됩니다.
여기서 코드를 살펴보면:
struct insa: 구조체 insa를 정의합니다. 이 구조체는 이름을 나타내는 문자열(name)과 나이를 나타내는 정수(age)로 구성됩니다.
a[] = {"Kim",28,"Lee",38,"Park",42,"Choi",31};: 구조체 배열 a를 선언하고 초기화합니다. 배열의 각 요소는 이름과 나이를 번갈아가며 포함합니다.
struct insa *p;: 구조체 포인터 p를 선언합니다.
p = a;: 포인터 p를 배열 a의 첫 번째 요소를 가리키도록 설정합니다.
p++;: 포인터 p를 다음 요소로 이동시킵니다. 이로써 p는 두 번째 요소를 가리키게 됩니다.
printf("%s\n", p->name);: 포인터 p가 가리키는 구조체의 name 멤버를 출력합니다. 즉, 현재 p가 가리키는 요소의 이름을 출력합니다.
printf("%d\n", p->age);: 포인터 p가 가리키는 구조체의 age 멤버를 출력합니다. 즉, 현재 p가 가리키는 요소의 나이를 출력합니다.
2회 18번
#include <stdio.h>
int main(){
int ary[3];
int s = 0;
*(ary+0)=1;
ary[1] = *(ary+0)+2;
ary[2] = *ary+3;
for(int i=0; i<3; i++){
s=s+ary[i];
}
printf("%d",s);
이 코드는 정수 배열을 선언하고 초기화한 후, 배열 요소들의 합을 계산하여 출력합니다.
여기서 각 줄의 의미를 살펴보면:
int ary[3];: 크기가 3인 정수 배열 ary를 선언합니다.
int s = 0;: 정수 변수 s를 0으로 초기화합니다. 이 변수는 배열 요소들의 합을 저장할 것입니다.
*(ary+0)=1;: 배열의 첫 번째 요소에 1을 할당합니다. 이는 배열 인덱스를 사용하지 않고도 포인터 연산을 통해 배열 요소에 접근하는 방법을 보여줍니다.
ary[1] = *(ary+0)+2;: 배열의 두 번째 요소에 첫 번째 요소의 값에 2를 더한 값을 할당합니다.
ary[2] = *ary+3;: 배열의 세 번째 요소에 배열의 첫 번째 요소의 값에 3을 더한 값을 할당합니다. 이 부분은 조금 주의가 필요한데, *ary는 배열의 첫 번째 요소를 가리키는 포인터이며, 여기에 3을 더하는 것입니다.
for(int i=0; i<3; i++) { s=s+ary[i]; }: 배열의 모든 요소를 반복하여 합을 계산합니다.
printf("%d",s);: 배열 요소들의 합인 s를 출력합니다.
따라서 코드의 출력은 배열의 각 요소가 다음과 같이 설정되어 있을 때:
ary[0] = 1
ary[1] = 1 + 2 = 3
ary[2] = 1 + 3 = 4
배열 요소들의 합인 s는 1 + 3 + 4 = 8이 됩니다. 따라서 코드의 출력은 8이 됩니다.
3회 12번
#include <stdio.h>
int main(){
int *arr[3];
int a = 12, b = 24, c = 36;
arr[0] = &a;
arr[1] = &b;
arr[2] = &c;
printf("%d\n", *arr[1] + **arr + 1);
}
이 문제는 **arr 포인터가 2개가 붙어있는 경우가 처음 이 문제를 보았을 때 느낀 의문점으로 정리하였습니다.
결론부터 말하면 **arr 은 *arr[0]을 의미하고 *arr[0]은 그 위치의 값 즉 12를 의미 합니다.
또한 변수 선언에서의 int arr[3] 과 arr[3] = &d; 은 다릅니다.
int arr[3]은 3개의 공간을 의미하고 arr[3]은 int arr[4] 인곳에 마지막 값을 의미합니다.
즉 int arr[4]에는 arr[0], arr[1], arr[2], arr[3] 의 4 공간들이 존재합니다.
이 코드는 포인터 배열을 사용하여 정수형 변수들의 주소를 저장하고, 그 주소를 통해 변수들의 값을 참조하고 출력하는 예제입니다.
여기서 코드의 동작을 살펴보겠습니다:
int *arr[3];: 포인터 배열 arr을 선언합니다. 이 배열은 포인터들의 배열이며, 각 포인터는 정수를 가리키게 됩니다.
int a = 12, b = 24, c = 36;: 정수형 변수 a, b, c를 선언하고 각각 값을 할당합니다.
arr[0] = &a; arr[1] = &b; arr[2] = &c; : 포인터 배열 arr의 각 요소에 변수 a, b, c의 주소를 할당합니다.
printf("%d\n", *arr[1] + **arr + 1);: arr[1]은 b의 주소를 가리키고, *arr[1]은 b의 값을 의미합니다. **arr은 arr[0]이 가리키는 주소에 있는 값, 즉 a의 값을 의미합니다. 따라서 식 *arr[1] + **arr + 1은 b의 값인 24와 a의 값인 12를 더하고 1을 더한 값을 나타냅니다 37(24 + 12 + 1)
3회 17번
#include <stdio.h>
struct jsu {
char name[12];
int os, db, hab, hhab;
};
int main(){
struct jsu st[3] = {{"데이터1", 95, 88},
{"데이터2", 84, 91},
{"데이터3", 86, 75}};
struct jsu* p;
p = &st[0];
(p + 1)->hab = (p + 1)->os + (p + 2)->db;
(p + 1)->hhab = (p+1)->hab + p->os + p->db;
printf("%d\n", (p+1)->hab + (p+1)->hhab);
}
위 코드는 구조체 배열을 사용하여 세 명의 학생의 정보를 저장하고 있습니다. 각 학생은 이름과 OS, DB 과목에 대한 점수를 가지고 있습니다. 그런 다음, 포인터를 사용하여 배열의 두 번째 요소의 hab과 hhab 멤버를 계산하고, 이를 출력합니다.
이 코드를 실행하면, 두 번째 학생의 hab 값과 hhab 값의 합이 출력됩니다. 이 값은 다음과 같이 계산됩니다:
hab: 두 번째 학생의 hab 값은 두 번째 학생의 os 값과 세 번째 학생의 db 값을 더한 값입니다. 즉, 84 + 75 = 159가 됩니다.
hhab: 두 번째 학생의 hhab 값은 두 번째 학생의 hab 값과 첫 번째 학생의 os와 db 값을 더한 값입니다. 즉, 159 + 95 + 88 = 342가 됩니다.
따라서 출력은 hab 값과 hhab 값의 합인 159 + 342 = 501이 됩니다.
따라서 코드의 출력은 501이 됩니다
22년도 문제
2회 8번
#include <stdio.h>
struct A{
int n;
int g;
};
int main() {
struct A a[2];
for(int i=0;i<2;i++){
a[i].n=i, a[i].g=i+1;
}
printf("%d",a[0].n+a[1].g);
}
이 코드는 구조체 배열을 사용하여 각 요소에 값을 할당하고, 배열의 첫 번째 요소의 n 값과 두 번째 요소의 g 값을 더하여 출력하는 예제입니다.
여기서 코드의 동작을 살펴보겠습니다:
struct A a[2];: 구조체 배열 a를 선언합니다. 이 배열은 A라는 구조체 형식의 요소를 두 개 가지고 있습니다.
for(int i=0;i<2;i++): 반복문을 사용하여 배열의 각 요소에 값을 할당합니다. i가 0일 때와 1일 때 두 번 반복합니다.
a[i].n=i, a[i].g=i+1;: 배열의 각 요소에 n과 g 값을 할당합니다. 첫 번째 요소의 n 값은 i이고, g 값은 i+1입니다. 두 번째 요소의 n 값은 1이 되고, g 값은 2가 됩니다.
a[0].n = 0, a[0].g = 1 -> a[1].n =1 . a[1].g = 2
출력은 첫 번째 요소의 n 값인 0과 두 번째 요소의 g 값인 2를 더한 결과인 2가 됩니다.
2회 16번
#include <stdio.h>
int main(int argc, char*argv[]) {
int a[4]={0,2,4,8};
int b[3]={};
int i=1;
int sum=0;
int *p1;
for(i;i<4;i++){
p1=a+i;
b[i-1]=*p1-a[i-1];
sum=sum+b[i-1]+a[i];
}
printf("%d",sum);
return 0;
}
이 코드는 배열 a와 배열 b를 사용하여 계산을 수행하고, 그 결과를 출력하는 예제입니다.
여기서 코드의 동작을 살펴보겠습니다:
int a[4]={0,2,4,8};: 크기가 4인 정수형 배열 a를 선언하고 초기화합니다. 요소들은 0, 2, 4, 8로 초기화됩니다.
int b[3]={};: 크기가 3인 정수형 배열 b를 선언하고, 모든 요소를 0으로 초기화합니다.
int i=1;: 정수형 변수 i를 선언하고 1로 초기화합니다.
int sum=0;: 정수형 변수 sum을 선언하고 0으로 초기화합니다. 이 변수는 결과의 합을 저장합니다.
int *p1;: 정수형 포인터 p1을 선언합니다.
for(i;i<4;i++): 반복문을 사용하여 배열 a와 배열 b를 이용하여 계산을 수행합니다. i가 1부터 3까지 반복합니다.
p1=a+i;: 포인터 p1을 배열 a의 i번째 요소를 가리키도록 설정합니다.
b[i-1]=*p1-a[i-1];: 배열 b의 i-1번째 요소에 p1이 가리키는 값과 배열 a의 i-1번째 요소의 차를 할당합니다.
sum=sum+b[i-1]+a[i];: sum 변수에 b[i-1]과 a[i]를 더한 값을 누적합니다.
printf("%d",sum);: 계산된 합인 sum을 출력합니다.
따라서 코드는 다음과 같이 동작합니다:
b[0]은 a[1] - a[0]이므로 2 - 0 = 2가 됩니다.
b[1]은 a[2] - a[1]이므로 4 - 2 = 2가 됩니다.
b[2]은 a[3] - a[2]이므로 8 - 4 = 4가 됩니다.
a[1] = 2, a[2] =4, a[3] =8 이기 때문에
sum은 2 + 2 + 4 + 2 + 4 + 8 = 22가 됩니다.
따라서 코드의 출력은 22가 됩니다.
3회 13번
int main() {
int s, el = 0; // 완전수 개수를 나타내는 변수 el 초기화
// 6부터 30까지의 수에 대해 반복
for (int i = 6; i <= 30; i++) {
s = 0; // 약수의 합을 나타내는 변수 s 초기화
// 해당 수의 약수를 구하고 약수의 합을 계산
for (int j = 1; j <= i / 2; j++) {
if (i % j == 0) { // 약수인 경우
s += j; // 약수를 약수의 합에 더함
}
}
// 약수의 합이 해당 수와 같으면 완전수로 판별
if (s == i) {
el++; // 완전수의 개수를 증가
}
}
printf("%d", el); // 완전수의 개수 출력
return 0;
}
완전수는 자신을 제외한 모든 양의 약수의 합이 자기 자신과 같은 자연수를 말합니다. 예를 들어, 6은 자신을 제외한 약수인 1, 2, 3의 합이 자기 자신인 6과 같으므로 완전수입니다.
따라서 주어진 프로그램은 6부터 30까지의 수 중에서 완전수를 찾는 것입니다. 이 프로그램은 주어진 범위 내에서 각 수의 약수를 모두 구하고, 약수의 합이 해당 수와 같으면 그 수를 완전수로 간주하여 개수를 셉니다.
실제로 프로그램을 실행해보면, 6, 28이 완전수인 것을 확인할 수 있습니다. 이들의 약수 합을 살펴보면 다음과 같습니다:
6: 1 + 2 + 3 = 6
28: 1 + 2 + 4 + 7 + 14 = 28
따라서 이 프로그램을 실행하면 결과로 "2"가 출력됩니다.
23년도 문제
1회 10번 - 이진수에서 십진수로 만들기 위해 가, 나 쓰세요
#include <stdio.h>
int main(void) {
int input = 101110;
int di = 1;
int sum = 0;
while (input > 0) {
sum = sum + (input (가)(나) * di);
di = di * 2;
input = input / 10;
}
printf("%d", sum);
return 0;
}
먼저 답은 (가) = % , (나) = 10 또는 2
2진수를 10진수로 변환하는 방법은 1 * 2^5 + 0 * 2^4 + 1 * 2^3 + 1 * 2^2 + 1 * 2^1 + 1 * 2^0 입니다.
101110의 값에서 1의 자리 숫자를 구하기 위해 %(나머지) 를 해줍니다. 고로 1의 자리값은 0 이 나오고 곱하는 값인 di 값이 2배 씩 증가하는 것을 유추하여 1 * 2^5 + 0 * 2^4 + 1 * 2^3 + 1 * 2^2 + 1 * 2^1 + 1 * 2^0 이런 식이 나오게 추론할 수 있습니다. 그 후 input = input/10 을 통해 101110/10 = 10111이 되어 1의 자리를 제거해줍니다.
다시 10111 % 10을 통해 나머지 2의 자리가 1인걸 알 수 있고 곱하기 2를 하며 계속 더해주면 원하는 값을 얻을 수 있습니다. 최종적으로 while 문을 빠저나올 값을 출력하게 되는 코드입니다.
2회 3번 - 홍길동, 김철수, 박영희 순서대로 입력 했을 경우
#include<stdio.h>
#include<stdlib.h>
char n[30];
char *test() {
printf("입력하세요 : ");
gets(n);
return n;
}
int main()
{
char * test1;
char * test2;
char * test3;
test1 = test();
test2 = test();
test3 = test();
printf("%s\n",test1);
printf("%s\n",test2);
printf("%s",test3);
return 0;
}
결과는 박영희만 3번 나오게됩니다.
문제는 gets()가 입력을 읽는 방식에 있습니다. gets() 함수는 개행 문자('\n')가 나타날 때까지 표준 입력 스트림(stdin)에서 문자를 읽습니다. 그런 다음 개행 문자 자체를 포함하여 이러한 문자를 'n' 배열에 저장합니다.
"홍길동", "김철수", "박영희"를 각각 입력하고 Enter 키를 누르면 gets()는 개행 문자와 함께 이러한 각 문자열을 읽습니다. 이 개행 문자는 배열에서 추가 바이트를 차지합니다. 따라서 30자 이내의 "박영희"를 입력하면 실제로는 줄바꿈 문자와 함께 배열을 채우게 됩니다.
따라서 문자열을 인쇄할 때 개행 문자로 인해 후속 printf() 호출이 다른 문자열을 표시하는 것을 방지하기 때문에 "박영희"만 표시됩니다.
이 문제를 해결하려면 gets() 대신 fgets() 사용을 고려할 수 있습니다. fgets()를 사용하면 읽을 최대 문자 수를 지정하여 버퍼 오버플로를 방지할 수 있습니다. 또한 올바른 문자열 처리를 보장하기 위해 입력 문자열을 읽은 후 입력 문자열에서 개행 문자를 제거할 수 있습니다.
2회 9번
#include <stdio.h>
#define MAX_SIZE 10
int isWhat[MAX_SIZE];
int point= -1;
void into(int num) {
if (point >= 10) printf("Full");
isWhat[++point] = num;
}
int take() {
if (isEmpty() == 1) printf("Empty");
return isWhat[point--];
}
int isEmpty() {
if (point == -1) return 1;
return 0;
}
int isFull() {
if (point == 10) return 1;
return 0;
}
int main(int argc, char const *argv[]){
int e;
into(5); into(2);
while(!isEmpty()){
printf("%d", take());
into(4); into(1); printf("%d", take());
into(3); printf("%d", take()); printf("%d", take());
into(6); printf("%d", take()); printf("%d", take());
}
return 0;
}
스택의 구조로 후입선출 나중에 들어온게 먼저 나가는 구조이다.
1. main() 함수가 실행됩니다.
2. into(5) 함수 호출로 스택에 5가 추가됩니다.
3. into(2) 함수 호출로 스택에 2가 추가됩니다. -> 5 2
4. 스택에서 데이터를 꺼내고 출력합니다. 현재 스택에는 2가 출력됩니다. -> 5
5. into(4) 함수 호출로 스택에 4가 추가됩니다.
6. into(1) 함수 호출로 스택에 1이 추가됩니다. -> 5 4 1
7. 스택에서 데이터를 꺼내고 출력합니다. 현재 스택에는 1이 출력됩니다. -> 5 4
8. into(3) 함수 호출로 스택에 3이 추가됩니다. -> 5 4 3
9. 스택에서 데이터를 꺼내고 출력합니다. 현재 스택에는 3이 출력됩니다. -> 5 4
10. 다시 데이터를 꺼내고 출력 하면 4가 출력 -> 5
11. into(6) 호출로 6이 추가 -> 5 6
12. 마지막으로 나머지 값들을 두번 출력하게 된다.
따라서 출력 결과는 " 213465 "가 됩니다. 처음 스택에 넣은 순서대로 데이터가 꺼내져 출력되는 것을 확인할 수 있습니다.
3회 15번
#include<stdio.h>
int f(int n) {
if(n<=1) return 1;
else return n*f(n-1);
}
int main() {
printf("%d", f(7));
}
n!=n×(n−1)×(n−2)×…×2×1로 정의됩니다. 여기서 f() 함수는 재귀적으로 호출되며, n이 1 이하일 때는 1을 반환하고, 그렇지 않으면 재귀 호출을 합니다. f(7)을 호출하여 7의 팩토리얼을 계산하면 7 * 6 * .... * 1 = 5040