[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]);
  • ‘주소’ 개념 매우 중요. 포인터 부분에서 다시 언급.
  • 배열의 이름은 배열의 첫 번째 주소이다. 이 문장을 인지만 하고 넘어가자.


image-20210719134830595

  • 컴퓨터 어딘가 메모리에 변수들이 크기만큼 할당
  • int형 변수는 크기 4byte
  • int 배열은, int형 변수가 여러 개 있는 것!
  • 해당 크기만큼 메모리가 할당


image-20210719135116526

  • 메모리적인 관점에서 보면, int nums[3] = {10, 20, 30} 은 위와 같은 상태로 저장되어 있음
  • 메모리적인 관점에서 개념적으로 이해하고 넘어가자!


원소 접근 에러

image-20210719135738710

  • 위에서 유효 범위를 벗어나 참조하면 실행 오류가 발생한다! 라고 한 부분.
  • 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… 는 컴퓨터 메모리 어딘가의 ‘주소’

memoryAccessAboutArray




함수와 배열

  • 함수에 배열을 넘기는 방법
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][]);




연습문제

배열 요소의 빈도 출력하기

image-20210721230048324

#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]);
	}
}



배열 요소에서 선택된 숫자의 빈도 출력하기

image-20210721225915319



배열 역순으로 정렬하기

image-20210721230321861



배열의 최대 / 최솟값 찾기

  • 배열 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);
}




© 2020.07. by Sanggoe

Powered by Sanggoe