0

我有两个问题:

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

编辑:好的,你们中的一些人的建议很有意义。该字符串可能被读取为“\nmys​​tring”。所以我想我现在的问题是,我将如何从字符串中删除第一个 \n ?

4

7 回答 7

1

因为您没有指定\n为分隔符。

于 2009-05-10T21:18:56.890 回答
1

您的“随机”选择是完全错误的。事实上,它总是会选择第一行: rand() % 1总是 0。

在不知道存在的行数的情况下,无法统一选择随机行。

另外,为什么要使用# 作为分隔符?Getline,默认情况下,获取一行(以 \n 结尾)。

于 2009-05-10T21:20:50.227 回答
1

换行符可以从您打印的第二行出现。这是因为,该getline函数在看到该#字符时停止,并在下次从其左侧调用它时恢复,即#根据您的输入文件,该字符过去的字符是换行符。阅读有关有效使用rand().

一个建议是一次性读取整个文件,将行存储在 a 中vector,然后根据需要输出它们。

于 2009-05-10T21:25:19.437 回答
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 回答
0

因为 # 是您的分隔符,所以在该分隔符之后存在的 \n 将成为您下一行的开头,从而使 \n 在您的行前面。

于 2009-05-10T21:27:30.887 回答
0

1)你没有添加\nselected_line. 相反,通过指定'#'您根本不会删除\n文件中的多余字符。请注意,您的文件实际上看起来像这样:

第一行\n 第一行\n #\n 第二行\n <\pre>

所以第二行实际上是“\n第二行\n”。

2)不。如果你想随机选择一行,那么你需要先确定文件中的行数。

于 2009-05-10T21:29:05.017 回答
0

在决定使用哪一行后,您可以使用 std::string 类的 substr 方法删除 \n :

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

As others have said, if you want to select the lines with uniform randomness, you'll need to read all the lines first and then select a line number. You could also use if (rand() % (++nlines+1)) which will select line 1 with 1/2 probability, line 2 with 1/2*1/3 probability, etc.

于 2009-05-10T21:38:49.697 回答