Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > std::search и std::istream_iterator


Автор: X-3R1 8.4.2009, 10:48
Вопрос почему появляется эксепшн в подобном случае:

Код

    std::ifstream cmdFile( path.c_str() );

    std::istream_iterator<std::string> it(cmdFile);
    std::istream_iterator<std::string> end;

    std::vector<std::string> block;
    block.push_back( "part " );
        block.push_back( "modify" );
        block.push_back( "rigid_body" );
        block.push_back( "name_and_position" );

        std::search( it, end, block.begin(), bock.end() );          // вылетает эксешпн istream_iterator is not dereferencable


Протрассировал std:: search, эксепшн в функции:

Код

template<class _FwdIt1,
    class _FwdIt2,
    class _Diff1,
    class _Diff2> inline
    _FwdIt1 _Search(_FwdIt1 _First1, _FwdIt1 _Last1,
        _FwdIt2 _First2, _FwdIt2 _Last2, _Diff1 *, _Diff2 *)
    {    // find first [_First2, _Last2) match
    _DEBUG_RANGE(_First1, _Last1);
    _DEBUG_RANGE(_First2, _Last2);
    _Diff1 _Count1 = 0;
    _Distance(_First1, _Last1, _Count1);
    _Diff2 _Count2 = 0;
    _Distance(_First2, _Last2, _Count2);

    for (; _Count2 <= _Count1; ++_First1, --_Count1)                      // эксепшн на второй итерации
        {    // room for match, try it
        _FwdIt1 _Mid1 = _First1;
        for (_FwdIt2 _Mid2 = _First2; ; ++_Mid1, ++_Mid2)
            if (_Mid2 == _Last2)
                return (_First1);
            else if (!(*_Mid1 == *_Mid2))                                       // а точнее тут при *_Mid1
                break;
        }
    return (_Last1);
    }


Эксепшн, на второй итерации основного цикла, почему-то при ++_First1, _First1 (входной итератор) становится невалидным. Ошибка при разыменовывании _Mid1.

Другие алгоритмы, типа std::find работают smile

Автор: mrbrooks 8.4.2009, 11:16
X-3R1, сливай из файла сначало в контейнер из файла в тот же вектор (через std::copy), а затем уже в этом векторе ищи значения из blok. Тебе нужен еще итератор для определения - нашел ли что или нет std:smile

Добавлено через 49 секунд
гы. смайл заменил 
Цитата

smile


Добавлено через 1 минуту и 34 секунды
фак.
Код

std::search

Автор: X-3R1 8.4.2009, 11:19
Угу это как вариант, но так бы не хотелось временную память создавать (

Автор: Lazin 8.4.2009, 11:23
это не exception а assert
скорее всего дело в чтении файла, видимо после прочтения первой строки, читать становится нечего...

Автор: mrbrooks 8.4.2009, 11:25
Цитата(X-3R1 @  8.4.2009,  11:19 Найти цитируемый пост)
Угу это как вариант, но так бы не хотелось временную память создавать ( 

дело в том что бы найти значение нужен итератор типа
Код

std::istream_iterator<std::string>::iterator it;

К этому итератору результат из 
Код

std::search( it, end, block.begin(), bock.end() );

не присвоить.

да забыл сказать - у меня все нормально компилится с твоим кодом. я бы на твоем месте сделал проверку на
Код

std::ifstream cmdFile( path.c_str() );
if (cmdFile)
{
//твой код
}

 возможно файл либо не открывается, либо его нет. 

Автор: X-3R1 8.4.2009, 11:28
Не, данные из файла прочитались нормально, std::find же работает. Такая же фигня, когда пытаюсь данные из файла загнать вначале в std::stringstream smile а потом уже работать с его входными итераторами.

Добавлено через 6 минут и 16 секунд
Цитата(mrbrooks @  8.4.2009,  09:25 Найти цитируемый пост)
дело в том что бы найти значение нужен итератор типа
    
std::istream_iterator<std::string>::iterator it;

К этому итератору результат из 

std:smile( it, end, block.begin(), bock.end() );

не присвоить.

Не совсем так, для работы этого алгоритма пойдут любые итераторы, поиск же производится через разыменовывание и operator ==():

Код

 else if (!(*_Mid1 == *_Mid2))  
                break;



Цитата(mrbrooks @  8.4.2009,  09:25 Найти цитируемый пост)
да забыл сказать - у меня все нормально компилится с твоим кодом. я бы на твоем месте сделал проверку

Да, проверка есть:
Код

    std::ifstream cmdFile( path.c_str() );

    if (!cmdFile)
    {
        SysLog::error( (std::string("Can't open the cmd file: ") + path).c_str() );
        return;
    }

Автор: mrbrooks 8.4.2009, 12:09
Цитата(X-3R1 @  8.4.2009,  11:28 Найти цитируемый пост)
Не совсем так, для работы этого алгоритма пойдут любые итераторы, поиск же производится через разыменовывание и operator ==():

у меня не подошли любые итераторы.

Автор: Lazin 8.4.2009, 12:27
Цитата(mrbrooks @  8.4.2009,  12:09 Найти цитируемый пост)
у меня не подошли любые итераторы

это как?

данный код ищет в файле последовательность строк:
Цитата
part 
modify
rigid_body
name_and_position
причем первая строка должна-быть обязательно с пробелом на конце

Автор: mrbrooks 8.4.2009, 12:33
Lazin, 
за этот код студия мне вломила в печень
Код

std::istream_iterator<std::string>::iterator it;
it = std::search( it, end, block.begin(), bock.end());


хотя возможно - я что то не учел.

Автор: X-3R1 8.4.2009, 12:39
Цитата(mrbrooks @  8.4.2009,  10:33 Найти цитируемый пост)
за этот код студия мне вломила в печень


угу, потому что вместо
Код

std::istream_iterator<std::string>::iterator it;

надо
Код

std::istream_iterator<std::string> it;



Цитата(Lazin @  8.4.2009,  10:27 Найти цитируемый пост)
причем первая строка должна-быть обязательно с пробелом на конце

Нет в первой строке лишний пробел вкрался случайно smile

Автор: mrbrooks 8.4.2009, 12:43
X-3R1, здесь опечатка произошла - копировал твой код и ничерта не исправил.  smile
По этому будет так:
Код

std::vector<std::string>::iterator v;
v = std::search( it, end, block.begin(), bock.end());


Добавлено через 52 секунды
Собственно за это и получил в печень.

Автор: Lazin 8.4.2009, 12:56
Цитата(mrbrooks @  8.4.2009,  12:43 Найти цитируемый пост)
Собственно за это и получил в печень

алгоритм возвращает std::istream_iterator<std::string>

Добавлено через 2 минуты и 13 секунд
попробовал это запустить у себя, получаю ту-же ошибку, хотя по идее все должно работать... smile 

Автор: mrbrooks 8.4.2009, 13:05
Цитата(Lazin @  8.4.2009,  12:56 Найти цитируемый пост)
алгоритм возвращает std::istream_iterator<std::string>

я и это попробывал. 2008 студия шлет меня так же подальше. 

потому я говорил о промежуточном контейнере. 

Автор: Lazin 8.4.2009, 13:15
Цитата(mrbrooks @  8.4.2009,  13:05 Найти цитируемый пост)
потому я говорил о промежуточном контейнере

тогда придется читать весь файл в память, для чего тогда вообще использовать итератор?
странно то, что файл можно прочитать через итератор it, но внутри алгоритма файл читаться перестает
выглядит это примерно так:
в std:smile создается копия итератора it, при первом проходе все работает, так-как при создании временной копии итератора реальное чтение из файла не происходит
далее выполняется оператор ++ для копии итератора, который вызывает оператор >> т.е пытается прочитать след. значение из файла, и происходит ошибка, с mingw этот код работатет

Добавлено через 45 секунд
вместо std:smile следует подставить std :: search smile 

Автор: mrbrooks 8.4.2009, 13:34
Цитата(Lazin @  8.4.2009,  13:15 Найти цитируемый пост)
тогда придется читать весь файл в память, для чего тогда вообще использовать итератор?

а как же тогда я узнаю результат без итератора?

к примеру как http://cplusplus.com/reference/algorithm/search/

Добавлено через 1 минуту и 20 секунд
Цитата(Lazin @  8.4.2009,  13:15 Найти цитируемый пост)
вместо std:smile следует подставить std :: search smile  

рожа смайла скрыла твою идею

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)