31번
#include<stdio.h>
#include<string.h>
int main(int argc, char* argv[]) {
int n, i;
char p[] = "korea seoul";
n = strlen(p);
for (i = n - 1; i >= 0; i--)
printf("%c", p[i]);
printf("%d", n);
return 0;
}
문자열 출력과 그 문자열의 길이를 출력하는 코드
1) #include<string.h>
: strlen 함수 사용하기 위해 헤더 포함.
2) int n, j;
: 정수형 변수 n, j 선언.
3) char p[] = "korea seoul";
: 문자열 배열 p 선언하면서 초기화. 배열의 크기는 마지막에 널문자(\0)가 자동으로 포함되므로 11 + 1 = 12.
p | k | o | r | e | a | s | e | o | u | l | \0 | |
p[0] | p[1] | p[2] | p[3] | p[4] | p[5] | p[6] | p[[7] | p[8] | p[9] | p[10] | p[11] |
4) n = strlen(p);
: 문자열 p의 길이를 계산해서 n에 저장. 문자열 p는 공백 포함하여 11이므로 n = 11.
⊙ 배열 크기 : 12
⊙ 문자열 길이 : 11
5) for문
: for(i = 10; i >= 0; i--)은 문자열 p를 역순으로 출력하는 반복문. i는 10부터 시작하여 0보다 크거나 같을 때까지 하나씩 감소하며 실행.
6) printf("%c", p[i]);
: 마지막 문자부터 첫 번째 문자까지 역순으로 출력.
7) printf("%d", n);
: for문의 루프가 종료된 후 문자열 길이를 출력.
[출력]
luoes aerok11
32번
#include<stdio.h>
void main() {
int a[] = { 2, 4, 6, 8, 10 };
int b[] = { 1, 2, 3, 4, 5 };
int *ap = a, * bp = b + 2, c, d;
c = *(ap++);
d = *(++bp);
printf("%d, %d, %d, %d\n", *ap, c, *bp, d);
}
1) int a[] = { 2, 4, 6, 8, 10 }; int b[] = { 1, 2, 3, 4, 5 };
: 정수형 배열 a 선언하면서 초기화. 정수형 배열 b 선언하면서 초기화.
a는 100번지, b는 200번지로 시작한다고 가정하자.
a | 2 | 4 | 6 | 8 | 10 | |
100 | 100 | 101 | 102 | 103 | 104 |
b | 1 | 2 | 3 | 4 | 5 | |
200 | 200 | 201 | 202 | 203 | 204 |
2) int *ap = a;
: a는 현재 100번지를 가리키고 그것을 포인터변수 ap에 저장하하므로 ap는 100번지를 가리키고 있음.
3) int *bp = b + 2;
: b는 현재 200번지를 가리키고 있고, +2를 하면 202번지고 그것을 포인터변수 bp에 저장하므로 bp는 202번지를 가리키고 있음.
4) int c, d;
: 정수형 변수 c, d선언
5) c = *(ap++);
: *(ap++)는 괄호가 우선순위 높다고 안에 것을 먼저 계산하는 것이 아닌 *ap를 출력 후 ++ 연산을 해줘야 함. 즉 *ap는 현재 100번지를 가리키고 그 공간의 값은 2이므로 2를 변수 c에 저장하고 *ap는 ++ 연산을 하여 100번지가 아닌 101번지의 공간을 가리킴. (c = 2, ap는 101번지)
5) d = *(++bp);
: *(++bp)는 bp가 현재 202번지를 가리키므로 ++가 앞에 있으므로 먼저 ++를 해주면 203번지를 가리키고 그 공간의 값을 변수 d에 저장함. 따라서 변수 d는 203번지가 가리키는 값인 4를 저장. (d = 4, bp는 203번지)
6) printf("%d, %d, %d, %d\n", *ap, c, *bp, d);
: *ap, c, *bp, d 값을 정수로 출력하면 4, 2, 4, 4
[출력]
4, 2, 4, 4
여기서 잠깐
헷갈릴 수 있으니 한 번 정리하고 가기.
#include<stdio.h>
void main() {
int code[] = { 10, 20, 30, 40, 50, 60 };
int* p = &code;
printf("%d ", ++*p);
printf("%d ", ++(*p));
printf("%d ", (*p)++);
printf("%d\n", *p);
printf("%d ", *p++);
printf("%d ", *++p);
printf("%d\n", *p);
printf("%d ", *(p++));
printf("%d ", *(++p));
printf("%d\n", *p);
}
1) int code[] = { 10, 20, 30, 40, 50, 60 };
: 정수형 배열 code 선언 하면서 초기화. (code의 첫 번째 공간을 100번지로 가정.)
code | 10 | 20 | 30 | 40 | 50 | 60 | |
100 | 100 | 101 | 102 | 103 | 104 | 105 |
2) int *p = &code;
: 포인터 배열 p에는 code의 주소값인 100번지를 저장.
3) 출력
① ++*p : p는 100번지를 저장하고 있으므로 그 주소값의 값인 10에 ++연산(1 + 10) 하면 11을 출력. (*p + 1이랑 같은 의미)
100번지에는 10이 아닌 11로 변경.
② ++(*p) : 위와 같은 의미. 따라서 현재 100번지는 11을 가지고 있으므로 ++연산(1 + 11)을 하면 12를 출력.
현재 100번지는 11이 아닌 12로 변경.
③ (*p)++ : 잘 알아둬야 함! p의 주소값 100번지의 12를 출력 후 ++ 연산(12 + 1)하면 100번지 공간은 13으로 변경.
☞ 해당하는 값이 변경!
④ *p : 현재 p의 주소값은 100번지로, 100번지의 값은 13을 출력.
4) 출력
① *p++ : 잘 알아둬야 함! p의 주소값 100번지의 13을 출력 후 ++ 연산을 함.
이 때 그 공간의 값이 아닌 p가 가지고 있는 주소값이 ++ 연산 되는 것. 따라서 100번지에서 101번지로 변경. (p는 101번지)
☞ 해당하는 주소값(공간)이 변경!
② *++p : p의 주소값에서 ++연산 후 그 값을 구하는 것.
p는 101번지를 저장하고 있으므로 ++연산하면 102번지로 변경하고 그 값인 30을 출력. (p는 102번지)
③ *p : 현재 p의 주소값의 값을 출력. 현재 102번지로, 102번지의 값은 30을 출력. (p는 102번지)
5) 출력
① *(p++) : p의 주소값을 ++하기 전 그 값을 구 한 후, p의 주소값을 ++연산.
현재 p는 102번지로, 102번지의 값 30을 출력 후 p의 주소값은 ++연산하면 103번지. (p는 103번지)
② *(++p) : p의 주소값을 ++연산 후 그 주소값의 값을 구함.
현재 p는 103번지를 가지고 있고 ++연산하면 104번지의 주소값을 가지고 있음. 그 주소값의 값은 50을 출력. (p는 104번지)
③ *p : 현재 p의 주소값의 값을 출력. 현재 104번지로, 104번지의 값은 50을 출력. (p는 104번지)
[출력값]
11 12 12 13
13 30 30
30 50 50
33번
#include<stdio.h>
void main() {
char a[30] = { "ENG\0INE\0AC" };
char (*p)[5];
p = a;
printf("%s, ", p);
printf("%s ", ++p);
printf("%s", ++p);
}
1) char a[30] = { "ENG\0INE\0AC" };
: 길이 30인 문자열 배열 a 선언하면서 초기화. 여기서 문자열들은 NULL(\0) 문자를 만나면 해당 문자열이 종료.
a의 시작 주소를 100번지로 가정.
2) char (*p)[5];
: 문자열 배열 가리키는 포인터 p를 선언. p는 길이가 5인 문자열을 가리킴.
P | E | N | G | \0 | I |
N | E | \0 | A | C |
3) p = a;
: 포인터 p는 문자열 배열 a의 시작 주소로 초기화.
⊙ p : 100번지
⊙ p[0] = "ENG\0I" → 100번지
⊙ p[1] = "NE\0AC" →101번지
4) 출력
① printf("%s, ", p);
: p가 현재 100번지고 문자열은 NULL을 만나면 종료되기 때문에 100번지인 ENG\0I에서 NULL 문자 전인 ENG만 출력. (p는 100번지)
② printf("%s ", ++p);
: ++p를 사용하여 현재 p의 주소값 100번지를 101번지로 증가시켜 해당 문자열을 출력. NULL 문자 전인 NE 출력. (p는 101번지)
③ printf("%s", ++p);
: ++p를 사용하여 현재 p의 주소값 101번지를 102번지로 증가하고 해당 문자열을 출력. (p는 102번지)
하지만 p가 가리키는 주소값의 문자열은 없으므로 아무것도 출력하지 않음.
[출력]
ENG, NE
34번
#include<stdio.h>
void main() {
char *p[3] = { "ENG", "INER", "AC" };
printf("%c, %c, %c\n", *p[0], *p[1], *p[2]);
printf("%s, %s, %s\n", p[0] + 1, p[1] + 1, p[2] + 1);
}
1) char *p[3] = { "ENG", "INER", "AC" };
: 세 개의 문자열 가리키는 포인터 배열 선언하면서 초기화.
⊙ p[0] = "ENG"
⊙ p[1] = "INER"
⊙ p[2] = "AC"
p[0] | E | N | G | ||
p | p[1] | I | N | E | R |
100 | p[2] | A | C |
2) printf("%c, %c, %c\n", *p[0], *p[1], *p[2]);
① *p[0] : "ENG" 문자열의 첫 번째 문자를 가리키므로 'E' 출력.
= *(p + 0) = *(*(p + 0) + 0) = p[0][0] // 0행 0열 가리킴
② *p[1] : "INER" 문자열의 첫 번째 문자를 가리키므로 'I' 출력.
=*(p + 1) = *(*(p + 1) + 0) = p[1][0] // 1행 0열 가리킴
③ *p[2] : "AC" 문자열의 첫 번째 문자를 가리키므로 'A' 출력.
=*(p + 2) = *(*(p + 1) + 0) = p[2][0] // 2행 0열 가리킴
3) printf("%s, %s, %s\n", p[0] + 1, p[1] + 1, p[2] + 1);
① p[0] + 1 : "ENG" 문자열의 두 번째 문자부터 끝까지 출력. (\0을 만나기 전까지 출력.) 따라서 "NG" 출력.
② p[1] + 1 : "INER" 문자열의 두 번째 문자부터 끝까지 출력. (\0을 만나기 전까지 출력.) 따라서 "NER" 출력.
③ p[2] + 1 : "AC" 문자열의 두 번째 문자부터 끝까지 출력. (\0을 만나기 전까지 출력.) 따라서 "C" 출력.
⊙ %c는 "character"를 나타냄. 하나의 문자를 출력하는데 사용. 따라서 문자 값 자체를 출력.
⊙ %s는 "String"을 나타냄. 문자열을 출력하는데 사용. 따라서 문자열의 시작주소부터 NULL 문자를 만나기 전까지 출력.
[출력]
E, I, A
NG, NER, C
35번
#include<stdio.h>
int main(int argc, char* argv[]) {
int i, a[5] = { 10, 25, 30, 40, 80 };
void *p = a + 2;
*(int *)p += 12;
*((int *)p + 2) += 2;
for (i = 0; i < 5; i++)
printf("%d ", a[i]);
}
1) int i, a[5] = { 10, 25, 30, 40, 80 };
: 정수형 변수 i 선언. 길이가 5인 정수형 배열 a 선언하면서 초기화.
a | 10 | 25 | 30 | 40 | 80 | |
100 | 100 | 101 | 102 | 103 | 104 |
2) void *p = a + 2;
: 포인터 변수 p는 배열의 세 번째 요소인 a[2]의 주소를 가리킴. 즉 a는 현재 100번지로 100 + 2 = 102번지를 가리킴.
3) *(int *)p += 12;
: p를 int 포인터로 캐스팅하고 해당 위치의 값을 12 증가시킴. *p는 a[2]의 값이므로 30 + 12 = 42의 값으로 변경됨.
4) *((int *)p + 2) += 2;
: p + 2를 int 포인터로 캐스팅하고 해당 위치의 값을 2 증가시킴. p + 2는 p는 현재 a[2]이고, +2하면 a[4]를 가리킴. 따라서 a[4]의 값인 80을 +2하면 82의 값으로 변경됨.
5) for문
: 배열 a의 각 요소를 출력함.
a | 10 | 25 | 42 | 40 | 82 | |
100 | 100 | 101 | 102 | 103 | 104 |
[출력]
10 25 42 40 82
36번
#include<stdio.h>
void main() {
int a[2][3] = { {-3, 14, 5}, {1, -10, 8} };
int *b[] = { a[0], a[1] };
int *p = b[1];
printf("%d, ", *b[1]);
printf("%d, ", *(--p - 2));
printf("%d\n", *(*(a + 1) + 1));
}
1) int a[2][3] = { {-3, 14, 5}, {1, -10, 8} };
: 2차원 정수 배열 a 선언하면서 초기화. 첫 번째 시작 위치를 100번지로 가정.
⊙ a : 100번지 → a는 100번지인 -3을 가리키는 것이 아닌 a[0]인 100번지를 가리키는 것
⊙ a[0] : 100번지(-3, 14, 5) → -3 : 100번지 / 14 : 101번지 / 5 : 102번지
⊙ a[1] : 103번지(1, -10, 8) → 1 : 103번지 / -10 : 104번지 / 8 : 105번지
a | a[0] (100) |
-3 (100) |
14 (101) |
5 (102) |
100 | a[1] (103) |
1 (103) |
-10 (104) |
8 (105) |
2) int* b[] = { a[0], a[1] };
: 포인터 배열 b 선언하면서 배열 a의 각 행의 시작 주소를 가리키도록 초기화.
⊙ b[0] = a[0] = {-3, 14, 5}
⊙ b[1] = a[1] = {1, -10, 8}
3) int *p = b[1];
: 포인터 p는 b[1]을 가리키므로 p는 a[1]을 가리킴. 즉 p는 {-1, 10, 8}을 가리킴.
4) 출력
① printf("%d, ", *b[1]);
: b[1]은 a[1]을 가리키므로 {1, -10, 8}의 첫 번째 요소 a[1][0]인 1을 출력. 따라서 *b[1] = 1.
(b[1]은 a[1]를 가리키고 a[1]은 103번지를 나타내므로 103번지의 값인 1을 출력)
② printf("%d, ", *(--p - 2));
: p는 현재 b[1]인 a[1]을 가리키고 a[1]은 103번지를 가리킴. -- 연산하면 102번지 가리키고 -2를 하면 100번지를 가리킴. 따라서 100번지의 값인 -3을 출력.
p는 b[1] 즉 a[1]을 가리키고 있었으므로, -- 연산하면 p는 b[0] 즉 a[0]을 가리킴. 왼쪽으로 -2 하면 -3을 출력 : a[0][0]의 값
③ printf("%d\n", *(*(a + 1) + 1));
: 현재 a는 100번지를 가리키지만 100번지인 -3을 가리키는 것이 아닌 행 대표 주소 a[0]을 가리키고 +1을 하면 a[0]이 아닌 a[1]을 가리킴.
*(a + 1)은 a[1]의 공간의 값으로 해석되고 103번지를 의미함.
*(103번지 + 1)은 *(104번지) 계산되고, 104번지의 값은 -10이므로 -10을 출력.
③ *(*(a + 1) + 1)
1) *(*(a + 1) + 1) : a는 현재 a[0]의 100번지를 가리킴. 따라서 +1을 하면 a는 a[0], a[1]의 행을 가지고 있으므로 a[0] 다음인 a[1]을 의미.
2) *(*(a + 1) + 1) : a + 1은 a[1]을 의미하고 앞에 *을 붙이면 a[1]의 값을 의미하므로 a[1]은 103번지를 가리키므로 103번지를 의미.
3) *(*(a + 1) + 1) : 103번지 + 1 = 104번지를 의미.
4) *(*(a + 1) + 1) : 104번지 앞에 *을 붙이면 104번지의 값을 의미하므로 -10을 출력.
[출력]
1, -3, -10
37번
#include<stdio.h>
int main()
{
int a[2][3][5] = {
{
{1, 2, 3, 4, 5},
{6, 7, 8, 9, 10},
{11, 12, 13, 14, 15}
},
{
{ 16, 17, 18, 19, 20 },
{21, 22, 23, 24, 25},
{26, 27, 28, 29, 30}
} };
printf("%d\n", *(*(*(a + 1) + 2) + 3) + *(**a + 2) + *(**(a + 1) + 2));
return 0;
}
1) 3차원 배열
: 3차원 정수 배열 a 선언 하면서 초기화. a의 첫 번째 주소를 100번지로 가정. (면, 행, 열)
a (100) |
a[0] (100) |
a[0][0] (100) |
1 (100) |
2 (101) |
3 (102) |
4 (103) |
5 (104) |
a[0][1] (105) |
6 (105) |
7 (106) |
8 (107) |
9 (108) |
10 (109) |
||
a[0][2] (110) |
11 (110) |
12 (111) |
13 (112) |
14 (113) |
15 (114) |
||
a[1] (115) |
a[1][0] (115) |
16 (115) |
17 (116) |
18 (117) |
19 (118) |
20 (119) |
|
a[1][1] (120) |
21 (120) |
22 (121) |
23 (122) |
24 (123) |
25 (124) |
||
a[1][2] (125) |
26 (125) |
27 (126) |
28 (127) |
29 (128) |
30 (129) |
2) printf("%d\n", *(*(*(a + 1) + 2) + 3) + *(**a + 2) + *(**(a + 1) + 2));
① *(*(*(a + 1) + 2) + 3)
ⅰ. (a + 1) : a는 a[0]을 가리키고 있으며 a + 1은 a[1]을 의미. (a[0], a[1]의 면으로 이루어져 있으므로)
ⅱ. *(a + 1) : a[1]의 값은 a[1][0]을 의미. (a[1]은 a[1][0]의 대표주소이므로)
ⅲ. *(a + 1) + 2 : a[1][0]에서 +2를 하면 a[1][2]를 의미. (a[1][0], a[1][1], a[1][2]의 행으로 이루어져 있으므로)
ⅳ. *( *(a + 1) + 2) : a[1][2]의 값은 125번지를 가리킴.
ⅴ. *(*(a + 1) + 2) + 3 : 125번지 + 3 = 128번지를 의미.
ⅵ. *(*(*(a + 1) + 2) + 3) : 128번지의 값은 29를 의미하므로 29를 출력.
② *(**a + 2)
ⅰ. **a : a가 가리키는 100번지 공간은 a[0](a의 값)을 가리키고 a[0]이 가리키는 100번지 공간은 a[0][0](a의 값의 값)을 가리킴.
따라서 a의 값의 값은 a[0][0]인 100번지를 의미.
ⅱ. **a + 2 : a[0][0]은 100번지를 의미하고 +2를 하면 102번지를 의미.
ⅲ. *(**a + 2) : 102번지의 값은 3을 의미하므로 3을 출력.
③ *(**(a + 1) + 2)
ⅰ. a + 1 : a는 a[0]을 가리키고 +1을 하면 a[1]을 의미.
ⅱ. **(a + 1) : a+1의 값의 값은 a[1]인 115번지의 값은 a[1][0]인 115번지를 의미.
ⅲ. **(a + 1) + 2 : 115번지 + 2를 하면 117번지를 의미.
ⅳ. *(**(a + 1) + 2) : 117번지의 값은 18을 의미하므로 18을 출력.
따라서 29 + 3 + 18 = 50을 출력하게 됨. 헷갈리면 표를 그려서 100번지 시작을 가정하여 면, 행 대표주소를 작성하며 생각해보자.
[출력]
50
38번
#include<stdio.h>
int main(int argc, char* argv[]) {
int i = 10, *ip = &i;
char c = 'D', *cp = &c;
*ip++ = ++i;
++*--ip;
++*cp++;
*--cp = c + 3;
printf("i= %d, c = %c\n", i, c);
return 0;
}
1) int i = 10, *ip = &i;
: 정수형 변수 i를 선언하면서 10으로 초기화하고, ip는 i의 주소값을 가리키는 포인터 변수.
2) char c = 'D', * cp = &c;
: 문자 변수 c를 선언하면서 'D'로 초기화하고, cp는 c의 주소값을 가리키는 포인터 변수.
3) 연산
① *ip++ = ++i;
ⅰ.++i : 계산하면 i는 ++ 연산하여 10에서 11로 증가. (i = 11)
ⅱ. *ip++는 ip가 가리키는 위치(i)에 ++i 값을 할당한 후, ip는 후위 증감 연산으로 ip + 1이 되어 다른 주소값을 가리킴.
ⅲ. 따라서 i의 값은 11이고, ip는 i가 아닌 다른 주소값을 가리킴.
② ++*--ip;
ⅰ. --ip : 계산하면 ip는 -- 연산하여 다시 i의 주소값을 가리킴.
ⅱ. *--ip : i의 주소값의 값을 의미하므로 11을 의미.
ⅲ. ++*--ip : 11은 ++연산하여 12를 의미. 따라서 i = 12
③ ++*cp++;
ⅰ. cp++ : cp가 가리키는 곳을 참조(c = 'D')하고, 이후 cp는 다음 주소값을 가리킴.
ⅱ. ++*cp : cp가 가리키는 c값을 ++연산 하면 c = 'E'로 변경.
④ *--cp = c + 3;
ⅰ. --cp : 계산하면 cp는 -- 연산하여 다시 c의 주소값을 가리킴.
ⅱ. *--cp : c의 주소값의 값을 의미하므로 'E'를 의미.
ⅲ. c + 3 : 현재 c는 E를 의미하므로 +3을 하면 E, F, G, H 즉 'H'로 변경
따라서 i = 12, c = 'H'를 출력하게 됨.
[출력]
i= 12, c = H
! 강의 보며 혼자 공부한 것으로,
틀린 거 있을 시 댓글로 가르쳐 주시면 감사하겠습니다!
'Studying > 정보처리기사' 카테고리의 다른 글
[정보처리기사 실기]_JAVA언어 특강(6) (3) | 2024.10.02 |
---|---|
[정보처리기사 실기]_JAVA언어 특강(5) (0) | 2024.10.02 |
[정보처리기사 실기]_C언어 특강(3) (4) | 2024.09.30 |
[정보처리기사 실기]_C언어 특강(2) (2) | 2024.09.28 |
[정보처리기사 실기]_C언어 특강(1) (3) | 2024.09.28 |