본문 바로가기

C

C vs Python 함수와 배열

내가 적었던 글들을 살펴보는 시간을 가졌다.

이땐 이런걸 배워서 저런 글을 썼고 어떤 감정을 가지고 있었구나 하는 고찰의 시간.

 

사실 내가 적었어도 다 읽긴 귀찮았고

대충 기억에 남으니 앞으로 어떻게 써야겠다 하는 피드백이 더 중요했다.

 

배운 것들을 모두 담기엔 어렵지만

이번 충북대학교 공동훈련센터에서 진행하는

IoT 기반 스마트솔루션 개발자 양성과정 중에는

최대한 중요한 점을 위주로 기록해봐야겠다.

 

* 주제가 중구난방처럼 보이지만 나름 교육 커리큘럼대로 작성이 되고있다(모토 : 그날 배운건 그날의 기록으로!)

 

 

1. 함수

긴말할거 없이 C나 파이썬이나 함수 사용하는것이 비슷하다 못해 똑같다고 생각한다.

하지만 역시나 그렇듯 몇가지 규율이 존재한다

 

우선 비교하기 쉽게 눈으로 봐보자면

 

파이썬 함수 예제

 

C 함수 예제

 

 

이런 느낌이다

 

주황색 네모칸이 함수의 제목이라 보면되고

안에 내용물들이 작동을 하는것인데 로직은 비슷하다

 

 

파이썬 함수 호출

 

C 함수 호출

 

함수 예제 이미지에서 보이듯 파이썬과 C의 차이가 있는데

 

파이썬 : def 로 사용자 임의 함수 설정
C : 사용자 임의 함수여도 앞에 타입이 붙음(int, double, float ...)

이런식으로 간결하냐 귀찮냐의 차이다

 

 

C를 배우기 전에 들었던 상식으로는

파이썬은 인터프리터 언어이기 때문에 위에서 아래로 차례대로 줄을 읽어가고,

C는 컴파일 언어이기 때문에 순서가 뒤죽박죽이어도 상관없댔나 라는 식으로 흘려들은 적이 있다

 

하지만 지금까지 배우면서 느낀점으론 C라고 완전 뒤죽박죽이어도

정해줄 건 정해줘야 한다는 점이랄까?

그리고 솔직히 파이썬과 큰 차이는 많이 느끼지 못하고 있다

 

왜 이런 이야길 하느냐?

 

C 함수 선언

바로 이 부분 때문이다

 

아무거나 지정해줘도 읽어들이던 파이썬 바보와 달리

C 멍청이는 main 함수가 반드시 필요하다

 

그리고 맨 아래쪽에서 대충 어쩌구(), 저쩌구(), 이거(), 저거() 라고 선언해줘도

함수를 순서대로 잘 읽어주던 바보 파이썬과 달리

C 멍청이는 함수를 호출하는 명령보다 함수가 뒤에 있으면 어딨는지 모른다

그래서 함수 호출을 하기 전 노란색 네모칸과 같이 미리 선언을 해주어야

함수들이 명령보다 뒤쪽에 있어도 아 그런 함수가 있구나 하고 알아듣는다(호출 명령은 초록색 네모칸 안에 존재)

 

 

 

내 기준으로 이러한 방식이 어렵진 않지만

파이썬이 많이 편했구나 하고 느끼게 됐다

 

C 에서의 함수는 가장 불편한건 따로 있다

바로 함수의 매개변수의 타입을 지정해주어야 한다는것

int check_year(int year);				/////////////
int check_month(int month);				//함수 선언//
int check_day(int year, int month, int day);		/////////////
int checkNumber = 1;

int check_year() 함수의 매개변수를 지정해주는 곳에 int 타입이 붙어있는게 보이는가?

 

난 파이썬에선 뭐가 올지 모르니까

그냥 매개변수 이름만 던져줘도 알아서 해줬는데

C는 왤케 응애냐구..

 

아무튼 저 매개변수 때문에 컴퓨터가 컴파일 하는것이 아닌

내 뇌가 컴파일을 하게된다

 

" 여기에 어떤 타입이 올거니까 매개변수 타입은 어떤식으로 해야겠다

그리고 호출할때는 어떤 타입에 어떤 변수에 뭐가 계산되는지 다 계획하고 써야지~ "

 

이게 된다면 좋겠는데 내 뇌는 만들어지다 만 html 이다

계속해서 C를 쓰게 된다면 이러한 부분에 대한 연습과 컴퓨터 계산 원리 등에 대한

꾸준한 공부가 필요하다고 느꼈다

 

 

[ 함수 예제 문제 ]

많은 시간을 허비한 + 어려운 점을 느낀 문제 :

함수를 활용하여
연, 월, 일을 입력받아 잘못된 날짜가 입력되면 유효한 날짜가 입력될 때까지 계속 입력받도록 해보자
(윤년 계산 및 각 달의 일수가 맞도록 진행)

 

- 어려웠던 점 :

 윤년을 계산해주는 함수, 각 월이 1~12월 까지인지 확인하는 함수, 각 월의 날짜가 맞는지 확인하는 함수 등 여러가지 함수를 사용했다. 항상 의심이 드는 점은 동일하거나 비슷한 계산을 통해 유추할 수 있는 결과값이 있을 것이라는 생각이다.하지만 매번 이 생각을 기반으로 효율적인 프로그램을 짜보자 하는데 잘 되지 않는다.

 미리 계획하고 구성하는 것이 된다면 좋겠지만 지금은 일단 하나의 계산을 실행해주는 프로그램을 짜고 그 뒤에 전체적인 흐름을 보면서 수정해 나가고 있다. 다시 뜯어보고 비슷하거나 하나의 함수에서 결과를 도출할 수 있는 것이 있다면 수정해 나가고 싶지만 아직은 눈에 많이 익지 않은 현장이다. 그러다보니 계속해서 함수가 생겨나거나 중간에 계산이 꼬인다면 처음부터 수정해나가야 하는 점 등에서 어려움을 느꼈다.

 

- 해결 :

 역시나 멀수록 돌아가라는 옛말이 틀리지 않았다. 처음부터 끝까지 머릿속이나 정리하면서 구성을 짜고 그에 맞추어 프로그램을 쓴다? 어림도 없지. 난 아직 애기일 뿐이었다. 처음부터 끝까지 하나에 대한 계산이 끝날 수 있는 코드를 짜고 하나씩 앞으로 나아갔다. 

 그러다보니 어떤 부분에서의 어떤 결과값이 나오고, 어떤식으로 구성을 해야하는지 서서히 보이기 시작했다. 일단 시작부터 하라는 말이 떠올랐고, 말 그대로 머리부터 들이 밀었다. 하지만 먼저 프로그램의 구성을 기획하고 구성에 맞추어 코드를 작성하는 것을 연습해야겠다는 생각이 들었다.

 

 

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int check_year(int year);						/////////////
int check_month(int month);						//함수 선언//
int check_day(int year, int month, int day);				/////////////
int checkNumber = 1;

int main(void)
{
	int year, month, day, ckYear;

	while (1) {
		checkNumber = 1;
		printf("날짜 입력(연 월 일) : ");
		scanf("%d %d %d", &year, &month, &day);

		ckYear = check_year(year);		// 윤년 체크용 변수 ckYear
		month = check_month(month);
		day = check_day(ckYear, month, day);

		if (checkNumber == 0)
			printf("== 다시 입력해주세요 ==\n\n");
		else {
			printf("입력한 날짜는 %d년 %d월 %d일 입니다\n", year, month, day);
			return 0;
		}
	}
}

int check_year(int year)
{
	int yunday, day;
	if (year % 100 == 0 && year % 400 == 0 || year % 4 == 0 && year % 100 != 0) {		// 윤년 판단
		return 2;				// 윤년일 경우 yunday = True
	}																	

	else {
		return -1;				// 윤년이 아닐 경우 yunday = False
	}
		
}

int check_month(int month)
{
	if (month > 12 && month < 1) {
		printf("잘못된 월입니다\n");
		return checkNumber = 0;
		return 0;
	}
	else
		return month;
}

int check_day(int year, int month, int day)
{
	int max;
	if (year == 2) {
		switch (month) {
		default:				// default : 31일
			max = 31;
			break;

		case 4: case 6: case 9: case 11:	// 4,6,9,11월 케이스
			max = 30;
			break;

		case 2:					// 2월 윤년 케이스
			max = 29;
			break;
		}
		if (max < day) {
			printf("잘못된 날짜입니다\n");
			return checkNumber = 0;
		}
		else
			return day;
	}

	else if (year == -1) {
		switch (month) {
		default:
			max = 31;
			break;

		case 4: case 6: case 9: case 11:
			max = 30;

		case 2:					// 2월 평년 케이스
			max = 28;
		}
		if (max < day) {
			printf("잘못된 날짜입니다\n");
			return checkNumber = 0;
		}
		else
			return day;
	}
	
}

 

 

 

 

 

2. 배열

딥러닝과 머신러닝까지 배우면서 numpy 배열은 수도없이 봤다

3차원까지도 나아갔는데 이정도야 껌이지뭐~

 

 

 

 

 

 

 

 

 

C 접을 뻔했다

 

기껏해야 파이썬 리스트랑 비슷하네~ 라고 생각했다

 

파이썬의 리스트
C 배열

모양만 보면 얼추 둘이 비슷하게 생겨서 쉬울것 같은데

언제나 그렇듯 C에는 타입이 들어가있다

 

또한, list = [] 와 같이 빈 리스트를 간단하게 만들어주는 파이썬과 달리

C 는 배열의 크기와 초기값을 정해주지 않으면 힝 싫어 안 만들어 줄거야 하고 만들어주지 않는다

 

배열 자체는 파이썬 딥러닝에서 3차원까지 만져봤던 터라

이해하기가 굉장히 난해한 편은 아니었으나,

한가지 문제점이 발생한다

 

 

엄청나게 간단한 건줄 알았던 무작위로 나열된 수로 구성된 배열에서

최소값 최대값을 찾는것 자체가 어려웠던것..!

 

파이썬에서 min(), max() 로 금방 찾아내던 것이

C에서는 뭐? 오름차순 내림차순? 배열을 정렬해? 그리고 인덱스로 찾아?

많은 과정을 거쳐야 min max를 찾을 수 있었다

 

아래 그 과정을 공유해본다

 

#define ARR_SIZE 10
#include <stdio.h>

void print_array(int data[], int x)
{
	int i, min;

	for (i = 0; i < x; i++) {
		printf("%d ", data[i]);
	}


	min = data[x - 1];
	printf("최소값 : %d", min);
	printf("\n");
}

int main(void)
{
	int data[] = { 23, 45, 62, 12, 99, 83, 23, 50, 72, 37 };
	int size = sizeof(data) / sizeof(data[0]);
	int min, temp, i, j;

	for (i = 0; i < size - 1; i++) {
		min = i;
		for (j = i + 1; j < size; j++) {
			if (data[min] < data[j]) {
				min = j;
			}
		}
		if (i != min) {
			temp = data[i];
			data[i] = data[min];
			data[min] = temp;
		}
		printf("i = %d 일때 정렬 결과 : ", i);
		print_array(data, size);
	}
	printf("최소값 : %d\n", data[size - 1]);
	printf("최대값 : %d", data[0]);
}

 

- 어려웠던 점

: 솔직히 배열을 이해한다는 과정에선 크게 어려운 점이 없었다

그러나 중첩 반복문에서의 변수들이 왔다 갔다 하는 과정 중,

같은 변수에 같은 값이 반복해서 들어가는 듯한 어지러운 과정을 거쳤는데

이 부분에 대한 이해가 단번에 가지는 않았다

 

- 해결

: 바로 위 코드에서 보는것처럼 min = i 였다가 min = j 였다가 temp 에 값을 주었다가 등등

변수들이 겹치기 시작하니 헷갈렸다

그러던 중 같이 교육을 받는 수강생 중 한명과 이야기 해 보니

data[i] 와 같은 배열의 자리를 지정해 주는것, min = i 와 같이 값을 지정해 주는것으로 구분을 지으니

이해가 잘 되었다고 하여 관점이 바뀌었다

 

그저 변수에 대한 값이 계속해서 바뀌니 이해가 어려웠고

변수에 대한 값을 지정해주는 것과 배열의 자리를 바꿔주는 것으로 나누어 생각하니 이해가 빨랐다.

 

내일은 이어서 C 에서 가장 많은 포기자가 나오는 포인터를 배운다고 했는데

걱정도 앞서지만 주말에도 긴장의 끈을 놓지 못하게 하는

타이트함이 나를 성장시키는 것 같아 조금 더 기쁘다

 

배열 문제 풀다 자야지

'C' 카테고리의 다른 글

C 배열과 포인터 그리고 함수 적용  (1) 2023.02.27
C vs Python 조건문, 반복문  (4) 2023.02.22
C 입출력 ASCII 코드 그리고 비트 연산자  (1) 2023.02.20