0

2 つの質問があります。

1) コードが selected_line 文字列の先頭に改行を追加するのはなぜですか?
2) ファイルからランダムな行を返すために使用しているアルゴリズムは十分であり、問​​題は発生しないと思いますか?

サンプル ファイルは次のとおりです。

line
number one
#
line number two

私のコード:

int main()
{
    srand(time(0));
    ifstream read("myfile.dat");
    string line;
    string selected_line;
    int nlines = 0;
    while(getline(read, line, '#')) {
        if((rand() % ++nlines) == 0)
            selected_line = line;
    }
    // this is adding a \n at the beginning of the string
    cout << selected_line << endl; 
}

編集: OK、あなたの何人かが提案したことは非常に理にかなっています。文字列はおそらく "\nmys​​tring" として読み取られています。だから私は今私の質問だと思います、文字列から最初の \n をどのように削除しますか?

4

7 に答える 7

1

区切りとして指定しないからです\n

于 2009-05-10T21:18:56.890 に答える
1

おそらくあなたが望むのは次のようなものです:

std::vector<std::string> allParagraphs;
std::string currentParagraph;

while (std::getline(read, line)) {        
    if (line == "#") { // modify this condition, if needed
        // paragraph ended, store to vector
        allParagraphs.push_back(currentParagraph);
        currentParagraph = "";
    else {
        // paragraph continues...
        if (!currentParagraph.empty()) {
            currentParagraph += "\n";
        }
        currentParagraph += line;
    }          
}

// store the last paragraph, as well
// (in case it was not terminated by #)
if (!currentParagraph.empty()) {
    allParagraphs.push_back(currentParagraph);
}

// this is not extremely random, but will get you started
size_t selectedIndex = rand() % allParagraphs.size();

std::string selectedParagraph = allParagraphs[selectedIndex];

ランダム性を高めるには、代わりにこれを選択できます。

size_t selectedIndex 
    = rand() / (double) (RAND_MAX + 1) * allParagraphs.size();

これは、 によって返される最下位ビットrand()がまったくランダムに動作しない傾向があるためです。

于 2009-05-10T21:38:29.043 に答える
1

あなたの「ランダムな」選択は完全に間違っています。実際、常に最初の行が選択されます: rand() % 1は常に 0 です。

存在する行数を知らずにランダムな行を一様に選択する方法はありません。

また、なぜ区切り文字として # を使用しているのですか? デフォルトでは、Getline は行を取得します (\n で終わります)。

于 2009-05-10T21:20:50.227 に答える
1

改行は、印刷する 2 行目から表示できます。これは、getline関数が文字を見ると停止し、次に関数#が左の場所から呼び出されたときに再開するためです。つまり、#入力ファイルによると改行である文字を過ぎた文字です。を効果的に使用する方法については、C FAQ 13.16rand()を参照してください。

1 つの提案は、ファイル全体を一度に読み取り、行を a に格納してvectorから、必要に応じて出力することです。

于 2009-05-10T21:25:19.437 に答える
0

使用する行を決定した後、 std::string クラスの substr メソッドを使用して \n を削除できます。

if ( line.substr(0,1) == "\n" ) { line = line.substr(1); }

他の人が言ったように、均一なランダム性で行を選択する場合は、最初にすべての行を読み取ってから行番号を選択する必要があります。if (rand() % (++nlines+1)) を使用して、1/2 の確率で行 1、1/2*1/3 の確率で行 2 などを選択することもできます。

于 2009-05-10T21:38:49.697 に答える
0

# は区切り文字であるため、その区切り文字の直後に存在する \n が次の行の先頭になり、\n が行の前になります。

于 2009-05-10T21:27:30.887 に答える
0

\n1) に を追加していませんselected_line。代わりに、ファイル内'#'の余分な文字を削除しないように指定するだけです。\nファイルは実際には次のようになっていることに注意してください。

行\n 1 番目\n #\n 2 番目の行\n <\pre>

したがって、行番号 2 は実際には「\n行番号 2\n」です。

2) いいえ。行をランダムに選択する場合は、最初にファイル内の行数を決定する必要があります。

于 2009-05-10T21:29:05.017 に答える