티스토리 뷰

Study/C

쉽풀C - 11장 포인터

Corinee 2023. 2. 7. 20:49
728x90

1. 포인터를 이용하여 자기가 사용하는 CPU의 바이트 순서를 살펴보는 프로그램을 작성해보자. 바이트 순서(byte ordering, endian)은 컴퓨터의 메모리에 바이트를 배열하는 방법이다. 바이트 순서는 큰 단위가 앞에 나오는 빅 엔디언(Big-endian)과 작은 단위가 앞에 나오는 리틀 엔디언(Little-endian)으로 나눌 수 있다. 아래의 프로그램에 주석을 추가하라.

종류 0x12345678의 표현
빅 엔디언 12 34 56 78
리틀 엔디언 78 56 34 12
#include<stdio.h>

int main(void) {
	int x = 0x12345678;
	unsigned char* xp = (char*)&x;

	// 인텔 CPU는 리틀 엔디언이다. 
	printf("바이트 순서: %x %x %x %x\n", xp[0], xp[1], xp[2], xp[3]);
	return 0;
}

 

 

2. 2개의 정수의 합과 차를 동시에 반환하는 함수를 작성하고 테스트하라. 포인터 매개 변수를 사용한다.

#include<stdio.h>

void get_sum_diff(int x, int y, int* p_sum, int* p_diff); 

int main(void) {
	int sum, diff;

	get_sum_diff(100, 200, &sum, &diff);
	printf("원소들의 합=%d\n원소들의 차=%d\n", sum, diff);
	
	return 0;
}

// 2개의 정수의 합과 차를 동시에 반환하는 함수
void get_sum_diff(int x, int y, int* p_sum, int* p_diff) {
	*p_sum = x + y;
	*p_diff = x - y;
}

 

 

3. 정수 배열을 받아서 요소들을 난수로 채우는 함수를 작성하고 테스트하라. 난수는 라이브러리 함수인 rand()를 사용하여 생성한다.

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define SIZE 10

void array_fill(int* A, int size); // 정수 배열을 받아서 요소들을 난수로 채우는 함수

int main(void) {
	int array[SIZE];

	srand((unsigned)time(NULL)); // 난수 생성을 위한 시드 설정

	array_fill(array, SIZE);

	for (int i = 0; i < SIZE; i++)
		printf("%d ", *(array + i)); // array[i]와 같음
	
	return 0;
}

void array_fill(int* A, int size) {
	for (int i = 0; i < size; i++) {
		*A = rand();
		A++;
	}
}

 

 

4. 정수 배열의 요소들을 화면에 출력하는 함수를 작성하고 테스트하라. 출력 형식은 A[ ] = { 1, 2, 3, 4, 5 }와 같은 형식이 되도록 하라.

#include<stdio.h>
#define SIZE 10

void array_print(int* A, int size); // 정수 배열의 요소들을 화면에 출력하는 함수

int main(void) {
	int array[SIZE] = { 1,2,3,4 }; // 나머지 6개 요소들은 0으로 초기화

	array_print(array, SIZE);	
	return 0;
}

void array_print(int* A, int size) {
	printf("A[] = { ");
	for (int i = 0; i < size; i++) 
		printf("%d ", *(A + i));
	printf("}\n");
}

 

 

5. 학생들의 평점은 4.3점이 만점이라고 하자. 배열 grades[ ]에 학생 10명의 학점이 저장되어 있다. 이것을 100점 만점으로 변환하여서 배열 scores[ ]에 저장하는 함수를 작성하고 테스트하라.

#include<stdio.h>
#define STUDENT 10 // 학생의 수

void convert(double* grades, double* scores, int size); // 학점 변환 함수
void print_array(double* A, int size); // 배열 출력 함수

int main(void) {
	double grades[STUDENT] = { 0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.3 };
	double scores[STUDENT];

	convert(grades, scores, STUDENT);

	print_array(grades, STUDENT); 
	print_array(scores, STUDENT);
	
	return 0;
}

void convert(double* grades, double* scores, int size) {
	for (int i = 0; i < size; i++)
		*(scores + i) = *(grades + i) * 100. / 4.3; // 점수 변환은 비례식을 사용. 즉 100:4.3=x:y
}

void print_array(double* A, int size) {
	for (int i = 0; i < size; i++)
		printf("%0.2lf ", *(A + i));
	printf("\n");
}

 

 

6. 정수 배열 A[ ]를 다른 정수 배열 B[ ]에 복사하는 함수를 작성하고 테스트하라.

#include<stdio.h>
#define SIZE 10

void array_copy(int* A, int* B, int size); // 정수 배열 A[]를 정수 배열 B[]에 복사하는 함수
void print_array(int* A, int size); // 정수 배열 출력 함수

int main(void) {
	int A[SIZE] = { 1,2,3 };
	int B[SIZE];

	array_copy(A, B, SIZE); // 배열 A를 배열 B에 복사
	print_array(A, SIZE); // 배열 A 출력
	print_array(B, SIZE); // 배열 B 출력

	return 0;
}

void array_copy(int* A, int* B, int size) {
	int i;
	for (i = 0; i < size; i++)
		*(B + i) = *(A + i);
}

void print_array(int* A, int size) {
	int i;
	printf("A[] = ");
	for (i = 0; i < size; i++)
		printf("%d ", *(A + i));
	printf("\n");
}

 

 

7. 직원들의 기본급이 배열 A[ ]에 저장되어 있다. 배열 B[ ]에는 직원들의 보너스가 저장되어 있다. 기본급과 보너스를 합하여 이번달에 지급할 월급의 총액을 계산하고자 한다. A[ ]와 B[ ]를 더하여 배열 C[ ]에 저장하는 함수를 작성하고 테스트하라. 즉 모든 i에 대하여 C[i] = A[i] + B[i]가 된다.

#include<stdio.h>
#define SIZE 10

void array_add(int* A, int* B, int* C, int size); // 배열 A와 배열 B를 더하여 배열 C에 저장하는 함수
void print_array(int* A, int size); // 정수 배열 출력 함수

int main(void) {
	int A[SIZE] = { 1,2,3 };
	int B[SIZE] = { 0 };
	int C[SIZE];

	array_add(A, B, C, SIZE); 

	printf("A[] = ");
	print_array(A, SIZE); // 배열 A 출력

	printf("B[] = ");
	print_array(B, SIZE); // 배열 B 출력

	printf("C[] = ");
	print_array(C, SIZE); // 배열 C 출력

	return 0;
}

void array_add(int* A, int* B, int* C, int size) {
	int i;
	for (i = 0; i < size; i++)
		*(C + i) = *(A + i) + *(B + i);
}

void print_array(int* A, int size) {
	int i;
	for (i = 0; i < size; i++)
		printf("%d ", *(A + i));
	printf("\n");
}

 

 

8. 직원들의 월급이 배열 A[ ] 에 저장되어 있다고 가정하자. 이번 달에 회사에서 지급할 월급의 총액을 계산하고자 한다. 정수형 배열 요소들의 합을 구하여 반환하는 함수를 작성하고 테스트하라.

#include<stdio.h>
#define SIZE 10

int array_sum(int* A, int size); // 정수형 배열 요소들의 합을 구하여 반환하는 함수
void print_array(int* A, int size); // 정수 배열 출력 함수

int main(void) {
	int A[SIZE] = { 1,2,3 };

	printf("A[] = ");
	print_array(A, SIZE); // 배열 A 출력

	printf("월급의 합=%d\n", array_sum(A, SIZE));

	return 0;
}

int array_sum(int* A, int size) {
	int sum = 0;
	for (int i = 0; i < size; i++)
		sum += *(A + i);
	return sum;
}

void print_array(int* A, int size) {
	int i;
	for (i = 0; i < size; i++)
		printf("%d ", *(A + i));
	printf("\n");
}

 

 

9. 직원들의 월급이 저장된 배열에서 월급이 200만 원인 사람을 찾고 싶을 때가 있다. 주어진 값을 배열 A[ ]에서 탐색하여 배열 요소의 인덱스를 반환하는 함수를 작성하고 테스트하라.

#include<stdio.h>
#define SIZE 5

int search(int* A, int size, int search_value); 

int main(void) {
	int salary[SIZE] = { 100,200,300,400,500 };
	int index;

	index = search(salary, SIZE, 200);
	if (index == -1)
		printf("같은 값을 찾지 못했습니다.\n");
	else
		printf("월급이 200만원인 사람의 인덱스=%d\n", index);

	return 0;
}

// 주어진 값을 배열 A에서 찾아 인덱스를 반환하는 함수
int search(int* A, int size, int search_value) {
	int i;
	for (i = 0; i < size; i++) {
		if (*(A + i) == search_value) // 같은 값이 있는 경우
			return i; // 인덱스 값을 반환
	}
	return -1; // 주어진 값을 찾지 못한 경우 -1 반환
}

 

 

10. 2개의 정수를 입력받아서 최대 공약수와 최소 공배수를 반환하는 함수를 작성하고 테스트하라. 최대 공약수는 유클리드의 방법을 사용하여서 계산한다.

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>

void get_lcm_gcd(int x, int y, int* p_lcm, int* p_gcd);
int get_gcd(int x, int y);

int main(void) {
	int x, y;
	int lcm; // 최소 공배수
	int gcd; // 최대 공약수

	printf("두 개의 정수를 입력하시오: ");
	scanf("%d %d", &x, &y);

	get_lcm_gcd(x, y, &lcm, &gcd);

	printf("최소공배수는 %d입니다.\n", lcm);
	printf("최대공약수는 %d입니다.\n", gcd);

	return 0;
}

// 두 개의 정수를 입력받아서 최대 공약수와 최소 공배수를 반환하는 함수
void get_lcm_gcd(int x, int y, int* p_lcm, int* p_gcd) {
	int max = (x > y) ? x : y; // x와 y 중 더 큰 수
	int min = (x < y) ? x : y; // x와 y 중 더 작은 수

	x = max, y = min;
	*p_gcd = get_gcd(x, y); // 최대 공약수 구하기
	*p_lcm = (x * y) / *(p_gcd); // 최소 공배수 구하기
}

// 순환 호출을 이용하여 최대 공약수를 구하는 함수. x는 y보다 커야 함.
int get_gcd(int x, int y) {
	if (y == 0)
		return x;
	else
		return get_gcd(y, x % y);
}

 

 

11. 2개의 정렬된 정수 배열 A[ ]와 B[ ]가 있다고 가정하자. 이 2개의 배열을 합쳐서 하나의 정렬된 배열 C[ ]로 만드는 함수를 작성하고 테스트한다. 다음과 같은 함수 원형을 가진다고 가정하라.

#include<stdio.h>

void merge(int* A, int* B, int* C, int size);
void print_array(int* A, int size); // 배열 출력 함수

int main(void) {
	int A[] = { 2,5,7,8 };
	int B[] = { 1,3,4,6 };
	int C[8];

	merge(A, B, C, 4); // 배열 A와 배열 B를 합쳐서 배열 C에 저장(작은 순서대로)

	printf("A[] = ");
	print_array(A, 4); // 배열 A 출력

	printf("B[] = ");
	print_array(B, 4); // 배열 B 출력

	printf("C[] = ");
	print_array(C, 8); // 배열 C 출력

	return 0;
}

void merge(int* A, int* B, int* C, int size) {
	int ai = 0, bi = 0, ci = 0; // 각각 배열 A, B, C의 인덱스
	for (; ai < size && bi < size;) {
		// 배열 A와 배열 B중 작은 값을 배열 C에 저장한다.
		if (A[ai] < B[bi]) {
			C[ci++] = A[ai++];
		}
		else {
			C[ci++] = B[bi++];
		}
	}
	for (; ai < size; ci++) { // A 배열의 값이 남아있으면 C 배열에 차례로 모두 저장
		C[ci] = A[ai++];
	}
	for (; bi < size; ci++) { // B 배열의 값이 남아있으면 C 배열에 차례로 모두 저장
		C[ci] = B[bi++];
	}
}

void print_array(int* A, int size) {
	int i;
	for (i = 0; i < size; i++)
		printf("%d ", *(A + i));
	printf("\n");
}

 

 

12. 우리가 프로그램을 하다보면 사용자로부터 2개의 정수를 받아오는 경우가 많다. 이것을 함수로 구현해두고 필요할 때마다 사용하면 편리할 것이다. 하지만 한 가지 문제가 있다. C에서 함수는 하나의 값만 반환할 수 있다. 2개 이상의 값을 반환하려면 다른 방법을 사용해야 하는데 다음과 같이 포인터도 사용할 수 있다.

위와 같은 원형을 가지는 함수를 작성하고 이것을 이용해서 정수의 합을 계산하는 프로그램을 작성해보자.

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#define SIZE 50

void get_int(int* px, int* py); // 2개의 정수 값을 반환하는 함수

int main(void) {
	int x, y;

	get_int(&x, &y);
	printf("정수의 합은 %d\n", x + y);

	return 0;
}

void get_int(int* px, int* py) {
	printf("2개의 정수를 입력하시오(예: 10 20): ");
	scanf("%d %d", px, py);
}
728x90