2016-12-07 14 views
0

Я пытаюсь исключить комментарии, пустые строки и дополнительные пробелы в текстовом файле, а затем пропустить оставшиеся элементы. Каждому токену требуется пространство до и после.Токсизировать элементы из текстового файла, удаляя комментарии, лишние пробелы и пустые строки в C++

exampleFile.txt 
var 

/* declare variables */a1 , 
b2a ,  c, 

Вот что работает как сейчас,

string line; //line: represents one line of text from file 
ifstream InputFile("exampleFile", ios::in); //read from exampleFile.txt 

//Remove comments 
while (InputFile && getline(InputFile, line, '\0')) 
{ 
    while (line.find("/*") != string::npos) 
    { 
     size_t Begin = line.find("/*"); 
     line.erase(Begin, (line.find("*/", Begin) - Begin) + 2); 
     // Start at Begin, erase from Begin to where */ is found 
    } 
} 

Это удаляет комментарии, но я не могу показаться, чтобы выяснить способ разметить в то время как это происходит.

Так что мои вопросы:

  • Можно ли удалить комментарии, пробелы и пустые строки и разметить все в это время заявление?
  • Как я могу реализовать функцию для добавления пробелов между каждым токеном до их токенизации? Токены, подобные c, должны быть распознаны как c и, в отдельности.

Благодарим вас за помощь!

+1

Отключить тему: сохранить поиск: 'while ((size_t Begin = line.find ("/* "))! = String :: npos)' – user4581301

+0

Off topic: Что делать, если комментарий блока не заканчивается на такая же линия? – user4581301

+1

И еще одна тема: подумайте о том, что произойдет, когда программа найдет/* in 'while (line.find ("/* ")! = String :: npos)'. – user4581301

ответ

0

Если вам нужно пропустить символы пробелов, и вам не нужны новые строки, я бы рекомендовал прочитать файл с помощью operator>>. Вы могли бы просто написать:

std::string word; 
bool isComment = false; 
while(file >> word) 
{ 
    if (isInsideComment(word, isComment)) 
     continue; 

    // do processing of the tokens here 
    std::cout << word << std::endl; 
} 

Если вспомогательная функция может быть реализована следующим образом:

bool isInsideComment(std::string &word, bool &isComment) 
{ 
    const std::string tagStart = "/*"; 
    const std::string tagStop = "*/"; 

    // match start marker 
    if (std::equal(tagStart.rbegin(), tagStart.rend(), word.rbegin())) // ends with tagStart 
    { 
     isComment = true; 
     if (word == tagStart) 
      return true; 

     word = word.substr(0, word.find(tagStart)); 
     return false; 
    } 

    // match end marker 
    if (isComment) 
    { 
     if (std::equal(tagStop.begin(), tagStop.end(), word.begin())) // starts with tagStop 
     { 
      isComment = false; 
      word = word.substr(tagStop.size()); 
      return false; 
     } 

     return true; 
    } 

    return false; 
} 

Для примера это будет распечатать:

var 
a1 
, 
b2a 
, 
c, 

Вышеупомянутые логика должна также обрабатывайте многострочные комментарии, если вам интересно.

Однако следует отметить, что реализация функции должна быть изменена в соответствии с вашими предположениями относительно токенов комментариев. Например, они всегда отделены пробелами от других words? Или возможно, что выражение var1/*comment*/var2 будет проанализировано? Приведенный выше пример не будет работать в такой ситуации.

Таким образом, другой вариант был бы (то, что вы уже начали внедрять), чтение строк или даже фрагментов данных из файла (для обеспечения соответствия токенов начала и конца комментария) и учебных позиций маркеров комментариев с помощью find или regex удалите их потом.

+0

Я понимаю, это полезно! Спасибо! –

+0

'line == tagStart' только улавливает всю строку. При чтении строки из файла строка устанавливается на всю строку. Поэтому мне нужно сравнить часть строки с «/ *» или «* /», используя, например, строку [i] + line [i + 1], но это приводит к ошибкам ввода. –

+0

Не уверен, что я понимаю вас правильно. Чтобы избежать путаницы, я обновил имя переменной 'line' до' word', так как это то, что он содержит (а не строку файла вообще). Если вам нужно обрабатывать такие случаи, как 'var/* comment */var', я также обновил функцию для использования' std :: equal'. Но, как я писал, это общая идея и должна быть адаптирована к вашим конкретным потребностям. Вероятно, есть более подробная информация, которую вы не поделили в вопросе, который потребует обновлений внедрения. – Dusteh