Предотвращение дублирования кода внутри и вне цикла - PullRequest
0 голосов
/ 19 декабря 2011

У меня проблема с переписыванием цикла:

else if( "d" == option || "debug" == option )
{
    debug(debug::always) << "commandline::set_internal_option::setting debug options: "
                         << value << ".\n";
    string::size_type index = 0;
    do
    {
        const string::size_type previous_index = index+1;
        index=value.find( ',', index );
        const string item = value.substr(previous_index, index);
        debug::type item_enum;
        if( !map_value(lib::debug_map, item, item_enum) )
            throw lib::commandline_error( "Unknown debug type: " + item, argument_number );

        debug(debug::always) << "commandline::set_internal_option::enabling " << item
                             << " debug output.\n";
        debug(debug::always) << "\n-->s_level=" << debug::s_level << "\n";
        debug::s_level = static_cast<debug::type>(debug::s_level ^ item_enum);
        debug(debug::always) << "\n-->s_level=" << debug::s_level << "\n";
    } while( index != string::npos );
}

value - это что-то вроде string("commandline,parser"), и проблема в том, что при первом запуске мне нужно substr(previous_index, index), но в каждой последующей итерацииМне нужно substr(previous_index+1, index), чтобы пропустить через запятую.Есть ли какой-то простой способ, который я пропускаю, или мне придется повторять вызов find вне цикла для начальной итерации?

Ответы [ 5 ]

4 голосов
/ 19 декабря 2011

Поскольку ваша цель - предотвратить дублирование кода:

std::vector<std::string> v;
boost::split(v, value, [](char c) { c == ','; });

Если вы хотите создать свою собственную функцию разделения, вы можете сделать что-то вроде этого:

template<typename PredicateT>
std::vector<std::string> Split(const std::string & in, PredicateT p)
{
    std::vector<std::string> v;
    auto b = in.begin();
    auto e = b;
    do {
        e = std::find_if(b, in.end(), p);
        v.emplace_back(b,e);
        b = e + 1;        
    } while (e != in.end());

    return v;
}
3 голосов
/ 20 декабря 2011

Почему бы не обновить previous_index после принятия substr?

string::size_type index = 0;
string::size_type previous_index = 0;
do {
  index=value.find( ',', previous_index );
  const string item = value.substr(previous_index, index);
  previous_index = index+1;
} while( index != string::npos );

Не проверено, но это должно сработать (только с одним словом памяти).

1 голос
/ 19 декабря 2011

Начать с -1?

string::size_type index = -1;
do
{
    const string::size_type previous_index = index + 1;
    index=value.find(',', previous_index);
    const string item = value.substr(previous_index, index - previous_index);
} while( index != string::npos );
0 голосов
/ 19 декабря 2011

Во-первых, я думаю, что есть небольшая ошибка:

В вашем коде выражение index=value.find( ',', index ); не меняет значение index, если оно уже является индексом символа запятой в строке (что всегда имеет место, за исключением первой итерации цикла).

Поэтому вы можете заменить while( index != string::npos ); на while( index++ != string::npos ); и previous_index = index+1 на previous_index = index.

Это также должно решить вашу исходную проблему.

уточнить:

string::size_type index = 0;
do
{
    const string::size_type previous_index = index;
    index = value.find( ',', index );
    const string item = value.substr(previous_index, index - previous_index);
} while( index++ != string::npos );
0 голосов
/ 19 декабря 2011

Глупое (и несколько нечитабельное) решение будет выглядеть примерно так:

string::size_type once = 0;
/* ... */
const string::size_type previous_index = index+1 + (once++ != 0); // or !!once
...