C 表现出奇怪行为的getopt()函数

C 表现出奇怪行为的getopt()函数,c,command-line-interface,command-line-arguments,getopt,command-line-tool,C,Command Line Interface,Command Line Arguments,Getopt,Command Line Tool,将选项参数的getopt()添加到已存在的程序会导致奇怪的行为 该程序接受字符串输入,然后从文件中读取单词(每一个都在新行上),并检查该字符串是否在文件中。如果在文件中,该字符串将发送到现有的.txt文件,如果不在,则发送到不存在的.txt文件。 问题在于getopt()及其表现出的奇怪行为(选项分别为-n和-e以更改不存在和存在的文件) #包括 #包括 #包括 intmain(intargc,char*argv[]){ 字符字[80]; _文件[80]中的字符单词_; int-ch; FILE

将选项参数的getopt()添加到已存在的程序会导致奇怪的行为

该程序接受字符串输入,然后从文件中读取单词(每一个都在新行上),并检查该字符串是否在文件中。如果在文件中,该字符串将发送到现有的.txt文件,如果不在,则发送到不存在的.txt文件。 问题在于getopt()及其表现出的奇怪行为(选项分别为-n和-e以更改不存在和存在的文件)

#包括
#包括
#包括
intmain(intargc,char*argv[]){
字符字[80];
_文件[80]中的字符单词_;
int-ch;
FILE*existing=fopen(“existing.txt”,“w”);//打开现有和不存在的文件流
文件*non_existing=fopen(“non-existence.txt”,“w”);
while((ch=getopt(argc,argv,n:e:)!=-1){
开关(ch){
案例“n”:
不存在=fopen(optarg,“w”);
打破
案例“e”:
现有=fopen(optarg,“w”);
打破
违约:
fprintf(stderr,“未知选项参数:%s”,optarg);
返回1;
}
argc-=optind;
argv+=optind;
}
printf(“输入zawardsu:\n”);
而(scanf(“%79s[^\n]”,&word)){//扫描输入的主循环
如果(strcmp(字,“退出”)==0){
printf(“您现在完成了!\n”);
打破
}
FILE*input=fopen(argv[1],“r”);//在这里初始化流,以便为每个循环重置它,下一个循环从它上次切断的地方开始
while((fscanf(输入,“%79s[^\n]\n”,&word_in_文件)!=EOF)){//循环扫描输入文件
如果(strcmp(word_in_file,word)==0){//如果word在输入文件中,则将其打印到现有文件
fprintf(现有,“%s\n”,字);
打破
}              
}
if(strcmp(word,word\u in_file)!=0)//如果word不在输入文件中,则将其打印到不存在的文件中
fprintf(不存在,“%s\n”,word);//在主循环中,因为它需要在完成所有单词后执行此检查
}   
fclose(现有);//关闭一些数据流
fclose(不存在);
返回0;
}
因此,每当我像那样启动它时-
/check-n Nexname.txt-e Exname.txt infle.txt
它只是segfaults,堆栈转储类似于
Exception:STATUS\u ACCESS\u违例rip=001801C189A

然后我尝试-
/check-nNexname.txt-eExname.txt infle.txt
。这次它没有崩溃,但它只生成并写入第一个选项的参数文件,而第二次它只写入默认值

如果我试着只使用一个选项,比如-
/check-nNexname.txt infle.txt
,它会在我写下第一个单词后停止程序

编辑:当我这样做时,它也不会出错
/check-n Nexname.txt-eExname.txt infle.txt

有人能给我解释一下这种行为的原因(以及如何纠正它)吗


我知道我可以使用主函数args来做同样的事情,但是我想尝试一下getopt()函数,以便熟悉它

如果您将代码缩进得更好,那么很明显,您是在
循环中修改
argv
argc
,而不是在处理完所有选项后执行一次。

为默认文件名创建字符数组。
将文件指针设置为空。
将命令选项复制到字符数组中。
检查重复的文件名。
打开文件。
从标准文本中扫描一个单词。
扫描输入文件中的单词,尝试查找匹配项。
读取输入文件后,从stdin中倒带下一个单词。
关闭所有文件

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

void useage ( char *name);

int main ( int argc, char *argv[]) {
    char non_existing_file[80] = "Non-existent.txt";//default file name
    char existing_file[80] = "Existing.txt";
    char input_file[80] = "Default.txt";
    char word[80] = "";
    char word_in_file[80] = "";
    int ch = 0;
    //do not open files. Could be argument or default
    FILE *existing = NULL;
    FILE *non_existing = NULL;
    FILE *input = NULL;

    opterr = 0;//suppress default error messages

    while ( ( ch = getopt ( argc, argv, "n:e:")) != -1) {
        switch ( ch) {
            case 'n':
                if ( optarg) {//optarg not NULL
                    strncpy ( non_existing_file, optarg, 79);
                    non_existing_file[79] = 0;//make sure zero terminated
                }
                break;
            case 'e':
                if ( optarg) {
                    strncpy ( existing_file, optarg, 79);
                    existing_file[79] = 0;
                }
                break;
            case '?':
                if ( optopt == 'e' || optopt == 'n') {
                    fprintf ( stderr, "option -%c requires an argument.\n", optopt);
                }
                else {
                    fprintf ( stderr, "\ninvalid option -%c\n", optopt);
                }
            default:
                useage ( argv[0]);
                return 1;
        }
    }

    if ( ! strcmp ( non_existing_file, existing_file)) {
        fprintf ( stderr, "\nduplicate file names for options -e and -n\n");
        useage ( argv[0]);
        return 1;
    }
    if ( optind < argc) {//another argument to process
        if ( ! strcmp ( non_existing_file, argv[optind])
        || ! strcmp ( argv[optind], existing_file)) {
            fprintf ( stderr, "\ninput file name matches file name for options -e or -n\n");
            useage ( argv[0]);
            return 1;
        }
        strncpy ( input_file, argv[optind], 79);
        input_file[79] = 0;
    }

    //open files

    if ( NULL == ( input = fopen ( input_file, "r"))) {
        fprintf ( stderr, "could not open %s\n", input_file);
        return 1;
    }
    else {
        printf ( "%s opened\n", input_file);
    }

    if ( NULL == ( existing = fopen ( existing_file, "w"))) {
        fclose ( input);//close the already opened
        fprintf ( stderr, "could not open %s\n", existing_file);
        return 1;
    }
    else {
        printf ( "opened %s\n", existing_file);
    }

    if ( NULL == ( non_existing = fopen( non_existing_file, "w"))) {
        fclose ( input);//close the already opened
        fclose ( existing);
        fprintf ( stderr, "could not open %s\n", non_existing_file);
        return 1;
    }
    else {
        printf ( "opened %s\n", non_existing_file);
    }

    int found = 0;
    printf ( "Enter ZA WARDSU:\n");
    while ( 1 == scanf ( "%79s", word)) { //Main loop that scans stdin
        if ( strcmp ( word , "exit") == 0) {
            printf ( "You are now done!\n");
            break;
        }
        found = 0;
        while ( 1 == fscanf ( input, "%79s", word_in_file)) { // loop that scans the input file
            if ( strcmp ( word_in_file, word) == 0 ) {//if word is in the input file, print it to the existing file
                fprintf ( existing, "%s\n", word);
                found = 1;
                break;
            }
        }
        if ( ! found) {//if word isn't in the input file, print it to the non_existing file
            fprintf ( non_existing, "%s\n", word);//In main loop because it needs to do this check after it's gone through all the words
        }
        rewind ( input);//back to start of input to check for next word
    }

    fclose ( existing);
    fclose ( non_existing);
    fclose ( input);
    return 0;
}

void useage ( char *name) {
    fprintf(stderr
    , "\nUsage:\n\t%s [-eopte] [-noptn] [opt]\n or\n\t%s [-e opte] [-n optn] [opt]\n"
    , name, name);
}
#包括
#包括
#包括
无效使用(字符*名称);
int main(int argc,char*argv[]){
char non_existing_file[80]=“non-existence.txt”;//默认文件名
char existing_文件[80]=“existing.txt”;
字符输入_文件[80]=“Default.txt”;
字符字[80]=“”;
_文件中的字符单词_[80]=“”;
int ch=0;
//不打开文件。可能是参数或默认值
文件*existing=NULL;
文件*不存在=空;
文件*input=NULL;
opterr=0;//抑制默认错误消息
while((ch=getopt(argc,argv,n:e:)!=-1){
开关(ch){
案例“n”:
if(optarg){//optarg非空
strncpy(非现有文件,optarg,79);
不存在的\u文件[79]=0;//确保以零结尾
}
打破
案例“e”:
如果(optarg){
strncpy(现有的_文件,optarg,79);
现有_文件[79]=0;
}
打破
案例“?”:
如果(optopt='e'| | optopt=='n'){
fprintf(stderr,“选项-%c需要一个参数。\n”,optopt);
}
否则{
fprintf(标准,“\n无效选项-%c\n”,optopt);
}
违约:
使用率(argv[0]);
返回1;
}
}
如果(!strcmp(非现有文件,现有文件)){
fprintf(stderr,“\n复制选项-e和-n的文件名\n”);
使用率(argv[0]);
返回1;
}
如果(optind#include <stdio.h>
#include <string.h>
#include <unistd.h>

void useage ( char *name);

int main ( int argc, char *argv[]) {
    char non_existing_file[80] = "Non-existent.txt";//default file name
    char existing_file[80] = "Existing.txt";
    char input_file[80] = "Default.txt";
    char word[80] = "";
    char word_in_file[80] = "";
    int ch = 0;
    //do not open files. Could be argument or default
    FILE *existing = NULL;
    FILE *non_existing = NULL;
    FILE *input = NULL;

    opterr = 0;//suppress default error messages

    while ( ( ch = getopt ( argc, argv, "n:e:")) != -1) {
        switch ( ch) {
            case 'n':
                if ( optarg) {//optarg not NULL
                    strncpy ( non_existing_file, optarg, 79);
                    non_existing_file[79] = 0;//make sure zero terminated
                }
                break;
            case 'e':
                if ( optarg) {
                    strncpy ( existing_file, optarg, 79);
                    existing_file[79] = 0;
                }
                break;
            case '?':
                if ( optopt == 'e' || optopt == 'n') {
                    fprintf ( stderr, "option -%c requires an argument.\n", optopt);
                }
                else {
                    fprintf ( stderr, "\ninvalid option -%c\n", optopt);
                }
            default:
                useage ( argv[0]);
                return 1;
        }
    }

    if ( ! strcmp ( non_existing_file, existing_file)) {
        fprintf ( stderr, "\nduplicate file names for options -e and -n\n");
        useage ( argv[0]);
        return 1;
    }
    if ( optind < argc) {//another argument to process
        if ( ! strcmp ( non_existing_file, argv[optind])
        || ! strcmp ( argv[optind], existing_file)) {
            fprintf ( stderr, "\ninput file name matches file name for options -e or -n\n");
            useage ( argv[0]);
            return 1;
        }
        strncpy ( input_file, argv[optind], 79);
        input_file[79] = 0;
    }

    //open files

    if ( NULL == ( input = fopen ( input_file, "r"))) {
        fprintf ( stderr, "could not open %s\n", input_file);
        return 1;
    }
    else {
        printf ( "%s opened\n", input_file);
    }

    if ( NULL == ( existing = fopen ( existing_file, "w"))) {
        fclose ( input);//close the already opened
        fprintf ( stderr, "could not open %s\n", existing_file);
        return 1;
    }
    else {
        printf ( "opened %s\n", existing_file);
    }

    if ( NULL == ( non_existing = fopen( non_existing_file, "w"))) {
        fclose ( input);//close the already opened
        fclose ( existing);
        fprintf ( stderr, "could not open %s\n", non_existing_file);
        return 1;
    }
    else {
        printf ( "opened %s\n", non_existing_file);
    }

    int found = 0;
    printf ( "Enter ZA WARDSU:\n");
    while ( 1 == scanf ( "%79s", word)) { //Main loop that scans stdin
        if ( strcmp ( word , "exit") == 0) {
            printf ( "You are now done!\n");
            break;
        }
        found = 0;
        while ( 1 == fscanf ( input, "%79s", word_in_file)) { // loop that scans the input file
            if ( strcmp ( word_in_file, word) == 0 ) {//if word is in the input file, print it to the existing file
                fprintf ( existing, "%s\n", word);
                found = 1;
                break;
            }
        }
        if ( ! found) {//if word isn't in the input file, print it to the non_existing file
            fprintf ( non_existing, "%s\n", word);//In main loop because it needs to do this check after it's gone through all the words
        }
        rewind ( input);//back to start of input to check for next word
    }

    fclose ( existing);
    fclose ( non_existing);
    fclose ( input);
    return 0;
}

void useage ( char *name) {
    fprintf(stderr
    , "\nUsage:\n\t%s [-eopte] [-noptn] [opt]\n or\n\t%s [-e opte] [-n optn] [opt]\n"
    , name, name);
}