2009-01-31 45 views
27

Vì vậy, tôi đang ở trong Linux và tôi muốn có một chương trình chấp nhận đối số khi bạn thực hiện nó từ dòng lệnh.Chuyển đối số vào chương trình C từ dòng lệnh

Ví dụ,

./myprogram 42 -b -s

Vì vậy, sau đó chương trình sẽ lưu trữ con số 42 như một int và thực hiện một số phần của mã tùy thuộc vào những gì nó được lập luận như -b hoặc -s.

+0

Định dạng chuẩn cho dòng lệnh chuyển đối số tùy chọn như '-b' và '-s' trước bất kỳ đối số không tùy chọn nào như '42'. Vì vậy, định dạng dòng lệnh chuẩn, chính thống sẽ là "./myprogram -b -s 42". Tránh lệch khỏi tiêu chuẩn đó. [... chi tiết trong bình luận tiếp theo ...] –

+0

Xem phần 12 (Quy ước về tiện ích) của Định nghĩa cơ sở của tiêu chuẩn POSIX tại http://www.opengroup.org/onlinepubs/009695399/toc.htm. –

+1

@ Jonathan Leffler: Thứ tự không quan trọng. Hàm 'getopt_long' thực hiện điều đúng bất kể thứ tự. Xem câu trả lời của tôi. – jfs

Trả lời

36

Bạn có thể sử dụng getopt.

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

int 
main (int argc, char **argv) 
{ 
    int bflag = 0; 
    int sflag = 0; 
    int index; 
    int c; 

    opterr = 0; 

    while ((c = getopt (argc, argv, "bs")) != -1) 
    switch (c) 
     { 
     case 'b': 
     bflag = 1; 
     break; 
     case 's': 
     sflag = 1; 
     break; 
     case '?': 
     if (isprint (optopt)) 
      fprintf (stderr, "Unknown option `-%c'.\n", optopt); 
     else 
      fprintf (stderr, 
        "Unknown option character `\\x%x'.\n", 
        optopt); 
     return 1; 
     default: 
     abort(); 
     } 

    printf ("bflag = %d, sflag = %d\n", bflag, sflag); 

    for (index = optind; index < argc; index++) 
    printf ("Non-option argument %s\n", argv[index]); 
    return 0; 
} 
+0

Tôi đã thêm ví dụ về mã. – jfs

+2

Không nên anh/cô ấy hiểu "đối số chính đi qua" đầu tiên? ;) – OscarRyz

+0

Nó sẽ hoạt động trên Linux vì hàm getopt() là GNU getopt() và bạn thường không đặt POSIXLY_CORRECT trong môi trường, và GNU getopt() sau đó xử lý các đối số tùy chọn trước các đối số 'tệp', ngay cả khi chúng tuân theo đối số tệp như trong ví dụ. Trên nền tảng POSIX, nó sẽ không hoạt động .... –

25

Trong C, điều này được thực hiện bằng đối số truyền cho chức năng main() của bạn:

thông tin
int main(int argc, char *argv[]) 
{ 
    int i = 0; 
    for (i = 0; i < argc; i++) { 
     printf("argv[%d] = %s\n", i, argv[i]); 
    } 
    return 0; 
} 

thêm có thể được tìm thấy trực tuyến như Arguments to main bài viết này.

+0

Xin lỗi - đó không phải là một x-ref đáng sợ. Có một lỗi trong tuyên bố rằng "Tuyên bố của đối số argv thường là một cuộc gặp gỡ đầu tiên của người lập trình mới với con trỏ tới mảng con trỏ và có thể chứng minh đáng sợ" (argv là một mảng con trỏ, không phải là con trỏ tới một mảng con trỏ). –

+1

Ngoài ra, trang tiếp theo sẽ hiển thị trình phân tích cú pháp tùy chọn quảng cáo thay vì sử dụng trình phân tích cú pháp getopt() hoặc getopt_long() chuẩn - đó chỉ là lời khuyên đơn giản. Không - nó không phải là một tài liệu tham khảo tốt. –

+2

Trong C, tham chiếu đến một mảng là một địa chỉ, giống như một con trỏ là một địa chỉ. Vì vậy, argv có thể được gọi là cả hai "một mảng" và "một con trỏ đến một mảng". Đây là một trong những điểm đơn giản đẹp của C cũng như một trong những điểm gây nhầm lẫn. –

6

Hãy xem thư viện getopt; nó khá nhiều tiêu chuẩn vàng cho loại điều này.

10

Cân nhắc sử dụng getopt_long(). Nó cho phép cả hai lựa chọn ngắn và dài trong bất kỳ sự kết hợp nào.

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

/* Flag set by `--verbose'. */ 
static int verbose_flag; 

int 
main (int argc, char *argv[]) 
{ 
    while (1) 
    { 
     static struct option long_options[] = 
    { 
     /* This option set a flag. */ 
     {"verbose", no_argument,  &verbose_flag, 1}, 
     /* These options don't set a flag. 
     We distinguish them by their indices. */ 
     {"blip", no_argument,  0, 'b'}, 
     {"slip", no_argument,  0, 's'}, 
     {0,   0,     0, 0} 
    }; 
     /* getopt_long stores the option index here. */ 
     int option_index = 0; 

     int c = getopt_long (argc, argv, "bs", 
       long_options, &option_index); 

     /* Detect the end of the options. */ 
     if (c == -1) 
    break; 

     switch (c) 
    { 
    case 0: 
     /* If this option set a flag, do nothing else now. */ 
     if (long_options[option_index].flag != 0) 
     break; 
     printf ("option %s", long_options[option_index].name); 
     if (optarg) 
     printf (" with arg %s", optarg); 
     printf ("\n"); 
     break; 
    case 'b': 
     puts ("option -b\n"); 
     break; 
    case 's': 
     puts ("option -s\n"); 
     break; 
    case '?': 
     /* getopt_long already printed an error message. */ 
     break; 

    default: 
     abort(); 
    } 
    } 

    if (verbose_flag) 
    puts ("verbose flag is set"); 

    /* Print any remaining command line arguments (not options). */ 
    if (optind < argc) 
    { 
     printf ("non-option ARGV-elements: "); 
     while (optind < argc) 
    printf ("%s ", argv[optind++]); 
     putchar ('\n'); 
    } 

    return 0; 
} 

liên quan:

4

Thay vì getopt(), bạn cũng có thể xem xét sử dụng argp_parse() (một giao diện thay thế cho cùng một thư viện).

Từ libc manual:

getopt là tiêu chuẩn hơn (các ngắn lựa chọn duy nhất phiên bản của nó là một phần của tiêu chuẩn POSIX), nhưng sử dụng argp_parse thường dễ dàng hơn, cho cả rất đơn giản và các cấu trúc rất phức tạp, bởi vì nó có nhiều công việc bẩn hơn cho bạn.

Nhưng tôi luôn hài lòng với tiêu chuẩn getopt.

N.B. GNU getopt với getopt_long là GNU LGPL.

+0

"getopt là GNU LGPL": Điều đó phụ thuộc vào getopt. Nó đã được thực hiện nhiều lần. Một trong Mac OS X được cấp phép BSD. – dmckee

+0

Và AT & T phát hành một trong những năm 80 vào miền công cộng, hoặc một cái gì đó rất gần với phạm vi công cộng. Điểm của McKee rất hợp lệ - GNU getopt() [và getopt_long()] là LGPL (hoặc các phiên bản cũ hơn là GPL); không phải tất cả các phiên bản của getopt() là GPL hoặc LGPL. –

+0

Tôi đồng ý với ý kiến ​​của bạn và chỉnh sửa bài đăng của tôi. Cảm ơn bạn. – sastanin

4

khác đã trúng cái này trên đầu:

  • các đối số tiêu chuẩn để main(int argc, char **argv) cung cấp cho bạn truy cập trực tiếp vào dòng lệnh (sau khi đã được đọc sai và tokenized bằng vỏ)
  • có rất cơ sở tiêu chuẩn để phân tích cú pháp dòng lệnh: getopt()getopt_long()

nhưng khi bạn đã nhìn thấy mã để sử dụng chúng là một chút dài dòng, và khá idomatic. Tôi thường đẩy nó ra khỏi cái nhìn với một cái gì đó như:

typedef 
struct options_struct { 
    int some_flag; 
    int other_flage; 
    char *use_file; 
} opt_t; 
/* Parses the command line and fills the options structure, 
* returns non-zero on error */ 
int parse_options(opt_t *opts, int argc, char **argv); 

điều đó đầu tiên trong chính:

int main(int argc, char **argv){ 
    opt_t opts; 
    if (parse_options(&opts,argc,argv)){ 
     ... 
    } 
    ... 
} 

Hoặc bạn có thể sử dụng một trong những giải pháp đề xuất trong Argument-parsing helpers for C/UNIX.

Các vấn đề liên quan