2024.01.24(수)
코드의 묶음
반환형(return type) 함수명(매개변수 목록(parameters)) {
함수 내용
}
int Add(int a, int b) { return a + b; }
void
타입을 사용블록(
{}
)의 내부 공간에 선언되는 변수 → 해당 블록 안에서만 사용 가능
블록(
{}
)의 외부 공간에 선언되는 변수 → 프로그램이 실행되는 동안 사라지지 않음
블록(
{}
)의 내·외부 공간에서 선언할 수 있는 변수로 변수의 범위를 파일 범위로 제한 → 프로그램이 실행되는 동안 사라지지 않음
블록(
{}
) 내부에서만 사용할 수 있고, 한 번 초기화 되면 이후에 함수 호출 시 값의 초기화를 무시함
자신이 선언된 소스 파일에서만 사용할 수 있고, 외부에서는 가져다 쓸 수 없음
같은 속성을 가진 것들을 나열해 놓은 것
배열 선언
자료형 배열명[크기]; // index 0 ~ (크기 - 1)
int scores[10]; // int 형 scores 변수 10개 선언 (index 0 ~ 9)
배열 초기화
자료형 배열명[크기] = { 값, 값, 값 };
int scores[] = {100, 90, 80}; // 배열 크기는 자동적으로 3이 됨
int grades[10] = {0}; // 전체를 0으로 초기화
int avg[5] = {80, 70}; // avg[0]은 80으로, avg[1]은 70으로, 나머지는 모두 0으로 초기화
배열 접근 및 할당
배열명[index] = 값;
배열 복사
int arr1[5] = {1, 2, 3, 4, 5};
int arr2[5];
arr2 = arr1; // 직접 대입하면 에러 발생
#include <stdio.h>
int main() {
int arr1[5] = {1, 2, 3, 4, 5};
int arr2[5];
for (int i = 0; i < 5; i++) {
arr2[i] = arr1[i];
}
return 0;
}
memcpy
를 사용할 수도 있음#include <string.h>
int main() {
int arr1[5] = {1, 2, 3, 4, 5};
int arr2[5];
memcpy(arr2, arr1, sizeof(arr1));
return 0;
}
문자열에 이름을 붙여주면 변수로 사용 가능
char 배열명[크기] = "문자열";
char s1[10] = "Hello";
선언과 동시에 할당하면 크기 생락 가능
문자열 길이 + 1(NULL 문자(\0
)) 만큼의 크기로 자동 지정됨
char s1[] = "Hello"; // 선언과 동시에 할당하면 크기 생락 가능
배열이므로 문자열을 바로 할당하면 에러가 발생하고 요소를 하나씩 지정해줘야함
또는 strcpy
사용
#define _CRT_SECURE_NO_WARNINGS // strcpy 보안 경고로 인한 컴파일 에러 방지
#include <stdio.h>
#include <string.h> // strcpy 함수가 선언된 헤더 파일
int main()
{
char s1[10] = "Hello"; // 크기가 10인 char형 배열을 선언하고 문자열 할당
char s2[10]; // 크기가 10인 char형 배열을 선언
strcpy(s2, s1); // s1의 문자열을 s2로 복사
return 0;
}
포인터 변수의 줄임말로 메모리의 주소값을 저장하고 있는 변수 또는 메모리를 가리키는 변수
*
기호를 붙여 포인터 변수 선언 (주소값만 저장하겠다는 의미)int *p; /* p는 int형을 갖는 객체(object)를 가리키는 포인터 변수 */
int* p; /* 포인터는 이름 앞에 붙기 보다는 형에 붙는 것이 좀 더 가독성에 도움이 된다 */
&
를 통해 변수의 주소값을 얻어올 수 있음*
를 통해 개체의 값에 접근 가능int i = 1;
int* p = &i;
printf("%d\n", i); /* 1 출력 */
printf("%d\n", *p); /* 1 출력 */
j = *&i; // j = i;와 같은 구문
배열의 이름은 해당 배열의 첫 번째 요소의 주소값을 가짐
(arr = &arr[0]
또는*arr = arr[0]
)
arr + i = &arr[i]
또는 *(arr + i) = arr[i]
#include <stdio.h>
int main()
{
int arr[] = {1, 2, 3, 4, 5};
printf("%p\n", arr); // 0x7ffebad7f0e0
printf("%p\n", &arr[0]); // 0x7ffebad7f0e0
printf("%d\n", *(arr + 4)); // 5
printf("%d\n", arr[4]); // 5
return 0;
}
💡 배열의 이름은 주소값을 갖는 포인터이지만 상수이므로 주소값 변경 불가능!
배열의 이름 = 포인터 상수 ≠ 포인터 변수
char date[8] = "June 14";
/*
"June 14"는 리터럴이 아니다!
다음과 같은 표현이다.
char date[8] = {'J', 'u', 'n', 'e', ' ', '1', '4', '\0'};
[J][u][n][e][ ][1][4][\0]
date⬏
*/
char* date = "June 14"; // date [·] –→ [J][u][n][e][ ][1][4][\0]
char* planets[] = {"Mercury", "Venus", "Earth",
"Mars", "Jupiter", "Saturn",
"Uranus", "Neptune", "Pluto"};
#include <stdio.h>
void func(int* pArr) {
for (int i = 0; i < 5; i++) {
printf("함수 안의 배열 : %d\n", *(pArr + i));
}
}
int main()
{
int arr[] = {1, 2, 3, 4, 5};
func(arr);
return 0;
}
반환형(return type)* 함수명(매개변수 목록(parameters)) {
함수 내용
}
int* get_max(int* left, int* right)
{
if (*left > *right) {
return left;
} else {
return right;
}
}
함수의 주소값을 저장하는 포인터
반환형(return type) (*함수(포인터)명)(매개변수 목록(parameters))
func = &func
)#include <stdio.h>
int sum(int a, int b) {
return a + b;
}
int main() {
int (*ptrSum)(int a,int b);
ptrSum = sum; //&sum = sum
printf("sum의 주소: %p\n", &sum); // 0x00081023
printf("ptrSum의 값: %p\n", ptrSum); // 0x00081023
printf("ptrSum의 주소: %p\n", &ptrSum); // 0x0026FB04
printf("ptrSum(%d, %d) = %d\n", 3, 4, ptrSum(3, 4)); // ptrSum(3, 4) = 7
return 0;
}
#include <stdio.h>
int sum(int a, int b) {
return a + b;
}
int func(int a, int (*funcPointer)(int, int)) {
return a + funcPointer(3, 4);
}
int main() {
printf("%d", func(10, sum)); // 17
return 0;
}
사각형의 넓이를 구하는 함수를 작성해보자. 사용자로부터 두 정수(가로의 길이, 세로의 길이)를 각각 입력 받아 함수의 전달인자로 전달하고, 사각형의 넓이를 출력하는 함수를 작성하자. 그리고 이 함수를 main에서 호출하여 출력해보자.
#include <stdio.h>
int get_rectangle_area(int width, int height)
{
return width * height;
}
int main()
{
int width, height;
printf("가로, 세로 길이를 입력하세요: ");
scanf("%d %d", &width, &height);
printf("사각형의 넓이는 %d입니다.\n", get_rectangle_area(width, height));
return 0;
}
사용자로부터 두 수를 입력 받아, 두 수를 비교하여 최대값과 최소값을 구하는 함수를 정의하라. 그리고 main 함수에서 이 함수들을 호출하여 결과값을 출력하도록 하라.
/******************************************************************************
출력 예)
두 정수를 입력하시오 : 5 3
최대값 : 5 최소값 : 3
*******************************************************************************/
#include <stdio.h>
int min(int a, int b)
{
return a <= b ? a : b;
}
int max(int a, int b)
{
return a >= b ? a : b;
}
int main()
{
int num1, num2;
printf("두 정수를 입력하시오 : ");
scanf("%d %d", &num1, &num2);
printf("최대값 : %d 최소값 : %d\n", max(num1, num2), min(num1, num2));
return 0;
}
커피 자판기가 있다. 100원 넣으면 '블랙커피', 200원 넣으면 '밀크커피'가 나온다. 자판기가 함수와 같은 블랙박스라고 했었다. 자판기를 함수로 구현해보자. 즉, 사용자로부터 정수형 가격(100, 200)을 입력 받아 100을 입력 받으면 '블랙커피'를 출력하고, 200을 입력 받으면 '밀크커피'를 출력하면 된다.
#include <stdio.h>
void coffee_vending_machine(int price)
{
if (price == 100) {
printf("블랙커피\n");
} else if (price == 200) {
printf("밀크커피\n");
} else {
printf("올바른 가격을 입력하세요.\n");
}
}
int main()
{
int money;
printf("자판기에 넣을 돈을 입력하세요 (100 또는 200): ");
scanf("%d", &money);
coffee_vending_machine(money);
return 0;
}
책 읽기 마라톤 기능을 가진 프로그램을 구현해보자. 책 읽기 마라톤이란 내가 읽은 책들의 페이지 수를 누적 계산하는 기능이다. 그날 그날 읽은 책들의 페이지 수를 사용자로부터 입력 받으면 최종 누적된 페이지 수에 새로 입력된 페이지 수가 추가로 더해지고, 다시 갱신된 최종 페이지 수가 출력되는 것이다. 한 번의 출력이 끝나면 다시 읽은 책의 페이지 수를 사용자로부터 입력 받고, 누적된 최종 페이지 수를 출력한다. 이 과정을 사용자가 -1을 입력할 때까지 계속 반복한다. 이 기능을 함수로 구현하되, 페이지의 누적 결과를 저장하는 변수를 전역 변수로도 구현해보고, static 변수로도 구현해보도록 한다.
/******************************************************************************
출력 예)
읽은 책의 페이지 수를 입력하시오: 30
최종 누적 페이지: 30
읽은 책의 페이지 수를 입력하시오: 20
최종 누적 페이지: 50
읽은 책의 페이지 수를 입력하시오: -1
더 분발하세요.
*******************************************************************************/
#include <stdio.h>
int total_pages = 0;
void page_accumulator(int pages) {
total_pages += pages;
}
int main()
{
int pages;
while (1) {
printf("읽은 책의 페이지 수를 입력하시오: ");
scanf("%d", &pages);
if (pages == -1) {
break;
}
page_accumulator(pages);
printf("최종 누적 페이지: %d\n", total_pages);
}
printf("더 분발하세요.\n");
return 0;
}
#include <stdio.h>
int page_accumulator(int pages) {
static int total_pages = 0;
total_pages += pages;
return total_pages;
}
int main()
{
int pages;
while (1) {
printf("읽은 책의 페이지 수를 입력하시오: ");
scanf("%d", &pages);
if (pages == -1) {
break;
}
printf("최종 누적 페이지: %d\n", page_accumulator(pages));
}
printf("더 분발하세요.\n");
return 0;
}
배열 arr1의 값을 배열 arr2에 복사하되, 배열 요소를 역순으로 저장하도록 하고, 복사된 arr2의 요소값들을 출력하도록 하라.
/******************************************************************************
int arr1[5] = {1, 2, 3, 4, 5}일 경우
출력 예)
배열 arr2[0] = 5
배열 arr2[1] = 4
배열 arr2[2] = 3
배열 arr2[3] = 2
배열 arr2[4] = 1
*******************************************************************************/
#include <stdio.h>
int main()
{
int arr1[5] = {1, 2, 3, 4, 5};
int arr2[5];
for (int i = 0; i < 5; i++) {
arr2[4 - i] = arr1[i];
}
for (int i = 0; i < 5; i++) {
printf("배열 arr2[%d] = %d\n", i, arr2[i]);
}
return 0;
}
포인터 오랜만에 다시 보니 이해가 잘된다. 옛날에는 왜 어렵게 느껴졌을까..