PythonCodeFight-Day10

Day_10

Intro

Q16. Are Similar?

Two arrays are called similar if one can be obtained from another by swapping at most one pair of elements in one of the arrays.

Given two arrays a and b, check whether they are similar.
제출 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
def areSimilar(a, b):
if a == b: # 둘이 같으면 참
return True
else: # 다를 때
# 정렬한 값이 같은 경우, 스왑해야하는 갯수를 체크하면 된다
c = sorted(a)
d = sorted(b)
diffCount = 0
# 정렬한 값이 같은 경우
if c == d:
for i in range(len(c)):
if a[i] != b[i]:
diffCount += 1

if diffCount > 2:
return False
return True
# 정렬한 값이 다른 경우
else:
return False

작성 흐름 (제출 코드에도 같은 주석)

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
# 테스트 케이스
a = [1,2,3]
b = [2,1,3]

if a == b: # 둘이 같으면 참
print("True")
else: # 다를 때
# 정렬한 값이 같은 경우, 스왑해야하는 갯수를 체크하면 된다
c = sorted(a)
d = sorted(b)
diffCount = 0
# 정렬한 값이 같은 경우
if c == d:
# 전체 길이만큼 보면서
for i in range(len(c)):
# 원래 값에서 차이가 있는 갯수를 센다
if a[i] != b[i]:
diffCount += 1

# 차이 값이 2개인 경우 한 번 스왑을 해서 해결할 수 있지만, 그 이상인 경우 한 번으로 해결 불가능
if diffCount > 2:
print("False")
break
print("True")
# 정렬한 값이 다른 경우
else:
print("False")

PythonCodeFight-Day9

Day_9

Intro

Q14. alternatingSums

Several people are standing in a row and need to be divided into two teams. The first person goes into team 1, the second goes into team 2, the third goes into team 1 again, the fourth into team 2, and so on.

You are given an array of positive integers - the weights of the people. Return an array of two integers, where the first element is the total weight of team 1, and the second element is the total weight of team 2 after the division is complete.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def alternatingSums(a):
team1 = 0
team2 = 0
for i in range(len(a)):
if i % 2 == 0: # 2로 나눈 나머지가 0인 경우
team1 += a[i]
else: # 2로 나눈 나머지가 1인 경우
team2 += a[i]

Sums = list()
Sums.append(team1)
Sums.append(team2)

return Sums

처음에 리스트로 만들어서 합산을 하려고 했는데, 굳이 리스트 없이 홀수끼리의 합과 짝수끼리의 합을 구해서 배열에 넣고 리턴하면 되는 것이었다. 복잡하게 생각할 필요 없었던 문제

Q15. Add Border

Given a rectangular matrix of characters, add a border of asterisks(*) to it.

1
2
3
4
5
6
7
8
9
10
11
def addBorder(picture):

border = "*"*(len(picture[0])+2)

for i in range(len(picture)):
picture[i] = "*"+picture[i]+"*"

picture.insert(0,border)
picture.append(border)

return picture

작성 흐름

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 테스트 케이스
picture = ["abc",
"ded"]

# 테스트 케이스 출력해보기
print(picture)
# 첫 단어의 사이즈 확인해보기
print(picture[0])
# string 자료형의 경우 문자열을 더하여 문자열을 늘릴 수 있음
print("*" + picture[0] + "*")

# 위 아래 테두리 형태 만들기
border = "*"*(len(picture[0])+2)

# 기존 단어에 테두리 추가하기
for i in range(len(picture)):
picture[i] = "*"+picture[i]+"*"

# 테두리가 추가된 입력에 위아래 테두리 추가하기
picture.insert(0,border)
picture.append(border)

# 출력해서 확인
print(picture)

PythonCodeFight-Day8

Day_8

Intro

Q13. reverseInParentheses

Write a function that reverses characters in (possibly nested) parentheses in the input string.

Input strings will always be well-formed with matching ()s.

1
2
3
4
5
6
7
8
9
10
def reverseInParentheses(inputString):
#[출처] [python] codeSignal 문제풀이 (13~15)|작성자 Jun
s = inputString

while '(' in s : #괄호가 다 없어질때까지 반복
fb = s.rfind('(') # rfind : 뒤에서부터 문자열 탐색
bb = s[fb:].find(')') #find : 앞에서부터 문자열 탐색
s = s[:fb] + s[fb+1:fb+bb][::-1] + s[fb+bb+1:] #부분적으로 슬라이스 가능

return s

문제를 못 풀겠어서 코드파이트 같이하는 오픈카톡방 방장님의 코드를 이용했음
처음에는 스택을 이용해서 접근하면 어떨까 고민하고 머리를 굴려봤는데, 괄호 안에 괄호가 반복되는 경우를 어떻게 처리해야할지 감이 하나도 오질 않았다. 그렇다고 다른 방법이 떠오르지 않아서 작성해두신 답을 그대로 이용했다.

이용한 답을 보니 while 뒤에 ‘(‘ in s 와 같은 문법을 이용할 수 있다는 것을 알게 되었다.

PythonCodeFight-Day7

Day_7

Intro.

Q12. Sort by Height

Some people are standing in a row in a park. There are trees between them which cannot be moved. Your task is to rearrange the people by their heights in a non-descending order without moving the trees. People can be very tall!

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
def sortByHeight(a):
IdxSet_minus1 = []

sort_a = []
cnt_minus1 = 0
cnt_sort = 0

for i in range(len(a)):
if a[i] == -1:
IdxSet_minus1.append(i)

b = sorted(a)
for i in range(len(IdxSet_minus1)):
b.pop(0)

for i in range(len(a)):
if cnt_minus1 < len(IdxSet_minus1):
if i == IdxSet_minus1[cnt_minus1]:
sort_a.append(-1)
cnt_minus1 += 1
else:
sort_a.append(b[cnt_sort])
cnt_sort += 1
else:
sort_a.append(b[cnt_sort])
cnt_sort += 1

return sort_a

고민 흐름

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
31
32
33
34
35
36
37
38
39
40
41
# 테스트 케이스
a = [-1, 150, 190, 170, -1, -1, 160, 180]

# -1인 인덱스를 저장할 공간
IdxSet_minus1 = []

# 새롭게 정렬한 값을 넣어줄 공간
sort_a = []

# 두 가지의 행렬을 비교해서 값을 넣을 것이기 때문에, 각 값의 인덱스
cnt_minus1 = 0
cnt_sort = 0

# '-1' 이 들어있는 위치의 인덱스를 모으기
for i in range(len(a)):
if a[i] == -1:
IdxSet_minus1.append(i)

# 주어진 케이스를 오름차순으로 정렬
b = sorted(a)

# 정렬한 케이스에서 -1 값 빼내기
for i in range(len(IdxSet_minus1)):
b.pop(0)

# 배열의 전체 길이만큼 반복
for i in range(len(a)):
# 만약, 넣어야하는 -1 이 남아있는 경우
if cnt_minus1 < len(IdxSet_minus1):
# 찾아둔 -1 의 인덱스 값인 경우
if i == IdxSet_minus1[cnt_minus1]:
sort_a.append(-1)
cnt_minus1 += 1
# 찾아둔 -1 의 인덱스 값이 아닌 경우
else:
sort_a.append(b[cnt_sort])
cnt_sort += 1
# -1 이 더이상 없는 경우
else:
sort_a.append(b[cnt_sort])
cnt_sort += 1

PythonCodeFight-Day6

Day_6

Intro.

Q11. isLucky

Ticket numbers usually consist of an even number of digits. A ticket number is considered lucky if the sum of the first half of the digits is equal to the sum of the second half.

Given a ticket number n, determine if it’s lucky or not.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
def isLucky(n):
n_str = str(n)

n_list = list(n_str)

sumFront = 0
sumSecond = 0

for i in range(len(n_list)):
if i < len(n_list)/2:
sumFront += int(n_list[i])
print(int(n_list[i]))
else:
sumSecond += int(n_list[i])
print(int(n_list[i]))

if sumFront == sumSecond:
return True
else:
return False

고민 흐름

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
# 테스트 케이스를 바꿔가면서 확인
n = 234036

# 붙어있는 숫자를 앞과 뒤로 분리해야하기 때문에, 쪼개는 방법을 생각하던 중 입력으로 받은 수를 string으로 변환
n_str = str(n)

# string으로 변환한 입력을 list로 바꾸면 list로 다룰 수 있게 됨
n_list = list(n_str)

# 앞의 합과 뒤의 합
sumFront = 0
sumSecond = 0

# 전체 리스트의 값을 순회하기
for i in range(len(n_list)):
# 앞의 반일 경우
if i < len(n_list)/2:
sumFront += int(n_list[i])
print(int(n_list[i]))
# 뒤의 반일 경우
else:
sumSecond += int(n_list[i])
print(int(n_list[i]))

# 값 비교
if sumFront == sumSecond:
return True
else:
return False

PythonCodeFight-Day5

Day_5

Q10. commonCharacterCount

Given two strings, find the number of common characters between them.

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
def commonCharacterCount(s1, s2):
s3 = list(s1)
s4 = list(s2)

save = list()

if len(s3) >= len(s4):
for i in range(len(s4)):
Character = s4[i]
try:
Idx = s3.index(Character)
except:
pass
else:
save.append(s3.pop(Idx))
else:
for i in range(len(s3)):
Character = s3[i]
try:
Idx = s4.index(Character)
except:
pass
else:
save.append(s4.pop(Idx))

return len(save)

작성 흐름

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
31
32
33
34
35
36
37
# def commonCharacterCount(s1, s2):

# 테스트를 위한 문자열
s1 = "aabcc"
s2 = "adcaa"

# 뒤에서 인덱스 찾고 pop 할 때 str형은 pop을 할 수 없어서 list 처리를 해주는 부분
s3 = list(s1)
s4 = list(s2)

save = list()

# 알고리즘
# 두 입력 중 길이가 짧은 녀석을 먼저 찾는다.
# 짧은 녀석의 길이로 반복을 한다
# 짧은 녀석의 첫 값을 확인한다.
# 긴 녀석에서 해당 값을 찾아서 pop 하고, 이를 다른 리스트에 저장한다.
if len(s1) >= len(s2):
for i in range(len(s2)):
Character = s2[i]
try:
Idx = s3.index(Character)
except:
pass
else:
save.append(s3.pop(Idx))
else:
for i in range(len(s1)):
Character = s1[i]
try:
Idx = s4.index(Character)
except:
pass
else:
save.append(s4.pop(Idx))

print(len(save))

[15] 정렬 (sort)

C언어 정렬 정리

참고 문헌 (Ch 73) : https://dojang.io/mod/page/view.php?id=637

거품 정렬 구현하기

가장 기본적인 정렬 방법으로 처음부터 끝까지 값을 비교하면서 하나하나 바꾸는 정렬 방법

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
31
32
33
34
35
#include <stdio.h>

void bubble_sort(int arr[], int count) // 매개변수로 정렬할 배열과 요소의 개수를 받음
{
int temp;

for (int i = 0; i < count; i++) // 요소의 개수만큼 반복
{
for (int j = 0; j < count - 1; j++) // 요소의 개수 - 1만큼 반복
{
if (arr[j] > arr[j + 1]) // 현재 요소의 값과 다음 요소의 값을 비교하여
{ // 큰 값을
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp; // 다음 요소로 보냄
}
}
}
}

int main()
{
int numArr[10] = { 8, 4, 2, 5, 3, 7, 10, 1, 6, 9 }; // 정렬되지 않은 배열

bubble_sort(numArr, sizeof(numArr) / sizeof(int)); // 거품 정렬 함수 호출

for (int i = 0; i < 10; i++)
{
printf("%d ", numArr[i]); // 1 2 3 4 5 6 7 8 9 10
}

printf("\n");

return 0;
}

퀵 정렬 함수 사용하기

퀵 정렬 함수는 C언어에서 제공해준다. 정렬할 배열이나 메모리 주소, 요소 개수, 요소 크기, 비교 함수를 넣어서 진행한다.

  • qsort(정렬할 배열, 요소 개수, 요소 크기, 비교 함수);
  • qsort(정렬할 메모리 주소, 요소 개수, 요소 크기, 비교 함수);

비교 함수란 각 요소를 어떻게 비교할 것인지 알려주는 함수를 의미한다. 이는 직접 구현해서 넣어주어야 한다.

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
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <stdio.h>
#include <stdlib.h> // qsort 함수가 선언된 헤더 파일

int compare(const void *a, const void *b) // 오름차순 비교 함수 구현
{
int num1 = *(int *)a; // void 포인터를 int 포인터로 변환한 뒤 역참조하여 값을 가져옴
int num2 = *(int *)b; // void 포인터를 int 포인터로 변환한 뒤 역참조하여 값을 가져옴

// 오름차순 정렬 조건
if (num1 < num2) // a가 b보다 작을 때는
return -1; // -1 반환

if (num1 > num2) // a가 b보다 클 때는
return 1; // 1 반환

return 0; // a와 b가 같을 때는 0 반환

// // 내림차순 정렬 조건
// if (num1 < num2) // a가 b보다 작을 때는
// return 1; // 1 반환

// if (num1 > num2) // a가 b보다 클 때는
// return -1; // -1 반환

// return 0; // a와 b가 같을 때는 0 반환
}

int main()
{
int numArr[10] = { 8, 4, 2, 5, 3, 7, 10, 1, 6, 9 }; // 정렬되지 않은 배열

// 정렬할 배열, 요소 개수, 요소 크기, 비교 함수를 넣어줌
qsort(numArr, sizeof(numArr) / sizeof(int), sizeof(int), compare);

for (int i = 0; i < 10; i++)
{
printf("%d ", numArr[i]); // 1 2 3 4 5 6 7 8 9 10
}

printf("\n");

return 0;
}

[14] 구조체를 입력으로 이용하는 함수 (function using struct as input)

C언어 함수 정리

참고 문헌 (Ch 65) : https://dojang.io/mod/page/view.php?id=570

함수에서 구조체 매개변수 사용하기

구조체 매개변수 사용하기

함수에서 구조체를 매개변수로 사용하기 위해서는 struct 키워드와 구조체 이름으로 매개변수를 지정한다.

1
2
3
반환값자료형 함수이름(struct 구조체이름 매개변수)
{
}

예시

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
#include <stdio.h>
#include <string.h> // strcpy 함수가 선언된 헤더 파일

struct Person {
char name[20];
int age;
char address[100];
};

void printPerson(struct Person p) // 반환값 없음, 구조체 매개변수 한 개 지정
{
// 구조체 매개변수 멤버의 값 출력
printf("이름: %s\n", p.name); // 이름: 홍길동
printf("나이: %d\n", p.age); // 나이: 30
printf("주소: %s\n", p.address); // 주소: 서울시 용산구 한남동
}

int main()
{
struct Person p1;

strcpy(p1.name, "홍길동");
p1.age = 30;
strcpy(p1.address, "서울시 용산구 한남동");

printPerson(p1); // 함수를 호출할 때 구조체 변수 전달, 멤버가 복사됨

return 0;
}

이 역시 구조체 변수의 모든 멤버가 매개변수로 복사되기 때문에, 구조체의 크기가 커질수록 비효율적인 방법이 된다. 따라서 포인터로 전달해주는게 메모리 관리 차원에서 더욱 효과적이다.
또한 이런 경우, 함수 내에서 구조체의 값을 변경하더라도 바깥의 구조체에는 영향을 끼치지 않는다.

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
31
32
33
34
#include <stdio.h>
#include <string.h> // strcpy 함수가 선언된 헤더 파일

struct Person {
char name[20];
int age;
char address[100];
};

void setPerson(struct Person p) // 반환값 없음, 구조체 매개변수 한 개 지정
{
// 매개변수로 받은 구조체 멤버의 값 변경
strcpy(p.name, "고길동");
p.age = 40;
strcpy(p.address, "서울시 서초구 반포동");
}

int main()
{
struct Person p1;

strcpy(p1.name, "홍길동");
p1.age = 30;
strcpy(p1.address, "서울시 용산구 한남동");

setPerson(p1); // 함수를 호출할 때 구조체 변수 전달, 멤버가 복사됨

// setPerson에서 변경한 값은 영향을 미치지 않음
printf("이름: %s\n", p1.name); // 이름: 홍길동
printf("나이: %d\n", p1.age); // 나이: 30
printf("주소: %s\n", p1.address); // 주소: 서울시 용산구 한남동

return 0;
}

구조체 포인터 매개변수 사용하기

괄호 안에서 구조체 이름 뒤에 *를 붙여서 포인터 형태의 매개변수로 이용한다.

1
2
3
반환값자료형 함수이름(struct 구조체이름 *매개변수)
{
}

예시

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
31
32
33
34
#include <stdio.h>
#include <string.h> // strcpy 함수가 선언된 헤더 파일

struct Person {
char name[20];
int age;
char address[100];
};

void setPerson(struct Person *p) // 반환값 없음, 구조체 포인터 매개변수 한 개 지정
{
// 매개변수로 받은 포인터에서 구조체 멤버의 값 변경
strcpy(p->name, "고길동");
p->age = 40;
strcpy(p->address, "서울시 서초구 반포동");
}

int main()
{
struct Person p1;

strcpy(p1.name, "홍길동");
p1.age = 30;
strcpy(p1.address, "서울시 용산구 한남동");

setPerson(&p1); // 함수를 호출할 때 구조체 변수의 메모리 주소를 전달

// setPerson에서 변경한 값이 출력됨
printf("이름: %s\n", p1.name); // 이름: 고길동
printf("나이: %d\n", p1.age); // 나이: 40
printf("주소: %s\n", p1.address); // 주소: 서울시 서초구 반포동

return 0;
}

[13] 배열을 입력으로 이용하는 함수 (function using array as input)

C언어 함수 정리

참고 문헌 (Ch 64): https://dojang.io/mod/page/view.php?id=562

배열 매개변수 사용하기

함수의 입력(매개변수)으로 배열을 사용하기 위해서는 입력(매개변수) 이름 뒤에 []를 붙이거나 매개변수를 포인터로 지정해주면 된다.

1
2
3
4
5
6
7
반환값자료형 함수이름(자료형 매개변수[])
{
}

반환값자료형 함수이름(자료형 *매개변수)
{
}

예시

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>

void printArray(int arr[], int count) // 배열의 포인터와 요소의 개수를 받음
{
for (int i = 0; i < count; i++)
{
printf("%d ", arr[i]);
}

printf("\n");
}

int main()
{
int numArr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

printArray(numArr, sizeof(numArr) / sizeof(int)); // 배열과 요소의 개수를 넣음

return 0;
}

입력으로 들어오는 arr[]은 배열의 메모리 주소를 담고있는 포인터이기 때문에, 배열의 크기를 입력으로 넣어 주어야 한다.
특히 요소의 개수를 넣어줄 때, 배열의 크기 변화에 대응하기 위해서 sizeof 를 이용해야한다.
또한 arr[]로 입력(매개변수)를 지정한 경우 이는 포인터이기 때문에 배열의 요소를 변경하면 함수 바깥에 있는 배열의 값도 바뀌게 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>

void setElement(int arr[]) // 배열의 포인터를 받음
{
arr[2] = 300; // 매개변수로 받은 배열의 요소를 변경
}

int main()
{
int numArr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

setElement(numArr); // 배열을 넣어줌

printf("%d\n", numArr[2]); // 300: setElement에서 변경한 값이 출력됨

return 0;
}

매개변수를 포인터로 지정하면 아래와 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>

void printArray(int *arr, int count) // 매개변수를 포인터로 지정하여 배열을 받음
{
for (int i = 0; i < count; i++)
{
printf("%d ", arr[i]);
}

printf("\n");
}

int main()
{
int numArr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

printArray(numArr, sizeof(numArr) / sizeof(int)); // 배열과 요소의 개수를 넣음

return 0;
}

이를 이용하면 함수 안에서 배열의 요소를 바꾸는 함수를 작성할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>

void swapElement(int arr[], int first, int second) // 배열의 포인터와 인덱스를 받음
{
int temp;

temp = arr[first];
arr[first] = arr[second];
arr[second] = temp;
}

int main()
{
int numArr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

swapElement(numArr, 0, 1); // 배열과 값을 서로 바꿀 인덱스를 넣음

printf("%d %d\n", numArr[0], numArr[1]); // 2 1: swapElement에 의해서 배열 요소의 값이 서로 바뀜
return 0;
}

2차원 배열 매개변수 사용하기

함수에서 2차원 배열을 매개변수로 사용하려면 매개변수 이름 뒤에 [][가로 크기] 를 붙이고 가로 크기를 지정하거나, 괄호로 묶은 포인터 뒤에 [가로 크기]를 붙인다.

1
2
3
4
5
6
7
반환값자료형 함수이름(자료형 매개변수[][가로크기])
{
}

반환값자료형 함수이름(자료형 (*매개변수)[가로크기])
{
}

예시 (두 개의 대괄호를 이용한 방법)

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
31
32
33
#include <stdio.h>

// ↓ 배열의 가로 크기 지정
void print2DArray(int arr[][5], int col, int row) // 2차원 배열의 포인터와 가로, 세로 크기를 받음
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
printf("%d ", arr[i][j]);
}

printf("\n");
}
}

int main()
{
int numArr[2][5] = {
{ 1, 2, 3, 4, 5 },
{ 6, 7, 8, 9, 10 }
};

int col = sizeof(numArr[0]) / sizeof(int); // 5: 2차원 배열의 가로 크기를 구할 때는
// 가로 한 줄을 요소의 크기로 나눠줌

int row = sizeof(numArr) / sizeof(numArr[0]); // 2: 2차원 배열의 세로 크기를 구할 때는
// 배열이 차지하는 공간을 가로 한 줄의 크기로 나눠줌

print2DArray(numArr, col, row); // 2차원 배열과 가로, 세로 크기를 넣음

return 0;
}

예시 (포인터와 대괄호를 이용한 방법)

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
31
32
#include <stdio.h>

void print2DArray(int (*arr)[5], int col, int row) // 매개변수를 포인터로 만든 뒤 가로 크기 지정
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
printf("%d ", arr[i][j]);
}

printf("\n");
}
}

int main()
{
int numArr[2][5] = {
{ 1, 2, 3, 4, 5 },
{ 6, 7, 8, 9, 10 }
};

int col = sizeof(numArr[0]) / sizeof(int); // 5: 2차원 배열의 가로 크기를 구할 때는
// 가로 한 줄을 요소의 크기로 나눠줌

int row = sizeof(numArr) / sizeof(numArr[0]); // 2: 2차원 배열의 세로 크기를 구할 때는
// 배열이 차지하는 공간을 가로 한 줄의 크기로 나눠줌

print2DArray(numArr, col, row); // 2차원 배열과 가로, 세로 크기를 넣음

return 0;
}

[12] 포인터를 입력으로 이용하는 함수 (function using pointers as inputs)

C언어 함수 정리

참고 문헌 (Ch 63): https://dojang.io/mod/page/view.php?id=549

포인터 매개변수 사용하기

일반적인 자료형을 이용했을 때의 결과

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <stdio.h>

void swapNumber(int first, int second) // 반환값 없음, int형 매개변수 두 개 지정
{
int temp; // 임시 보관 변수

temp = first;
first = second;
second = temp;
}

int main()
{
int num1 = 10;
int num2 = 20;

swapNumber(num1, num2); // 변수 num1과 num2를 넣어줌

printf("%d %d\n", num1, num2); // 10 20: swapNumber 함수와는 상관없이
// 처음 저장한 10과 20이 출력됨

return 0;
}

반환형이 void이기 때문에, 두 변수를 받아서 처리하더라도 아무런 변화가 나타나지 않는다.
매개변수를 포인터로 이용해야 해당 주소값에 있는 변수에 직접 접근해서 값을 바꿀 수 있다.

1
2
3
반환값자료형 함수이름(자료형 *매개변수1, 자료형 *매개변수2)
{
}

예시

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <stdio.h>

void swapNumber(int *first, int *second) // 반환값 없음, int 포인터 매개변수 두 개 지정
{
int temp; // 임시 보관 변수

// 역참조로 값을 가져오고, 값을 저장함
temp = *first;
*first = *second;
*second = temp;
}

int main()
{
int num1 = 10;
int num2 = 20;

swapNumber(&num1, &num2); // &를 사용하여 num1과 num2의 메모리 주소를 넣어줌

printf("%d %d\n", num1, num2); // 20 10: swapNumber에 의해서 num1과 num2의 값이 서로 바뀜

return 0;
}

매개변수 포인터의 처리를 이해하기 쉽게 하는 방법

매개변수에서 처리할 포인터를 받아오는 경우, 입력과 출력에 대한 표시를 해주는 경우가 있다.

1
2
3
4
5
6
7
8
9
10
#define IN
#define OUT

// ↓ 일반적인 매개변수
void GetValue(IN int a, OUT int *b)
{ // ↑ 값이 바깥으로 나오는 매개변수
printf("%d\n", a);

*b = 10;
}

IN과 OUT 표시는 컴파일 할 때 아무런 영향을 주지 않는 매크로가 된다. 사람만 알아볼 수 있는 부분

void 포인터 매개변수 사용하기

void 포인터 매개변수를 이용하면, 자료형 변환을 하지 않아도 모든 자료형을 함수에 넣을 수 있다.

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include <stdio.h>

enum TYPE {
TYPE_CHAR,
TYPE_INT,
TYPE_FLOAT
};

void swapValue(void *ptr1, void *ptr2, enum TYPE t) // 반환값 없음, void 포인터 매개변수 두 개와
{ // 변수의 자료형을 알려줄 열거형을 받음
switch (t)
{
case TYPE_CHAR: // 문자면 char *로 변환한 뒤 역참조하여 값을 서로 바꿈
{
char temp;
temp = *(char *)ptr1;
*(char *)ptr1 = *(char *)ptr2;
*(char *)ptr2 = temp;
break;
}
case TYPE_INT: // 정수면 int *로 변환한 뒤 역참조하여 값을 서로 바꿈
{
int temp;
temp = *(int *)ptr1;
*(int *)ptr1 = *(int *)ptr2;
*(int *)ptr2 = temp;
break;
}
case TYPE_FLOAT: // 실수면 float *로 변환한 뒤 역참조하여 값을 서로 바꿈
{
float temp;
temp = *(float *)ptr1;
*(float *)ptr1 = *(float *)ptr2;
*(float *)ptr2 = temp;
break;
}
}
}

int main()
{
char c1 = 'a';
char c2 = 'b';
swapValue(&c1, &c2, TYPE_CHAR); // 변수의 메모리 주소와 TYPE_CHAR를 넣음
printf("%c %c\n", c1, c2); // b a: swapValue에 의해서 값이 서로 바뀜

int num1 = 10;
int num2 = 20;
swapValue(&num1, &num2, TYPE_INT); // 변수의 메모리 주소와 TYPE_INT를 넣음
printf("%d %d\n", num1, num2); // 20 10: swapValue에 의해서 값이 서로 바뀜

float num3 = 1.234567f;
float num4 = 7.654321f;
swapValue(&num3, &num4, TYPE_FLOAT); // 변수의 메모리 주소와 TYPE_FLOAT를 넣음
printf("%f %f\n", num3, num4); // 7.654321f 1.234567:
// swapValue에 의해서 값이 서로 바뀜

return 0;
}

이중 포인터 매개변수 사용하기

포인터 매개변수를 이용해서 정수, 실수 등의 값 대신 포인터(메모리 주소)를 얻어오기 위한 방법이 필요!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.h>
#include <stdlib.h> // malloc, free 함수가 선언된 헤더 파일

void allocMemory(void *ptr, int size) // 반환값 없음, void 포인터 매개변수 지정
{
ptr = malloc(size); // ptr은 allocMemory를 벗어나면 사용할 수 없음
}

int main()
{
long long *numPtr = NULL;

// numPtr과 할당할 크기를 넣어줌
allocMemory(numPtr, sizeof(long long));

*numPtr = 10; // 메모리가 할당되지 않았으므로 실행 에러
printf("%lld\n", *numPtr);

free(numPtr);

return 0;
}

디버그 포인트로 찍어보니, 선언한 값에 내용물이 아무것도 들어있지 않다. 이를 해결하기 위해서 이중 포인터를 이용.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.h>
#include <stdlib.h> // malloc, free 함수가 선언된 헤더 파일

void allocMemory(void **ptr, int size) // 반환값 없음, void 이중 포인터 매개변수 지정
{
*ptr = malloc(size); // void **ptr을 역참조하여 void *ptr에 메모리 할당
}

int main()
{
long long *numPtr;

// 단일 포인터 long long *numPtr의 메모리 주소는 long long **와 같음, 할당할 크기도 넣음
allocMemory(&numPtr, sizeof(long long));

*numPtr = 10;
printf("%lld\n", *numPtr);

free(numPtr); // 동적 메모리 해제

return 0;
}

이렇게 하면 값이 되게 잘나온다. 이해가 잘 안되니까 보면서 좀 더 생각해보기


문자열 매개변수 사용하기

매개변수로 문자열을 받을 땐 매개변수를 문자열 포인터로 지정! 여러가지 형태로 문자열 입력을 지정할 수 있다.

char 포인터 매개변수 1개로 이용

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>

void helloString(char *s1) // 반환값 없음, char 포인터 매개변수 한 개 지정
{
printf("Hello, %s\n", s1); // Hello, 와 매개변수를 조합하여 문자열 출력
}

int main()
{
helloString("world!"); // Hello, world!: 함수를 호출할 때 문자열을 전달

return 0;
}

베열 형태의 문자열도 전달할 수 있음

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>

void helloString(char *s1) // 반환값 없음, char 포인터 매개변수 한 개 지정
{
printf("Hello, %s\n", s1); // Hello, 와 매개변수를 조합하여 문자열 출력
}

int main()
{
char s1[10] = "world!"; // 배열 형태의 문자열

helloString(s1); // Hello, world!: 함수를 호출할 때 배열 전달

return 0;
}

매개변수 뒤에 []를 붙여서 설정, 이 때 크기는 생략!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>

void helloString(char s1[]) // 반환값 없음, char 배열을 매개변수로 지정, 크기 생략
{
printf("Hello, %s\n", s1); // Hello, 와 매개변수를 조합하여 문자열 출력
}

int main()
{
char s1[10] = "world!"; // 배열 형태의 문자열

helloString(s1); // Hello, world!: 함수를 호출할 때 배열 전달
helloString("world!"); // Hello, world!: 함수를 호출할 때 문자열 전달

return 0;
}