2015-03-19 20 views
0


Я пытаюсь узнать больше о C++, и я в процессе создания (довольно простой) 2D-редактор карт. В настоящее время у меня есть система, которая работает очень хорошо, но я пытаюсь улучшить использование тегов.(C++) Parsing Pseudo-XML

То, что я хочу сделать
Я хочу, чтобы иметь возможность загрузить текстовый файл, и он хранить все данные, которые я, возможно, потребуется в уровне (включая, но не ограничиваясь ими: плитка, фон , объекты, проигрыватель и т. д.). Эти текстовые файлы будут сгенерированы моим редактором карт, поэтому я полностью контролирую, как они созданы, и их структуру. Хотя это не школьный проект, я пытаюсь узнать больше о C++, поэтому я предпочел бы использовать как можно меньше зависимостей (в настоящее время я использую только SFML, но я не думаю, что это важно для этого), поэтому я не использую существующий XML Parser.



//Call to my parser 
getTagContents("Resources/xmltester.txt", "mytag"); 


// 
void getTagContents(std::string fileToBeParsedLocation, std::string tagName) 
{ 
int lineNumberToFindTagName = 0; 
int lineNumberToFindTagNameEnd = 0; 

std::vector<int> tagsLine; 
std::vector<int> tagsPos; 
std::vector<std::string> tagContents; 

std::string tempLine; 


std::fstream fileToBeParsed(fileToBeParsedLocation); 

if (fileToBeParsed.is_open()) 
{ 
    while (!fileToBeParsed.eof()) 
    { 
     while (std::getline(fileToBeParsed, line)) 
     { 
      //Opening tag 
      if (line.find("<" + tagName + ">") == -1) 
      { 
       lineNumberToFindTagName++; 
      } 
      else 
      { 
       std::size_t pos = line.find("<" + tagName + ">"); 
       std::cout << "Found tag " << tagName << " opening at line " << lineNumberToFindTagName << " at position " << pos << std::endl; 
       tagsLine.push_back(lineNumberToFindTagName); 
       tagsPos.push_back(pos); 
       lineNumberToFindTagName++; 

       //Test 
       //std::getline(fileToBeParsed, tempLine); 
       //std::cout << tempLine; 
       //This returns really strange values 
      } 

      //Closing tag 
      if (line.find("</" + tagName + ">") == -1) 
      { 
       lineNumberToFindTagNameEnd++; 
      } 
      else 
      { 
       std::size_t pos = line.find("</" + tagName + ">"); 
       std::cout << "Found tag " << tagName << " closing at line " << lineNumberToFindTagNameEnd << " at position " << pos << std::endl; 
       tagsLine.push_back(lineNumberToFindTagNameEnd); 
       tagsPos.push_back(pos); 
       lineNumberToFindTagNameEnd++; 
      } 
     } 
    } 


    //Size of tagContents will always be half of either tagsLine or tagsPos (it doesn't matter which) 

    for (int i = 0; i < tagsPos.size()/2; i++) 
    { 
     for (int j = 0; j < tagsLine[i]; j++) 
     { 
      //I think this is where most of the stuff I need to add should go 

     } 
     std::getline(fileToBeParsed, tempLine); 
     std::stringstream stream(tempLine); 
     std::cout << "Line contents: " << tempLine << "<>" << std::endl; 
    } 
} 
for (int i = 0; i < tagsPos.size(); i++) 
{ 
    std::cout << tagsLine[i] << "." << tagsPos[i] << std::endl; 
} 
getchar(); 
getchar(); 
} 


чем дело
Это может быть в основном из-за моей некомпетентности, но я понятия не имею, как использовать тот факт, что я знаю, что теги e и значение позиции, чтобы читать между ними. Это должно быть тривиально, но я не могу найти способ удостовериться, что я могу прочитать любое количество тегов правильно ...


Любые идеи? (И спасибо заранее)

+0

А как насчет закрытия тега? Зная положение «>» открытия и «<» закрывающего тега, вы можете читать контент между ними с помощью функции 'get()' 'fstream'. Чтобы установить позицию курсора на символ «>», вы можете использовать функцию 'seekg()'. – Amadeusz

+0

Лично я не уверен, что XML - лучший выбор здесь. Пока вы не познакомитесь с тем, как основные функции синтаксического анализа работают на C++, лучше создать более простой формат. Что-то, что очень похоже на то, как данные хранятся в самой игре. – Galik

+0

Amadeusz, я думал о подобном подходе, но я обеспокоен тем, что не буду читать больше одной строки. Одна из частей данных, которую я пытаюсь сохранить, - это моя карта сама, и хотя я буду знать после прочтения файла, насколько она велика, она потенциально может быть огромной (не уверен, что могут быть аппаратными ограничениями, м надеясь, что это может быть даже до нескольких сотен тысяч с каждой стороны). Если это просто невозможно, я могу попытаться найти другой метод. – user4678593

ответ

0

Не делайте этого. Вы пытаетесь реализовать парсер XML без знания методов анализа. Этот проект никогда не может закончиться ничем иным, как полным провалом.

Что вам нужно, это существующий синтаксический анализатор XML, и есть два его варианта: синтаксический анализ в стиле SAX, который читает файл в последовательности, и разбор DOM-стиля, который считывает файл в полную структуру данных.

Наиболее популярная библиотека синтаксического анализа в стиле SAX для C (и C++) является expat. Я не уверен, имеет ли он объектно-ориентированную C++-оболочку, но если нет, если вы действительно знаете C++, вы можете реализовать это за меньшее время, чем требуется для собственного XML-синтаксического анализатора.

Если вам нужен синтаксический анализ в стиле DOM, одним из вариантов будет обработка событий в синтаксическом анализаторе SAX и построение дерева синтаксического анализа. Другой вариант - посмотреть, есть ли какие-либо библиотеки разбора C/C++ в DOM-стиле. Вероятно, библиотека C++ была бы лучшим выбором, поскольку библиотеки типа DOM по своей сути объектно-ориентированы, и вы хотите использовать для них полные возможности языка C++.

Чтобы узнать больше о различных подходах к разбору XML см http://en.wikipedia.org/wiki/XML#Programming_interfaces

Простой API для XML означает SAX и Document Object Model означает DOM.

Если вы действительно хотите реализовать свой собственный синтаксический анализатор XML, лучше сначала изучить предыдущий уровень (например, синтаксический анализ на основе SAX и разбор на основе DOM) и решить, какой из них вы хотите иметь. Ваш синтаксический анализатор прототипов не является ни тем, ни другим, и franky не выглядит как успешный подход для синтаксического анализа XML вообще.

+0

Не могли бы вы рассказать о том, почему вы не думаете, что это хороший подход (просто пытаясь узнать здесь)? Я полагаю, что если я смогу понять, как читать с определенной позиции (что я уже знаю), я могу решить, что делать с данными, когда я его прочитаю. Поскольку я делаю файлы для чтения, я могу легко контролировать формат. Благодарю. – user4678593

+0

Это похоже на популярный вопрос разбора HTML/XML с регулярными выражениями. Да, вы можете это сделать, но никогда не защищаете все возможные файлы HTML/XML. Я предполагаю, что если вы будете контролировать формат, подход может быть прекрасным на некоторое время, но затем, когда возникнет необходимость в расширении формата, вы быстро застрянете. Рассмотрите возможность того, что кто-то редактирует файлы с помощью текстового редактора таким образом, который делает их нечитаемыми вашим хакерским синтаксическим анализатором, но читаемым надлежащим синтаксическим анализатором XML. Если вы действительно хотите использовать подход, который используете, то, возможно, кто-то может помочь. – juhist

+0

Хотя я хотел бы быть готовым к любому событию, если кто-то задевает файлы, это их вина, и ради меня, узнав, как это работает, это то, что я собираюсь игнорировать. Если вы все еще думаете, что я не должен пытаться, дайте мне знать; вы можете убедить меня: P (Из любопытства, насколько вероятно, что кто-то возится с файлами, вы получите что-то, что может читать XML, но я не могу, если я пытаюсь прочитать все, что есть между тегами?) – user4678593