💾 Data Structure
: 0909 Review - Pointer, Array, String, Structure
🤍 1 - 'struct'
1. 단일 구조체 변수 ( `user.name` )
: 하나의 구조체 인스턴스
직관적으로 구조체의 각 멤버에 접근 가능
- ex) 개인 정보가 담긴 단일 사용자를 처리할 때
struct user user1;
user1.name = "cat";
printf("%s\n", user1.name);
2. 구조체 배열 ( `user[i].name` )
: 여러 개의 구조체 인스턴스를 배열로 관리
배열 인덱스로 각각 구조체에 접근 가능
- ex) 다수의 사용자 정보를 저장하고 처리할 때
struct user users[10];
users[0].name = "cat";
printf("%s\n", users[0].name);
3. 구조체 포인터 ( `user->name` )
: 동적 메모리나 포인터로 전달된 구조체
함수 간 구조체를 복사하지 않고 포인터로 전달 가능
- ex) 동적으로 메모리를 할당한 후 포인터로 구조체에 접근할 때
struct user* userPtr = (struct user*)malloc(sizeof(struct user));
userPtr->name = "cat";
printf("%s\n", userPtr->name);
요약
- `user.name` : 단일 구조체
- `user[i].name` : 여러 개의 구조체를 배열로
- `user->name` : 동적 메모리나 포인터
- 구조체에 접근하는 방식이 다른 것은 메모리 관리와 데이터 접근 방식이 다르기 때문
🤍 2 - `'qsort'`
1. 정수 배열 ( `int[]` )
- 포인터를 `int*`로 캐스팅한 후 역참조하여 두 정수를 비교
// 배열 선언
int arr[] = {5, 3, 8, 1, 2};
// comp 함수
int comp(const void* a, const void* b) {
return (*(int*)a - *(int*)b);
}
2. 실수 배열 ( `double[]` )
- double 타입의 실수 값을 비교할 때 소수점 연산이 필요하므로 두 값을 뺀 결과로 비교
// 배열 선언
double arr[] = {3.5, 2.1, 4.8, 1.9};
// comp 함수
int comp(const void* a, const void* b) {
double diff = *(double*)a - *(double*)b;
return (diff > 0) - (diff < 0); // 양수, 음수, 0 반환
}
3. 구조체 배열
- 구조체의 특정 멤버(여기서는 `name` )를 기준으로 비교할 때는 포인터를 구조체로 캐스팅한 후 해당 멤버를 사용
// 구조체 정의
typedef struct {
char name[20];
int age;
} Person;
// 구조체 배열 선언
Person people[] = {{"Alice", 30}, {"Bob", 25}, {"Charlie", 35}};
// comp 함수 (이름을 기준으로 정렬):
int comp(const void* a, const void* b) {
return strcmp(((Person*)a)->name, ((Person*)b)->name);
}
- 여러 멤버를 기준으로 정렬할 때
// comp 함수 (나이를 기준으로, 나이가 같으면 점수로 정렬)
int comp(const void* a, const void* b) {
Person* s1 = (Person*)a;
Person* s2 = (Person*)b;
if (s1->age != s2->age)
return s1->age - s2->age;
else
return (s1->score > s2->score) - (s1->score < s2->score);
}
4. 포인터 배열 ( `char* arr[]` )
- 포인터 배열의 각 요소는 문자열을 가리키는 포인터( `char*` ) (문자열의 주소를 저장하고 있음)
- `qsort`의 `a`, `b`는 배열의 요소를 가리킴
- 이를 `*(const char**)`로 포인터를 역참조한 후 포인터가 가리키는 실제 문자열을 비교
// 배열 선언: 각 요소는 문자열의 시작 주소를 가리킴
char* strings[] = {"apple", "banana", "cherry"};
// qsort 호출: 요소 크기는 `sizeof(char*)` (포인터의 크기)
qsort(strings, 3, sizeof(char*), comp);
// comp 함수: 포인터를 역참조하여 문자열을 비교
int comp(const void* a, const void* b) {
return strcmp(*(const char**)a, *(const char**)b);
}
5. 이차원 배열 ( `char arr[20][20]` )
- 이차원 배열의 각 요소는 고정된 크기의 `char[20]` 배열 (요소가 문자열을 직접 포함)
- `qsort`의 `a`, `b`는 문자열 배열의 시작 주소를 가리킴
- 이를 `(const char*)`로 캐스팅하여 문자열 비교
// 배열 선언: 각 요소는 20개의 문자를 저장할 수 있는 배열
char strings[20][20] = {"apple", "banana", "cherry"};
// qsort 호출: 요소 크기는 `sizeof(strings[0])` (각 행의 크기)
qsort(strings, 3, sizeof(strings[0]), comp);
// comp 함수: 문자열 배열의 시작 주소를 이용해 문자열 비교
int comp(const void* a, const void* b) {
return strcmp((const char*)a, (const char*)b);
}
포인터 배열과 2D 배열의 구분 방법
- 포인터 배열: 각 요소는 문자열을 가리키는 포인터이므로, `*(const char**)a`로 포인터를 역참조하여 문자열을 비교
- 이차원 배열: 각 요소는 문자열을 직접 저장하는 char[] 배열이므로, `(const char*)a`로 배열의 시작 주소를 캐스팅하여 문자열을 비교
| 항목 | 포인터 배열 ( `char*` ) | 이차원 배열 ( `char[20]` ) |
| 배열 선언 방식 | `char* arr[]` | `char arr[20][20]` |
| qsort 호출 시 요소 크기 | sizeof(char*) | `sizeof(char[20]) | sizeof(strings[0])` |
| 타입 캐스팅 | `(const char**)a`, `*(const char**)b` | `(const char*)a` , `(const char*)b` |
- 이차원 배열에서 `strings[0]`은 배열의 첫 번째 행을 가리킴.
(= 첫 번째 문자열을 저장하는 20칸짜리 배열인 `char[20]`)
'과목 일반' 카테고리의 다른 글
| [자료구조] 🎓 중간고사 오답노트 (0) | 2024.12.30 |
|---|---|
| [자료구조] 0930 Review - 자기 참조 구조체 Node 문제 (1) | 2024.12.24 |
| [프로그래밍 기초] 🎓 기말고사 오답노트 (3) | 2024.12.02 |
| [프로그래밍 기초] 🎓 중간고사 오답노트 (4) | 2024.11.30 |
| [자료구조] 열혈 자료구조⛑️ #1 (1) | 2024.11.28 |