반응형

malloc 함수를 설명하기 전에 변수가 저장되는 메모리 공간의 종류들에 대해 설명을 먼저 해보고자 합니다.

 

메모리 공간은 여러 가지가 있지만 대표적으로 전역변수가 저장되는 Data영역 , 지역변수가 저장되는 Stack영역. 그리고 메모리의 은행 창고의 역할을 하는 Heap영역이 있습니다. 이 글에서 쓰는 동적 메모리란 사용자가 메모리를 자유자재로 할당받는다는 것을 의미합니다. 즉, Heap영역으로부터 메모리를 필요한만큼 빌려쓰고 반환을 합니다.

이게 참 좋은게 배열을 다룰 때입니다.

예를 들어서, 대학교에서 어떤 강의의 수강생에 대한 재수강 여부를 관리하고자 합니다. 여러분들도 아시다시피 중간에 수강철회하는 사람, 새로 수강신청을 한 사람들이 있습니다. 즉, 상황에 따라 유동적으로 바뀝니다.

대략 이 강의를 50명 정도가 듣는다 치고  배열을 [50]으로 잡았는데, 생각보다 많은 사람이 빠져나가서 할당한 메모리가 남게 되었습니다.

즉, 메모리를 쓸데없이 많이 쓰고 있는 상태이므로 이러한 프로그램은 상당히 비효율적입니다.

이를 위해 상황에 따라 유동적으로 메모리를 할당하겠다. 하는게 C언어에서는 '동적 메모리 할당 malloc함수' 입니다.

 

그럼 이를 활용한 간단한 소스코드를 보면서 설명하겠습니다.

#include <stdio.h>
#include <stdlib.h>

int main()
{
	int i,count; // 학생 수 , 점수  
	int sum = 0;
	
	printf("학생 몇명임? : "); 
	scanf("%d",&count);
	int *student = malloc(sizeof(int)*count);
	if (student == NULL)
	{
		printf("Fail to Allocation.\n");
		exit(1);
	} 
	
	for (i=0; i<count; i++)
	{
		printf("[%d/%d] score? : ",i+1,count);
		scanf("%d",&student[i]);
		sum += student[i];
	}
	
	for (i=0; i<count; i++)
	{
		printf("[%d/%d] Score : %d\n",i+1,count,student[i]);
	}
	
	printf("%d",sum/i);
	
	
	free(student);
	return 0;
}

1. 제일 먼저 동적메모리 함수를 사용하기 위해선 stdlib.h 헤더파일을 선언해야 합니다.

2. 이제 눈여겨 봐야할 점.  malloc과 free입니다.

이 둘은 항상 같이 다니는 세트입니다. malloc : 메모리 빌려줘!  free : 메모리 갚어!

int *student = malloc(sizeof(int)*count);

이 코드의 의미를 보겠습니다. malloc을 통해서 int (4Byte) 자료형 크기의 메모리를 받을건데 그건 count 수만큼 합산해서 빌려줘! 이겁니다. 즉, count = 5면  20Byte를 빌리겠다는거겠죠?

 

포인터변수 student가 할당받은 메모리 공간의 주소를 가리키고 있습니다. 

 

3. if (student == NULL) 은 만약 할당받은 메모리 공간이 없다면 아래 몸체에 Fail to Allocation을 출력하여 뭔가 오작동되었음을 알립니다.

 

4. 이제 할당받은 student들의 점수를 채워넣도록 하겠습니다. 20Byte 크기의 공간을 빌렸으니 5명의 점수를 입력받습니다.

 

5. 프로그램 종료 시 사용한 20Byte를 반환하기 위해 free(student)를 해주었습니다. 이를 안할 시, 메모리 누수가 되어 지뢰찾기 하는데 메모리를 오지게 사용하게 되는 꼴이 됩니다.

 

이를 통해서 우리는 메모리를 필요한만큼만 사용해서 보다 효율적으로 관리를 하는게 가능해졌습니다.

아래는 동적메모리할당을 활용한 간단한 성적 관리 프로그램입니다.

 

#include <stdio.h>
#include <stdlib.h>

int main()
{
	int i,count; // 학생 수 , 점수  
	int sum = 0;
	
	printf("학생 몇명임? : "); 
	scanf("%d",&count);
	int *student = malloc(sizeof(int)*count);
	if (student == NULL)
	{
		printf("Fail to Allocation.\n");
		exit(1);
	} 
	
	for (i=0; i<count; i++)
	{
		printf("[%d/%d] score? : ",i+1,count);
		scanf("%d",&student[i]);
		if (student[i] > 100 || student[i] < 0)
		{
			printf("wrong!\n");
			return;
		 } 
		sum += student[i];
	}
	
	int average = sum/i;
	printf("\n\n");
	
	
	printf("평균 점수는 : %d\n",average);
	
	for (i=0; i<count; i++)
	{
		if (student[i]<average)
		{
			printf("[%d] 평균 아래입니다.재수강하세요. \n",i+1);	
		}
		
		else if (student[i]>=average)
		{
			printf("[%d ]PASS.\n",i+1);
		}
	} 
	
	
	free(student);
	return 0;
}
반응형
반응형

C언어를 공부하면서 가장 어려웠던 3가지 개념을 꼽으라면  동적메모리할당, 포인터, 구조체였던거 같습니다.

오늘 작성할 글은 포인터입니다. 저도 많이 부족하지만 포인터에 대한 간략한 이해를 도와보겠습니다.

 

포인터는 어떤 변수가 메모리 공간을 할당받고 저장되어있을 때, 그 변수가 살고있는 메모리 주소값을 가리키는 것입니다. 말 그대로 진짜 'Point!'인 셈이죠.  레이저 포인터할 때 그 포인터입니다.

 

우리가 어떤 변수의 초기값을 선언할 때는 항상 그 값들이 가지는 고유주소를 배정받게 됩니다. 이 주소의 값을 보는 방법은 printf를 통해 형식 지정자 "%p"를 사용하면 됩니다.

5라는 값은 현재 000000000062FE1C 라는 주소에서 살고 있군요.

 

* 주의사항 : 앰퍼샌드 & 기호는 두개를 쓰면 'AND'를 의미하는 논리연산자지만 하나만 쓴다면 해당 변수의 고유주소값을 호출하는 기능을 합니다. 위 소스코드를 보면 저는 number라는 변수의 주소값을 알기 위해 &number라 표현했습니다. 여기까진 이해될겁니다.

 

그럼 반대로 생각해볼 수도 있습니다. &가 변수가 가지는 고유주소를 호출하는 기능을 한다면 반대로 해당 주소에 살고 있는 변수값을 호출하는 것도 되지않나?

맞습니다. 그게 바로 * 연산자 입니다.

포인터 변수 pointer를 선언하고 &number로 초기화시켰습니다. 그리고 이에 대한 주소와 변수값을 출력했더니

위에 number의 주소와 변수값과 동일하게 나옵니다.

 

여기서 주목할 것은 4개의 printf들입니다.

일반 변수는 값을 호출할 때는 ("%d", 변수명) , 주소값을 호출할 때는 ("%p",&변수명)입니다.

근데 포인터 변수일 때는 반대입니다.

맨 위에 설명했듯이 포인터는 메모리 공간을 할당받은 변수가 살고있는 '주소값'을 가리키기 때문입니다.

따라서 주소값을 호출할 때는 ("%p",포인터변수명) , 값을 호출할 때는 ("%d" , *포인터변수명) 입니다.

 

&가 주소값을 알고싶을 때 쓰는거라면 *는 변수값을 알고싶을 때 쓰는 것이라 했으니까요.

그러면 위의 소스코드 결과를 한번 봅시다. 주소값 동일하구요. 같은 주소에 살지만 변수가 다르게 나왔습니다.

왜냐?

#include <stdio.h>

int main()
{
	int number = 5;  // 1. 처음에 number 변수에 5로 초기화했구요.
	printf("%p\n",&number);  // 2. number의 메모리 주소값을 호출
	printf("%d\n",number); // 3. number의 변수값 5를 호출
	
	int *pointer = &number;  // 4. 포인터변수 *pointer를 선언한 뒤 number의 
                             // 메모리 주소값으로 초기화
	*pointer = 3;  // 5. 포인터변수 값을 3으로 초기화
	printf("%p\n",pointer); // 6. pointer가 가리키는 메모리 주소는 number의 메모리 주소와 동일
	printf("%d",*pointer);  // 7. 4번이 실행되었으니 포인터변수를 통해 기존의 값 5에서 3으로 
                            // 변경한 것이 출력됨.
	
	return 0;
}

이렇기 때문입니다.

 

그럼 이쯤에서 포인터를 왜 배우며, 왜 쓰는지 생각해볼때가 온거 같습니다.

예시를 들겠습니다.

같은 수업을 듣는 학생 3명 A,B,C가 있다 합시다. 이 중 A는 공부를 잘해서 수업 중에 배운 내용을 잘 요약정리했어요. 그래서 친구인 B,C를 도와주기 위해 본인이 공부한 내용을 다시 또 종이에 써서 각각 나눠줬습니다.

그냥 교재의 몇페이지, 몇페이지 부분이 중요하니 그 부분들을 자세히 읽어봐라. 하면 될걸 말이죠.

 

컴퓨터도 똑같습니다. 일일이 함수를 만들어주면서 거기에 매개변수를 전달해서 실행하게 하면, 직관적으로는 괜찮아보이지만 함수가 사용하는 메모리도 발생하게 되고  프로그램을 수행하는데 있어서도 처리속도가 증가할 수 밖에 없습니다. 즉, 위 A학생이 종이를 쓴 것은 메모리 사용을 의미하구요. 공부한 내용을 종이에다 쓰는 행동은 프로그램을 수행하는 것이라 보면 됩니다. 딱봐도 시간 & 공간 다 불필요한 낭비죠.

교재의 N페이지를 읽어봐라. 한 마디면 시간절약 공간절약이니까요.

 

그래서 포인터를 쓰는 겁니다.  여기까진 이해 잘 되었으리라 생각합니다.

뒤에 문자열을 설명할 때도, 동적메모리를 설명할 때도 쭉 포인터를 같이 설명할테니  여기선 마지막으로 1차원 배열과 포인터의 관계에 대해 적고 끝내겠습니다.

 

배열은 변수들이 모여있는 하나의 아파트라 보면 되었습니다.

int num[6] = {0,1,2,3,4,5}는  num이라는 아파트에 0 , 1 , 2 , 3 , 4 , 5 라는 사람들이 살고 있습니다. 근데 다 같이 사는게 아니라 각 호수에 1명씩 들어가 살고 있다 보시면 됩니다.

왜냐하면, 배열은 변수의 수에 따라 메모리 공간을 할당해주는 것이기 때문에 이들은 모두 다 다른 메모리주소값을 갖고 있습니다.

다 다르죠? 근데 신기한게 뒷자리 숫자가 4씩 증가하는거 같아보입니다. 따라서 추측하건데 num은 int 자료형으로 선언되었기에 4Byte씩 할당되었음으로 파악됩니다.

이걸 주목해야해요.

첫번째 인덱스의 주소만 알면 그 뒤의 인덱스들의 주소는 자연스럽게 파악이 되거든요.

즉, 포인터 연산을 통해 배열의 데이터 주소들로 접근이 굉장히 용이해진다는 점. 이 개념까지 갖고 가시면 되겠습니다.

 

좀 더 이어서 쓰면 글이 길어질 것 같아 여기까지로 끊고 문자열이나 배열 예제들 풀 때 계속해서 덧붙여 설명하겠습니다.

반응형
반응형

10818번: 최소, 최대 (acmicpc.net)

 

10818번: 최소, 최대

첫째 줄에 정수의 개수 N (1 ≤ N ≤ 1,000,000)이 주어진다. 둘째 줄에는 N개의 정수를 공백으로 구분해서 주어진다. 모든 정수는 -1,000,000보다 크거나 같고, 1,000,000보다 작거나 같은 정수이다.

www.acmicpc.net

 

주어진 문제는 이렇습니다. 입력받을 정수의 개수를 먼저 선언한 뒤, 정수들을 입력했을 때  최소, 최대값만 나오게 하는 것입니다. 일단 문제를 딱 읽었을 때, 배열과 조건문. 그리고 기준이 될 최대&최소 변수의 선언이 필요해보입니다.

#include <stdio.h>

int main()
{
	int i,count;
    int max = -1000000;
    int min = 1000000;
	scanf("%d",&count);
	
	int num[count];
	for (i=0; i<count; i++)
	{
		scanf("%d",&num[i]);
	}
	
	return 0;
}

따라서 기본적인 틀은 이렇게 잡을 수 있겠습니다. 배열의 크기를 입력받았고 (=입력받을 정수의 개수) 각 배열안에

넣을 정수들을 for문으로 입력받았습니다.

 

중요한건 최대,최소값의 기준입니다. 

 

max를 가장 낮은 값, min을 가장 높은 값으로 했습니다. 따라서, if문에서 처음에는 무조건 num[0]이  max가 되고 min이 됩니다. 제가 입력한 숫자 25,32,46,8,3을 보면

num[0] = 25
num[1] = 32
num[2] = 46
num[3] = 8
num[4] = 3

입니다. 즉, num[0]은 max=min=25가 되었습니다.

이제 if (num[i]>max)부터 볼게요.  num[1]>25라면  max=num[1]이 됩니다. num[1]은 32이므로  max= 32가 되었고

if (num[i]<min)은  32<25는 성립하지 않으므로 min = 25입니다. 이걸 5번째 인덱스까지 반복할 경우

 

max는 46, min은 3이 됩니다. 하나하나 파헤쳐보면 의외로 어렵지 않습니다.

우리가 기억할 것은 프로그래밍에서 알고리즘과 여러 문법들은 그저 사고력을 현실화시키기 위한 도구일뿐. 수학적 사고력이 가장 중요하므로 한 문제를 두고 끊임없이 고민하도록 합시다.

반응형
반응형

printf("Welcome, Let's C Language.");  // 초등학생도 쉽게 이해시켜주는 C언어 글을 포스팅합니다.

 

안녕하세요. 비전공자 출신 SW Test 엔지니어 Crush on Study입니다. 

이번 글에서는 조건에 따라 다른 화면을 출력시킬 수 있도록 해주는 '조건문'에 대해 배워보겠습니다.

 

Q. 먼저 이전 시간에 배운 내용을 잠깐 복습해봅시다.

A. 1) Switch문에 대해 배웠습니다.

- Switch문은 트리거를 생성하여 어떤 값을 입력하냐에 따라 다른 결과를 출력할 수 있도록 생성한 문법입니다.

if문과 비슷한 개념이지만 여러개의 다중조건을 처리하고자할 때는 Switch문이 코드도 좀 더 깔끔한 느낌입니다.

통상적으로는 if문을 많이 쓰긴하나, switch문도 알아둘 필요가 있겠습니다.

2) default와 break문에 대해 배웠습니다.

- default는 if문으로 치면 else와 동일합니다.  if / else if가  case 1 , case 2, ..... 같은거고 그 이외의 조건에 해당하는 값을 입력했을 때는 default 구문이 실행되도록 합니다. 

break문은 switch에 있어서 가장 중요한 문법인데요. 각 case마다 break를 아래에 적어주지않으면 그 다음 case들도 모두 실행이 됩니다. 

 

딱 보고 기억 나는게 없다. 하면 바로 이 전글을 참고하세요.

https://crush-on-study.tistory.com/213

 

[C언어] #6. Switch / case문법

printf("Welcome, Let's C Language."); // 초등학생도 쉽게 이해시켜주는 C언어 글을 포스팅합니다. 안녕하세요. 비전공자 출신 SW Test 엔지니어 Crush on Study입니다. 이번 글에서는 조건에 따라 다른 화면을..

crush-on-study.tistory.com

 

오늘 해볼 것은 배열입니다.

배열이 왜 필요하냐?

우리는 어떤 변수를 선언하기 위해서는 다음과 같은 작업을 거칩니다.

int a=1;
int b=2;
int c=3;
int d=4;
.
.

몇개 안되는 변수면 이정도 수고는 그래요. 할만 합니다. 근데? 변수가 수백개는 된다면?? 아니 수십만개?

그때도 일일이 변수를 선언한다면 손가락 깨질겁니다. 그런 것을 방지하고자 나온게 배열입니다.

1차원 배열

// # 7. 1차원 배열 & 2차원 배열 강의


// 1차원 배열
#include <stdio.h>

int main()
{
    int num[10] = {1,2,3,4,5,6,7,8,9,10};

    for (int i=0; i<10; i++)
    {
        printf("%d , ",num[i]);
    }
    return 0;
}

보시면 10개의 변수를 'num'이라는 함수에 넣었습니다. 그리고 num 옆에 대괄호 표시로 변수의 개수를 적어두었습니다.

이 의미는 num 함수에 현재 10개의 변수가 담겨져 있다! 라는겁니다. 어떤가요? 확실히 일일이 선언하는 것보다 깔끔하고 짧습니다. 이렇게 배열을 선언한 것을 출력하기 위해서는 이제 아래 printf문에 적은 것처럼 num[i] 을 적어줘야 합니다.

 

여기서 주목해볼 것은 for문에 적힌 식들입니다. 보시면 저는 변수 i를 0에서부터 시작하고 9까지만 출력되게 하였습니다. 근데 num[10]에 담은 것은 1부터 10까지인데 뭔가 1씩 차이가 나는게 아닌가? 싶을겁니다.

아래를 봅시다.

1. 배열
배열은 위에서 변수들을 저장해놓는 기능을 한다했는데요. 좀 더 자세히 말하면 변수들의 '아파트' 같은 개념이라 보시면 됩니다. 변수 0,1,2,3,4,5,6,7,8,9들이 num 아파트에 입주를 했다 보시면 됩니다.  즉, 같은 아파트 내에 있어도 상세주소는 다른거죠. num아파트 101호, 102호, 201호,.... 이런식으로 말이죠.

변수와 주소값을 출력

직접 출력을 해봤습니다. 1이라는 친구는 0000002ffa1ff600이라는 주소에서 살고있군요.

그 외에도 다른 친구들도 제각각의 주소를 할당받았습니다. 맨 뒤에 00 04 08 0c 10 ~ 이런식으로 증가하는거보니까

int형으로 받아서 그런지 4byte씩 늘어나는게 보입니다.

제가 변수는 1부터 10으로 설정을 했지만, 배열 인덱스의 시작은 0부터 시작합니다. 따라서, 변수 1이 살고있는 인덱스는 0층, 2는 1층.... 이런식으로 진행됩니다.

문자 배열

문자의 배열도 똑같습니다. char는 1byte니까  주소값도 1씩만 늘어나는게 보입니다. 

근데 char의 경우는 앞에서도 말했지만 문자 딱 하나씩만 받기때문에  배열에다가 ' ' 작은따옴표를 해줘야하는데요.

그럼 일일이 저렇게하지말고 한번에 적는건 안되나요? 라는 의문이 들겁니다. 당연히 가능하지만 문자열을 적고자할 때는 'Null 포인트'에 대해 고려하고 있어야 합니다.

문자열 Null 메모리

바로 저부분 \0입니다. 이는 절대문자 '0'을 의미하는게 아니라 아스키코드 상 문자열의 종료를 의미하고 있습니다.

따라서 문자열을 배열로 입력받고자 할 때는 글자 수 크기에다가 항상 1만큼 더해준 값을 고려해야한다는 점.

이게 중요한 포인트입니다.

 

마지막으로 2차원 배열을 보겠습니다.

2차원 배열도 별거없습니다. 막연하게 행은 가로, 열은 세로~ 이렇게 외워도 되지만요.

num[i][j]에서 j는 배열 하나에 몇 개의 원소가 들어가 있고! 라는 의미구요. i는 그 배열이 몇 개이다! 라는 의미라고 받아들이셔도 도움이 될 듯 합니다.

제가 약간 테트리스마냥 해놔서 이해가 안될 수 있는데 아래에 좀 더 쉽게 표현해보았습니다.  num[3][4]에 저장된 숫자들을 적어놓고 [1][2]에 해당하는 번호를 출력해보았습니다.

7이 나온 이유를 봅시다.

위에서 말한것에 따르면 하나의 배열에 4개의 원소가 담겨있다라는 뜻이고, 그 배열이 총 3개있다! 입니다.

따라서 num[1][2]를 해석하고자할 때는 뒤에 [2]부터 보면 됩니다. 배열의 인덱스는 0부터 시작하니까, 2는 세번째 원소에 해당합니다.

그러면 5,7,11로 추려지네요. 그다음 보니까 [1]이 있습니다. 즉 1은 두번째 배열을 의미합니다.

따라서 [4,6,7,8] 배열을 의미하므로 num[1][2]는 7이 됩니다. 이해 되죠?

반응형
반응형

printf("Welcome, Let's C Language.");  // 초등학생도 쉽게 이해시켜주는 C언어 글을 포스팅합니다.

 

안녕하세요. 비전공자 출신 SW Test 엔지니어 Crush on Study입니다. 

이번 글에서는 조건에 따라 다른 화면을 출력시킬 수 있도록 해주는 '조건문'에 대해 배워보겠습니다.

 

Q. 먼저 이전 시간에 배운 내용을 잠깐 복습해봅시다.

A. 1) while문에 대해 배웠습니다.

- while문은 for문과 마찬가지로 반복문 유형 중 하나입니다. 다만, for문의 구조는 옆에 초기값 선언, 조건식, 증감식을 한번에 적어줬다면 while문은 위에 초기값 선언, while 옆에 조건식 선언, while 몸통에 증감식 선언. 이런 식으로 나눠서 구조를 짜야했었습니다. 

2) do while문에 대해 배웠습니다.

- do while문은 while문과 차이점이 있습니다.

while do while
조건을 먼저 확인하고 수행을 결정한다.
조건이 충족되지 않는다면 프로그램 종료.
먼저 임시로 수행을 1번 한 뒤에, 조건을 확인한다.
만약 조건이 일치하지 않으면 1번 출력으로 끝.

 

딱 보고 기억 나는게 없다. 하면 바로 이 전글을 참고하세요.

https://crush-on-study.tistory.com/212

 

[C언어] #5. while 반복문과 do ~ while 반복문

printf("Welcome, Let's C Language."); // 초등학생도 쉽게 이해시켜주는 C언어 글을 포스팅합니다. 안녕하세요. 비전공자 출신 SW Test 엔지니어 Crush on Study입니다. 이번 글에서는 조건에 따라 다른 화면을..

crush-on-study.tistory.com

switch 구문 강의 소스코드

// #6. switch 구문 강의

#include <stdio.h>

int main()
{
    int choice;

    printf("Welcome to choice game.\n");
    printf("Let's choice the number : ");
    scanf_s("%d",&choice);

    switch (choice)
    {
   		 case 1:
    	{
        printf("you choice no.1\n");
        break;
   		 }
    
    	case 2:
   		 {
        printf("you choice no.2\n");
        break;
   		 }
    
   		 default:
         {
        printf("you choice another.\n");
        break;
        }
    }

    return 0;
}

오늘할 것은 switch구문입니다. 제가 이거 배울 때 딱, 생각난게  "아, 이거 가지고 밸런스 게임 만들어야겠다 ㅋㅋㅋㅋㅋ" 였습니다. ㅋ  일단 구조들을 먼저 살펴봅시다. 처음보는게 있네요. default입니다.

1. Switch 구문
Switch는 if문과 비슷해보이지만, 트리거를 통해 수행된다는 점에서 차이가 있습니다. Switch의 구조는 위에서 변수 초기화와 printf, scanf를 통해 입력을 받을 준비를 먼저 해놓는걸 시작으로 합니다.

그 아래에 Switch를 적는데요. 옆에다 우리가 scanf로 받은 choice를 트리거로 해둡니다. 
만약 1을 입력했으면 "You choice no.1" 이라는 구문이 나오겠죠? 코드보시면 눈치를 채셨겠지만 1,2를 제외한 다른 값을 입력했을 때는 default 구문이 실행됩니다.

다른거 하나 만들어서 해본 결과입니다. 2를 누르면 case 2만 실행이 됩니다. 근데 왜 구문마다 break를 해야할까요?

만약 break를 적지않는다면 아래와 같은 결과가 나옵니다.

저는 수달이 좋다고 3번을 찍었는데 break가 없어서 3번 아래 구문도 함께 실행이 되어버렸습니다. 따라서 Switch구문을 사용할 때는 각 case마다 break를 적어주는게 중요한 포인트라 할 수 있습니다.

반응형
반응형

printf("Welcome, Let's C Language.");  // 초등학생도 쉽게 이해시켜주는 C언어 글을 포스팅합니다.

 

안녕하세요. 비전공자 출신 SW Test 엔지니어 Crush on Study입니다. 

이번 글에서는 조건에 따라 다른 화면을 출력시킬 수 있도록 해주는 '조건문'에 대해 배워보겠습니다.

 

Q. 먼저 이전 시간에 배운 내용을 잠깐 복습해봅시다.

A. 1) for문에 대해 배웠습니다.

- 프로그램이 어떤 특정 트리거에 의해서만 수행되는걸 원할 때 우리는 조건문을 통해 구현하기로 했습니다. if와 else if는 선언할 때, 옆에 조건식을 함께 적어준 다음  조건이 맞을 때, 수행할 구문을 아래 적어놔주었습니다. else는 '이 밖의 모든 것' 이라는 의미로 if와 else if에서 지정한 조건 이외의 모든 경우에 해당할 때  수행할 구문을 적어줍니다.

따라서, else는 조건식을 따로 적지 않는다고 배웠습니다.

 

2) 증감 연산자에 대해 배웠습니다.

- 조건문을 구현하고자 할 때, 항상 따라붙는 연산자들입니다. == 는 동치를 !=는 불일치를 &&는 AND를 ||는 OR을 의미합니다. 추가로 산술 연산자 중에서도 조금 생소한 개념인 %에 대해 배웠습니다. %는 나눗셈을 할 때, 몫이 아닌 나머지 값만을 출력하고자 할 때 사용합니다. 보통 %은 홀수,짝수를 구분하고자 할 때 자주 사용합니다.

 

딱 보고 기억 나는게 없다. 하면 바로 이 전글을 참고하세요.

https://crush-on-study.tistory.com/210?category=1002287 

 

[C언어] #4. 반복문 for문과 이중 for문

printf("Welcome, Let's C Language."); // 초등학생도 쉽게 이해시켜주는 C언어 글을 포스팅합니다. 안녕하세요. 비전공자 출신 SW Test 엔지니어 Crush on Study입니다. 이번 글에서는 조건에 따라 다른 화면을..

crush-on-study.tistory.com

while문 강의 소스코드

// #5. while문 강의
#include <stdio.h>

int main()
{
    int i=1;

    while(i<=10)
    {
        printf("[%d] Hello, friend? can you give me money?\n",i);
        i++;    

        if (i>10)
        {
            break;
        }
    }


    return 0;
}

여러분. 10번 찍어 안넘어 가는 나무가 되는 사람이 되십쇼. 

아무튼, 이번 while문 역시 for문과 똑같은 기능을 하는 반복문입니다.  기능은 같으나 구조가 조금 차이가 있어요.

 

for문 같은 경우는  for 옆에 셋팅을 한번에 넣는다면  while은 다릅니다.

1) 일단 초기값은 while문 위에다 먼저 선언을 해줍니다.

2) 조건식만 while문 옆에다 적어줍니다.

3) 증감식을 while문 안에다 적어줍니다.

 

이 구조만 지키시면 while문 뚝딱입니다.

 

자, 근데 처음보는 명령어가 하나 보이네요. 바로 break문입니다.

사실 여기 소스코드에서는 조건식 범위 안에서만 반복수행되기 때문에 이를 다 마치면 자동으로 종료가 됩니다. 그래서 break문을 사용할 필요는 없는데, 설명을 위해 첨가했습니다.

1. break
이름 그대로 브레이크를 걸다. 멈추다. 그런 의미입니다. 만약 i=1로 하고 조건을 i<=10으로 했다해도, 여러분들이 마음이 바뀌어서 5까지만 출력하면 프로그램을 종료하게 만들고 싶다. 하시면 break문을 쓰면 됩니다.

break문

바로 이런 식으로 걸어주면 while 조건식에서는 10까지 반복수행해라! 했어도 i==5를 마주할 때 종료해버립니다.

 

자, 근데 do~while문을 설명하기에 앞서 while문의 실행구조를 마지막으로 살펴보고자 합니다.

while문의 실행 구조를 알아보자

이런 식으로 조건을 수정했어요. 그러면 상식 상 printf에 들어있는 문구는 실행이 되지 않을 것입니다. 그리고 역시 예상대로 결과값에는 아무것도 출력되지 않은 채 끝났습니다.

왜냐하면 while문은 먼저 조건부터 확인을 한다음에 실행을 하기 때문인데요. do~while문은 이것의 반대입니다. 먼저 실행을 한 다음 조건을 확인합니다.

2. do ~ while문
좀 더 자세히 말하자면 do~while문은 '기미상궁' 같은 문법이다! 라고 보시면 됩니다. 조건을 확인하기 전에 일단 한번은 임의로 수행을 합니다. 그 후, 조건을 확인한 뒤 조건에 맞는다면 다시 수행을 반복합니다. 하지만 한번 임의로 수행한 뒤에 '어? 맛이 별론데?' 하면 이제 뒤에는 수행이 안됩니다.

Visual Studio Code가 좋은게 이렇게 do를 적고 중괄호 { 를 타이핑하면 저렇게 구조를 한번에 보여줍니다. 

보시는 바와 같이 do { }에다가는 실행할 코드를 적구요.  while의 소괄호 ( )에다가는 조건식만 적어주면 됩니다.

아, 바로 위에 코드 사진에 stdio.h 헤더파일을 선언 안했었네요. ㅈㅅㅈㅅ 아무튼 이런식으로 코드를 작성해본 뒤에 돌려보면?

결과값

짜잔. 일단 수행 한번은 무조건 합니다. 이게 do~while문과 while문의 차이입니다.

 

퀴즈

Q1. while문을 이용하여 1에서부터 100까지 자연수들의 합을 구하는 프로그램을 작성해주세요.

반응형
반응형

printf("Welcome, Let's C Language.");  // 초등학생도 쉽게 이해시켜주는 C언어 글을 포스팅합니다.

 

안녕하세요. 비전공자 출신 SW Test 엔지니어 Crush on Study입니다. 

이번 글에서는 조건에 따라 다른 화면을 출력시킬 수 있도록 해주는 '조건문'에 대해 배워보겠습니다.

 

Q. 먼저 이전 시간에 배운 내용을 잠깐 복습해봅시다.

A. 1) 조건문 if / else / else if에 대해 배웠습니다.

- 프로그램이 어떤 특정 트리거에 의해서만 수행되는걸 원할 때 우리는 조건문을 통해 구현하기로 했습니다. if와 else if는 선언할 때, 옆에 조건식을 함께 적어준 다음  조건이 맞을 때, 수행할 구문을 아래 적어놔주었습니다. else는 '이 밖의 모든 것' 이라는 의미로 if와 else if에서 지정한 조건 이외의 모든 경우에 해당할 때  수행할 구문을 적어줍니다.

따라서, else는 조건식을 따로 적지 않는다고 배웠습니다.

 

2) 논리 연산자에 대해 배웠습니다.

- 조건문을 구현하고자 할 때, 항상 따라붙는 연산자들입니다. == 는 동치를 !=는 불일치를 &&는 AND를 ||는 OR을 의미합니다. 추가로 산술 연산자 중에서도 조금 생소한 개념인 %에 대해 배웠습니다. %는 나눗셈을 할 때, 몫이 아닌 나머지 값만을 출력하고자 할 때 사용합니다. 보통 %은 홀수,짝수를 구분하고자 할 때 자주 사용합니다.

 

딱 보고 기억 나는게 없다. 하면 바로 이 전글을 참고하세요.

https://crush-on-study.tistory.com/209

 

[C언어] #3. 조건문 if , else if , else / 논리 연산자

printf("Welcome, Let's C Language."); // 초등학생도 쉽게 이해시켜주는 C언어 글을 포스팅합니다. 안녕하세요. 비전공자 출신 SW Test 엔지니어 Crush on Study입니다. 이번 글에서는 조건에 따라 다른 화면을..

crush-on-study.tistory.com

3중 for 반복문

// # 4. 반복문 강의입니다.

#include <stdio.h>

int main()
{
    int x,y,z;

    for (x=1; x<=5; x++)
    {
        for (y=1; y<x; y++)
        {
            for (z=1; z<y; z++)
            {
                printf("z's %d, ",z);
            }
            printf("\n");
            printf("y's %d -> ",y);
        }
        printf("\n");
        printf("------- x's %d ------- ",x);
    }
    return 0;
}

자, 갑자기 뭔가 괴랄해졌습니다. 이게... 이게 대체 뭐야!! 하겠지만. 그 누구보다도 for문을 쉽게 설명해드리겠습니다.

 

일단 우리가 직장에 다니고 있다 생각합시다. 월~금까지는 대부분의 직장인분들이 근무를 할겁니다.

즉, 5일간은 동일한 업무시간을 갖는다고 가정할 때, 이를 C언어로 표현한다면

printf("월요일입니다. 일 합시다.");
printf("화요일입니다. 일 합시다.");
printf("수요일입니다. 일 합시다.");
printf("목요일입니다. 일 합시다.");
printf("금요일입니다. 일 합시다.");

이렇게 나타낼 것입니다. 아, 근데 365일로 늘어난다하면 printf문을 365번이나 받아 적어야 합니다. 여간 귀찮은 일이 아닙니다. 그래서 등장한게 반복문입니다. 제목에 적은 바와 같이 반복문은 크게 3가지 유형으로 자주 쓰는데요.

 

첫번째로 볼 것이 for문입니다.

1. for문
for문의 구조를 먼저 봅시다. 제가 소스코드에 적은 내용을 보면요. for 옆에 여러가지 식들이 보입니다. 하나하나 구조를 살펴보겠습니다.

for ( 변수 초기값 선언, 변수에 대한 조건식, 변수의 증감식)
이런 식으로 나와있는데요. 제 소스코드를 보면 앞에서 x,y,z라는 정수형 자료타입의 변수들을 선언해 놨습니다.
그리고 제일 먼저 x의 초기값을 1이라고 정해놨습니다.

그러면 이제 x는 1을 시작점으로 해서 몇번까지 반복할 것인가? 를 추가로 정해줘야 합니다.  이게 변수에 대한 조건식입니다.
보시면 저는 1을 시작으로 해서 5까지의 범위 조건을 지정해놨습니다. 그러면 이제 1에서부터 5까지의 범위가 결정이 되었으니 어떤식으로 증감을 줄 것인지 고려해야 합니다.

저는 x를 1씩 증가시키기 위해서 x++ 라고 설정을 했습니다. 

* 주의해야할 점. for문에서 구조를 짤 때, 초기값 선언과 조건식은 쓰고나서 세미콜론 ; 을 적어줘야 합니다. 하지만 증감식의 경우는 세미콜론을 찍어주지 않습니다.

 

** ++라는 것은 증감 연산자의 한 종류입니다. 제가 미처 설명을 안한 부분인데 잠깐 이 의미를 보고자 합니다.

x = x+1;

위의 소스코드를 봅시다. 제가 x = x+1; 이라고 적었습니다. 근데 수학을 한번이라도 접하신 분들은 이게 맞는 식이에요? 라는 의문을 가질 것입니다.  예. 적어도 프로그래밍에서는 위의 식은 성립합니다.

x = x+1를 설명하기 위한 그림

프로그래밍에서는 일반적으로  '오른쪽에서 왼쪽으로 읽는다.' 라고 생각하셔도 됩니다. 즉, x = x+1라는 것은

오른쪽에 있는 x+1를  왼쪽에 있는 x라는 박스에 넣는다. 라고 생각하시면 됩니다. 자, 그럼 간단한 소스코드를 한번 짜보겠습니다.

x = x+1를 설명하기 위한 소스코드
결과값

저는 x에다가 5라는 값을 입력했습니다. 그 후, x의 값을 출력하기 전에  x = x+1을 적어두었습니다.

그래서 x = 5가  처음에 오른쪽에 있는 x + 1의 x에 들어갔습니다. 그 후, 오른쪽의 x+1을  왼쪽에 x라는 박스에다 집어 넣었습니다. 그래서 값이 6으로 나온 것입니다.

이처럼 변수의 값이 1씩 증가하는 식인 x=x+1을 보다 간단히 표현한 것이 x++입니다. ++는 1씩 증가해라. 라는 의미인데요. 그러면 눈치 빠르신 분들은 --는 당연히 1씩 감소해라! 라는 연산자임을 알게 됩니다.

 

자, 그러면

for (int i =1; i<=5; i++)
{
	printf("%d ",i);
 }
 
 return 0;

이 소스코드를 출력하면 1 2 3 4 5로 출력됨을 알 수 있습니다. 그럼 이중 for문은 뭘까요?

2중 for문을 설명하기 위한 그림

바로 이 그림을 보면 이해가 됩니다. 

x는 제가 소스코드를 작성할 때, 제일 먼저 구현한 첫번째 for문의 변수입니다. 1부터 시작한다할 때 쭉 값이 이어질텐데요. 이제 바로 아래에 y변수에 대한 for문을 입력했고 조건식에 y<x라고 적어두었습니다.

 

이 경우는 x=1일 경우 y는 0만이 해당됩니다. 근데, 제 소스코드를 보시면 y변수의 시작점을 1이라 잡았습니다.

즉, x=1만 출력되고 그 아래 y는 출력되지 않습니다.

 

그러면 x=2일 경우를 봅시다. x=2로 넘어갈 때, y<x에 맞는 값은 y=1입니다. 따라서, y=1까지만 출력됩니다.

그러면 x=3일 때는요? y<x 조건식에 따르면 y=1,2가 해당됩니다. 따라서 y=1, y=2까지만 출력됩니다.

마찬가지로 x=4라면 y=1,2,3이 해당 될 것입니다.  3중, 4중이 되어도 동일한 규칙이 적용될 것입니다.

마치 고등학교 때 배운 수열같은 개념이죠.

 

조건식을 꼭 y<x로 안해도 됩니다. y<=x라고 하면

 

x=1 , y=1

x=2, y=1,2

x=3, y=1,2,3

 

이런 식으로 출력이 되겠군요.

 

 

퀴즈

Q1. 다음 아래와 같은 결과값을 출력하는 소스코드를 작성해보세요. (이중 for문으로 구현할 것)

반응형
반응형

printf("Welcome, Let's C Language.");  // 초등학생도 쉽게 이해시켜주는 C언어 글을 포스팅합니다.

 

안녕하세요. 비전공자 출신 SW Test 엔지니어 Crush on Study입니다. 

이번 글에서는 조건에 따라 다른 화면을 출력시킬 수 있도록 해주는 '조건문'에 대해 배워보겠습니다.

 

Q. 먼저 이전 시간에 배운 내용을 잠깐 복습해봅시다.

A. 1) 주석처리에 대해 배웠습니다.

- 주석은 컴파일할 때 처리되지 않는 부분으로 100이면 100이 주석을 통해 소스코드에 대한 설명란으로 활용하고 있다 했습니다. 

 

2) \n (개행)에 대해 배웠습니다.

printf("안녕하세요. 저는 Crush on Study입니다.\n");
printf("잘 부탁드립니다.");

이런 소스코드가 주어졌을 때, 출력되는 예상 값은 

안녕하세요. 저는 Crush on Study입니다.

잘 부탁드립니다.

여야 합니다.  왜냐? \n이 적혀있기 때문입니다.

 

* 배열에 대해서도 간단히 짚어봤지만 배열은 패스하도록 하겠습니다. 추후에 자세히 다룰겁니다.

 

3) %s 형식지정자에 대해 배웠습니다.

- %c는 문자 하나만을 주고받는 형식지정자지만 %s는 문자 하나뿐만 아니라 문자열도 주고받는 형식지정자라 하였습니다. 따라서, %s가 %c보다 더 널리쓰인다고까지 배웠습니다. 그리고 이에 대응하는 자료형 타입은 char입니다.

 

 

딱 보고 기억 나는게 없다. 하면 바로 이 전글을 참고하세요.

https://crush-on-study.tistory.com/208

 

[C언어] #2. 주석 처리와 신상 정보 프로그램 구현하기

printf("Welcome, Let's C Language."); // 초등학생도 쉽게 이해시켜주는 C언어 글을 포스팅합니다. 안녕하세요. 비전공자 출신 SW Test 엔지니어 Crush on Study입니다. 이번 글에서는 주석 처리에 대한 소개와..

crush-on-study.tistory.com

조건문 소스코드

// # 3. 조건문 강의입니다. 

#include <stdio.h>

int main()
{   
    int choice=1;
    printf("Welcome to True or no.\n");
    printf("Let's check your truth.\n");

    printf("Are you MoSol? : ");
    scanf_s("%d",&choice);

    if (choice==1)
    {
        printf("Yes i respect you. wish your happy Mosol Life.\n");
        return 0;
    }

    else
    {
        printf("ok, you just Mosol.\n");
        return 0;
    }

	return 0;
}

소스코드들을 하나씩 살펴보겠습니다. 이제 대충 틀은 잡힙니다. printf, scanf_s를 사용하기 위해 전처리구문에 선언한 stdio.h 헤더파일. 그 후, 함수를 실행할 공간인 main함수를 잡고, 그 안에 소스코드를 입력하는 것이였죠.

근데 오늘 새로운 개념을 보게 되었습니다.

1. if
어원 그대로 if는 '만약에' 라는 뜻을 담고 있습니다. 공교롭게도 지금 태연 만약에 듣는 중인데 개띵곡이니까 들으러가십시오.
아무튼 if를 선언하면 옆에다가 이제 조건식을 적어줘야 합니다. 

직관적으로 봐도 if (choice==1) 의 구문을 보면 1을 선택할 때, 아래 { } 사이에 적힌 코드가 실행되도록 하는 것 같습니다. 그렇죠? 만약 위에서 choice로 1번을 입력받았다면, Yes i respect you. wish your happy Mosol Life.
이 문구가 출력될 것입니다.

자, 근데 바로 아래에 else 라는 명령어가 보입니다. 새로 보는 애군요. 근데 얘는 if처럼 옆에 따로 조건식이 없습니다. 

2. else
자, else의 뜻은 if에서 적은 조건문을 제외한 나머지에 해당하는 경우에 else의 몸통 {   } 안에 들은 내용을 수행해라. 이겁니다. 만약 위 소스코드에서 choice == 1이 아닌 0,2,27427,16,-273,...... 이런 값들을 적었다면 if 구문에 있는 애들은 수행을 안하고 else 구문에 있는 애들을 수행합니다.

출력 화면

네, 1이 아닌 다른 값을 아무거나 넣었더니 저보고 모솔이랍니다. 근데 저 결혼했는데 ㅋ.ㅋ

추가로 여기 소스코드엔 없지만 else if도 한번 보겠습니다.

else if는 옆에 조건식이 적혀있습니다. 어려운 개념은 아닙니다. if 조건식 이외에도 추가로 적어줄 조건문이 있다면 else if를 여러번 반복해서 써도 됩니다. 혹은 그냥 else 생략하고 if (조건식1) , if (조건식2) , if(조건식3)....  else  이런식으로 해도 됩니다.

 

근데 여러분. 만약 조건이 많은 프로그램을 구현해야할 경우, if 노가다를 하는게 여간 귀찮은게 아닙니다. 실행속도를 고려할 때도 그렇구요. 그래서 오늘 추가로 공부해볼 개념이 '논리 연산자'입니다.

 

우리가 보통 수학 공부할 때,  + - * / 같은 사칙연산을 마주한적이 많을거에요. 이런 사칙연산자를 '산술 연산자' 라고 합니다. 계산에 관련된 연산자입니다.  논리 연산자는 위의 소스코드에서도 잠깐 봤겠지만 '==' 같은 등호를 논리연산자라 합니다. 

즉, A == B 라는 말은 A와 B가 같다는 말입니다. 

 

Q. =랑 다른가요?

A. 같습니다. 근데 뒤에 나올 논리연산자들을 보면 다 기호가 1쌍(2개씩)을 이루고 있어서 그냥 ==로 똑같이 1쌍으로 통일하자~ 라는 의미에서 같게 적용된거라 보시면 됩니다.

  의미 예시
1. == 일치한다. A==B
A랑 B가 같다.
2. != 일치하지 않는다. A!=B
A랑 B가 다르다.
3. && AND 연산자. 앞의 조건식, 뒤의 조건식 둘다 만족해야 한다. A==1 && B ==5
A가 1, B가 5인 경우에만 구문을 실행해라.
4. || OR 연산자. 앞의 조건식 혹은 뒤의 조건식 둘 중 하나만 만족해도 된다. A == 1 || B == 5
A가 1이거나 B가 5면 구문을 실행해라.
이 경우는 둘다 1,5여도 실행한다.
5. %  (산술 연산자) 나머지 값만 보여준다. C = 5;  printf("%d",C%4);
출력값은 1. 왜냐? 5를 4로 나눴을 때 나머지 값은 1이니까.
6. >= , <= 크거나 같다. 혹은 작거나 같다. A>=B
A가 B보다 크거나 같으면 구문을 실행해라.

 

 

퀴즈

Q1. 소개팅을 나가려 한다. 근데 남자분의 키가 적어도 여자분의 키보다 컸으면 좋겠다. 여자분의 키가 163cm일 때, 남자분과의 매칭이 성사될 수 있도록 남자분의 키를 조건식을 사용해서 코드를 짜봐라. (if/else문과 논리연산자)

반응형

+ Recent posts