티스토리 뷰

C | 자료구조

[C] C프로그래밍 실습 (1)

rimo (리모) 2022. 9. 22. 04:48

'C 프로그래밍 실습'에서는 1학년 때 C를 배우면서 했던 실습 내용들을 모아 볼 예정입니다. 제가 처음 배웠던 언어는 파이썬이었는데요. 대학을 가서 처음으로 프로그래밍을 배운 저에게 파이썬은 너무나 어려운 언어였습니다. 프로그래밍적 사고를 익히게 해준건 다음으로 배운 C언어였죠.  정리를 하면서 의미를 되새겨 보려고 합니다.

 

기초부터 시작합니다.

 


 

Hello Wolrd!

#include <stdio.h>
int main(void)
{
	printf("Hello World! \n");      // Hello World 출력
	return 0;
}

먼저 #iclude를 사용해 studio(standard input output) 헤더 파일을 가져온다. main 함수를 정의한 뒤 printf 함수로 문자열 “Hello World”를 출력한다. 마지막으로 0을 반환하여 종료한다.

 

 

 

+ #include <stdio.h>가 뭘까?

stdio.h는 해석하면 표준 입출력 헤더 파일을 말합니다.  위에서 사용한 printf부터 putchar, puts, getchar, scanf, fopen, fget... 등등 여러 함수들이 정의되어있습니다.  이 함수들을 이용하기 위해서는 include 명령어를 사용해 헤더 파일을 불러와야 합니다. 위 프로그램에서는 printf를 사용해 Hello Wolrd! 를 출력하기 위해 사용된 것이죠. 

 

 

+ main함수는 왜 int형일까?  return 0;는 꼭 써야할까?

C언어 표준에서는 main함수를 int형으로 선언하도록 되어있습니다. 따라서 반환 값이 꼭 있어야 하는데 보통 return 0;를 적곤 합니다. 이게 프로그램 내에서 사용되는 값이 아니라 문득, 굳이 적어하나?라는 의문이 들 수 있습니다. 하지만 return 0는 의미 없는 값이 아니라 프로그램의 종료 상태를 OS에게 알리는 값입니다. 대부분의 OS에서 0은 정상종료 1은 비정상 종료를 의미합니다. 위의 코드는 'Hello World를 출력하고 정상 종료하세요.'가 되겠네요.

 

 

 

 

 

printf 함수로 여러 문장 출력하기

#include <stdio.h>
int main(void)
{
	printf("안녕하세요? \n");     // 안녕하세요? 출력
	printf("인사드립니다. \n");   // 인사드립니다. 출력
	return 0;   
}

 

#include <stdio.h>
int main(void)     
{
	printf("이름 : 홍길동 \n");	  // 이름: 홍길동 출력
	printf("주소: 서울시 종로구 \n");  // 주소 : 서울시 종로구 출력
	printf("전화번호: 111-2222 \n");  // 전화번호 : 111-2222 출력
	return 0;    
}

 

 

 

 

형식지정자 %d

#include <stdio.h>
int main(void)
{
	int price = 22000;
	printf("제품의 가격은 %d원입니다. \n", price);    //%d 형식지정자, 정수형으로 출력
	return 0;
}

 

int형 변수 price를 22000으로 초기화한다. 형식 지정자 %d를 이용하여 '제품의 가격은 22000입니다'를 출력한다.

 


 

자료형과 형식지정자

#include <stdio.h>                    
int main(void)  
{
	short i;                       // short(정수형)변수 i선언
	i = 32767;
	printf("i= %d\n", i);           // i= 32767 출력
	
    return 0;
}

형식지정자 %d를 사용해 short형(-32,768 ~ 32,767) 변수 i를 10진수 형태로 출력하는 프로그램이다. 

 

 

 

 

형식지정자 %o

// i의 값을 형식 지정자 o%를 사용해 8진수 형태로 출력
#include <stdio.h>
int main(void)
{
	short i;
	i = 32767;
	printf("i= %o\n", i);          // i= 77777
	
    return 0;
}

 

 

 

형식지정자 %x

// i의 값을 형식지정자 x%를 사용해 16진수 형태로 출력
#include <stdio.h>
int main(void)
{
	short i;
	i = 32767;
	printf("i= %x\n", i);     // i= 7fff

	return 0;
}

 

 

 

 

오버플로우

#include <stdio.h>
int main(void)
{
	short i;
	i = 32768;
	printf("i= %d\n", i); // i= -32768

	return 0;
}

'i = 32768'이 출력되어야 하나, 음수 값이 출력된 것을 볼 수 있다. 이는 short형이 표현할 수 있는 정수 값의 범위를 넘어버린, 일명 오버플로우가 일어났기 때문이다.

 

 

+ 오버플로우가 일어나면 왜 최소값부터 시작이 될까?

흔히 자료형의 범위가 원처럼 이어져있어 오버플로우나 언더플로우가 일어나면 초과한 만큼 더하거나 빼라고 합니다. 왜 그럴까요? 이진법으로 계산을 직접 해보면 확실히 알 수 있습니다. 위의 short는 부호형 변수이고 2바이트의 크기를 가지고 있습니다. 맨 앞 자리수는 부호를 표시합니다. (0:양수, 1 음수) 따라서 표현할 수 있는 최대값은 0111 1111 1111 1111 (32767)이 되죠. 여기에 1을 더하니 1000 0000 0000 0000이 되면서 -32768로 해석되는 것입니다.

 

 

 

 

unsigned 자료형

#include <stdio.h>
int main(void)
{
	unsigned short i;  // 비부호형 0 ~ 65535
	i = 32768;
	printf("i= %d\n", i); // i= 32768

	return 0;
}

올바르게 출력된 것을 볼 수 있다. unsinged short기 때문에 범위를 확장하여 65535까지 표현할 수 있게 되었기 때문이다.

 

 

 

 

 

부동소수점

#include <stdio.h>
int main(void)
{
	float x;
	x = 1.2345678901234567890;
	printf("x = %10.20f\n", x);    // %10.20f : 전체 출력 필드의 크기10, 소수는 20 자리
	
	return 0;
}

형식지정자로 소수점 20자리까지 표현할 수 있도록 하였으나, float형은 6개 정도의 유효 숫자를 저장할 수 있으므로 8번째 자릿수부터는 정확한 값이 출력되지 않는 것을 확인할 수 있다.

 

 

 

 

부동소수점 자료형의 오버플로우

#include <stdio.h>
int main(void)
{
	float x;
	x = 1e39;    
	printf("x = %10.20f\n", x);  // inf

	return 0;
}

 

float가 저장할 수 있는 범위를 넘어 오버플로가 발생하였다. 실수형 변수들의 경우 최소값으로 되돌아가지 않고 inf가 출력된다.

 

 

#include <stdio.h>
int main(void)
{
	float x;
	x = 1.23456e-46;
	printf("x = %10.20f\n", x);
	
	return 0;
}

float가 표현할 수 있는 정밀도 보다 작은 숫자기에 잘 표현되지 않은 것을 확인할 수 있다.

 

 

 

 

 

double과 float의 차이점

#include <stdio.h>
int main(void)
{
	double x;
	x = 1.234567891234567890;
	printf("x = %10.20f\n", x);
	
	return 0;

}

double형은 float형보다 정밀도가 높기에 소수점이 제대로 표기되는 것을 볼 수 있다. 

 

 

 

 

 

형식지정자 %lf

#include <stdio.h>
int main(void)

{
	double x;

	printf("실수를 입력하십시오:");
	scanf("%lf",&x); // 실수형 입력받기

	printf("실수형식으로는 %f입니다. \n", x);  // 89.567000
	printf("지수형식으로는 %e입니다.\n", x);   // 8.956700e+01

	return 0;
}

실수 형식을 출력할 때는 %f(또는 lf) 지수 형식을 출력할 때는 %e를 사용할 수 있다.

 

 

 

 

평 계산하기

// 평계산기
#include <stdio.h>
#define SQMETER_PER_PYEONG 3.3058

int main(void)
{
	double x, y;

	printf("평을 입력하세요 :");
	scanf("%lf", &x);

	y = SQMETER_PER_PYEONG * x;
	printf("%lf 평방미터입니다", y);

	return 0;
}

 

근접한 평방미터 계산을 위해 SQMETER_PER_PYEONG를 정의해 계산에 사용하였으며 소수점까지 자세히 나타내기 위해 double형을 이용하였다.

 

 


 

scanf

#include <stdio.h>
int main(void)
{
	double x, y;

	printf("x의 값을 입력하시오 :");
	scanf("%lf", &x);

	y = 3*x*x*x-7*x*x+9;
	printf("다항식의 값은 %lf입니다.", y);

	return 0;
}

scanf를 사용하여 실수를 입력받아 \(3x^3 - 7x^2 + 9\) 값을 출력하는 프로그램이다. 

 

 

 

+ C4996, CRT_SECURE_NO_WARNINGS?  scanf_s를 사용해야 할까?

Visual Studio 2005 이상부터 scanf 등을 사용할 때 해당 오류가 발생하는 것을 확인할 수 있습니다. 먼저 오류가 발생하는 이유는 안정성 때문입니다. C에서 문자열이나 파일을 읽어들일 때 버퍼나 스택 등 메모리 오류가 발생하는 것을 막기 위함인데, 때문에 크기를 명시하도록 하는 _s 함수의 사용을 권장합니다. (저도 지금은 _s 함수를 사용하려 노력하는 편입니다.)

 

 

++ 아래 문장 중 하나를 소스코드 첫 줄에 써넣으면 오류가 발생하지 않는다!

#define _CRT_SECURE_NO_WARNINGS 

#pragma warnings(disable: 4996)

 

 

 

 

 

scanf로 정수 입력받기

#include <stdio.h>                      
int main(void)
{
	int x, y;

	printf("첫 번째 정수를 입력하시오:");
	scanf("%d", &x);     // 10진수 정수형으로 x값 받기
	printf("두 번째 정수를 입력하시오:");
	scanf("%d", &y);    // 10진수 정수형으로 y값 받기
    
	// 몫은 3이고 나머지는 1입니다.
	printf("몫은 %d이고 나머지는 %d입니다.", x / y, x % y); 

	return 0;
}

 

#include <stdio.h>                      
int main(void)
{
	int x, y;        

	printf("첫 번째 정수를 입력하시오:");
	scanf("%d", &x);   // 10진수 정수형으로 x값 받기
	y = x*x*x;
	printf("세제곱값은 %d*%d*%d = %d입니다.",x,x,x, y);

	return 0;
}

 

 

 

scanf로 여러개의 정수 한번에 입력받기

#include <stdio.h>                      
int main(void)
{
	int x, y, z, answer;

	printf("정수를 3개 입력하시오:");
	scanf("%d %d %d", &x, &y, &z); // 정수 3개 한번에 입력받기
	answer = x * y - z;
	printf("%d*%d-%d = %d ", x, y, z, answer);

	return 0;
}

 

 

 

 

 

자리수 분리해 출력하기

#include <stdio.h>                      
int main(void)
{
	int x;

	printf("정수를 입력하시오:");
	scanf("%d", &x);
	printf("백의 자리수 :%d\n",x/100);
	x = x % 100;
	printf("십의 자리수 :%d\n",x/10);
	x = x % 10;
	printf("일의 자리수 :%d\n",x);

	return 0;
}

 

세 자리 정수를 입력받은 뒤, 각 자릿수를 분리하여 출력하는 프로그램이다. scanf를 사용하여 x를 입력받고 x를 100으로 나눈 몫을 백의 자리로 출력, 나머지를 x에 다시 저장한 뒤 다시 10으로 나누어 십의 자리 출력, 그 나머지를 다시 x의 저장한 뒤 일의 자리로 출력한다. 

 

 

 

 

 

수식 계산하기

#include <stdio.h>                      
int main(void)
{
	int x;
	double y;

	printf("정수를 입력하시오:");
	scanf("%d", &x);
	y = (x*x*x-20.0)/(x-7.0);
	printf("수식의 값은 %lf입니다.", y);

	return 0;
}

 

 

 

 

정수부 구하기

#include <stdio.h>                      
int main(void)
{

	double x, y;
	int a;
    
	printf("2개의 실수를 입력하시오:");
	scanf("%lf %lf", &x, &y);
	a = x + y;
	
	printf("합의 정수부 = %d ", a);     

	return 0;
}

두 개의 실수를 입력받은 후 정수 부분의 합만을 출력하는 프로그램이다. 실수를 입력받기 위한 double형 변수 x, y와 정수부를 저장할 정수형 변수 a를 선언한다. scanf를 사용하여 실수 x, y를 입력받고, x+y의 결과를 a에 저장한다. 저장이 되면서 형 변환이 일어나 정수부만이 출력되는 것을 확인할 수 있다.

 

 

 

 

 

점과 점사이의 거리 구하기

#include <stdio.h> 
#include <math.h>
int main(void)
{
	int x1, x2, y1, y2;

	printf("첫번째 점 (x1,y1):");
	scanf("%d %d", &x1, &y1);
	printf("두번째 점 (x2,y2):");
	scanf("%d %d", &x2, &y2);
 
 	//sqrt = 제곱근 pow(a,b)= a의 b승
	printf("Distance= %lf ", sqrt(pow(x2 - x1, 2) + pow(y2 - y1, 2)));
    
	return 0;
}

 

두 개의 점의 좌표를 입력받아 점과 점 사이의 최단거리를 구하는 프로그래밍이다. math.h의 함수들을 이용하였다. 두 점의 좌표를 저장할 변수 x1, x2, y1, y2를 선언하고 scanf를 사용하여 점의 좌표를 입력받는다. 그리고 점과 점 사이의 거리 공식을 이용해 최단 거리를 계산한다.  

 

 

 

 

감사합니다.

 


공부한 내용을 복습/기록하기 위해 작성한 글이므로 내용에 오류가 있을 수 있습니다.

 

댓글
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Total
Today
Yesterday