How do I parse a line into pieces and ignore parts of it?

馋奶兔 提交于 2019-12-13 10:05:05

问题


I am sorry. I wasn't clair previously. I have a file that include data in the following format

A(3)

B(4),A

C(2),A

E(5),A

G(3),A

J(8),B,H

H(7),C,E,G

I(6),G

F(5),H

...

These data represent a graph.

I will use the critical path method to calculate how to get through this text file.

the char is the step the int is the length of each task the other char is step that come before the first char

So I have created the class Task to read the file and its constructor have the following parameters

    Tache::Tache(char step2, int duration, list<Task*> precedentTask)

    {

          this->step = step2;
          this -> duration = duration; 
          for(list<Task*>::iterator it = this-> precedentTask.begin(); it != this-> precedentTask.end(); it++)
         {
              this-> precedentTask.push_back(*it);
         }
   }

In the main I added

string line;
list<Task> *allTaches = new list<Task>();

  while(getline(file, line, ','))
 {
       //I want to be able to receive the parse line from the file and add it like
     //allTaches.push_back(line)
     //But the format needs to look like (Char, duration, <a list of> PrecedentChar)           
     //when I do 
     cout<< line << Lendl;
    it prints 
    A(3)
    B(4)
    A
    C(2)
    A
    E(5)
    A 
 }

So I am not sure to know what to do really.


回答1:


You can use a regular expression to parse out the pieces you need and then pass them to Task

In c++ that is done using std::regex

The code below will help you understand how to parse out the pieces, applying them to test is a simple step from there, but best done by you to make sure the concept is clear.

First we will need a regular expression that grabs each piece, this is called a capture group and all that is needed is to use parenthesis

If we break down what you have - it is:

Something, an open paren we dont want, Something, a close paren we dont want, a comma we don't want, and Something

in simple regex that would be:

(.*)\((.*)\),(.*)

But things are never so simple

The first Something ends with the open paren, so we want everything but that first open paren: ([^(]) the ^ means not, the square bracket [] means every character

The second Something ends with the close paren, so we have ([^)])

The third something excludes the optional comma, but we can use (.*) and then group the , in an optional * (There is likely a better way to do this)

We also need to double escape the \ once for the compiler and once for regex

We also need to allow for people entering random spaces in there so we add * in all breaks

This leads to our regex:

*([^(]*) *\\( *([^)]*) *\\) *(, *(.*))*

Then we search and if found it will be in the result and we can iterate it to get the pieces.

#include <iostream>
#include <string>
#include <regex>

int main()
{
        // std::string seq = "A(4),B";
        std::string seq = "A(4)";

        try {
                std::regex rgx(" *([^(]*) *\\( *([^)]*) *\\) *(, *(.*))*");
                std::smatch result;
                if(std::regex_search(seq, result, rgx))
                {
                        std::cout << "Size=" << result.size() << std::endl;
                        for(size_t i=0; i<result.size(); ++i)
                        {
                                std::cout << result[i] << std::endl;
                        }
                }
                else
                {
                        std::cout << "NO MATCH" << std::endl;
                }
        } catch (std::regex_error& e) {

                std::cout << "BAD REGEX" << std::endl;
        }

}



回答2:


What you're actually looking to do here is create an extraction operator for your Tache object. I'm going to assume that your code looks something like this:

typedef char Task;

struct Tache {
    char step;
    int duration;
    list<Task> precedentTask;
};

Your extraction operator will be a method of Tache. It's brute force implementation will look something like this:

istream& operator>>(istream& lhs, Tache& rhs) {
    string line;

    getline(lhs, line, '\n');

    stringstream ss(line);

    ss >> rhs.step;
    ss.ignore(numeric_limits<streamsize>::max(), '(');
    ss >> rhs.duration;
    ss.ignore(numeric_limits<streamsize>::max(), ')');

    const regex re("\\s*,\\s*([a-zA-Z])");
    string precedentTasks;

    getline(ss, precedentTasks);

    rhs.precedentTask.clear();

    transform(sregex_token_iterator(cbegin(precedentTasks), cend(precedentTasks), re, 1), sregex_token_iterator(), back_insert_iterator<list<Task>>(rhs.precedentTask), [](const string& i) {
        return i.front();
    });

    return lhs;
}

Live Example



来源:https://stackoverflow.com/questions/33923863/how-do-i-parse-a-line-into-pieces-and-ignore-parts-of-it

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!