Простой C ++ токенайзер - PullRequest
       9

Простой C ++ токенайзер

0 голосов
/ 31 августа 2018

Я пишу программу для вызова на HackerRank, и мне нужно проанализировать HRML, язык разметки, похожий на HTML:

<tag1 value = "Hello World"></tag1>

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

tag1.tag2.tag3~attribute_name

Функция ведет себя так, как будто строковый итератор останавливается, когда встречает тильду. Вот код:

#include<iostream>
#include<string>
#include<vector>
using namespace std;

void tokenize_string(vector<string>& vector, string str)
{
    string current_token;

    for (auto i = str.begin(); i != str.end(); i++)
    {

        if (isalnum(*i))
        {
            current_token += *i;
        }
        else
        {
            //We extracted a token
            vector.push_back(current_token);
            current_token = "";
        }
    }

    //Remove empty strings that the previous loop placed into the vector
    for (auto i = vector.begin(); i != vector.end(); i++)
    {
         if (*i == "")
        {
            vector.erase(i);
            i = vector.begin();
        }
    }
} 
int main()
{
    //A simple test
    vector<string> tag_tokens;
    vector<string> query_tokens;

    tokenize_string(tag_tokens, "<tag1 name=\"Hello\">");
    tokenize_string(query_tokens, "tag1.tag2.tag3~name");

    for (auto it = tag_tokens.begin(); it != tag_tokens.end(); it++)
    {
        cout << *it << ' ';
    }
    cout << '\n';
    for (auto it = query_tokens.begin(); it != query_tokens.end(); it++)
    {
        cout << *it << ' ';
    }
    cout << '\n';
    cin.get();
    return 0;
}

Ответы [ 2 ]

0 голосов
/ 31 августа 2018

Вот другой способ сделать это, который требует меньше строк кода:

void tokenize_string(
    std::vector< std::string >& output,
    const std::string& csv,
    const string& delimiters )
{
    for( char del : delimiters ) {
      std::stringstream sst(csv);
      std::string a;
      while( getline( sst, a, del) )
        output.push_back(a);
   }
}
0 голосов
/ 31 августа 2018

Это потому, что вы не учитываете последний токен после достижения конца входной строки i != str.end().
Добавьте vector.push_back(current_token); после цикла for, как показано ниже, чтобы учесть последний токен.

void tokenize_string(vector<string>& vector, string str)
{
    string current_token;

    for (auto i = str.begin(); i != str.end(); i++)
    {

        if (isalnum(*i))
        {
            current_token += *i;
        }
        else
        {
            //We extracted a token
            vector.push_back(current_token);
            current_token = "";
        }
    }
                vector.push_back(current_token);   ///-------->pushes last token

    //Remove empty strings that the previous loop placed into the vector
    for (auto i = vector.begin(); i != vector.end(); i++)
    {
         if (*i == "")
        {
            vector.erase(i);
            i = vector.begin();
        }
    }
}
...