在 C++ 程序的命令行上传递文件内容

在 C++ 程序的命令行上传递文件内容

我有以下程序(我们称之为program.cc):

int main() {
  int x, y, sum;
  std::cout << "A program which adds two integers\n";
  std::cout << "Enter 1st integer: ";
  std::cin >> x;
  std::cout << "Enter 2nd integer: ";
  std::cin >> y;
  sum = x + y;
  std::cout << "Sum is " << sum << std::endl;
  return 0;
}

我目前正在编写一个 bash 脚本,该脚本将获取一个文件并将其作为参数通过命令行推送给此 cpp 程序。如您所见,上述程序要求两个输入。

我知道如何传递文件内容以用作 stdin 的输入。但是如果您想通过命令行将文件内容作为参数传递,该怎么做呢?

为了详细说明,假设 file.txt 是我感兴趣的文件,它只包含两个在不同行上的整数。

编辑:我尝试了 xargs 命令:

       xargs program.cc < file.txt > outputresult.txt

但这最终会打印出我在 cout 中的内容,例如:

     A program which adds two integers
     Enter 1st integer: Enter 2nd integer: Sum is 2

我只想要所有参数都通过后的结果。我该怎么做?

答案1

按照你的写作方式,你需要通过内容xargs文件的权限,而不是文件本身(顺便说一句,也不需要)。一种方法是使用输入重定向

a.out < file

例如:

$ cat file
4 
7
$ ./a.out < file
A program which adds two integers
Enter 1st integer: Enter 2nd integer: Sum is 11

做同样的事情的另一种方法是打印文件的内容并通过管道将其传递给程序:

$ cat file | ./a.out 
A program which adds two integers
Enter 1st integer: Enter 2nd integer: Sum is 11

当然,一个更简洁的方法是编写程序,使其可以接受参数而不是读取标准输入:

./a.out 4 7

或者,编写它以便它可以在内部打开文件并解析其输入数据:

./a.out file

无论如何,为了仅获取输出中的最后一行,将其余部分打印到标准错误:

#include <iostream>

int main() {
  int x, y, sum;
  std::cerr << "A program which adds two integers\n";
  std::cerr << "Enter 1st integer: ";
  std::cin >> x;
  std::cerr << "Enter 2nd integer: ";
  std::cin >> y;
  std::cerr << "\n";
  sum = x + y;
  std::cout << "Sum is " << sum << std::endl;
  return 0;
}

现在运行:

$ ./a.out < file > output.txt
A program which adds two integers
Enter 1st integer: Enter 2nd integer: 
$ cat output.txt
Sum is 11

或者,手动给出值:

$ ./a.out > output.txt 
A program which adds two integers
Enter 1st integer: 4
Enter 2nd integer: 7

$ cat output.txt 
Sum is 11

答案2

正如 terdon 已经指出的那样,要做到这一点,您要么stdin从文件重定向(并使用 eg 调用程序program <inputfile.txt),要么更改程序以便它解析从命令行传递的参数(并使用 eg 调用程序program 1 2);

在第一种情况下,cout如果stdin没有连接到终端,则要抑制前两个 s;在第二种情况下,cout如果从命令行传递的参数不够,则要抑制前两个 s;

isatty()说到第一种方法,您可以使用该函数(在中定义的 POSIX 函数)检查文件描述符是否连接到终端unistd.h

int isatty(int fd);

如果fd是一个打开的文件描述符,并且连接到终端,该函数将返回1;如果fd不是打开的文件描述符,或者没有连接到终端,该函数将返回0

#include <iostream>
#include <unistd.h>

int main() {
    int x, y, sum;
    std::cout << "A program which adds two integers\n";
    if(isatty(0)) {
        std::cout << "Enter 1st integer: ";
    }
    std::cin >> x;
    if(isatty(0)) {
        std::cout << "Enter 2nd integer: ";
    }
    std::cin >> y;
    sum = x + y;
    std::cout << "Sum is " << sum << std::endl;
    return 0;
}

stdin这样,仅当尚未重定向时,才会提示用户插入数字:

user@user-X550CL ~/tmp % ./a.out               
A program which adds two integers
Enter 1st integer: 1
Enter 2nd integer: 2
Sum is 3
user@user-X550CL ~/tmp % cat inputfile.txt 
3
4
user@user-X550CL ~/tmp % ./a.out <inputfile.txt 
A program which adds two integers
Sum is 7

说到第二种方法,这里有一个非常粗略的例子,说明如何解析从命令行传递的参数(从命令行传递的参数存储在中argv,它是一个指向字符的指针数组,因此您必须将每个参数转换为整数,但不要使用atoi()!使用一些允许您检查参数是否为数字的东西。我atoi()只是为了简单起见才使用的):

#include <iostream>
#include <cstdlib>

int main(int argc, char *argv[]) {
    int x, y, sum;
    std::cout << "A program which adds two integers\n";
    if(argc == 3) {
        x = atoi(argv[1]);
        y = atoi(argv[2]);
    }
    else {
        std::cout << "Enter 1st integer: ";
        std::cin >> x;
        std::cout << "Enter 2nd integer: ";
        std::cin >> y;
    }
    sum = x + y;
    std::cout << "Sum is " << sum << std::endl;
    return 0;
}

这样,仅当命令行传递的参数不够时,才会提示用户插入数字:

user@user-X550CL ~/tmp % ./a.out
A program which adds two integers      
Enter 1st integer: 1
Enter 2nd integer: 2
Sum is 3
user@user-X550CL ~/tmp % ./a.out 3
A program which adds two integers
Enter 1st integer: ^C
user@user-X550CL ~/tmp % ./a.out 3 4
A program which adds two integers
Sum is 7

答案3

因此,您可以做以下几件事:

  1. 您可以使用类似如下的方法在 C++ 中输出到文件
  2. 您可以删除cout << "Enter...代码中的行,这样程序的唯一输出就是文件中的内容。
  3. 您可以使用错误输出流(cerr 而不是 cout)并相应地操作输出。如果您希望 cout 可见且 cerr 在文件中,请执行以下操作xargs program.cc < file.txt 2> outputresult.txt(使用2>而不是 >)。如果您希望 cerr 可见且 cout 在文件中,请按照上面的方法操作,只需>
  4. 保持现在的输出不变,但再运行两次以从代码中删除不需要的行:

cat outputresult.txt | grep Sum > tempfile && mv tempfile outputresult.txt

您可以使用如下代码实现此功能:

./program.cc < file.txt | grep Sum > outputresult.txt

但是,此方法需要写换行符,因此您必须确保每个换行符都在新行中输出。

我个人建议使用 C++ 中的文件管理或者 cout 和 cerr hack,具体取决于程序的用途。

相关内容