Click here to Skip to main content
14,974,371 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
The file has
CompanyNo, Items baught (3 from every company), totalpaid, totalreturn(due to bad product), relation with other company(if any(companyNo))

a787, apple, banana, strawberry, "32,888.00", "0.0" k798, g456
f238, "Orange, Juice", Kiwi, "20,666.03", 0.0
g456, "Fresh, Beef", Lamb, Chicken, "40,500.00", "4,134.00", f238

and so on
I am trying to read it into a class

class Company {

    std::string CompanyNo;
    std::string Item1;
    std::string Item2;
    std::string Item3;
    double Paid;
    double Return;
    vector<std::string> RelatedTo;

public:

    Company(std::string CompanyNo, std::string Item1, std::string Item2, std::string Item3, double paid, double Return, std::vector<std::string> RelatedTo)
    {
        this->CompanyNo = CompanyNo;
        this->Item1 = Item1;
        this->Item2 = Item2;
        this->Item3 = Item3;
        this->Paid = Paid;
        this->Return = Return;
        this->RelatedTo = RelatedTo;
    };

    ~Client() {};

    Company(const Company& cn) {
        this->CompanyNo = cn.CompanyNo;
        this->Item1 = cn.Item1;
        this->Item2 = cn.Item2;
        this->Item3 = cn.Item3;
        this->Paid = cn.Paid;
        this->Return = cn.Return;
        this->RelatedTo = cn.RelatedTo;
    };

    Company() {};

    Company operator= (Company cn) {
        this->CompanyNo = cn.CompanyNo;
        this->Item1 = cn.Item1;
        this->Item2 = cn.Item2;
        this->Item3 = cn.Item3;
        this->Paid = cn.Paid;
        this->Return = cn.Return;
        this->RelatedTo = cn.RelatedTo;
        return cn;
    }

    void setCompanyNo(std::string i) { CompanyNo = i; };
    void setItem1(std::string i1) { Item1 = i1; };
    void setItem2(std::string i2) { Item2 = i2; };
    void setItem3(std::string i3) { Item3 = i3; };
    void setPaid(double p) {Paid = p; };
    void setReturn(double r) { Return = r; };
    void setRelatedTo(std::vector<std::string> rt) { RelatedTo = rt; }


    std::string getCompanyNo() const { return CompanyNo; }
    std::string getItem1() const { return Item1; }
    std::string getItem2() const { return Item2; }
    std::string getItem3() const { return Item3; }
    double getPaid() const { return Paid; }
    double getReturn() const { return Return; }
    vector<std::string> getRelatedTo() const { return RelatedTo; }

};


At the bottom is what I have tried but doesn't really store each value into the class. This is my first time reading complicated file with different number of coloums and commas between strings and doubles like "32,888.00" should store like 32888.00 in class and through file is comma delimited items like "orange, juice" should store like orange, juice rather then orange and juice separatly. And relation to other should store as vector since company can have relation with many companies or non. Any help would be appreciated thank you

What I have tried:

vector <Company> Info;

Company parseLine(string str)
{
    vector<string> store;
    string tok;
    stringstream evaluator;
    Company retv;

    evaluator << str;
    {
        char double_quote_remover;
        evaluator >> double_quote_remover; 
        getline(evaluator, tok, '"'); 
        char comma_remover;
        evaluator >> comma_remover; 
    }

    char ch;

    while (evaluator >> ch && ch != ','); 

    tok = ""; 
    ch = ' '; 

    while (evaluator >> ch) {  
        if (isalpha(ch)) { evaluator.putback(ch); ch = ','; } 
        if (ch == '\"') getline(evaluator, tok, '\"'); 
        else if (ch == ',') getline(evaluator, tok, ','); 
            store.push_back(tok);
        tok = ""; 
    }

    retv.setRelatedTo(store); 

    return retv; 

}

bool readFile()
{
    std::ifstream myFile("Data.txt");
    if (!myFile.is_open())
    {
        cout << "FAILED" << "\n";
        return false;
    }
    string str;

    getline(myFile, str); 

    int i = 0;
    while (std::getline(myFile, str))
    {
        Company Company = parseLine(str);
        Info.push_back(Company);
    }
    return true;
}

int main()
{
    bool data = readFile();

}
Posted
Updated 12-Apr-21 20:00pm
Comments
KarstenK 13-Apr-21 2:36am
   
tip: such format has always the pitfall that the delimiters break the format when in data. Like: "New" Coke as brand name.
Richard MacCutchan 13-Apr-21 4:00am
   
The logic is fairly simple for each token in the string:
1. Skip leading spaces.
2. If first non-blank character is double quote, set terminator to double quote, else use default.
3. Copy all characters until terminator is found.
4. If terminator is double quote, reset it to default.
5. Continue copying until terminator is found.
6. Repeat until end of string.

In a real world situation you would need additional error checks to ensure the data is well formed, but you can probably guarantees that for your test.
Rick York 13-Apr-21 11:48am
   
Richard is on the right track here. The key thing to know when you are in the middle of a quoted string or not. If you know much about state machines this is a fairly straight-forward application for one.

1 solution

It's called CSV (Comma Separated Values) and if you do a quick Google you will find loads of examples / libraries which can read it: read csv c - Google Search[^]

Personally, I wouldn't write my own - it's not a trivial job to get right because of the "quoted strings" and "newlines in strings are permitted" elements. That's not saying you can't, it's perfectly feasible, it's just that there are lots of existing examples that are tested and working already, and I'd use one of those to save me a fair amount of time in testing.
   

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)




CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900