2015-02-21 4 views
0

Я пытаюсь закрепить мою строку из всех комментариев. Комментарии в коде обозначены знаком «;» перед предложением. И иногда конец программ обозначается символом ";;"Удалить символы до следующего ' n'

Итак, представьте, у нас есть

push 34 ; example 
push 45 
add 

Для того, чтобы обнаружить "вхождение"; Я делаю это:

std::size_t findComment = _string.find(";"); 

Я хотел бы быть в состоянии сделать это:

_string = _string.erase(findComment, '\n'); 

Удалить everythin между положением и первым «\ п».

Заранее спасибо :)

UPDATE:

Я взял версию Конрада. Это работает хорошо. Но если пользователь записать это на стандартный вывод:

push int32(50) 
push int32(50) 
add 
dump 
;; 

Он должен выполнять функции и отображение 100 (свалка отображения стека). Но поскольку он заканчивается на ";;" функция trim_comments удаляет сброс функции. Так что это не выполняется.

+0

Просто интересно, откуда вы берете эти строки? Если вы получите их из потока, подумайте об использовании 'std :: getline()', чтобы разделить строку на строки. –

ответ

0

Метод erase выполняет работу. Все, что вам нужно, это второй итератор для позиции \n.

// This code assumes that _string holds one line of the text. 
std::size_t findComment = _string.find(";;"); 
std::size_t findNewLine = _string.find("\n"); 
_string = _string.erase(findComment, findNewLine); 

Если необходимо обработать несколько строк, используйте ответ Konrads.

Если вы не хотите стирать новый символ линии, вы можете использовать --findNewLine перед стиранием.

+0

Это не будет работать для следующего: '_string =" foo \ nbar ;; baz ";' –

1

find has an overload, который позволяет указать начало поиска позиции:

typedef std::string::size_type size_type; 

size_type const comment_start = _string.find(";;"); 
size_type const newline = _string.find("\n", comment_start + 2); 
if (newline == std::string::npos) 
    _string.erase(comment_start); 
else 
    _string.erase(comment_start, newline - comment_start); 

Кроме того, обратите внимание на использование typedef в коде выше, ваш код использует неправильный тип для позиций, возвращенных find.

Однако этот код удаляет только один комментарий. Удаление нескольких комментариев с помощью итерации erase Ввод из строки довольно неэффективен. Вместо этого вы должны создать новую строку из фрагментов без комментариев. Чтобы эффективно создавать строки в C++, вы используете std::[o]stringstream class вместо голого std::string.

Вот пример реализации, который должен работать достаточно хорошо:

std::string trim_comments(std::string const& code) { 
    typedef std::string::size_type size_t; 

    std::string const comment_start = ";;"; 
    std::ostringstream result; 

    // Iteratively search for the start of the next comment and copy code before 
    // that into the result. 
    // We start by setting the previous comment end (the newline position) to 
    // the start of the code. 
    size_t newline_pos = 0; 

    while (newline_pos != std::string::npos) { 
     size_t const comment_pos = code.find(comment_start, newline_pos); 

     if (comment_pos == std::string::npos) { 
      // No more comments; copy the rest of the code from here until the 
      // end into the result and quit. 
      result << code.substr(newline_pos); 
      break; 
     } 

     result << code.substr(newline_pos, comment_pos - newline_pos); 
     // Find end of comment, assuming UNIX line endings. 
     newline_pos = code.find('\n', comment_pos + comment_start.length()); 
    } 

    return result.str(); 
} 

Вы заметите, что это совсем немного сложнее, чем предыдущий, короткий код. Это цена, которую мы платим за правильность. Более простое решение требует более сложных функций обработки текста, таких как регулярные выражения (которые поддерживаются на уровне C++ 11 и могут быть добавлены в C++ 98 через библиотеки).

+0

Вы ** можете ** искать \ n за пределами ';;', но зачем использовать для начала поиска на вторая половина двоеточия? – harper

+0

@harper Хорошая точка, я должен начать за этим. –

+0

size_t возвращает size_t http://www.cplusplus.com/reference/string/string/find/. Или мне что-то не хватает? –

0
std::size_t commentPos = s.find(";;"); 
if (commentPos != std::string::npos) { 
    std::size_t nlPos = s.find_first_of("\r\n", commentPos); 
    if (nlPos != std::string::npos) { 
     s.erase(commentPos, nlPos - commentPos); 
    } else { 
     s.erase(commentPos); 
    } 
} 
Смежные вопросы