1

sscanf()ファイルから読み取るために C++ で使用する方法がわかりません。

ファイルから 3 人のランナーの名前と、それぞれの 5 つのベスト タイムを読み取るプログラムに取り組んでいます。各ランナーのタイムを平均して、誰が最高のランナーかを言いたい. 私はファイルIOで絶対に苦労しています。

Cplusplus.com はいくつかの助けになりましたが、読み方、char* (名前) を float (時間) から分離する方法などについては実際には述べていません。

友人が説明のためにこのコード スニペットを見せてくれました。

while(file>>str) {
    sscanf (str.c_str(),"%d",&myint);
}    

読み方を説明してくれる人はいますか?

4

5 に答える 5

5

の使用sscanf()は少し古い方法と考えられていますが、非常に有益であり、マスターする価値があります。次のようなものを探していると思います:

sscanf(input, "%s %f", name, &time);

inputファイルの行です。基本のいくつかは、基本%s的な文字列と%fフロート用です。

プログラミングの開始をお楽しみください。経験を積むほど良くなります。

于 2012-08-11T00:17:08.987 に答える
1

基本的に、解析する変数をプレースホルダーで置き換えるsscanf関数の2番目の引数で文字列形式を指定します。

たとえば、ファイルが次の行で構成されていることを知っているとします。

Father bought 8 bottles of rum on day 1.  
Father bought 11 bottles of rum on day 2.  
Father bought 5 bottles of rum on day 3.  
Father bought 19 bottles of rum on day 4. 

あなたは毎日のボトルの量以外はその文字列の何も気にしません。変更されないパーツ、つまり「父がその日にラム酒のボトルを購入した」を修正し、ストリングから抽出するパーツのプレースホルダーを指定します。

コードは次のようになります。

int nDay, nBottles;
sscanf(str.c_str(), "Father bought %d bottles of rum on day %d", &nBottles, &nDay);
cout << "Day: " << nDay << ", bottles: " << nBottles << endl;

%の後の記号は、その部分が解析される変数のタイプを指定するだけです。dここでは10進数を意味します。

于 2012-08-11T00:57:33.963 に答える
1

printf の逆の場合は scanf。

「sscanf」の最初の「s」は、文字列をスキャンすることを意味します。「fscanf」はファイルをスキャンし、「scanf」は標準入力をスキャンします。

フォーマットは printf と同じです。

「5 x sprintf(s, "%d x", 5)」を s に出力sscanf("5 x", "%d x", &n)すると、5 が n に配置されます。それは常にprintfの反対です。

例外は%s. %sin printf はすべての文字列を出力します。printf("%s", str); str の内容に関係なく、str を出力します。scanf では%s、単語です。単語はスペースのないものです。したがって、 a%sを読むと、単語だけが読み上げられます。

sscanf(str, "%d", &a);str は "%d" (単一の 10 進数) の形式を持ち、この数値を a に変換していることを意味します (&a は 2 番目の引数であるため)。

例として

int a,b,c,d;
sscanf("10,20,30,40", "%d,%d,%d,%d", &a, &b, &c, &d);

a = 10、b = 20、c= 30、d = 40 となります。各 %d は次の引数まで読み取り、それぞれが単一の 10 進数を読み取ります。

于 2012-08-11T00:49:52.107 に答える
1

全体として、このsscanf()関数は、文字列で検出される値を記述するフォーマット文字列のガイダンスの下で、(C) 文字列をプログラム変数の一連の値に変換するために使用されます。

引用されたコードを分析する:

while (file >> str)
{
    sscanf(str.c_str(), "%d", &myint);
}

fileこれは入力ストリームであり、文字列であると想定できstrます。ループは、反復ごとに入力から文字列に 1 つの「単語」を読み取ります。whileここで、「単語」は一連の非空白文字であり、一連の空白文字が先行する可能性があります。

このsscanf()例のステートメントには、3 つの引数と無視される戻り値があります (むしろ危険です)。最初の引数は C スタイルの文字列であるため、読み取られた単語はstr.c_str()呼び出しで C 文字列に変換されます。2 番目の引数は、文字列にsscanf()何を期待するかを示すフォーマット文字列です。この場合、%d変換指定子は 10 進整数を示します。3 番目の引数は、変換された値が格納される対応する型へのポインターです。一般に、フォーマット文字列には多数の変換指定子を含めることができ、割り当てる変換指定子ごとに 1 つのポインター引数が必要です (割り当てを抑制することでデータをスキップできます)。

からの戻り値sscanf()は、成功した割り当て変換の数です。この場合、1 つの変換が完了したことを確認する必要があります。

あなたの例に基づいた実用的なミニチュアプログラムは次のとおりです。

#include <iostream>
#include <string>
#include <cstdio>
#include <cstdlib>

static void read_stuff(std::istream &file)
{
    std::string str;
    while (file >> str)
    {
        std::cout << "IN: <<" << str << ">>" << std::endl;
        int myint;
        if (sscanf(str.c_str(), "%d", &myint) != 1)
        {
            std::cerr << "Oops: sscanf() failed" << std::endl;
            std::exit(1);
        }
        std::cout << "GOT: " << myint << std::endl;
    }
}

int main()
{
    read_stuff(std::cin);
    return(0);
}

次の入力行を入力するとします123 234 345 abc。次に、プログラムは以下を生成します。

IN: <<123>>
GOT: 123
IN: <<234>>
GOT: 234
IN: <<345>>
GOT: 345
IN: <<abc>>
Oops: sscanf() failed

扱っている名前に名と姓が含まれ、おそらくミドルネームのイニシャルと 5 つの数字 (すべてが 1 行にある) が含まれている場合は、おそらく別のプロセスが必要になることに注意してください。を使用getline()して行全体を読み取ってから、それを解析しようとしsscanf()ます (または、stringstream代わりに a を使用することもできます)。もちろん、回線上で 5 つ未満の数字を処理する必要があります。I/O は常にトリッキーです。特に、エラーのあるデータも処理する必要がある場合は注意が必要です (また、製品品質のコードは常にエラーのあるデータを処理する準備ができている必要があります)。

于 2012-08-11T00:55:41.720 に答える
0

sscanf(str.c_str(), "%d", &myint)の代わりに使用するだけですsscanf(str, "%d", &myint)

について他の人が説明しているのを見ましたがsscanf、あなたの質問は少し違うと思います。

sscanfは C 関数ですが、C++ には C が含まれているため、C++ でも使用できsscanfます。stringしかし、Cで呼び出されるようなものはありません。このため、 は基本的に と同じ仕事をするすなわちsscanfとしてそのパラメーターを取ります。char*char pointerstring

C++ では、c_str()関数を使用して に変換するstring必要がありますchar pointer

于 2013-11-16T19:47:25.257 に答える