簡體   English   中英

C 中的 getopt() 在 if 語句后無法正常工作

[英]getopt() in C not working correctly after if statement

我想實現 Linux 方法頭命令的副本。 如果用戶輸入./cprogram head -(option here)我希望該選項出現,但由於某種原因,我的代碼從不輸入選項switch語句。 例如命令行代碼./cprogram head -n從不進入case 'n':語句。 該代碼在if語句之前運行以檢查argv[1]是否為"head"

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

int main(int argc, char **argv) {
    int b;
    int c;
    int nflag = 0;
    int Vflag = 0;
    int hflag = 0;
    int eflag = 0;
    int oflag = 0;
    char str[] = "head";
    if (strcmp(argv[1], str) == 0) {
        while ((c = getopt(argc, argv, "nVheo")) != -1) {
            switch (c) {
              case 'n':
                if (nflag||Vflag||hflag||eflag||oflag) {
                    printf("only one option\n");
                    exit(1);
                } else {
                    nflag++;
                    printf("n option\n");
                }
                break;
              case 'V':
                if (nflag||Vflag||hflag||eflag||oflag) {
                    printf("only one option\n");
                    exit(1);
                } else {
                    Vflag++;
                }
                break;
              case 'h':
                if (nflag||Vflag||hflag||eflag||oflag) {
                    printf("only one option\n");
                    exit(1);
                } else {
                    hflag++;
                }
                break;
              case 'e':
                if (nflag||Vflag||hflag||eflag||oflag) {
                    printf("only one option\n");
                    exit(1);
                } else {
                    eflag++;
                }
                break;
              case 'o':
                if (nflag||Vflag||hflag||eflag||oflag) {
                    printf("only one option\n");
                    exit(1);
                } else {
                    oflag++;
                }
                break;
              default:
                printf("invalid options\n");
                abort();
            }
        } 
    } else {
    }
}

我將非常感謝專家的眼睛來看看並發現我所缺少的東西。 提前致謝。

結合頂部評論中的所有建議:

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

int
main(int argc, char **argv)
{
    int b;
    int c;
    int nflag = 0;
    int Vflag = 0;
    int hflag = 0;
    int eflag = 0;
    int oflag = 0;
    char str[] = "head";

    if (argc < 2) {
        printf("not enough arguments\n");
        exit(1);
    }

    if (strcmp(argv[1], str) != 0) {
        printf("1st argument is not '%s'\n",str);
        exit(1);
    }

    // skip over the [matched] str
    --argc;
    ++argv;

    while ((c = getopt(argc, argv, "nVheo")) != -1) {
        if (nflag || Vflag || hflag || eflag || oflag) {
            printf("only one option\n");
            exit(1);
        }

        switch (c) {
        case 'n':
            nflag++;
            printf("n option\n");
            break;

        case 'V':
            Vflag++;
            break;

        case 'h':
            hflag++;
            break;

        case 'e':
            eflag++;
            break;

        case 'o':
            oflag++;
            break;

        default:
            printf("invalid options\n");
            abort();
            break;
        }
    }

    return 0;
}

要進行測試,請使用這些 [a shell 腳本test ] 調用:

./myprogram
./myprogram foo
./myprogram head
./myprogram head -n
./myprogram head -n -n

這是sh -x./test output:

+ ./myprogram
not enough arguments
+ ./myprogram foo
1st argument is not 'head'
+ ./myprogram head
+ ./myprogram head -n
n option
+ ./myprogram head -n -n
n option
only one option

更新:

上面的代碼有點“作弊”。 它通過將str (例如"head" )移動到作為程序名稱(例如./myprogram )的argv[0]中來消除它。 實際的程序名稱被丟棄。

更正確的方法是“滑動” argv以消除字符串並保留程序名稱:

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

int
main(int argc, char **argv)
{
    int b;
    int c;
    int nflag = 0;
    int Vflag = 0;
    int hflag = 0;
    int eflag = 0;
    int oflag = 0;
    char str[] = "head";

    if (argc < 2) {
        printf("not enough arguments\n");
        exit(1);
    }

    if (strcmp(argv[1], str) != 0) {
        printf("1st argument is not '%s'\n",str);
        exit(1);
    }

    // skip over the [matched] str
    for (int avidx = 1;  avidx < argc;  ++avidx)
        argv[avidx] = argv[avidx + 1];
    --argc;

    while ((c = getopt(argc, argv, "nVheo")) != -1) {
        if (nflag || Vflag || hflag || eflag || oflag) {
            printf("only one option\n");
            exit(1);
        }

        switch (c) {
        case 'n':
            nflag++;
            printf("n option\n");
            break;

        case 'V':
            Vflag++;
            break;

        case 'h':
            hflag++;
            break;

        case 'e':
            eflag++;
            break;

        case 'o':
            oflag++;
            break;

        default:
            printf("invalid options\n");
            abort();
            break;
        }
    }

    return 0;
}

要讓getopt()跳過argv[1]並從下一個元素解析選項,您應該在調用getopt()之前設置optind

optind = 2;

另請注意,在將argv[1]"head"進行比較之前,您還應該檢查argc > 1

這是修改后的版本:

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

int main(int argc, char **argv) {
    int b;
    int c;
    int nflag = 0;
    int Vflag = 0;
    int hflag = 0;
    int eflag = 0;
    int oflag = 0;
    char str[] = "head";

    if (argc > 1 && strcmp(argv[1], str) == 0) {
        optind = 2;  // skip argv[1]
        while ((c = getopt(argc, argv, "nVheo")) != -1) {
            if (nflag | Vflag | hflag | eflag | oflag) {
                fprintf(stderr, "only one option\n");
                exit(1);
            }
            switch (c) {
              case 'n':
                nflag++;
                printf("n option\n");
                break;
              case 'V':
                Vflag++;
                break;
              case 'h':
                hflag++;
                break;
              case 'e':
                eflag++;
                break;
              case 'o':
                oflag++;
                break;
              default:
                fprintf(stderr, "invalid option `%c'\n", c);
                abort();
            }
        } 
        /* perform head on files starting at argv[optind] */
    } else {
        /* test some other command */
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM