C ++ добавление возврата каретки в начале строки при чтении файла - PullRequest
0 голосов
/ 11 мая 2009

У меня два вопроса:

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

РЕДАКТИРОВАТЬ: ОК, то, что некоторые из вас предложили, имеет большой смысл. Строка, вероятно, читается как "\ nmystring". Итак, я думаю, теперь мой вопрос, как я могу удалить первый \ n из строки?

Ответы [ 7 ]

1 голос
/ 11 мая 2009

Что вы, вероятно, хотите, что-то вроде этого:

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(), обычно ведут себя не так случайно.

1 голос
/ 11 мая 2009

Новые строки могут появляться со второй напечатанной строки. Это связано с тем, что функция getline останавливает просмотр символа # и возобновляет его при следующем вызове с того места, где он слева от, то есть символа после #, который согласно вашему входному файлу является новой строкой. Прочитайте C FAQ 13.16 , чтобы эффективно использовать rand().

Одно из предложений - прочитать весь файл за один раз, сохранить строки в vector и затем вывести их по мере необходимости.

1 голос
/ 11 мая 2009

Ваш "случайный" выбор совершенно неверен. Фактически, он всегда будет выбирать первую строку: rand() % 1 всегда равно 0.

Невозможно равномерно выбрать случайную строку, не зная количества имеющихся строк.

Кроме того, почему вы используете # в качестве разделителя? Getline по умолчанию получает строку (заканчивающуюся \ n).

1 голос
/ 11 мая 2009

Поскольку вы не указываете \n в качестве разделителя.

0 голосов
/ 11 мая 2009

Вы можете использовать метод substr класса std :: string для удаления \ n после того, как вы решите, какую строку использовать:

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

Как уже говорили другие, если вы хотите выбрать строки с одинаковой случайностью, вам сначала нужно прочитать все строки, а затем выбрать номер строки. Вы также можете использовать if (rand ()% (++ nlines + 1)), который выберет строку 1 с вероятностью 1/2, строку 2 с вероятностью 1/2 * 1/3 и т. Д.

0 голосов
/ 11 мая 2009

1) Вы не добавляете \n к selected_line. Вместо этого, указав '#', вы просто не удаляете лишние символы \n в своем файле. Обратите внимание, что ваш файл на самом деле выглядит примерно так:

белье номер один \ n # \ П строка номер два \ n <\ До>

Таким образом, строка номер два на самом деле "\ nline номер два \ n".

2) Нет. Если вы хотите выбрать строку случайным образом, сначала вам нужно определить количество строк в вашем файле.

0 голосов
/ 11 мая 2009

Поскольку # - ваш разделитель, \ n, который существует сразу после этого разделителя, будет началом вашей следующей строки, поэтому \ n будет перед вашей строкой.

...