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); } ±Û¾´ÀÌ´Â Ç×»ó ÀÌ »À´ë Äڵ带 ÃÖ½ÅÀ¸·Î ¸¸µé·Á°í ÇÏ°í ÀÖ½À´Ï´Ù. ÃֽŠÄÚµå´Â
±Û¾´ÀÌÀÇ CVS¿¡¼ ¹Ù·Î º¼ ¼ö ÀÖ½À´Ï´Ù.
³¡ -- ½Å¼º±¹
|
Might as well be frank, monsieur. It would take a miracle to get you out of Casablanca. |