【问题标题】:command-line argument of "−" when making standard unix programs for C为 C 制作标准 unix 程序时“-”的命令行参数
【发布时间】:2018-02-26 14:20:05
【问题描述】:

删除C.c

#include <stdio.h>

int main(int argc, char **argv) {
    if (argc != 2) {
        int c;
        while((c = getchar()) != EOF) {
            if(c != 'c') {
                putchar(c);
            }
        }
    } else {
        for (size_t i = 0; argv[1][i] != '\0'; i++) {
            if(argv[1][i] != 'c') {
                putchar(argv[1][i]);
            }
        }
        putchar('\n');
    }
}

removeC.c 删除文件中的每个 c 然后将其打印到标准输出。例如,

$ gcc -Wall removeC.c
$ ./a.out abc
ab
$ echo abc | ./a.out
ab
$ ./a.out file1
ab

假设file1的内容也是'abc'

目标是让它像标准的 Unix 工具一样工作(但它允许不使用任何命令行选项,即“./a.out -w somefile”)。

如何处理“-”的命令行参数?

【问题讨论】:

  • 我没有测试,但如果您不提供参数,您的代码似乎会读取标准输入。因此,试试这个:cat file1 | ./a.out
  • 查看getopt 的手册页。
  • getopt 是你的答案,它有很好的文档记录,但你可以在这里寻找一个起点:stackoverflow.com/questions/17877368/…
  • 您的argc != 2 条件不包含任何参数,但也包含许多参数。您应该仔细区分这些情况;您应该(几乎可以肯定)以完全不同的方式处理 ./a.out./a.out *
  • 讽刺的答案是(U+2212 减号)被视为任何其他文件名。 (问题中引用的字符是 U+2212,而不是 U+002D 或 ASCII -。)大多数 POSIXy/UNIXy 应用程序只特别对待 --:所有以下参数都被视为文件名,即使它们以破折号-(U+002D 连字符-减号)。正如其他人所提到的,一些应用程序将- 视为标准输入的名称;即使您碰巧有一个名为- 的文件,这也不是问题,因为您始终可以使用相对路径来引用它,例如./-。)

标签: c unix


【解决方案1】:

通常,Unix 实用程序将仅由 - 组成的参数解释为等效于 stdin(如果它可以解释为输入文件),或者等效于 stdout(如果它肯定会被解释为输出文件) .

在这种情况下,如果它是一个命名文件,它将是一个输入文件,所以它通常等同于stdin

这是 Posix Utility Syntax Guidelines 的准则 #13:

准则 13:

对于使用操作数表示要打开以进行读取或写入的文件的实用程序,- 操作数应仅表示标准输入(或从上下文中明确指定输出文件时的标准输出) ) 或名为- 的文件。

【讨论】:

    【解决方案2】:

    您可以使用简单的 三元 运算符并检查 argv[1] 很容易地做到这一点。虽然这假定您没有以'-' 开头的其他选项,但您可以使用getopt 轻松调整它以适应这种情况。这是一个非常方便的“快速而肮脏”的设置,可以灵活地从文件或stdin 读取输入。

    #include <stdio.h>
    
    int main (int argc, char **argv) {
    
        int c;
        /* read from filename given as argv[1], or stdin by default or '-' */
        FILE *fp = argc > 1 && *argv[1] != '-' ? fopen (argv[1], "r") : stdin;
    
        if (!fp) {  /* validate file open for reading */
            fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
            return 1;
        }
    
        /* output reading from ... */
        printf ("reading from '%s'\n", fp == stdin ? "stdin" : argv[1]);
    
        while ((c = fgetc (fp)) != EOF)     /* read until EOF */
            putchar (c);
    
        if (fp != stdin) fclose (fp);   /* close file if not stdin */
    
        return 0;
    }
    

    输入文件示例

    $ cat dat/dog.txt
    my dog has fleas
    

    使用/输出示例

    stdin 读取,没有'-'

    $ echo "my dog has fleas" | ./bin/unix_read_file_or_stdin
    reading from 'stdin'
    my dog has fleas
    

    stdin读取'-'

    $ echo "my dog has fleas" | ./bin/unix_read_file_or_stdin -
    reading from 'stdin'
    my dog has fleas
    

    使用文件重定向从stdin读取,

    $ ./bin/unix_read_file_or_stdin <dat/dog.txt
    reading from 'stdin'
    my dog has fleas
    

    从文件中读取,

    $ ./bin/unix_read_file_or_stdin dat/dog.txt
    reading from 'dat/dog.txt'
    my dog has fleas
    

    这不能替代完整的 getopt 实现,但对于小型实用程序来说很方便。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-02-05
      • 1970-01-01
      • 2011-08-09
      • 2010-09-13
      • 1970-01-01
      • 1970-01-01
      • 2016-02-22
      相关资源
      最近更新 更多