[C] C언어 300제 - 중급(3)
161. 디렉터리 생성하기(_mkdir)
• 소스
#include <stdio.h>
// #include <direct.h> // Windows 전용
#include <sys/stat.h>
#include <unistd.h>
int main()
{
char *pathname = "/Users/jeonjoonsu/Desktop/무제 폴더/무제 폴더";
// 디렉터리를 생성하며, 퍼미션은 0755 (rwxr-xr-x)
if (mkdir(pathname, 0755) == -1) // _mkdir()은 Windows 전용
{
perror("디렉터리 생성 에러");
}
else
{
puts("디렉터리를 성공적으로 생성하였습니다.");
}
}
• 설명
_mkdir() 함수는 생성할 디렉터리 경로를 받아 디렉터리를 생성하며 window 전용 함수이다.
mkdir() 함수는 디렉터리 경로와 권한 모드를 받아 디렉터리를 생성하며 macOS 및 Linux에서 사용 가능하다.
• 결과 화면

162. 디렉터리 삭제하기(_rmdir)
• 소스
#include <stdio.h>
// #include <direct.h> // Windows 전용
#include <sys/stat.h>
#include <unistd.h>
int main()
{
char *pathname = "/Users/jeonjoonsu/Desktop/무제 폴더/무제 폴더";
if (rmdir(pathname) == -1) // _rmdir()은 Windows 전용
{
perror("디렉터리 삭제 에러");
}
else
{
puts("디렉터리를 성공적으로 삭제하였습니다.");
}
}
• 설명
_mkdir() 함수는 디렉터리 경로를 받아 디렉터리를 삭제하며 window 전용 함수이다.
mkdir() 함수는 디렉터리 경로를 받아 디렉터리를 삭제하며 macOS 및 Linux에서 사용 가능하다.
• 결과 화면

163. 현재 작업중인 디렉터리 구하기 (_getcwd)
• 소스
// Windows
// #include <stdio.h>
// #include <stdlib.h>
// #include <direct.h>
// int main()
// {
// char pathname[_MAX_PATH];
// _getcwd(pathname, _MAX_PATH);
// puts(pathname);
// }
// macOS
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <limits.h> // PATH_MAX
int main()
{
char pathname[PATH_MAX];
if (getcwd(pathname, sizeof(pathname)) != NULL)
{
puts(pathname);
}
else
{
perror("현재 작업 디렉터리를 가져올 수 없습니다");
}
}
• 설명
_getcwd() 함수는 작업 디렉터리가 저장될 버퍼와 버퍼의 길이를 받아 현재 작업 디렉터리를 구하며 Window 전용 함수이다.
getcwd() 함수는 작업 디렉터리가 저장될 버퍼와 버퍼의 길이를 받아 현재 작업 디렉터리를 구하며 macOS 및 Linux에서 사용 가능하다.
• 결과 화면

164. 현재 작업중인 디렉터리 변경하기 (_chdir)
• 소스
// Windows
// #include <stdio.h>
// #include <stdlib.h>
// #include <direct.h>
// int main()
// {
// char pathname[_MAX_PATH] = "/Users/jeonjoonsu/Desktop/무제 폴더/무제 폴더";
// if(_chdir(pathname) == 0) // error : -1
// {
// _getcwd(pathname, _MAX_PATH);
// puts(pathname);
// }
// }
// macOS
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <limits.h>
int main()
{
const char *new_path = "/Users/jeonjoonsu/Desktop/무제 폴더";
char pathname[PATH_MAX];
if (chdir(new_path) == 0) // 현재 작업 디렉토리 변경
{
if (getcwd(pathname, sizeof(pathname)) != NULL) // 현재 디렉토리 경로 얻기
{
puts(pathname);
}
else
{
perror("작업 디렉터리 경로 가져오기 실패");
}
}
else
{
perror("작업 디렉터리 변경 실패");
}
}
• 설명
_chdir() 함수는 변경될 디렉터리의 이름을 받아 현재 작업 디렉터리를 변경하며 Window 전용 함수이다.
chdir() 함수는 변경될 디렉터리의 이름을 받아 현재 작업 디렉터리를 변경하며₩ macOS 및 Linux에서 사용 가능하다.
• 결과 화면

165. 현재 작업중인 드라이브 구하기 (_getdrive)
• 소스
// Windows
#include <stdio.h>
#include <direct.h>
int main()
{
int drive;
drive = _getdrive();
printf("현재 드라이브 : %c \n",'A'+drive-1);
// 출력 : 현재 드라이브 : c
}
// macOS
// macOS 및 Linux에는 드라이브 개념이 없음
• 설명
_getdrive() 함수는 현재 드라이브를 구하며 Window 전용 함수이다. macOS 및 Linux에는 드라이브 개념이 없다.
• 결과 화면

166. 현재 작업중인 드라이브 변경하기 (_chdrive)
• 소스
// Windows
#include <stdio.h>
#include <direct.h>
int main()
{
int drive = 4;
if(_chdrive(drive) == 0) // error : -1
{
drive = _getdrive();
printf("변경된 드라이브 : %c \n",'A'+drive-1);
}
// 출력 : 변경된 그라이브 : D or 드라이브 변경 실패: Permission denied
}
// macOS
// macOS 및 Linux에는 드라이브 개념이 없음
• 설명
_chdrive() 함수는 변경할 드라이브를 숫자로 표현한 값을 받아 현재 작업 드라이브를 변경하는 Window 전용 함수이다. macOS 및 Linux에는 드라이브 개념이 없다.
• 결과 화면

167. 표준 입•출력 스트림 사용하기 (stdin, stdout)
• 소스
// Windows
#include <stdio.h>
int main()
{
printf("그대여 한 순간 조차 잊지 말아요~");
}
// 컴파일 후에 다음을 터미널에 입력
// 167.exe > file.txt
// 그러면 file.txt 파일이 생성된다.
• 설명
컴파일 후에 터미널에 167.exe > file.txt를 입력하면 그러면 file.txt 파일이 생성된다.
Window에서는 파일이 생성되지만, macOS에서는 에러가 발생하며 사용하지 못한다.
• 결과 화면

168. 현재까지 경과된 초의 수 구하기 (time)
• 소스
#include <stdio.h>
#include <time.h>
int main()
{
time_t now;
time(&now);
printf("1970년 1월 1일 부터 현재까지 경과된 초 : %ld \n",now);
}
• 설명
time() 함수는 경과된 시간을 읽어올 변수를 받아 1970년 1월 1일 0시를 기준으로 해서 현재까지 경과된 초의 수를 반환한다.
• 결과 화면

169. 날짜 및 시간 구하기 1 (locltime)
• 소스
#include <stdio.h>
#include <time.h>
int main()
{
time_t now;
struct tm t;
time(&now);
t = *localtime(&now);
printf("현재 날짜 및 시간 : %4d.%d.%d %d:%d:%d \n",
t.tm_year+1900, t.tm_mon+1, t.tm_mday,
t.tm_hour, t.tm_min, t.tm_sec);
}
• 설명
localtime() 함수는 time_t 타입의 시간 값을 받아, 이를 현지 시간(로컬 타임존 기준)으로 변환한 struct tm 구조체 포인터를 반환하는 함수입니다.
• 결과 화면

170. 날짜 및 시간 구하기 2 (_ftime)
• 소스
// Windows
#include <stdio.h>
#include <time.h>
#include <sys/timeb.h>
int main()
{
struct _timeb tb;
struct tm t;
_ftime(&tb);
t = *localtime(&tb.time);
printf("현재 날짜 및 시간 : %4d.%d.%d %d:%d:%d \n",
t.tm_year+1900, t.tm_mon+1, t.tm_mday,
t.tm_hour, t.tm_min, t.tm_sec);
}
// 출력 : 현재 날짜 및 시간 : 2025.6.24 23:10:32
• 설명
_ftime() 함수는 날짜 및 시간이 읽어진 _timeb 구조체 버퍼를 받아 현재 날짜 및 시간을 구하며 Window 전용 함수이다.
• 결과 화면

171. 세계 표준 시 구하기 (gmtime)
• 소스
#include <stdio.h>
#include <time.h>
int main()
{
time_t now;
struct tm t;
time(&now);
t = *gmtime(&now);
printf("세계 표준 시간 : %4d.%d.%d %d:%d:%d \n",
t.tm_year+1900, t.tm_mon+1, t.tm_mday,
t.tm_hour, t.tm_min, t.tm_sec);
}
• 설명
gmtime() 함수는 time_t 타입의 시간 값을 받아서, UTC(협정 세계시) 기준의 시간으로 변환해주는 함수입니다.
• 결과 화면

172. 날짜 및 식간을 문자열로 변환하기 (ctime)
• 소스
#include <stdio.h>
#include <time.h>
int main()
{
time_t now;
time(&now);
printf("현재 날짜 및 시간: %s",ctime(&now));
}
• 설명
ctime() 함수는 time_t 타입의 시간 값을 받아서, 사람이 읽기 쉬운 문자열 형태의 현지(local) 시간으로 변환해주는 함수입니다.
• 결과 화면

173. 날짜 및 시간을 더하거나 빼기 (mktime)
• 소스
#include <stdio.h>
#include <time.h>
int main()
{
time_t now;
struct tm t;
time(&now);
t = *localtime(&now);
t.tm_mday += 100;
mktime(&t);
printf("현재 날짜에 100일 더한 날짜 : %4d.%d.%d %d:%d:%d \n",
t.tm_year+1900, t.tm_mon+1, t.tm_mday,
t.tm_hour, t.tm_min, t.tm_sec);
}
• 설명
mktime() 함수는 struct tm 구조체에 저장된 현지(local) 시간 정보를 time_t 형식(UNIX 시간, 초 단위)으로 변환하는 함수이다.
• 결과 화면

174. 날짜 및 시간의 차이 구하기 (difftime)
• 소스
#include <stdio.h>
#include <time.h>
int main()
{
time_t s1, s2;
double gop;
int i;
time(&s1);
for(i=0; i<100000000; i++)
{
gop = gop * 100;
}
time(&s2);
printf("경과시간 : %g 초 \n", difftime(s2,s2));
}
• 설명
difftime() 함수는 종료 시간과 시작 시간을 받아 두 시간의 차이를 구한다.
• 결과 화면

175. 날짜 및 시간을 미국식으로 변환하기 (asctime)
• 소스
#include <stdio.h>
#include <time.h>
int main()
{
time_t now;
struct tm t;
now = time(NULL);
t = *localtime(&now);
printf("현재 날짜 및 시간 : %s \n", asctime(&t));
}
• 설명
asctime() 함수는 struct tm 구조체에 저장된 날짜 및 시간 정보를 사람이 읽을 수 있는 문자열로 변환해주는 함수이다.
• 결과 화면

176. 날짜 및 시간을 형식화하기 (strftime)
• 소스
#include <stdio.h>
#include <time.h>
int main()
{
time_t now;
struct tm t;
char buff[100];
now = time(NULL);
t = *localtime(&now);
strftime(buff,sizeof(buff),"%Y-%m-%d %I%M%S %p",&t);
puts(buff);
}
• 설명
strftime() 함수는 struct tm 구조체에 저장된 날짜와 시간 정보를 지정한 형식(format)에 따라 문자열로 변환해주는 함수이다.
• 결과 화면

177. 삼각 함수 사인 값 구하기 (sin)
• 소스
#include <stdio.h>
#include <math.h>
int main()
{
double x;
x = sin(1);
printf("sin(1) : %g \n",x);
}
• 설명
sin() 함수는 라디안 단위의 실수형 각도를 입력 받아, 해당 각도의 사인 값을 반환하는 함수이다.
• 결과 화면

178. 삼각 함수 아크 사인 값 구하기 (asin)
• 소스
#include <stdio.h>
#include <math.h>
int main()
{
double x;
x = asin(0.5);
printf("asin(0.5) : %g \n",x);
}
• 설명
asin() 함수는 아크사인 함수로, 주어진 값의 사인값이 되는 각도를 라디안 단위로 반환한다.
즉, 사인 값에서 각도를 구하는 함수이다.
• 결과 화면

179. 삼각 함수 x / y에 대한 아크 탄젠트 값 구하기 (atan2)
• 소스
#include <stdio.h>
#include <math.h>
int main()
{
double x;
x = atan2(1.0,1.0);
printf("atan2(1.0,1.0) : %g \n",x);
}
• 설명
atan2(y, x) 함수는 2개의 좌표 (y, x) 를 받아, 해당 점이 이루는 각도를 라디안(radian) 단위로 반환하는 함수이다.
• 결과 화면

180. 지수 함수 지수값 구하기 (exp)
• 소스
#include <stdio.h>
#include <math.h>
int main()
{
double x;
x = exp(1.0);
printf("exp(1.0) : %g \n",x);
}
• 설명
자연상수 e (약 2.71828...) 의 거듭제곱을 계산하는 함수이며, 입력값 x에 대해 exe^x 값을 반환한다.
• 결과 화면

181. 로그 함수 자연 로그값 구하기 (log)
• 소스
#include <stdio.h>
#include <math.h>
int main()
{
double x;
x = log(2.0);
printf("log(2.0) : %g \n",x);
}
• 설명
log () 함수는 자연로그(ln), 즉 밑이 e(≈2.71828) 인 로그를 계산하는 함수이며, 입력값 x에 대해 ln(x)\ln(x) 값을 반환한다.
• 결과 화면

182. 로그 함수 밑수를 10으로 하는 로그값 구하기 (log10)
• 소스
#include <stdio.h>
#include <math.h>
int main()
{
double x;
x = log10(2.0);
printf("log10(2.0) : %g \n",x);
}
• 설명
log10 () 함수는 밑이 10인 로그를 계산하는 함수이며, 입력값 x에 대해 log10(x)\log_{10}(x) 값을 반환한다.
• 결과 화면

183. 제곱근 구하기 (sqrt)
• 소스
#include <stdio.h>
#include <math.h>
int main()
{
double x;
x = sqrt(4.0);
printf("sqrt(4.0) : %g \n",x);
}
• 설명
sqrt () 함수는 제곱근(square root)을 계산하는 함수이며, 입력값 x에 대한 제곱근 값을 반환한다.
• 결과 화면

184. 절대값 구하기 (abs)
• 소스
#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("abs(1) : %d \n",abs(1));
printf("abs(-1) : %d \n",abs(-1));
}
• 설명
abs() 함수는 정수형(int)의 절댓값을 반환하는 함수입니다.
• 결과 화면

185. 주어진 값보다 작지 않은 최소 정수값 구하기 (ceil)
• 소스
#include <stdio.h>
#include <math.h>
int main()
{
printf("ceil(1.0) : %g \n",ceil(1.0)); // 1
printf("ceil(1.1) : %g \n",ceil(1.1)); // 2
printf("ceil(1.9) : %g \n",ceil(1.9)); // 2
printf("ceil(2.5) : %g \n",ceil(2.5)); // 3
printf("ceil(-2.5) : %g \n",ceil(-2.5)); // -2
printf("ceil(-3.0) : %g \n",ceil(-3.0)); // -3
}
• 설명
ceil () 함수는 입력된 실수값보다 크거나 같은 가장 작은 정수를 반환하는 함수이며, 올림(ceiling) 함수이다.
• 결과 화면

186. 주어진 값보다 크지 않은 최대의 정수값 구하기 (floor)
• 소스
#include <stdio.h>
#include <math.h>
int main()
{
printf("floor(1.0) : %g \n",floor(1.0)); // 1
printf("floor(1.1) : %g \n",floor(1.1)); // 1
printf("floor(1.9) : %g \n",floor(1.9)); // 1
printf("floor(2.5) : %g \n",floor(2.5)); // 2
printf("floor(-2.5) : %g \n",floor(-2.5)); // -3
printf("floor(-3.0) : %g \n",floor(-3.0)); // -3
}
• 설명
floor () 함수는 입력된 실수값보다 작거나 같은 가장 큰 정수를 반환하는 함수이며, 내림(floor) 함수이다.
• 결과 화면

187. 주어진 값을 정수와 소수로 분리하기 (modf)
• 소스
#include <stdio.h>
#include <math.h>
int main()
{
double x = 2.3, n, y;
y = modf(x,&n);
printf("2.3을 정수와 소수로 분리하면, %g와 %g이다. \n",n,y);
}
• 설명
modf () 함수는 실수(double)를 정수 부분과 소수 부분으로 분리해 주는 함수이다.
입력값을 정수 부분과 소수 부분으로 나누어, 정수 부분은 포인터 인자로 반환하고, 함수 반환값으로는 소수 부분을 돌려준다.
• 결과 화면

188. x의 y승 구하기 (pow)
• 소스
#include <stdio.h>
#include <math.h>
int main()
{
double x = 10.0, y = 3.0, r;
r = pow(x,y);
printf("10의 3승은 %g이다. \n",r);
}
• 설명
거듭제곱을 계산하는 함수이며, x의 y승을 계산하여 반환한다.
• 결과 화면

189. 난수 구하기 (srand, rand)
• 소스
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
int main()
{
int i;
srand((unsigned)time(NULL)); // 난수 발생기를 초기화
for(i=0; i<5; i++)
{
printf("난수 %d : %d \n",i,rand());
}
}
• 설명
rand () 함수는 0부터 RAND_MAX(보통 32767 이상) 사이의 의사 난수를 반환하는 함수이다.
난수 생성기를 초기화하지 않으면 항상 같은 순서의 난수를 생성한다.
srand () 함수는 rand() 함수가 생성하는 난수의 시작점을 설정하는 함수이다.
보통 프로그램 실행 시 한 번 호출하여 시드를 설정해야, 매 실행 시 다른 난수를 얻을 수 있다.
시드가 같으면 rand()가 반환하는 난수의 순서도 같다.
• 결과 화면

190. 숫자 정렬하기 (qsort)
• 소스
#include <stdio.h>
#include <stdlib.h>
int intcmp(const void* v1, const void* v2);
int main()
{
int i;
int array[5] = {5,3,1,2,4};
qsort(array,5,sizeof(array[0]),intcmp);
for(i=0; i<5; i++)
{
printf("%d",array[i]);
}
}
int intcmp(const void* v1, const void* v2)
{
int cmpvalue1, cmpvalue2;
cmpvalue1 = *(int*)v1;
cmpvalue2 = *(int*)v2;
return cmpvalue1 - cmpvalue2;
}
• 설명
qsort () 함수는 배열 정렬 함수로, 퀵 정렬 알고리즘을 기반으로 하며, 매우 유연해서 다양한 자료형을 정렬할 수 있다.
정렬할 배열의 시작 주소, 배열 요소의 개수, 각 요소의 크기, 두 요소를 비교하는 함수 포인터를 매개변수로 받아 정렬한다.
• 결과 화면

191. 이진 검색 사용하기 (bsearch)
• 소스
#include <stdio.h>
#include <stdlib.h>
#include <search.h>
int intcmp(const void* v1, const void* v2);
int main()
{
int key = 5, *ptr;
int array[10] = {150,27,33,1,5,100,99,75,81,10};
qsort(array,10,sizeof(array[0]),intcmp);
ptr = bsearch(&key,array,10,sizeof(array[0]),intcmp);
if(ptr)
{
puts("5를 찾았습니다.");
}
}
int intcmp(const void* v1, const void* v2)
{
int cmpvalue1, cmpvalue2;
cmpvalue1 = *(int*)v1;
cmpvalue2 = *(int*)v2;
return cmpvalue1 - cmpvalue2;
}
• 설명
bsearch() 함수는 이진 탐색(binary search)함수이며, 이미 정렬된 배열에서 특정 값을 빠르게 찾을 때 사용한다.
• 결과 화면

192. 매크로 상수 정의하기
• 소스
#include <stdio.h>
#define program void main(void)
#define println printf
#define MAX 100
#define MIN 0
program
{
println("MAX : %d, MIN : %d \n",MAX,MIN);
}
• 설명
• 결과 화면

193. 매크로 함수 정의하기 1
• 소스
#include <stdio.h>
#define max(x,y) x > y ? x : y
#define min(x,y) x < y ? x : y
int main()
{
printf("최대값 : %d \n",max(5,3));
printf("최소값 : %d \n",min(5,3));
printf("최대값 : %g \n",max(3.5,4.4));
printf("최소값 : %g \n",min(3.5,4.4));
}
• 설명
• 결과 화면

194. 매크로 함수 정의하기 2
• 소스
#include <stdio.h>
#define x_i(x,i) printf("x%s의 값은 %d이다.\n",#i,x##i)
int main()
{
int xa = 3, xb =5;
x_i(x,a);
x_i(x,b);
}
• 설명
매크로 정의 시 매개변수에 #을 사용하면 실매개변수 자체를 문자열로 치환한다.
그리고 ##을 사용하면, ##좌우의 매개변수를 연결하여 하나의 매개변수로 만들어 준다.
즉, x_i 매크로에서 #i는 문자열로 치환되며, x##i는 xi 변수로 치환된다.
• 결과 화면

195. 매크로 상수가 선언되었는지 검사하기
• 소스
#include <stdio.h>
#define COUNT 100
#if !defined COUNT
#define COUNT 90
#endif
int main()
{
printf("COUNT : %d \n", COUNT);
}
• 설명
#if !defined COUNT : COUNT가 정의되었는지 확인하고 #endif 문으로 종료한다.
• 결과 화면

196. 매크로 컴파일 에러 출력하기
• 소스
#include <stdio.h>
#if !defined COUNT
#error "COUNT MACRO is not defined!"
#endif
int main()
{
printf("COUNT : %d \n", COUNT);
}
• 설명
#error로 특정 매크로가 정의되지 않았을 때 경고 대신 컴파일 오류로 명확하게 알려주기 위해 사용한다.
• 결과 화면

197. 매크로 상수의 값을 검사하기
• 소스
#include <stdio.h>
#define COUNT 100
#if COUNT != 100
#error "COUNT != 100"
#endif
int main()
{
printf("COUNT : %d \n", COUNT);
}
• 설명
#if문으로 매크로 상수를 비교하고 #endif문으로 종료한다.
• 결과 화면

198. 매크로 상수의 선언을 취소하기
• 소스
#include <stdio.h>
#define COUNT 100
#if defined COUNT
#undef COUNT
#define COUNT 99
#else
#define COUNT 88
#endif
int main()
{
printf("COUNT : %d \n", COUNT);
}
• 설명
#undef로 매크로 상수의 선언을 취소한다.
• 결과 화면

199. 경고 에러를 발생시키지 않기
• 소스
#include <stdio.h>
#pragma warning(disable:4101)
int main()
{
int i;
}
• 설명
경고 에러 C4101을 출력하지 말라고 컴파일러에게 지시한다.
(Windows 환경의 MSVC 컴파일러 전용)
• 결과 화면

200. 내장된 매크로 사용하기
• 소스
#include <stdio.h>
void show_info() {
printf("현재 함수명: %s\n", __func__);
}
int main() {
printf("파일명 : %s\n", __FILE__);
printf("날 짜 : %s\n", __DATE__);
printf("시 간 : %s\n", __TIME__);
printf("줄 수 : %d\n", __LINE__);
show_info();
#ifdef __STDC__
printf("ANSI C 지원 여부: Yes (__STDC__ = %d)\n", __STDC__);
#endif
#ifdef __STDC_VERSION__
printf("C 표준 버전: %ld\n", __STDC_VERSION__);
#endif
}
• 설명
내장 매크로를 사용하면 로깅, 디버깅 메시지, 빌드 정보 출력에 매우 유용하게 사용 가능하다.
예를 들면 에러 로그를 남길 때 __FILE__, __LINE__, __func__를 사용하면 정확한 위치 추적 가능하다.
• 결과 화면

이 글은 초보자를 위한 C언어 300제 (김은철 지음, 정보문화사)을 참고하여 작성했습니다.