如何从文本文件中提取带有逗号分隔符的字符串并将逗号分隔符分隔的每个元素解析为 class 构造函数

How to extract string with comma delimiter from txt file and parse every element separete by comma delimiter into a class constructor

来源:文本文件存储帐户信息列表。例如:

10041249,Mr,Vincent,Rogan,Rogan Locksmiths Ltd,Nell,5287.000000,,491.691000,
10021250,Mrs,Adele,Cunningham,Cunningham Demolition Ltd,Dr Scott,2941.000000,,273.513000,
10051251,Mr,Rodney,Shaw,Shaw Meat Packaging Ltd,Eddie,7552.000000,,740.096000,
10001252,Mrs,Christine,Nichols,Nichols Scaffolding Ltd,Brad,6723.000000,Eddie:Brad:,672.300000,
10021253,Mr,Alexander,Marshall,Marshall Chemicals Ltd,Dr Scott,1768.000000,,173.264000,
10021254,Ms,Shirley,Hagman,On Point Sportswear Ltd,Dr Scott,52.000000,,5.200000,
....
....
....

如何从 txt 文件中提取带逗号分隔符的字符串并将逗号分隔符分隔的每个元素解析为 class 构造函数?

我已经尝试使用 stringstream 从每一行中提取数据。但它不起作用。 我得到的 EmployeeAccount class 在下面:

#include <iostream>
#include <sstream>
#include <string>

using namespace std;

class EmployeeAccount {
private:
    //member variable
    string acountNumber;
    string title; 
    string firstname; 
    string lastname; 
    string company; 
    string salesperson; 
    double purchaseValue; 
    string prev_salestaff; 
    double commission; 

public:

    //overload constructor
    EmployeeAccount(const string& employeeAccountInfo)
    {
        string str;
        stringstream employeeAccountStream(employeeAccountInfo);
        while (getline(employeeAccountStream, str, ','))
        {
            stringstream sso(str); 
                sso >> acountNumber; 
                sso >> title; 
                sso >> firstname; 
                sso >> lastname; 
                sso >> company; 
                sso >> salesperson; 
                sso >> purchaseValue; 
                sso >> prev_salestaff; 
                sso >> commission; 
        }
    }
    //Access methods
    string getAccountNumber() { return acountNumber; }; 
    string getTitle() { return title; }; 
    string getFirstname() { return firstname; }; 
    string getLastname() { return lastname; }; 
    string getCompany() { return company; }; 
    double getPurchaseValue() { return purchaseValue; }; 
    string getPrev_salesstaff() { return prev_salestaff; }; 
    double getCommission() { return commission; }; 
    string getAccountDetail() { return acountNumber + " " + title + " " + firstname + " " + lastname + " " + company;};

    //Destructor
    ~EmployeeAccount() {};
};

测试代码是这样的:

    cout << testEmployee.getAccountDetail() << endl;
    cout << testEmployee.getAccountNumber() << endl;
    cout << testEmployee.getTitle() << endl;
    cout << testEmployee.getFirstname() << endl;
    cout << testEmployee.getLastname() << endl;
    cout << testEmployee.getCompany() << endl;
    cout << testEmployee.getPurchaseValue() << endl;
    cout << testEmployee.getPrev_salesstaff() << endl;
    cout << testEmployee.getCommission() << endl;
}

解析 CSV 文件是个老话题了。您将在 Whosebug 上找到至少 100 个带有代码示例的答案。通常您会找到函数 std::getline 的解决方案。请阅读此处的文档。它可以从 std::ifstream 开始读取字符,直到或直到一个分隔符(在我们的例子中是一个逗号 ,),然后将结果(不带逗号)存储在一个字符串中,并从流中丢弃逗号。所以,把它扔掉。字符将存储在std::string中。如果需要数字或其他类型,我们需要使用适当的函数将字符串转换为其他类型。

示例:我们有一个由字符“1”、“2”和“3”组成的字符串,因此,“123”。引号表示字符串类型。如果我们想把这个字符串转换成一个整数,我们可以使用函数 std::stoi.

在您的例子中,您有 2 个双精度值。因此,我们会将文件的输入拆分为字符串,然后使用函数 std::stod.

将其中包含双精度值的 2 个字符串进行转换

您还需要知道的是,通常使用两步法。这样做是为了防止从一个 csv 行中提取所有字符串部分引起的潜在问题。所以,

  • 我们首先阅读完整的一行,
  • 然后将该行放入std::istringstream,最后
  • 读取输入并从那里拆分 CSV。

那么,剩下的就简单了。只需使用 std::getline 来获取您需要的数据。

最后但同样重要的是,要读取文件,我们只需打开它,逐行读取,创建一个“EmployeeAccount”并将其推送到 std::vector

最后我们做一些调试输出。

请参阅以下可能的实施建议之一:

#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <vector>


class EmployeeAccount {
private:
    //member variable
    std::string acountNumber;
    std::string title;
    std::string firstname;
    std::string lastname;
    std::string company;
    std::string salesperson;
    double purchaseValue; 
    std::string prev_salestaff;
    double commission; 

public:

    //overload constructor
    EmployeeAccount(const std::string& employeeAccountInfo)
    {
        std::istringstream employeeAccountStream(employeeAccountInfo);
        std::getline(employeeAccountStream, acountNumber, ',');
        std::getline(employeeAccountStream, title, ',');
        std::getline(employeeAccountStream, firstname, ',');
        std::getline(employeeAccountStream, lastname, ',');
        std::getline(employeeAccountStream, company, ',');
        std::getline(employeeAccountStream, salesperson, ',');
        std::string temp;
        std::getline(employeeAccountStream, temp, ',');
        purchaseValue = std::stod(temp);
        std::getline(employeeAccountStream, prev_salestaff, ',');
        std::getline(employeeAccountStream, temp, ',');
        commission = std::stod(temp);
    }
    //Access methods
    std::string getAccountNumber() const { return acountNumber; };
    std::string getTitle()  const { return title; };
    std::string getFirstname()  const { return firstname; };
    std::string getLastname()  const { return lastname; };
    std::string getCompany()  const { return company; };
    double getPurchaseValue()  const { return purchaseValue; };
    std::string getPrev_salesstaff()  const { return prev_salestaff; };
    double getCommission()  const { return commission; };
    std::string getAccountDetail()  const { return acountNumber + " " + title + " " + firstname + " " + lastname + " " + company;};

    //Destructor
    ~EmployeeAccount() {};
};
int main() {
    std::ifstream ifs{ "accounts.txt" };
    if (ifs) {

        // Here we will store all accounts
        std::vector<EmployeeAccount> accounts{};

        // Read the file line by line
        std::string line{};
        while (std::getline(ifs, line)) {

            // Create one account by splitting the input line
            EmployeeAccount account(line);

            // Add the new accounts to the vector of accounts
            accounts.push_back(account);
        }

        // Debug output. For all accounts that we read, output all data
        for (const EmployeeAccount& account : accounts) {

            std::cout << "\n--------------------------\n"
             << account.getAccountDetail() << '\n'
             << account.getAccountNumber() << '\n'
             << account.getTitle() << '\n'
             << account.getFirstname() << '\n'
             << account.getLastname() << '\n'
             << account.getCompany() << '\n'
             << account.getPurchaseValue() << '\n'
             << account.getPrev_salesstaff() << '\n'
             << account.getCommission() << '\n';
        }
    }
    else
        std::cerr << "\n*** Error: Could not open source file\n\n";
}