1. 배열
배열은 같은 데이터 타입을 가지는 여러 개의 값을 한데 모아 관리할 수 있는 구조입니다. C언어에서 자주 사용되는 기본 자료 구조로, 각 값들은 배열 내의 인덱스로 접근할 수 있습니다.
배열의 개념
- 배열은 각 원소의 위치 정보를 나타내는 인덱스와 그 인덱스에 해당하는 데이터 값의 쌍으로 이루어져 있습니다.
- 동일한 자료형을 갖는 여러 데이터의 집합으로, 같은 이름으로 참조됩니다.
- 각 데이터는 메모리 내의 연속적인 위치에 할당됩니다.
- 배열 내의 각 원소를 구분하기 위해 첨자(subscript)를 사용합니다.
데이터 타입(Data Type)
- 기본 자료 타입
- int, float, double, char 등 단일 값의 데이터 타입을 의미합니다.
- 군집 자료 타입
- 배열(Array): 기본 데이터 타입의 여러 개의 데이터를 묶어서 하나의 군집 형태로 사용하는 자료형입니다.
- 사용자 정의 자료 타입(구조체)
- C언어에서 제공하는 사용자 정의 자료형으로 서로 다른 데이터 형의 데이터를 묶어서 사용할 수 있습니다.
배열의 선언
type var_name[size];
int a[10];
위와 같이 선언하면 int형 변수 10개를 묶어서 배열 a로 사용합니다. 각 요소는 첨자를 사용해 접근하며, 예를 들어 a[0], a[1], ..., a[9] 등으로 사용합니다.
배열의 대표적인 정보
- 배열의 이름은 배열의 첫 데이터의 주소를 나타냅니다.
a = &a[0]; // 배열 a의 이름은 첫 번째 데이터의 주소를 가리킴
a + i = &a[i]; // 배열의 i번째 요소의 주소
*(a + i) = a[i]; // 배열의 i번째 요소에 접근하는 방법
배열 변수의 사용
- 반복문을 이용하여 배열의 각 변수를 처리할 수 있습니다.
sum = 0;
for (i = 0; i < n; i++) {
sum = sum + a[i];
}
위 예시는 배열의 모든 요소의 합을 계산하는 코드입니다. for문을 통해 각 요소에 접근하여 처리합니다.
2. 배열의 접근과 포인터
배열 개념
- 배열은 같은 자료형을 가진 연속적인 데이터 항목들의 집합입니다.
- 배열은 같은 타입의 여러 데이터들을 하나의 변수로 관리합니다.
- 예를 들어 int a[10];은 int 타입의 값을 10개 저장할 수 있는 배열입니다.
배열의 정보
- 배열을 선언할 때는 배열 이름과 크기, 그리고 각 항목의 자료형을 정의합니다.
- 1차원 배열: int a[10];
- 배열의 이름: a
- 배열의 크기: 10
- 배열 항목의 자료형: 정수 (int) - 2차원 배열: int b[7][9];
- 배열의 이름: b
- 배열의 크기: 7 x 9 = 63
- 배열 항목의 자료형: 정수(int) - n차원 배열: int a[d1][d2]...[dn];
- 배열의 이름: a
- 배열의 크기: d1 x d2 x ... 2 dn
- 배열 항목의 자료형: 정수(int)
- 1차원 배열: int a[10];
배열의 주소 계산
- 1차원 배열의 주소 계산: 배열의 데이터가 메모리에 연속적으로 저장되기 때문에 각 항목의 주소는 쉽게 계산됩니다.
- 예를 들어 int a[5] = {10, 20, 30, 40, 50}이 있고, a[0]의 주소가 1000번지이고 sizeof(int) = 4일 때:
- a[1]의 주소는 1000 + 1 * 4 = 1004 번지
- a[3]의 주소는 1000 + 3 * 4 = 1012 번지
- 예를 들어 int a[5] = {10, 20, 30, 40, 50}이 있고, a[0]의 주소가 1000번지이고 sizeof(int) = 4일 때:
- 다차원 배열의 주소 계산:
- 행 우선 저장 방식: 2차원 배열 int b[5][3];의 경우:
- b[i][j]의 주소는 b[0][0] + (i * d2 + j) * sizeof(int)로 계산됩니다.
- 예를 들어 b[1][2]의 주소를 계산할 때, b[0][0]의 주소가 100이고 sizeof(int) = 4라면:
b[1][2]의 주소 = 100 + (1 * 3 + 2) * 4 = 120
- 3차원 배열의 주소 계산:
- 배열 int ex[5][8][10];에서 ex[i][j][k]의 주소는 다음과 같이 계산됩니다:
ex[0][0][0]의 주소 + (i * d2 * d3 + j * d3 + k) * sizeof(int) - 예를 들어 ex[1][3][8]의 주소를 계산할 때, ex[0][0][0]의 주소가 100이고 sizeof(int) = 4라면:
주소 = 100 + (1 * 8 * 10 + 3 * 10 + 8) * 4 = 572
- 배열 int ex[5][8][10];에서 ex[i][j][k]의 주소는 다음과 같이 계산됩니다:
- 행 우선 저장 방식: 2차원 배열 int b[5][3];의 경우:
배열과 포인터의 관계
- 배열의 이름은 포인터:
- 배열의 이름 자체는 첫 데이터의 주소로서 포인터 타입의 변수입니다.
- 배열의 요소에 접근할 때, 배열 이름을 사용하여 첫 주소에서 오프셋을 더하는 방식으로 접근합니다.
- 포인터와 배열의 연산:
- a + i는 배열 a에서 i번째 요소의 주소를 나타냅니다.
- *(a + i)는 배열의 i번째 요소의 값을 의미합니다.
배열과 함수
- 배열을 함수의 매개변수로 넘길 때, 배열의 이름을 전달합니다.
- 배열을 함수에 전달하면, 실제 배열 데이터가 아닌 배열의 첫 번째 요소의 주소가 전달됩니다.
- 예시
float trunc_sum(float data[]);
int main() {
float xarray[10], fsum = 0.0;
int i;
printf("Enter 10 reals: ");
for (i = 0; i < 10; i++) {
scanf("%f", &xarray[i]);
fsum += xarray[i];
}
printf("Sum = %.2f\n", fsum);
printf("Truncation Value = %.2f\n", trunc_sum(xarray));
}
float trunc_sum(float data[]) {
float sum = 0.0;
int i, ivalue;
for (i = 0; i < 10; i++) {
ivalue = (int)data[i];
sum += (data[i] - ivalue);
}
return sum;
}
- 위 코드에서 xarray는 trunc_sum 함수에 배열의 첫 번째 요소의 주소를 전달합니다.
- 함수에서는 배열의 요소에 접근할 때 포인터처럼 동작합니다.
3. 배열의 연산
데이터 저장 및 접근
- 배열을 선언하고 데이터를 입력 받은 후, 특정 인덱스에 접근하여 값을 출력할 수 있습니다.
- 예시 코드:
int exarray[100], k;
for (k = 0; k < 10; k++) {
scanf("%d", &exarray[k]);
}
for (k = 9; k >= 0; k--) {
printf("%d ", exarray[k]);
}
위의 코드는 10개의 데이터를 입력 받고, 거꾸로 출력하는 예제입니다.
배열의 항목 삽입
- 주어진 배열에 데이터를 삽입하는 과정을 보여줍니다.
- 새로운 데이터를 삽입하기 위해 뒤의 항목들을 한 칸씩 밀어야 하며, 이를 통해 빈 자리에 새로운 값을 저장할 수 있습니다.
데이터 검색
- 특정 값을 배열에서 검색하는 알고리즘을 구현합니다.
- 선형 검색 방법으로, 배열을 순차적으로 탐색하여 원하는 값이 있는지 확인하고, 있다면 1을 반환하고, 없다면 0을 반환합니다.
4. 구조체의 정의와 활용
구조체는 여러 가지 자료형의 데이터를 하나로 묶어 관리할 수 있는 사용자 정의 자료형입니다. 예를 들어, 학생의 이름, 나이, 성적 등 서로 다른 자료형의 데이터를 하나로 묶어 처리할 때 구조체가 유용합니다.
구조체의 정의 예시:
typedef struct {
int id;
char name[20];
float score;
} Student;
위 코드에서는 Student라는 구조체가 정의되어 있으며, 학생의 학번(id), 이름(name), 성적(score)을 저장할 수 있습니다.
5. 구조체 배열의 활용
구조체 배열은 여러 개의 구조체를 배열로 관리할 수 있게 해줍니다. 예를 들어, 여러 명의 학생 정보를 관리하려면 Student 구조체 배열을 사용할 수 있습니다.
구조체 배열 선언 예시:
Student students[20]; // 20명의 학생 정보를 저장할 수 있는 구조체 배열 선언
이 배열을 사용하면 각 학생의 정보를 인덱스로 구분하여 저장하고, 데이터를 쉽게 접근할 수 있습니다.
데이터 입력 및 처리 예시:
for (int i = 0; i < 20; i++) {
printf("학생 정보를 입력하세요 (ID, 이름, 성적): ");
scanf("%d %s %f", &students[i].id, students[i].name, &students[i].score);
}
위 코드에서는 for 반복문을 사용하여 20명의 학생 정보를 입력받고 있습니다.
6. 구조체와 함수의 활용
구조체는 함수의 매개변수로 전달하여 데이터를 처리할 수 있습니다. 예를 들어, 학생 중에서 성적이 4.0 이상인 학생을 출력하는 함수를 작성할 수 있습니다.
성적이 4.0 이상인 학생 출력 함수:
void over40(Student students[], int n) {
printf("성적이 4.0 이상인 학생 목록:\n");
for (int i = 0; i < n; i++) {
if (students[i].score >= 4.0) {
printf("ID: %d, 이름: %s\n", students[i].id, students[i].name);
}
}
}
이 함수는 성적이 4.0 이상인 학생들의 정보를 출력합니다.
7. 최고 성적 학생 찾기
구조체와 배열을 사용하여 최고 성적을 받은 학생을 찾을 수도 있습니다.
최고 성적 학생을 반환하는 함수:
Student find_max(Student students[], int n) {
int max_index = 0;
for (int i = 1; i < n; i++) {
if (students[i].score > students[max_index].score) {
max_index = i;
}
}
return students[max_index];
}
이 함수는 최고 성적을 가진 학생을 찾아 반환합니다.
8. 파일 처리와 구조체 배열
구조체 배열을 사용하여 파일에서 데이터를 읽고 처리할 수 있습니다. 예를 들어, 수강 신청 데이터를 저장한 파일을 읽어 강좌 정보 등을 처리할 수 있습니다.
파일에서 강좌 정보를 읽어오는 코드:
FILE *file = fopen("course_data.txt", "r");
Course courses[MAX_CNUM]; // Course 구조체 배열 선언
int i = 0;
while (fscanf(file, "%s %s %u %u", courses[i].courseid, courses[i].tname, &courses[i].snum, &courses[i].roomnum) != EOF) {
i++;
}
fclose(file);
이 코드는 course_data.txt 파일에서 데이터를 읽어와 courses 구조체 배열에 저장합니다.
9. 구조체와 배열의 활용 예제
다음은 40명 이상의 수강생이 있는 강좌 코드를 출력하는 프로그램 예시입니다.
for (int i = 0; i < dnum; i++) {
if (courses[i].snum >= 40) {
printf("강좌 코드: %s\n", courses[i].courseid);
}
}
'IT개발및프로그래밍 > 자료구조' 카테고리의 다른 글
포인터와 구조체로 배우는 연결 리스트 기초 (0) | 2024.10.29 |
---|---|
포인터와 연결 리스트: 동적 자료 구조의 핵심 이해하기 (0) | 2024.10.21 |
C 프로그래밍 기초: 명령어 제어 구조 이해하기 (0) | 2024.10.21 |
프로그래밍 기초와 프로그램 번역 과정 (0) | 2024.10.21 |
프로그램과 알고리즘: 문제 해결을 위한 단계적 절차 (0) | 2024.10.21 |