2009-05-10 20 views
0

を読み取る際に、文字列のbegginingに改行を追加:C++私は2つの質問を持っているファイル

1)なぜ私のコードはselected_line列のbegginingに改行を追加していますか?
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 beggining of the string 
    cout << selected_line << endl; 
} 

感謝。

編集: OK、あなたが示唆しているものは、多くの意味があります。文字列はおそらく "\ nmystring"として読み込まれています。だから今私の質問は、私は文字列から最初の\ nを削除すると思いますか?

+0

データは何ですかファイルはどう? –

+0

Neilでは、データファイルは、単一の '#'文字を含む行で区切られた段落で構成されています。 –

答えて

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()によって返された最下位ビットがする傾向があるので、無作為に行動するわけではありません。

+0

優れたソリューション!本当にありがとう!私はあなたが投稿したこの解決策から多くを学んだ。再度、感謝します! – nmuntz

+0

あなたは大歓迎です。私はそれが宿題でないことを願っています:) – Reunanen

+0

心配しないで、私は学生ではありません。 –

1

\nを区切り文字として指定していないためです。

1

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

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

さらに、#をデリミタとして使用しているのはなぜですか? Getlineはデフォルトで行を取得します(\ nで終わります)。

+0

ファイルの行数を数えるには2回、行の総数に基づいてランダムな行を読み取るにはもう1回、ファイルを読み込む必要がありますか? 段落を読む必要があるため区切り記号として#を使用していますが、\ nに到達するまでではありません。 –

1

改行は、印刷する2行目から表示されます。これは、getline関数が#文字を見ることで停止し、次に入力したファイルから改行された文字(#を超える文字)が次の場所から呼び出されたときに再開するためです。 rand()を有効に使用してC FAQ 13.16を読んでください。

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

+0

えええええええええええええええええええええええええええええええええええええええええええええええええええばん - – Reunanen

0

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

0

1)\nselected_lineに追加していません。代わりに、'#'と指定すると、ファイル内の余分な文字が削除されません。\nあなたのファイルが実際にこのような何かに見えることに注意してください:

ライン\ nを ナンバーワン\ nの #\ nの 行番号2 \ n個前>

だから、行番号2は、実際にある

「\ < \ nline number two \ n "

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

+0

私は参照してください。文字列の先頭から「\ n」を取り除く簡単な方法はありますか? –

+0

ifstreamから空白を削除するには(getlineを呼び出す前に)次のようにします:while(isspace(read.peek()))read.ignore(); – Naaff

0

あなたは\を削除するにはstd :: stringクラスのSUBSTRメソッドを使用nはあなたの後に使用するライン決めることができました:

他人として
if (line.substr(0,1) == "\n") { line = line.substr(1); } 

が言った、あなたが持つ行を選択したい場合は均一なランダム性を得るには、最初にすべての行を読んでから、行番号を選択する必要があります。 1/2確率で1行目を選択するif(rand()nlines + 1)%(++ nlines + 1)を使用することもできます。

関連する問題