2012-02-11 16 views
0

私はインターネットをしばらく検索していましたが、C++でのファイル入力のために見つけることができるのは、ファイル名を知っているときだけです。C++でのファイル入力

私は、ファイルから0より大きい2つの数値の加算を実行するプログラムを作成しようとしていますが、scanfまたはcinは使用していません。私はファイルをメモリにロードしたいが、この状況に関して私が見つけることができるすべてのコードはファイル名の知識を必要とする。ファイルは、1行に2つの整数でフォーマットされ、スペースで区切られ、複数の整数行があります。プログラムは2つの数値の和を出力します。私はscanfで簡単にこれを行うことができますが、大量のファイルを与えられた場合は、そのファイルをメモリにロードします(後でマッピングを保存します)。

ファイルをメモリにロードすると、私はファイル名がわからないので、問題が生じます。私はプログラムがそうのように実行しますが、ほとんど生、および基本的なC++ IOのフォーム使用することにしたい:どのように私はファイルとして全体の「boatloadofnumbers」を取るために私のプログラムを開始すると

./myprog < boatloadofnumbers 

を、私はすることができますread()のようなより基本的な関数を使いますか? (また、上記の方法は、入力を渡す?何と呼ばれている?)

int main(){ 
    int a,b; 
    while (scanf("%i,%i",&a,&b)>-1){ 
     printf("%i\n",(a+b)); 
    } //endwhile 
    return 0; 
} //endmain 
+1

'C++のファイル入力で見つけられるのは、ファイル名を知っているときだけです。ファイルから読み込みしようとしていて、そのファイルが何を呼び出すのかわからない場合、あなたは完全にSOLです。明らかに。 –

+2

標準入力から読み込みますが、ファイルから読み込むことはありません。シェルがあなたのためにリダイレクトしています。 –

+0

@KerrekSB私は見る..しかし、データを読む別の方法はありますか?私はファイルが与えられた場合、私はいくつかのファイル操作を行うことができると思ったが、私はもうそれが事実ではないと思う。私は、scanfよりも基本的な入力方法で作業しようとしていました。数値ではなく、より大きなスケールでデータを読むことができるようになっています。正しい方向に向けることができると思いますか? –

答えて

0

どのようにそれは完全には明らかではありませんあなたがファイル名を知らないときにファイルを読むつもりです。ファイル名がのコンパイル時にになっているとは限りません。

./myprog boatloadofnumbers 

次に、あなたのファイル名がargv[1]であり、あなたがstd::ifstreamを使用してアクセスすることができます:それは大丈夫です、あなたはこのように、ランタイムでコマンドラインからこれを取得することができます。あなたは、あなただけのstd::cinを使用することができ、すべてのファイル名を必要としないredirection(例えば./myprog < boatloadofnumbersなど)を経由してstdin上で直接入力を与えられている場合

main()は、これらの状況の両方に対処します:

int main(int argc, char* argv[]) 
{ 
    if (argc == 2) 
    { 
     std::cerr << "Reading from file" << argv[1] << std::endl; 
     std::ifstream ifs(argv[1]); 
     if (ifs) 
     { 
      sum_lines(ifs); 
     } 
     else 
     { 
      std::cerr << "Could not read from " << argv[1] << std::endl; 
     } 
    } 
    else 
    { 
     std::cerr << "Reading from stdin" << std::endl; 
     sum_lines(std::cin); 
    } 
} 

サンプルsum_lines()は少し次のようになります。

void sum_lines(std::istream& is) 
{ 
    int first = 0, second = 0; 
    std::string line = ""; 
    while (std::getline(is, line)) 
    { 
     std::istringstream iss(line); 
     if (is >> first >> second) 
     { 
      std::cout << first << " + " << second << " = " << first + second << std::endl; 
     } 
     else 
     { 
      std::cerr << "Could not parse [" << line << "]" << std::endl; 
     } 
    } 
} 

これは、入力がどこから来るのか気にしません、ユニットテスト用にstd::istringstreamを簡単に注入することができます。また、これはファイル全体を一度に1行だけメモリに読み込まないので、averybigboatloadofnumbersを処理する必要があります。

1

あなたが述べるように、プログラムが呼び出されると、その後、boatloadofnumbersの内容は、STDから読み取ることができます:: CIN。

この方法は入力リダイレクトと呼ばれ、プログラムではなくシェルによって実行されます。

入力リダイレクションでは、通常、シェルはファイルの内容をバッファします。これは、計算を通じてファイルを一度にストリームする非常に速い方法です。

+0

入力はどのようにメモリにロードされますか?私がやってきたことから、内容を数字で読んで、計算してから出力します。私はファイルの形でコンテンツが与えられているので、 "number by number"より大きい規模でコンテンツを読みたいと思います。それ、どうやったら出来るの? –

+0

これは依存しています:答えを推測するコードを表示してください。 –

+0

コードは元の投稿に表示されます。 (すべての整数は> 0です...おそらくそれを言及しているはずです) –

0

シェルリダイレクトを使用すると、プログラムは標準入力から読み込むことができます。ただし、ファイルから読み込むことが望ましい場合もあります。これは、両方をサポートするのは簡単です:

cat data > ./prog 
./prog < data 

./prog -f data 

最初の二つは似ており、ファイルdataの内容は、プログラムの標準入力からご利用いただけます。 3行目は単にコマンドライン引数を渡します。ここでは、我々はこれをサポート方法は次のとおりです。

#include <cstdio> 
#include <cstring> 

void process_input(std::FILE * fp) 
{ 
    char buf[4]; 
    std::fread(buf, 4, 1, fp); 
    // ... 
} 

int main(int argc, char * argv[]) 
{ 
    std::FILE * fp = stdin; // already open! 

    if (argc >= 3 && 0 == std::strcmp(argv[1]. "-f")) 
    { 
     fp = std::fopen(argv[2], "rb"); 

     if (!fp) 
     { 
      std::fprintf(stderr, "Could not open file %s.\n", argv[2]); 
      return 1; 
     } 
    } 

    process_input(fp); 

    if (fp != stdin) { std::fclose(fp); } 
} 

同等、それは素敵な、普遍的な参照を持っているために、もう少し遠回りだが、あなたは、入出力ストリームと似た何かを達成することができます

#include <fstream> 

int main() 
{ 
    std::ifstream ifp; 

    if (/* as before */) 
    { 
     ifp.open(argv[2], std::ios::binary); 
     if (!ifp) { /* error and die */ } 
    } 

    std::ifstream & infile = ifp ? ifp : std::cin; 

    process_input(infile); 
}