Passando o conteúdo do arquivo na linha de comando para o programa c ++ [duplicado]

1

Eu tenho o seguinte programa (vamos chamá-lo de 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;
}

Atualmente estou escrevendo um script bash que pegaria um arquivo e o colocaria na linha de comando como argumentos sendo passados para este programa cpp. Como você pode ver, o programa acima pede duas entradas.

Eu sei como você pode passar o conteúdo de um arquivo para uso como entrada no stdin. Mas como você faria isso se quisesse passar o conteúdo de um arquivo como argumentos através da linha de comando?

Para elaborar, digamos, arquivo.txt é o arquivo em que estou interessado, que simplesmente contém dois inteiros em linhas separadas.

EDITAR: Eu tentei o comando xargs:

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

Mas isso acaba imprimindo o que tenho em cout, por exemplo:

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

Eu só quero o que é cout'ed após todos os meus argumentos foram passados. Como faço isso?

    
por E 4 6 30.09.2015 / 00:52

3 respostas

2

Do jeito que você escreveu, você precisa passar o conteúdo do arquivo para o seu programa, não o arquivo em si (e não há necessidade de xargs , a propósito). Uma maneira de fazer isso é usar o redirecionamento de entrada :

a.out < file

Por exemplo:

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

Outra maneira de fazer o mesmo é imprimir o conteúdo do arquivo e passar para o seu programa com um pipe:

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

Uma abordagem muito mais clara, é claro, seria escrever seu programa para que ele possa receber argumentos em vez de ler entradas padrão:

./a.out 4 7

Ou, escreva-o para abrir arquivos internamente e analisá-los para os dados de entrada:

./a.out file

De qualquer forma, para obter apenas a última linha na saída, imprima o restante para o erro padrão:

#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;
}

Agora, execute:

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

Ou para fornecer os valores manualmente:

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

$ cat output.txt 
Sum is 11
    
por terdon 30.09.2015 / 13:23
1

Como já indicou Terdon, para fazer isso você quer redirecionar stdin de um arquivo (e chamar o programa usando por exemplo program <inputfile.txt ) ou alterar seu programa para que ele analise argumentos passados da linha de comando (e chame o programa usando, por exemplo, program 1 2 );

No primeiro caso, você deseja suprimir os dois primeiros cout s se stdin não estiver conectado a um terminal e, no segundo caso, você quiser suprimir os dois primeiros cout s, por exemplo, se digamos, argumentos insuficientes não foram passados da linha de comando;

Falando do primeiro método, você pode verificar se um descritor de arquivo está conectado a um terminal usando a função isatty() (função POSIX definida em unistd.h ):

int isatty(int fd);

Se fd for um descritor de arquivo aberto conectado a um terminal, a função retornará 1 ; Se fd não for um descritor de arquivo aberto ou não estiver conectado a um terminal, a função retornará 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;
}

Desta forma, o usuário será solicitado a inserir os números somente se stdin não tiver sido redirecionado:

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

Falando do segundo método, aqui está um exemplo muito grosseiro de como analisar argumentos passados da linha de comando (argumentos passados da linha de comando são armazenados em argv , que é uma matriz de ponteiros para um caractere, então você Terá que converter cada argumento para um número inteiro, mas não use atoi() ! Use algo que lhe permita verificar se os argumentos são numéricos ou não. Eu usei atoi() apenas por uma questão de simplicidade):

#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;
}

Desta forma, o usuário será solicitado a inserir os números somente se argumentos suficientes não tiverem sido passados da linha de comando:

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
    
por kos 30.09.2015 / 14:13
0

Existem algumas coisas que você pode fazer:

  1. Você pode enviar para o arquivo dentro do C ++ usando algo como este .
  2. Você pode remover as linhas cout << "Enter... em seu código para que a única saída do programa seja o que entra no arquivo.
  3. Você pode contornar usando o fluxo de saída de erro (cerr em vez de cout) e manipular as saídas de acordo. Se você quiser cout visible e cerr no arquivo, faça xargs program.cc < file.txt 2> outputresult.txt (usando 2 > em vez de >). Se você quiser cerr visible e cout no arquivo, faça isso como você tinha acima com apenas > .
  4. Mantenha a saída como está agora, mas execute mais duas execuções que removam as linhas indesejadas do seu código:

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

Você pode implementar isso com seu código da seguinte forma:

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

Este método requer novas linhas a serem escritas, no entanto, você teria que ter certeza de que a saída seria cada uma em novas linhas.

Eu pessoalmente sugiro usar o gerenciamento de arquivos no C ++ ou no cout e no cerr hack, dependendo do uso do programa.

    
por Zzzach... 30.09.2015 / 02:28