简体   繁体   中英

command-line argument of "−" when making standard unix programs for C

removeC.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 removes every c in a file then prints it to stdout. For example,

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

assuming file1's contents is also 'abc'

The goal is to make it work like standard Unix tools (but it's allowed to not take any command line options, ie "./a.out -w somefile").

How do I deal with command-line argument of "−"?

Conventionally, Unix utilities interpret an argument consisting solely of - to be equivalent to stdin if it could be interpreted as an input file, or as equivalent to stdout if it definitely would be interpreted as an output file.

In this case it would be an input file if it were a named file, so it would normally be equivalent to stdin .

This is Guideline #13 of the Posix Utility Syntax Guidelines :

Guideline 13:

For utilities that use operands to represent files to be opened for either reading or writing, the - operand should be used to mean only standard input (or standard output when it is clear from context that an output file is being specified) or a file named - .

You can do it quite easily with a simple ternary operator and checking argv[1] . While this presumes you do not have other options beginning with '-' , you can easily adapt it for that case with getopt . This is quite a handy "quick and dirty" setup for flexibly reading input from either a file or 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;
}

Example Input File

$ cat dat/dog.txt
my dog has fleas

Example Use/Output

Read from stdin without '-' ,

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

Read from stdin with '-' ,

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

Read from stdin using redirection from file,

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

Read from file,

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

This is not a substitute for a full getopt implementation, but is handy for small utilities.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM