Линейное решение с некоторыми понятиями питона:
cur = ''
for line in lines():
prev = cur
cur, text = split_line_into_marker_and_remainder(line)
if cur && (cur == prev) :
print '</li><li>'
else :
nprev, ncur = kill_common_beginning(prev, cur)
for c in nprev: print '</li>' + ((c == '#') ? '</ol>' : '</ul>')
for c in ncur: print ((c == '#') ? '<ol>' : '<ul>' ) + '<li>'
print text
Вот как это работает: для обработки строки я сравниваю маркер для предыдущей строки с маркером для этой строки.
Я использую вымышленную функцию split_line_into_marker_and_remainder
, которая возвращает два результата, маркер cur
и сам текст. Тривиально реализовать его как функцию C ++ с 3 аргументами, входными и 2 выходными строками.
В основе лежит вымышленная функция kill_common_beginning
, которая уберет повторяющиеся части prev
и cur
. После этого мне нужно закрыть все, что осталось в предыдущем маркере, и открыть все, что осталось в текущем маркере. Я могу сделать это с заменой, отображением символов в строку или с помощью цикла.
Три строки будут довольно просты в C ++:
char * saved = prev;
for (; *prev && (*prev == *cur); prev++, cur++ ); // "kill_common_beginning"
while (*prev) *(prev++) == '#' ? ...
while (*cur) *(cur++) == '#' ? ...
cur = saved;
Обратите внимание, однако, что есть особый случай: когда отступ не изменился, эти строки ничего не выводят. Это хорошо, если мы за пределами списка, но это не очень хорошо в списке: так что в этом случае мы должны вывести </li><li>
вручную.