본문 바로가기

자격증/정보처리기사

[c언어] 문제 풀이

1. 

#include <stdio.h>
void main() 
{
	int a = (10,20);
    printf("%d", a);
    
    int b = (10,20,30);
    printf("%d", b);
    
    int c = (10,(20,30),40);
    printf("%d", c);

}

답 : 20,30,40

 

풀이 : 콤마 연산자는 맨 오른쪽의 값을 참조하게 됨 

 

 

2.

#include <stdio.h>

void main()
{
	int a = 16;
	printf("%d", a);
	printf("%o", a);
	printf("%x", a);

	int b = 17;
	printf("\n%d", b);
	printf("%o", b);
	printf("%x", b);
}

답 : 16, 20, 10

       17,21,11

 

풀이 :

16진수를 2진수로 바꾸면  10000

8진수로 출력하게 되면 3자리씩 자르게 되고, 010,000 이렇게 두 자리로 나뉘고, 결과는 20으로 출력

16진수로 출력하게 되면 4자리씩 자르게 되고, 0001, 0000 이렇게 두 자리로 나뉘고, 결과는 10으로 출력 

 

 

 

3.

정수 a,b에 각각 1,2 대입

a<b+2&&a<<1<=b

답 : 1

 

풀이 :

논리 연산자 &&를 기준으로 좌항과 우항으로 나누어 참 거짓을 확인

a<b+2에서 산술 연산자가 우선순위가 높기 때문에 1<4로 비교하여 참값을 리턴

a<<1<=b에서 시프트 연산자가 우선순위가 높기 때문에 a 값 1을 좌시프트 1해서, 2<=2를 비교하게 되고, 참값을 리턴 

좌항과 우항이 모두 참이기 때문에 최종적으로 참값인 1을 리턴 

 

 

4. 

#include <stdio.h>
main() 
{
    int num1 = 5;
    int num2 = -5;
    printf("%d %d", ~num1, ~num2);
}

답 : -6, 4

 

풀이 :

비트 NOT 연산자를 사용하게 되면 양수일 때는 부호와 상관없이 1증가 후, 음수로 변환하고, 

음수일 때는 부호와 상관없이 1 감소후 양수로 변환 

 

 

5.

#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;
			}
		}
	}
}

void main()
{
	int a[] = { 85, 75, 50,100,95 };
	align(a);
	for (int i = 0; i < 5; i++)
		printf("%d", a[i]);

	return 0;
}

답 : 50 75 85 95 100

풀이:

버블 정렬 

i=0일 떄,

j 비교값 85 75 50 100 95
0 85>75 75 80 50 100 95
1 85>50 75 50 85 100 95
2 85>100 75 50  85 100 95
3 100>95 75 50 85 95 100

i=1일 떄, 

j 비교값 80 75 50 100 95
0 75>50 50 75 85 95 100
1 75>85 50 75 85 95 100
2 85>95 50 75 85 95 100

 

 

6.

#include <stdio.h>
void main()
{
   int a,b;
    a=2;
    while(a-->0) {
    	printf("a= %d\n", a);
    }
    for(b=0; b<2; b++) {
    	printf("a=%d\n", a++);
    }
}

답 : a=1

       a=0

       a= -1

       a= 1

 

풀이 :

첫 번째 while 반복에서는 a가 0보다 클 때 반복을 수행

a를 비교할 때 후위 증감이기 떄문에, 먼저 2값을 가지고 비교를 하게됨 

두 번째 for반복에서는 0부터 2보다 작을 떄까지 반복하면서 a값을 출력  

출력할 떄, a를 후위 증감을 하기 때문에 a값을 먼저 출력하고, 1 증가시킴

 

 

7.

int main() {
    char ch[5];
    char str[]= "abcde";
    int num[]= {1,2,3,4,5};
    printf("%d", sizeof(ch));
    printf("%d", sizeof(str));
    printf("%d", sizeof(num)/sizeof(int));
  	
    return 0;
}

답 : 5,6,5

 

풀이 :

char 배열 str에 abcde를 대입

int 배열 num에 1,2,3,4,5를 대입 

 

ch 배열은 5개의 공간을 확보하라고 했기 때문에, 5개의 길이를 갖게 됨 

str 배열은 null 문자가 포함되어 6개의 길이를 갖게 됨 

num 배열은 null 문자가 포함되지 않기 때문에 4byte씩 5개의 공간이 됨 

 

sizeof는 해당 공간의 Byte 수를 구하는 함수이고, sizeof(num)은 4byte씩 5개 20byte가 됨 

sizeof(int); int 자료형은 4byte이므로, 20/4 =5가 됨 

 

 

8.

#include <stdio.h>

void main() {
    int A = 10, B;
    int *C = &B;
    
    B= A--;
    B+= 20;
    printf("%d", *C);
}

답 : 30

 

풀이 :

 A,B 변수를 선언하고, A에는 10을 기본값으로 할당  

 C라는 포인터 변수를 선언하고, C 포인터 변수에 B 변수의 주소값을 대입하게 됨 

 A 변수는 100번지, B 변수는 200번지라고 가정했을 때, C 변수는 200번지를 가지고 있음 

100번지 200번지 300번지
A B C
10   200

B 변수에 A의 값을 먼저 B에 대입하고, A 변수의 값을 1 감소시킴

100번지  200번지 300번지
A B C
9 10 200

B 변수에 20을 더해줌 

100번지 200번지 300번지
A C
30 200

출력을 할 때, C 변수가 가리키고 있는 200번지의 값을 출력해줌 

 

 

9.

#include <stdio.h>
int main(void) {
    int n =4;
    int * pt = NULL;
    pt=&n;
    
    printf("%d", n+*pt-&*pt + n);
    return 0;
}

답 : 8

 

풀이 :

n 변수에 4를 대입하고, 포인터 변수 pt에 null을 대입 

pt에 n 변수의 주소값 100을 대입

주소값 100 200
변수명 n pt
값  100

출력문 

표기 &n *pt *&pt n
값  100 4 100 4

100+4-100+4 = 8

 

 

10.

#include <stdio.h>

int main(void) {
    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);
    
    return 0;
 }

답 :

KOREA

        EA

           K

           E

           M

 

풀이 :

 포인터 변수 p 에 KOREA를 연속으로 대입 

주소값  1000 100 101 102 103 104 105
변수명 p            
100 K O R E A \0

첫 번째 출력, p가 가리키고 있는 100번지 부터 \0을 만날 때까지 출력해서 KOREA 출력

두 번째 출력, p+3은 103이 되고, 103번지부터 \0을 만날 때까지 출력해서 EA 출력

세 번째 출력 ,p가 가리키고 있는 100번지의 값 하나를 출력하게 되므로 K가 출력 

네 번째 출력, (p+3)하게 되면 103이 되고 103번지의 값 하나를 출력하게 되어 E가 출력 

다섯 번째 출력, p가 가리키고 있는 100번지의 값 K에 2를 더하여 출력, K에 2를 더한다는 의미는 알파벳 순으로 K 다음, 다음에 있는 M을 의미하게 되서 M이 출력됨 

 

11.

#include <stdio.h>

int main(void) {
    int a[] = {1,2,4,8};
    int *p = a;
    p[1] = 3;
    a[1] = 4;
    a[2] = 5;
    printf("%d %d\n", a[1] +p[1], a[2]+p[2]);
    
    return 0;
}

답 : 8 10

 

풀이 :

a 배열을 선언하고 1,2,4,8을 초기값을 지정해줌 

주소값 1000
변수명 a
100
주소값 100 101 102 103
인덱스  [0] [1] [2] [3]
2 4 8

포인터 변수 p를 선언하고, a 값을 넣어줌 

주소값  2000
변수명 p
값  100

1차원 배열을 포인터 변수에 연결을 시키게 되면 포인터 변수도 배열하고 같이 인덱스를 사용할 수 있음

p[1]에 3을 대입

a[1]에 4를 대입 

p[2]에 5를 대입 

주소값 100 101 102 103
인덱스  [0] [1] [2] [3]
1 4 5 8

a[1]+p[1]는 똑같은 위치를 가리키고 있고, 4+4를 연산해서 8을 출력 

a[2]+p[2]는 똑같은 위치를 가리키고 있고, 5+5를 연ㅅ나해서 10을 출력 

 

 

12.

#include <stdio.h>
int main() {
    int data[][3] ={1,3,4,5,2,9,6,8,7};
    int *p = data[1];
    int x,y;
    x = *p;
    y = *(p+2);
    printf("x%d, y=%d\n", x,y);
    
    return 0;
}

답 : x=5 y=9

 

풀이 :

3행 3열의 2차원 배열을 선언하고 초기값을 대입 

data
(100)
data[0]
(100)
1
(100)
2
(101)
`3
(102)
data[1]
(103)
5
(103)
2
(104)
9
(105)
data[2]
(106)
6
(106)
8
(107)
7
(108)

포인터 변수 p에 data[1] 값을 대입 

data[1]은 행 대표 주소로 103번지를 가지고 있음 

x 변수에는 p가 현재 갖고 있는 103번지의 값을 대입해서 5가 대입됨 

y 변수에는 p+2, 105번지의 값을 대입해서 9가 대입 

 

 

13.

#include <stdio.h>
int main() {
	static char *c[] = {"aaa", "bbb", "ccc"};
    printf("%s", *(c+1));
    
    return 0;
}

답 : bbb

 

풀이 :

char형 배열 c를 만드는 데 해당 배열은 포인터 배열로 선언 

포인터 배열은 배열 요소가 값을 가지는 것이 아니라, 주소값을 가지는 것이 포인터 배열 

주소값 10  11 12
인덱스 [0] [1] [2]
100 200 300
100번지 a a a \0
200번지  b b b \0
300번지  c c c \0

배열 c의 0번 인덱스의 값은 100번지, 1번 인덱스의 값은 200번지, 2번 인덱스의 값은 300번지를 가리킴 

 

출력문에서는 문자열을 출력하고 있고, 문자열을 출력할 때는 시작 주소값부터 \0을 만날 때까지 출력

c+1에서는 c는 배열에서 첫 번째 요소의 주소값을 가지고 있기 때문에 10+1이 됨 

11번지의 값을 가지고 오게 되면 200이라는 주소값을 가지고 오게 되고, 200번지부터 \0을 만날때까지 출력을 하면 bbb가 출력됨 

 

 

14.

#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);
    
    return 0;
}

답 : 37

 

풀이 :

3개의 요소를 가진 arr을 선언하는데, arr 배열은 포인터 배열

a,b,c 변수를 선언하고, 각 12,24,36을 대입

arr 배열의 각 요소에 a,b,c의 각 주소값을 대입 

주소값  100 200 300
변수명  a b c
값  12 24 36
arr
(10)
주소값 10 11 12
인덱스 [0] [1] [2]
값  100  200 300

출력문에서 연산을 하나씩 보면,

*arr[1], arr[1]은 200주소값을 가지고 있고, 200번지의 값을 가져와서 24가 됨

**arr, arr은 10번지를 가리키고 있고, 10번지의 값은 100이고 100번지의 값은 12이다.

2차 포인터 같은 경우는 값의 값을 찾아가기 때문에 10번지의 값은 100, 100번지의 값은 12가 됨 

최종 출력은 24+12+1이 됨 

 

 

15.

#include <stdio.h>
#include <stdlib.h>
#define N 3

int main(void) {
	int (*in)[N], *out, sum=0;
    in = (int (*)[N])malloc(N*N*sizeof(int));
    out = (int*)in;
    for(int i=0; i <N*N; i++) out[i] =i;
    for(int i=0; i <N; i++)
    	sum += in[i][i];
    printf("%d", sum);
    return 0;
}

답 : 12

 

풀이 :

(*in)[3]의 형태는 배열 포인터의 형태 

배열 포인터의 경우는 뒤에 있는 숫자 3을 이용해 열을, 논리적으로 재구성하여 2차원 배열을 만들어줌 

 

배열 포인터 in을 선언하고, 포인터 변수 out을 선언 

sum 변수를 선언하고, 0을 초기값으로 대입 

in 배열 포인터에 동적으로 3*3*4를 이용해 9개의 int 형 배열을 선언 

이때, (int(*)[N])으로 3열의 배열로 구성하게 됨 

 

out에 in 배열 포인터를 담음 

반복을 돌면서 배열 포인터에 0~8까지 대입을 해줌

3행 3열의 배열이 만들어지고 in과 out은 같은 공간을 참조 

out
(100)
out[0]
(100)
0
(100)
1
(101)
2
(102)
out[1]
(103)
3
(103)
4
(104)
5
(105)
out[2]
(106)
6
(106)
7
(107)
8
(108)

두 번째 반복에서 i 값이 0부터 3보다 작을 때까지 반복을 수행 

i=0일 떄, in[0][0] 값을 sum에 누적산하여 sum에는 0이 대입

i=1일 떄, in[1][1] 값을 sum에 누적산하여 sum에는 4가 대입 

i=2일 떄, in[2][2] 값을 sum에 누적산하여 sum에는 12가 대입 

 

 

16.

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {
    int arr[2][3] = {1,2,3,4,5,6};
    int (*p)[2] = NULL;
    p = arr;
    printf("%d", *(p[0]+1) + *(p[1]+2));
    printf("%d", *(*(p+1)+0) + *(*(p+1)+1));
    
    return 0;
}

답 : 7, 7

 

풀이 :

2행 3열의 2차원 배열 arr을 선언하고, 초기값을 대입 

arr
(100)
arr[0]
(100)
1
(100)
2
(101)
3
(102)
arr[1]
(103)
4
(103)
5
(104)
6
(105)

배열 포인터 p를 선언하고, rr을 대입 

이때, 배열 포인터에서 [2] 값을 주었고, 논리적으로 2열로 다시 배치하라는 의미 

2열로 변경하면 논리적 구조가 변경됨

p
(100)
p[0]
(100)
1
(100)
2
(101)
p[1]
(102)
3
(102)
4
(103)
p[2]
(104)
5
(104)
6
(105)

첫 번째 출력문 , p[0]은 행 대표 주소로 100번지를 가짐 . 주소값 1을 더해서 101번지의 값 2를 취함 

p[1]은 행 대표 주소로, 102번지를 가지고, 주소값 2를 더해서 104번지의 값 5를 취함 

2와 5를 더해서 7이 출력됨 

 

두 번째 출력문, p+1에서 p는 첫 번째 행 대표 주소를 참조하기 때문에, 다음 행 대표 주솔르 가리키게 됨

그 다음 연산 p+1도 두 번째 행 대표 주소를 가리키고, 그 값인 102번지에 1을 더해 103번지의 값 4를 취함 

3과 4를 더해서 7이 출력됨 

 

 

17.

#include <stdio.h>

int main() {
   struct list {
    	int *fp;
    } data, *p;
    
    int x[] ={100,200,300,400};
    p = &data;
    p->fp = x + 1;
    printf("%d", *(++p->fp));
    
    return 0;
}

답 : 300

 

풀이 :

포인터형 변수 fp를 갖는 구조체 list를 선언하고, data , *p라는 객체를 생성 

x 배열을 선언하고 기본값을 대입 

구조체 p에 구조체 data의 주소값을 대입하여, p와 data가 같은 위치를 참조하게 만들어 줌 

x
(300)
주소값 300 301 302 303
인덱스 [0] [1] [2] [3]
값  100 200 300 400
주소값 100 100
변수명 data p

p가 가리키고 있는 공간의 fp 변수에 x+1하여 주소값 301을 대입 

출력문에서 ++p->fp는 p가 가리키고 있는 fp, 즉 301이라는 주소값에 1 증가시키라는 의미이고, 302번지가 됨 

302번지의 값을 출력하게 되면 300이 출력됨

 

 

18.

#include <stdio.h>

int star = 10; //전역 변수 
void printStar() {
	printf("%d\n", star);
}

int main() {
    int star = 5; // 지역 변수 
    printStar();
    printf("%d\n", star);
    
    return 0;
}

답 : 10

        5

 

풀이 :

젼역 변수 star를 선언하고 10을 대입 

main 함수에서 지역변수 star를 선언하고 5를 대입 

printStar() 함수를 호출 

printStar 함수에서 star를 출력하는데, 함수 내에서는 star 변수가 없기 때문에 , 전역변수로 선언된 star의 값 10을 출력

main 함수로 제어권이 넘어오고, star를 출력하게 되면 main 함수에서 선언된 star의 값 5가 출력

 

 

19.

#include <stdio.h>

int main(void) {
    int x=10, y=20;
    printf("%d", f(&x,y));
    printf("%d %d\n", x,y);
    return 0;
}

int f(int *i, int j) {
	*i+=5;
    return (2* *i+ ++j);
}

답: 51 15 20

 

풀이 :

정수형 변수 x와 y를 선언하고 각각 10,20을 대입 

첫 번째 출력, f 함수를 호출하는데, x 의 주소값과 y의 값을 가지고 호출 

주소값 100 200
변수명 x y
값  10 20

f 함수로 100번지와 20이라는 값이 전달 

f 함수에서는 i와 j 변수를 가지고 인자를 전달받음 

i는 100번지, j는 20이라는 값을 가짐 

 

*i+=5;sms *i=*i+5;이고, i 주소의 값에 5를 더하여 i 주소의 값을 변경하라는 의미 

i의 주소는 100번지이고, 100번지의 값을 변경

주소값 100 200
변수명 x y
값  15 20

2*  *i + ++j;를 수행하면 연산자 우선순위에 의해 ((2*15)+21)이 수행되어 51을 리턴 

첫 번째 출력은 리턴받은 51을 출력 

두 번째 출력은 현재 x값과 y값을 출력하는데 x값은 f 함수로 주소값이 전달되어 해당 주소의 값을 바꿨기 때문에 15를 출력하고, y는 값만 전달했기 때문에 20이 그대로 출력 

 

 

20.

#include <stdio.h>

int main() {
    int i;
    int x = 10;
    int *p;
    int a[100];
    for(i=0; i<100; i++)
    	a[i] = i*10;
    p = func(x,a);
    printf("sum=%d", x+a[0] + a[1] + p[0] + p[1]);
}

int *func(int a, int *x) {
    a= a+10;
    x= x+1;
    *x = *x*2;
    return x;
}

답 : sum = 70

 

풀이 : 

정수형 변수 i,x를 선언하고, x에 10을 대입 

포인터 변수 p 를 선언

정수형 배열 a를 선언하고, 100개의 요소를 할당. 각 요소에는 0부터 10씩 증가되며 값이 대입됨 

주소값 100 200
변수명 x p
값  10  
a
(300)
주소값 300 301 302 303 304 305 306 ...
인덱스  [0] [1] [2] [3] [4] [5] [6] ...
값  10  20 30 40 50 60 ...

func 함수를 호출하여 p 변수에 주소값을 리턴 받음 

func 함수는 a에는 10값과 x에 300번지를 인자로 받아 수행 

a에 10을 누적산하여 20을 대입, x에 1번지를 증가시켜 301번지로 변경

x의 값에 2를 곱하여 x의 값에 대입 

현재 x는 301번지이므로 301번지의 값이 10에서 20으로 변경됨 

301번지를 리턴하고, p는 301번지를 리턴값으로 받게 됨 

주소값 100 200
변수명 x p
값  10 301
a
(300)
주소값 300 301 302 303 304 305 306 ...
인덱스  [0] [1] [2] [3] [4] [5] [6] ...
값  20 20 30 40 50 60 ...

출력문을 순서대로 보면 x는 변경없이 10

a[0]은 0값을 가지고 있고 a[1]은 20 값을 가지고 있음 

p[0]은 p는 현재 301번지를 가리키고 있고, 배열과 똑같은 형태로 쓰일 때 301번지가 p[0]이 됨 

p[0]은 20값을 가짐 

p[1]은 302번지가 되고 20값을 가짐 

모두 더하게 되면 10 + 0 + 20 + 20 + 20 으로 70이 출력 

 

 

21.

#include <stdio.h>

void funCount();
int main(void) {
    int num;
    for(num=0; num <2; num++)
    	funCount();
    return 0;
}

void funCount() {
    int num = 0; //지역 변수 
    static int count; //정적 변수 
    printf("num=&d, count=%d\n", ++num, count++);
}

답: num =1, count =0

      num=1, count=1

 

풀이 :

main 함수에서 num 값을 0부터 2보다 작을 떄까지 반복하면서 funCount 함수를 호출

funCount에는 지역변수와 정적 변수 존재 

지역변수는 funCount 함수가 종료되면 메모리에서 사라지지만, 정적변수는 처음 한번 초기값을 설정한 후 , 프로그램이 끝날 때까지 메모리에 남아있게 됨 

 

num=0일 때, 지역 변수 num을 선증가하여 1출력, 정적 변수 count는 0출력 후 1증가, 

num=1일 떄, 지역 변수 num을 선증가하여 1출력, 정적 변수 count는 1출력후 1증가, 

지역 변수 num은 funCount 함수를 호출할 때, 생성이 되고, 함수가 끝나면 사라지기 때문에 계속 1만 출력하게 됨 

count는 정적 변수이기 떄문에 계속 메모리상에 남게 되어 , 누적산된 결과가 출력 

 

 

'자격증 > 정보처리기사' 카테고리의 다른 글

[java] 문제 풀이  (1) 2023.10.03
[소프트웨어 구축] 1. 소프트웨어 공학 개념  (0) 2023.09.27