Devel FilterCSkeleton
Skeleton Filter Program in C ¶1.1. Output Messages ¶ÇÊÅÍ ÇÁ·Î±×·¥Àº ¾î¶² »óȲÀÌ ¹ß»ýÇßÀ» ¶§, »ç¿ëÀÚ¿¡°Ô º¸°íÇϰųª, ¿¡·¯¸¦ Ãâ·ÂÇÒ ¶§°¡ Á¾Á¾ ¹ß»ýÇϱ⠶§¹®¿¡, °æ°í ¶Ç´Â ¿¡·¯ ¸Þ½ÃÁö¸¦ ³» º¸³»´Â °æ¿ì°¡ ÀÖ½À´Ï´Ù. ÇÊÅÍ ÇÁ·Î±×·¥Àº ±âº»ÀûÀ¸·Î ó¸®ÇÑ µ¥ÀÌÅ͸¦ Ç¥ÁØ Ãâ·ÂÀ» ÅëÇØ ³» º¸³»¹Ç·Î, ÀÌ·± ¸Þ½ÃÁöµéÀ» Ç¥ÁØ ÀÔ·ÂÀ¸·Î º¸³½´Ù¸é, µ¥ÀÌÅÍ¿Í ¼¯ÀÏ °æ¿ì°¡ Àֱ⠶§¹®¿¡ ´ëºÎºÐ Ç¥ÁØ Ãâ·ÂÀ» ½á¼ ¸Þ½ÃÁö¸¦ Ãâ·ÂÇÕ´Ï´Ù.
´ë°³ ÇÊÅÍ ÇÁ·Î±×·¥ÀÌ µû·Î Ãâ·ÂÇÏ´Â ¸Þ½ÃÁö´Â ÁÖ·Î °æ°í¼ºÀ̳ª, ¿¡·¯°¡ ¹ß»ýÇÑ °æ¿ì°¡ ´ëºÎºÐÀÔ´Ï´Ù. ¸¸¾à ½Ã½ºÅÛ ÇÔ¼ö¸¦ È£ÃâÇØ¼ ¿¡·¯°¡ ¹ß»ýÇÑ °æ¿ì¿¡´Â Àü¿ª º¯¼ö errno¿¡ ¿¡·¯ ¿øÀÎÀÌ ÀúÀåµÇ°Ô µÇ´Âµ¥ (¸ðµç ½Ã½ºÅÛ ÇÔ¼öµéÀÌ errno¸¦ ¾²´Â °ÍÀº ¾Æ´Õ´Ï´Ù.), ÀÌ °æ¿ì strerror(3)¸¦ ½á¼, ¿øÇÏ´Â ¿¡·¯ ¸Þ½ÃÁö¸¦ ¾òÀ» ¼ö ÀÖ½À´Ï´Ù.
¿¡·¯¸¦ ½±°Ô ó¸®Çϱâ À§ÇØ ¿ì¸®´Â GNU È®Àå ÇÔ¼öÀÎ error(3)¸¦ ¾µ °ÍÀÔ´Ï´Ù.
#include <error.h>
void error(int STATUS, int ERRNUM, const char *FORMAT, ...);
»ç¿ë¹ýÀº °£´ÜÇÕ´Ï´Ù. ¸ÕÀú, FORMAT°ú ±× ´ÙÀ½¿¡ µé¾î¿À´Â printf(3) ½ºÅ¸ÀÏ ÀÎÀÚ¸¦ ó¸®Çؼ Ç¥ÁØ ¿¡·¯·Î Ãâ·ÂÇÕ´Ï´Ù. ±×¸®°í ERRNUMÀÌ 0ÀÌ ¾Æ´Ñ °æ¿ì, error(3)´Â strerror(ERRNUM)À» ºÒ·¯¼ ¸Þ½ÃÁö¸¦ Ç¥ÁØ ¿¡·¯·Î Ãâ·ÂÇÕ´Ï´Ù. ±× ´ÙÀ½, STATUS°¡ 0ÀÌ ¾Æ´Ñ °æ¿ì exit(STATUS)¸¦ È£ÃâÇØ ÁÝ´Ï´Ù.
¿¹¸¦ µé¾î Á¦ÀÛÇÒ ÇÊÅÍ ÇÁ·Î±×·¥ÀÌ ÁöÁ¤ÇÑ ¼³Á¤ ÆÄÀÏ¿¡¼ ¿øÇÏ´Â ¼³Á¤À» ÀоîµéÀÎ´Ù°í °¡Á¤ÇØ º¾½Ã´Ù. ÀÌ ¼³Á¤ ÆÄÀÏ À̸§Àº INIT_FILEÀ̶õ ¸ÅÅ©·Î¿¡ ÀúÀåÀÌ µÇ¾î ÀÖ°í, À̸¦ fopen(3)À¸·Î ¿ ¶§, ¿¡·¯°¡ ¹ß»ýÇß´Ù°í °¡Á¤ÇսôÙ. ¶Ç, ÀÌ ÇÊÅÍ ÇÁ·Î±×·¥Àº ÁöÁ¤ÇÑ ¼³Á¤ ÆÄÀÏÀÌ Á¸ÀçÇÏÁö ¾Ê´Â °æ¿ì, °æ°í ¸Þ½ÃÁö¸¦ Ãâ·ÂÇϰí, ±âº» °ªÀ» ½á¼ µ¿ÀÛÇÑ´Ù°í °¡Á¤ÇսôÙ. ÀÌ °æ¿ì ¿ì¸®´Â ´ÙÀ½°ú °°Àº Äڵ带 ¸¸µé¾î¾ß ÇÕ´Ï´Ù:
FILE *fp;
fp = fopen(INIT_FILE, "r");
if (!fp) {
error(0, errno, "cannot open %s", INIT_FILE);
}
±×·¯¸é ³ªÁß¿¡ ÀÌ ÇÁ·Î±×·¥À» ½ÇÇàÇÒ ¶§ (ÇÁ·Î±×·¥ À̸§Àº "foo"¶ó°í °¡Á¤ÇսôÙ), INIT_FILEÀÌ ¾ø´Â °æ¿ì, ´ÙÀ½°ú °°ÀÌ °æ°í ¸Þ½ÃÁö°¡ Ãâ·ÂµÇ´Â °ÍÀ» ¾Ë ¼ö ÀÖ½À´Ï´Ù:
$ foo
foo: cannot open /etc/foorc: No such file or directory
$ _
1.2. Option Processing ¶°¡Àå ¸ÕÀú ó¸®ÇØ¾ß ÇÒ °ÍÀº command-line argument¸¦ ¹Þ¾Æ¼ ó¸®ÇÏ´Â °ÍÀÔ´Ï´Ù. ÀÌ´Â main() ÇÔ¼ö¸¦, µÎ °³ÀÇ ÆÄ¶ó¸ÞÅ͸¦ ¹Þ¾Æ¼ ó¸®ÇÏ°Ô ÇÒ ¼ö ÀÖ½À´Ï´Ù:
#include <stdio.h>
int
main(int argc, char *argv[])
{
int i;
for (int i = 0; i < argc; i++)
printf("argv[%d]: %s\n", i, argv[i]);
return 0;
}
À§ ¼Ò½º¸¦ ÄÄÆÄÀÏÇÏ°í ½ÇÇàÇØ º¸¸é argc¿Í argv°¡ ¾î¶°ÇÑ ¿ªÇÒÀ» ÇÏ´ÂÁö ½±°Ô ¾Ë ¼ö ÀÖ½À´Ï´Ù:
$ cc -Wall arg.c
$ ./a.out # argc == 1
argv[0]: ./a.out
$ ./a.out hello world # argc == 3
argv[0]: ./a.out
argv[1]: hello
argv[2]: world
$ ls *.c
arg.c hello.c
$ ./a.out *.c # argc == # of .c files plus 1.
argv[0]: ./a.out
argv[1]: arg.c
argv[2]: hello.c
$ _
¿É¼ÇÀ» ó¸®Çϱâ À§Çؼ getopt(3)À̳ª getopt_long(3) ÇÔ¼ö¸¦ ¾²´Â °ÍÀÌ Æí¸®ÇÕ´Ï´Ù. ¸ÕÀú °¡Àå ÈçÇÑ '-h'¿Í '-v' (µµ¿ò¸»°ú ¹öÀü Ãâ·Â) ¿É¼ÇÀ» ¸¸µé¾î º¾½Ã´Ù.
getopt(3)¿Í getopt_long(3)Àº ¿É¼Ç 󸮸¦ ¸Å¿ì °£´ÜÇÏ°Ô ÇØ ÁÝ´Ï´Ù. ¸ÕÀú ´ëºÎºÐ UNIX ½Ã½ºÅÛÀº POSIX.2¿¡ ÁØÇÏ´Â getopt(3)¸¦ Á¦°øÇϸç, GNU ½Ã½ºÅÛ¿¡¼´Â È®Àå ÇÔ¼öÀÎ getopt_long(3)À» ¾µ ¼ö ÀÖ½À´Ï´Ù. getopt(3)°¡ ÇÑ ±ÛÀÚ ¿É¼Ç¸¸À» ó¸®ÇÒ ¼ö ÀÖ´Â ¹Ý¸é, getopt_long(3)Àº ÇÑ ±ÛÀÚ ¿É¼Ç »Ó¸¸ ¾Æ´Ï¶ó ±ä ¿É¼Çµµ ó¸® °¡´ÉÇÕ´Ï´Ù:
#include <unistd.h>
int getopt(int ARGC, char * const ARGV[], const char *OPTSTRING);
extern char *optarg;
extern int optind, opterr, optopt;
#include <getopt.h>
int getopt_long(int ARGC, char * const ARGV[], const char *OPTSTRING,
const struct option *LONGOPTS, int *LONGINDEX);
¸ÕÀú µÎ ÇÔ¼öÀÇ ¼¼¹øÂ° ÆÄ¶ó¸ÞÅÍÀÎ OPTSTRING¿¡ ´ëÇØ ¾Ë¾Æ º¾½Ã´Ù. ÀÌ ÆÄ¶ó¸ÞÅÍ¿¡´Â, ÀÌ ÇÁ·Î±×·¥ÀÌ Ã³¸®ÇÒ ¼ö ÀÖ´Â ÇÑ ±ÛÀÚ ¿É¼ÇµéÀÇ ¸ñ·ÏÀ» ½á ÁÝ´Ï´Ù. ¸¸¾à ¿É¼ÇÀÌ ÀÎÀÚ¸¦ ¹Þ´Â´Ù¸é ¿É¼Ç ±ÛÀÚ µÚ¿¡ ':'µµ ½á ÁÝ´Ï´Ù. ¸¸¾à ¿É¼Ç¿¡ ´ëÇÑ ÀÎÀÚ¸¦ »ý·«ÇÒ ¼ö ÀÖ´Â °æ¿ì¿¡´Â ':'¸¦ µÎ°³ ½á ÁÝ´Ï´Ù. ¿¹¸¦ µé¾î ÇÁ·Î±×·¥ÀÌ Ã³¸®ÇÏ´Â ¿É¼ÇÀÌ '-h', '-v', '-q', '-o FILE' ÀÌ ³×°³¶ó°í Çϸé, OPTSTRINGÀº "hvqo:"°¡ µË´Ï´Ù.
ÀÌÁ¦ getopt(3)ÀÇ ¸®ÅÏ °ª¿¡ ´ëÇØ ¾Ë¾Æº¾½Ã´Ù. getopt(3)Àº ÇÁ·Î±×·¥¿¡ Àü´ÞµÈ ÀÎÀÚ¸¦ Çϳª¾¿ ó¸®ÇÕ´Ï´Ù. Áï, °³¹ßÀÚ´Â getopt(3)À» ÇÊ¿äÇÑ ¸¸Å ºÒ·¯¼, ÇÁ·Î±×·¥¿¡ Àü´ÞµÈ ¿É¼ÇÀ» ¸ðµÎ ó¸®ÇØ ÁÖ¾î¾ß ÇÕ´Ï´Ù. ´õ ÀÌ»ó ó¸®ÇÒ ¿É¼ÇÀÌ ¾ø´Â °æ¿ì, getopt(3)´Â -1À» ¸®ÅÏÇÕ´Ï´Ù. µû¶ó¼ ¿ì¸®´Â ´ÙÀ½°ú °°Àº Äڵ带 »ý°¢ÇÒ ¼ö ÀÖ½À´Ï´Ù:
int
main(int argc, char *argv[])
{
int ch;
while ((ch = getopt(argc, argv, "hvqo:")) != -1) {
...
}
...
}
getopt(3)´Â ÀÚ½ÅÀÌ Ã³¸®ÇÑ ¿É¼Ç ±ÛÀÚ¸¦ ¸®ÅÏÇØ ÁÝ´Ï´Ù. µû¶ó¼ getopt(3)°¡ '-h'¸¦ ó¸®Çß´Ù¸é 'h'¸¦ ¸®ÅÏÇÕ´Ï´Ù. µû¶ó¼ ¿ì¸®´Â getopt(3)ÀÇ °á°ú¸¦ switch ¹®ÀåÀ» ½á¼ ¿øÇÏ´Â ÀÛ¾÷À» ó¸®ÇØÁÖ¸é µË´Ï´Ù. ¸¸¾à ÇÁ·Î±×·¥ »ç¿ëÀÚ°¡ ¾Ë ¼ö ¾ø´Â ¿É¼ÇÀ» ½è´Ù¸é getopt(3)´Â '?'¸¦ ¸®ÅÏÇÕ´Ï´Ù. µû¶ó¼ À§ ¿¹Á¦ÀÇ while ¹®Àå ¾ÈÀº ´ÙÀ½°ú °°ÀÌ ¾µ ¼ö ÀÖ½À´Ï´Ù:
switch (ch) {
case 'h':
/* show help message and exit */
case 'v':
/* show version information and exit */
case 'q':
/* set quiet mode */
break;
case 'o':
/* set the output file name */
break;
case '?':
/* unknown option. ignored. */
break;
default:
/* getopt(3) returns unrecognized value. */
abort();
}
¸ÕÀú getopt(3)°¡ '?'¸¦ ¸®ÅÏÇß´Ù¸é, ÇÁ·Î±×·¥ »ç¿ëÀÚ°¡ ¾Ë ¼ö ¾ø´Â ¿É¼ÇÀ» ÁöÁ¤ÇÑ °ÍÀ» ¶æÇÕ´Ï´Ù. ÀÌ °æ¿ì getopt(3)´Â ÀÚµ¿À¸·Î ¾Ë ¼ö ¾ø´Â ¿É¼ÇÀÌ µé¾î¿Ô´Ù´Â ¿¡·¯ ¸Þ½ÃÁö¸¦ Ãâ·ÂÇÕ´Ï´Ù¸¸, ÀÌ °ÍÀ¸·Î ÃæºÐÇÏÁö ¾Ê½À´Ï´Ù. ¿ì¸®´Â ÀÌ °æ¿ì '-h'¸¦ ¾²¸é µµ¿ò¸»À» º¼ ¼ö ÀÖ´Ù´Â °Í±îÁö Ãâ·ÂÇØ ÁÙ °ÍÀÔ´Ï´Ù:
case '?':
/* getopt(3) prints "unknown option" message automatically. */
fprintf(stderr, "Try `opt -h' for more information.\n");
break;
´ÙÀ½À¸·Î, ÀÎÀÚ¸¦ ¹Þ´Â ¿É¼ÇÀÎ '-o FILE'¿¡ ´ëÇØ ´õ ¾Ë¾Æº¾½Ã´Ù. getopt(3)´Â ÀÎÀÚ¸¦ ¹Þ´Â ¿É¼ÇÀÌ µé¾î¿Ã °æ¿ì, Àü¿ª º¯¼ö optarg¿¡, ±× ¿É¼Ç ÀÎÀÚ¸¦ °¡¸®Å°´Â Æ÷ÀÎÅÍ °ªÀ» ÀúÀåÇØ µÓ´Ï´Ù. µû¶ó¼ ¿ì¸®´Â ÀÌ optarg¿¡¼ ¿øÇÏ´Â ÀÎÀÚ¸¦ ¾òÀ» ¼ö ÀÖ½À´Ï´Ù.
ÇѰ¡Áö ´õ, optarg´Â getopt(3)¸¦ ºÎ¸¦ ¶§ ´Ù¸¥ °ªÀ¸·Î µ¤¾î ½á Áú ¼ö ÀÖÀ¸¹Ç·Î, ´ÙÀ½°ú °°Àº ÄÚµå´Â À§ÇèÇÒ ¼ö ÀÖ½À´Ï´Ù:
const char *filename;
...
filename = optarg;
°¡Àå ¼Õ½¬¿î ¹æ¹ýÀº strdup(3) ÇÔ¼ö¸¦ ½á¼ ¸Þ¸ð¸®¸¦ ÇÒ´çÇÑ ´ÙÀ½, optarg°¡ °¡¸®Å°´Â ¹®ÀÚ¿À» º¹»çÇÏ´Â °ÍÀÔ´Ï´Ù:
const char *filename;
...
filename = strdup(optarg);
¸¶Áö¸·À¸·Î, getopt(3)¸¦ ½á¼ ¿É¼Ç 󸮸¦ ´Ù ³¡³Â´Ù¸é, ÀÌÁ¦ ÇÁ·Î±×·¥¿¡ Àü´ÞµÈ (¿É¼ÇÀÌ ¾Æ´Ñ) ÀÎÀÚµéÀ» ó¸®ÇØ¾ß ÇÕ´Ï´Ù. ÀÌ ¶§, ¿ì¸®´Â Àü¿ª º¯¼ö optind¿¡ ´ã±ä °ªÀ» ¾¹´Ï´Ù. optind¿¡´Â getopt°¡ argv[]¿¡ ÀÖ´Â ¿É¼ÇµéÀ» ó¸®ÇÏ°í ³ ¸¶Áö¸· ÀÎÀÚ¿¡ ´ëÇÑ index °ªÀÌ µé¾î ÀÖ½À´Ï´Ù. µû¶ó¼ ¿ì¸®´Â argv
[optind] ºÎÅÍ argv[argc - 1] ±îÁö ó¸®ÇÏ¸é µË´Ï´Ù. ¸¸¾à ÇÁ·Î±×·¥¿¡ Àü´ÞµÈ ÀÎÀÚµéÀÌ ¾ø´Â °æ¿ì¸¦ µû·Î ó¸®ÇÏ°í ½Í´Ù¸é, optind°¡ argc°¡ °°Àº °æ¿ì¸¦ ó¸®ÇÏ¸é µË´Ï´Ù. ¿¹¸¦ µé¾î À§ getopt¸¦ ¾´ while ¹®Àå ´ÙÀ½¿¡ ¾Æ·¡¿Í °°Àº Äڵ带 Ãß°¡ÇÏ¸é µË´Ï´Ù.
if (optind == argc) { /* there is no argument in the command-line. */
...
}
else {
int i;
for (i = optind; i < argc; i++) {
/* process each argv[i] here */
...
}
}
1.3. Skelton Template #1 ¶
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <error.h>
const char *program_name = "opt";
const char *version_string = "0.1";
int verbose_mode = 1;
const char *output_filename;
static void help_and_exit(void);
static void version_and_exit(void);
int
main(int argc, char *argv[])
{
int c;
while (1) {
c = getopt(argc, argv, "hvo:q");
if (c < 0)
break;
switch (c) {
case 'h':
help_and_exit();
break;
case 'v':
version_and_exit();
break;
case 'q':
verbose_mode = 0;
break;
case 'o':
output_filename = strdup(optarg);
break;
case '?':
error(0, 0, "Try `%s -h' for more information.\n", program_name);
break;
default:
abort();
}
}
if (optind == argc) { /* There is no more argument in the
command-line */
/* TODO: insert code for no argument */
}
else {
int i;
for (i = optind; i < argc; i++) {
/* Process each argv[i] here */
printf("processing %s\n", argv[i]);
}
}
return 0;
}
static void
help_and_exit(void)
{
static const char *msgs[] = {
"usage: opt [OPTION...] [FILES...]",
"",
" -h display this help and exit",
" -v output version information and exit",
" -q quite mode",
" -o FILE send output to file FILE. If FILE is `-', ",
" send output to stdout.",
"",
"Report bugs to <cinsky at gmail dot com>",
};
int i;
for (i = 0; i < sizeof(msgs) / sizeof(const char *); i++)
puts(msgs[i]);
exit(EXIT_SUCCESS);
}
static void
version_and_exit(void)
{
printf("opt version %s\n", version_string);
exit(EXIT_SUCCESS);
}
±Û¾´ÀÌ´Â Ç×»ó ÀÌ »À´ë Äڵ带 ÃÖ½ÅÀ¸·Î ¸¸µé·Á°í Çϰí ÀÖ½À´Ï´Ù. ÃֽŠÄÚµå´Â
±Û¾´ÀÌÀÇ
![]() ³¡ --
![]() |
Nile Is Like Emacs |