[C] C언어 스터디 4주차
Review
- 함수
- 간단한 review quiz!
#include <stdio.h>
#include <stdlib.h>
int countCall();
void addNumber(int);
void printValue_1();
int value_1 = 0; // 1) 전역변수
int main() {
int value_2 = 0; // 2)지역변수
printf("%d\n", value_1); // 출력결과 3) 0
countCall();
value_2 = countCall();
printf("%d\n", value_2); // 출력결과 4) 2
addNumber(countCall()+2);
printf("%d\n", value_1); // 출력결과 5) 5
printValue_1();
}
int countCall() {
static int value_3; // 6)정적변수, 지역변수
value_3++;
return value_3;
}
void addNumber(int value_4) { // 7)매개변수, (지역변수)
value_1 += value_4;
}
void printValue_1() { // 이 프로그램에선 한 번만 호출함
printf("%d\n", value_1); // 결과 8) 5
}
- 정의 형식
- 반환타입, 함수이름, 매개변수
- 선언부, 반환값
int functionName(int parameter) { return 10; }
- 지역변수, 전역변수, 정적변수
배열
배열이란?
동일한 타입의 변수들의 집합 // C언어에서. 파이썬은 다른 타입도 됨!!! list
변수를 하나하나 선언 할 수도 있지만.. 번거로움을 막기위해 사용
int arr[5] = {1,2,3,4,5}
선언 구문
- 자료형 배열이름 [배열 크기]
int arr[10]; // 선언
double values[3] = {99.8, 87.5, 100.0}; // 선언과 동시에 초기화
char str[10] = "string"; // 선언과 동시에 초기화
- 배열의 SIZE : 해당 자료형 크기 x 개수 만큼의 크기가 할당 됨
- char arr[10]은 1byte x 10
- int arr[10]은 4byte x 10
- double arr[10]은 8byte x 10
원소 접근
- 배열 선언 후 배열 원소에 접근하려면 배열 이름 뒤에 대괄호 사이 첨자(index)를 이용
int nums[3] = {10, 20, 30};
nums[0] : 10
nums[1] : 20
nums[2] : 30
- 인덱스는 0부터 시작. 컴퓨터는 1이 아닌 0부터 시작이다!
- 선언할때 [ ] 안에는 선언할 배열의 ‘크기’
- 후에 배열에 접근할 때는 그 크기-1 만큼. 0 ~ 크기-1
nums[3]; // error
nums[10]; // error
- 유효 범위를 벗어나 참조하면 실행 오류가 발생한다!
메모리적인 관점
- %p를 이용하면 해당 변수(메모리)의 주소가 출력된다.
printf("%p", nums);
printf("%p", nums[0]);
printf("%p", nums[1]);
printf("%p", nums[2]);
- ‘주소’ 개념 매우 중요. 포인터 부분에서 다시 언급.
- 배열의 이름은 배열의 첫 번째 주소이다. 이 문장을 인지만 하고 넘어가자.
- 컴퓨터 어딘가 메모리에 변수들이 크기만큼 할당
- int형 변수는 크기 4byte
- int 배열은, int형 변수가 여러 개 있는 것!
- 해당 크기만큼 메모리가 할당
- 메모리적인 관점에서 보면, int nums[3] = {10, 20, 30} 은 위와 같은 상태로 저장되어 있음
- 메모리적인 관점에서 개념적으로 이해하고 넘어가자!
원소 접근 에러
- 위에서 유효 범위를 벗어나 참조하면 실행 오류가 발생한다! 라고 한 부분.
- nums[3] ?? 분명 0~2까지 크기 3만큼만 할당했기 때문에, 설정되지 않은 부분을 참조하기에 에러가 나는 것!
배열의 사용
- 사용 방법 예제 (배열의 접근 방법을 응용해 사용하면 됨)
#define SIZE 3
int nums[3] = {20, 30, 10};
printf("nums[0] : %d\n", nums[0]);
printf("nums[1] : %d\n", nums[1]);
printf("nums[2] : %d\n", nums[2]);
// 길어지면 하나하나 언제 입력하나.. for문으로
for (int i=0; i<sizeof(nums)/sizeof(nums[0]); i++) {
printf("nums[%d] : %d\n", i, nums[i]);
}
- 위 nums 안의 숫자를 30, 20, 10으로 변경
int temp;
int nums[3] = {20, 30, 10};
temp = nums[0];
nums[0] = nums[1];
nums[1] = temp;
/*
nums[0] : 30
nums[1] : 20
nums[2] : 10
*/
- nums를 모두 0으로 초기화
nums[0] = 0;
nums[1] = 0;
nums[2] = 0;
.
.
.
// nums[100] 이면!?
/*
nums[0] : 0
nums[1] : 0
nums[2] : 0
*/
// 길어지면 하나하나 언제 입력하나.. for문으로
for (int i=0; i<100; i++) {
nums[i] = 0;
}
- 배열에 전공 점수를 입력받아 평균 구해 출력
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main() {
double scores[3];
double avg = 0.0;
scanf("%lf %lf %lf", &scores[0], &scores[1], &scores[2]);
for (int i = 0; i < 3; i++) {
printf("%d번째 점수 : %lf\n", i, scores[i]);
avg += scores[i];
}
printf("평균은 %.2lf 입니다.\n", avg / 3);
}
- 크기 10의 int형 배열 randNums를 선언하여, 랜덤 숫자들을 순차적으로 입력받고, 이를 모두 더해 평균을 구한 값과, 각각 숫자들을 모두 출력하는 프로그램 (실습 : 7분)
#include <stdio.h>
#include <stdlib.h>
#define SIZE 10
int main() {
// 크기 10 int형 배열 randNums[] 선언
// 추가적으로 필요한 변수 선언
srand((unsigned)time(NULL));
// randNums[] 0 ~ 9까지 random 숫자 대입
for( ) {
}
// randNums[] 0 ~ 9까지 모두 더해 평균을 구함
for( ) {
}
// randNums[] 0 ~ 9까지 각각 출력
for( ) {
}
return 0;
}
- 코드 예시
#include <stdio.h>
#include <stdlib.h>
#define SIZE 10
int main() {
int randNums[10]; // 크기 10 int형 배열 randNums[] 선언
int sum = 0; // 임시로 모두 더할 변수 선언
double avg = 0; // 추가적으로 필요한 변수 선언
srand((unsigned)time(NULL));
// randNums[] 0 ~ 9까지 random 숫자 대입, 더해서 평균 구하기
for (int i = 0; i < 10; i++) {
randNums[i] = rand() % 20 + 1; // 1 ~ 20
sum += randNums[i];
printf("%d ", randNums[i]);
}
avg = sum / 10; // 평균 구하기
printf("\n평균은 : %lf \n", avg);
return 0;
}
이차원 배열
- 행과 열 구조, 대괄호 두 개 필요
- x축 하나만 있다가, x축 y축 두 개로 늘어난 것!!
- 1차원 -> 2차원!!
선언 구문
- 자료형 배열이름 [배열 행크기] [배열 열크기]
int arr[2][4]; // 선언
int arr2[2][4] = {
{1,2,3,4},
{5,6,7,8}
}; // 선언과 동시에 초기화
char str[4][10] = {"hello", "test", "string", "hi"}; // 선언과 동시에 초기화
1,2,3,4
5,6,7,8
- 행렬에서 헷갈리기 쉬운 부분..
- 행(Row) 부분은, 가로 줄이 몇 줄인지
- 열(Column) 부분은, 세로 줄이 몇 칸인지
원소 접근
차원이 하나 늘어났을 뿐, 일차원 배열과 동일하다.
- 인덱스는 0부터 시작.
- 선언할때 [ ] 안에는 선언할 배열의 ‘크기’
- 후에 배열에 접근할 때는 그 크기-1 만큼. 0 ~ 크기-1
- 위의 경우 접근 가능한 범위는
arr2[0][0] 부터 ~ arr2[1][3] 까지
str[0][0] 부터 ~ str[3][9] 까지
- 유효 범위를 벗어나 참조하면 실행 오류가 발생한다!
arr2[2][0]; // error
str[0][10]; // error
이차원 배열의 사용
- 사용 방법 예제 (배열의 접근 방법을 응용해 사용하면 됨)
int nums[2][2] = { {1,2},{4,5} };
printf("nums[0][0] : %d\n", nums[0][0]);
printf("nums[0][1] : %d\n", nums[0][1]);
printf("nums[1][0] : %d\n", nums[1][0]);
printf("nums[1][1] : %d\n", nums[1][1]);
// 길어지면 하나하나 언제 입력하나.. 이중 for문으로
for (int row = 0; row < 2; row ++) {
for (int col = 0; col < 2; col ++) {
printf("nums[%d][%d] : %d\n", row, col, nums[row][col]);
}
}
- 마찬가지. 해당 인덱스로 접근해서 값을 바꾸거나 할 수 있다!
nums[1][1] = 10;
- 배열에 두 학생의 학점을 입력받아 각각의 평균 구해 출력
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main() {
double studentsScores[2][2];
double avg[2] = { 0.0, 0.0 };
scanf("%lf %lf %lf %lf", &studentsScores[0][0], &studentsScores[0][1], &studentsScores[1][0], &studentsScores[1][1]);
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
printf("%d번째 학생의 %d번째 점수 : %lf\n", i+1, j+1, studentsScores[i][j]);
avg[i] += studentsScores[i][j];
}
}
printf("첫 번째 학생의 평균은 %.2lf 입니다.\n", avg[0] / 2);
printf("두 번째 학생의 평균은 %.2lf 입니다.\n", avg[1] / 2);
}
메모리적인 관점
- 포인터 배울 때 다시 언급 예정
- 0x0039… 는 컴퓨터 메모리 어딘가의 ‘주소’
함수와 배열
- 함수에 배열을 넘기는 방법
int function1(int a);
int sumOfNumbers(int arr[]);
- 배열을 함수에 넘길 수 있다!!
- 값이 들어있는 배열 arr의 값을 모두 더해 평균을 반환하는 함수
#include <stdio.h>
double sumOfNumbers(int[], int);
void main() {
int arr[3] = {99, 98, 100};
printf("평균은 %lf\n", sumOfNumbers(arr, sizeof(arr)/sizeof(arr[0]))); // 배열의 이름은, 배열의 첫 번째 주소이다! / 배열의 원소 개수 3을 넘겨줌
}
double sumOfNumbers(int arr[], int size) {
int sum = 0;
for (int i=0; i<size; i++) {
sum += arr[i];
}
return sum/3;
}
- 이차원 배열을 함수로 넘길 수도 있다.
int sumOfNumbers(int arr[2][]);
연습문제
배열 요소의 빈도 출력하기
#include <stdio.h>
void main() {
int ary[] = { 1,3,4,5,6,7,8,9,2,0,0,5,0,1,5,9,1,9,6,3,4,1,5,4,6,7,9,8,5,1,3,4,6};
int howMany[10] = { 0 };
for (int i = 0; i < sizeof(ary) / sizeof(ary[0]); i++) {
howMany[ary[i]]++;
}
for (int i = 0; i < 10; i++) {
printf("%d : %d번 나왔습니다.\n", i, howMany[i]);
}
}
배열 요소에서 선택된 숫자의 빈도 출력하기
배열 역순으로 정렬하기
배열의 최대 / 최솟값 찾기
- 배열 array를 넘겨주어 최댓값을 찾아 반환하는 findMax, 최솟값을 반환하는 findMin 함수를 구현하시오.
- 함수, 배열, 반복문, 조건문 응용
int findMax(int []);
int findMin(int []);
int main() {
int array[] = {63, 87, 68, 98, 95, 55};
}
배열 내림차순 정렬하기
- 배열 array를 넘겨주어, 배열의 값을 내림차순으로 정렬하는 sortArray() 함수를 구현하시오.
- 함수, 배열, 반복문, 조건문 응용
- 배열 array를 넘겨주어, 배열의 모든 요소를 출력하는 printArray() 함수를 구현하시오.
void sortArray(int []);
void printArray(int []);
int main() {
int array[] = {63, 87, 68, 98, 95, 55};
printArray(__); // 63, 87, 68, 98, 95, 55 출력
sortArray(__);
printArray(__); // 98, 95, 87, 68, 63, 55 출력
}
배열 요소 비교하기
- 배열 arr1, arr2를 넘겨주어, 배열의 모든 값이 같으면 1, 하나라도 다르면 0을 반환하는 함수 compareArray() 함수를 구현하시오.
- 함수, 배열, 반복문, 조건문 응용
int compareArray(int [], int []);
int main() {
int arr1[] = {1, 2, 3};
int arr2[] = {1, 2, 3};
int arr3[] = {3, 4, 5};
int result;
result = compareArray(_, _)
// 두 배열이 같습니다 or 두 배열이 다릅니다
}
이차원 배열 요소 더하기
- 2차원 배열 A, B를 선언하여, 두 배열에 대해 행렬의 덧셈, 뺄셈 연산을 수행하는 addArray(), subArray() 함수를 구현하시오.
- 함수, 배열, 반복문 응용
void addArray(int A[4][], int B[4][], int result[4][]);
void subArray(int A[4][], int B[4][], int result[4][]);
void showResult(int result[4][]);
int main() {
int A[4][4] = {
{1,3,5,6},
{1,1,0,1},
{2,4,1,3},
{5,1,2,0}
};
int B[4][4] = {
{1,1,1,1},
{1,1,1,1},
{0,0,0,0},
{1,1,1,1}
};
int result[4][4];
addArray(A, B, result);
showResult(result);
subArray(A, B, result);
showResult(result);
}
이차원 배열 요소 합 구하기
(5, 5) 배열에 (4, 4) 값이 주어질 때, 매개변수로 넘겨 가로 합, 세로 합을 각각 계산하여 넣는 함수 calArray() 를 구현하시오
- 각 줄에 해당하는 값들을 모두 더해 그 줄의 마지막 열에 저장하고, 각 열에 해당하는 값들을 모두 더해 그 열의 마지막 행에 저장한다.
1 2 3 _ 2 3 4 _ 1 0 1 _ _ _ _ _ 이렇게 4x4 행렬에 3x3 값이 주어진 경우 가로 덧셈 1+2+3의 값을 _에 넣고 2+3+4의 값을 _에 넣고 1+0+1의 값을 _에 넣는다. 세로 덧셈 1+2+1의 값을 _에 넣고 2+3+0의 값을 _에 넣고 3+4+1의 값을 _에 넣고 마지막으로 각 더한 _의 값들을 모두 더해 우측 하단의 _에 저장한다. 그러면 출력은 1 2 3 6 2 3 4 9 1 0 1 2 4 5 8 34 가 된다.
2차원 배열 arr를 넘겨 모든 요소를 출력하는 printArray() 함수를 구현하시오.
- 함수, 배열, 반복문
void calArray(int [5][]);
void printArray(int [5][]);
int main() {
int arr[5][5] = {
{1,2,3,4},
{4,1,2,3},
{3,4,1,2},
{2,3,4,1}
};
printArray(arr);
calArray(arr);
printArray(arr);
}