-4

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.

Jonathan Mee
  • 37,899
  • 23
  • 129
  • 288
DrD4rk
  • 57
  • 1
  • 11
  • 2
    You parse the line where it says `Code here`. But seriously, you need to explain what does calling `Task` like that means - what are A and B, objects? strings? macro definitions? – Leeor Nov 25 '15 at 18:33
  • @Leeor It seems the question boils down to: I have formatted text in a file, and need to split out parts of each line so I can call `Task` on each line. – Glenn Teitelbaum Nov 25 '15 at 19:33
  • @GlennTeitelbaum, possible, but until he changes the question, I assume it's worse, and he wishes to chose objects by their names (otherwise the correct call is for example `Task("B", 4, "A")`) – Leeor Nov 25 '15 at 19:58
  • @Leeor seems that the first parameter is a single char, and the third is some mystical `task`, so yes, some help from OP is needed on that. There are two parts then to this question, parsing and translating, I can help on the first, and cleverly left the second as an exercize for the reader – Glenn Teitelbaum Nov 25 '15 at 20:03
  • @GlennTeitelbaum, Ah, missed the signature. – Leeor Nov 25 '15 at 20:08

2 Answers2

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;
        }

}
Glenn Teitelbaum
  • 10,108
  • 3
  • 36
  • 80
0

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

Jonathan Mee
  • 37,899
  • 23
  • 129
  • 288