无法将.CSV文件读取为代表向量结构的类

Unable to read .csv file into a class that represents a struct for a vector

本文关键字:向量 结构 CSV 文件 读取      更新时间:2023-10-16

我无法读取30行.CSV文件的内容到以下结构:

class Entry {
public:
    std::string GID;
    std::string DName;
    std::string Phone;
    std::string POC;
    std::string Item;
    std::string Category;
    double amount;
};

我希望能够创建一个可以读取称为" donations.csv"的CSV文件并删除逗号的函数,因为我想创建一个可能类似的向量:std::vector<Entry> entries;,以便我可以对多个基于多个项目进行分类在向量中的任何元素上。因此,例如说我想按dname进行排序,代码看起来像这样:

// sort by DName
std::sort(entries.begin(), entries.end(), [](const Entry& a, const Entry& b) {
    return a.DName.compare(b.DName) < 0;
});

我被告知不要使用多个向量,因为这不是安全有效的,但是如果它可以帮助某人,这就是如何将CSV文件读为多个向量的方法:
公平的警告,使用EOF控制器是错误的,请参阅此处
尽管此代码可以正常工作,我亲自对其进行了测试 - .CSV文件上无数次。

int main()
{
ifstream inFile;                    // Input file handler
ofstream outFile;                   // Output file handler
vector<string> GID;                 // Vector holding Gift ID
vector<string> DName;               // Vector holding Donor Name
vector<string> Phone;               // Vector holding Phone Number
vector<string> POC;                 // Vector holding point of contact
vector<string> Item;                // Vector holding item donated 
vector<string> Category;            // Vector holding type of item donated
vector<double> amount;              // Vector holding amount of donated items
int Input;                          // User selection choice from menu
// opening data file
inFile.open("Donations.csv");
if (!inFile)                        // If statement to check for file erroe
{
    cout << "Input file did not open. Program will exit." << endl;      // Does not compute!
    exit(0);
}
// reading contents
string str;                         // temp string to hold parse comma
double temp;                        // temp double to hold null spaces for atoi function/strtod
getline(inFile, str, ',');          // read first GID string outside of loop so that we
                                    // won't accidentally reach the end of the file in the MIDDLE of the loop
while (!inFile.eof())               // end of file not reached
{
    GID.push_back(str);
    getline(inFile, str, ',');      // get the contents of the line until a comma is encountered and push it into the necessary vector
    DName.push_back(str);
    getline(inFile, str, ',');
    Phone.push_back(str);
    getline(inFile, str, ',');
    POC.push_back(str);
    getline(inFile, str, ',');
    Item.push_back(str);
    getline(inFile, str, ',');
    Category.push_back(str);
    getline(inFile, str, 'n');     // get until the end of the line but split for parsing
    // convert string to double using strtod and c_str
    temp = strtod(str.c_str(), NULL);
    // now push double onto vector
    amount.push_back(temp);
    getline(inFile, str, ',');      // read in GID here instead of the top.  If we are at the end
                                    // of the file, it won't work and end-of-file flag will be set which is what we want.
}
inFile.close();
}

添加此方法:

friend std::istream& operator>>(std::istream& input, Entry& e);

到您的Entry结构。

将其添加到您的源代码:

std::istream&
operator>>(std::istream& input, Entry& e)
{
    input >> e.GID;
    input >> e.Dname;
    //.. input other members
    return input;
}

将您的容器更改为:

std::vector<Entry> database;

您的输入循环看起来像这样:

Entry e;
while (my_data_file >> e)
{
  database.push_back(e);
}

您可能还想搜索Internet以获取" Stackoverflow C 读取文件struct"以获取更多示例。

总而言之,创建一个结构或类以建模记录。
超载操作员>>在记录中阅读。
使用结构的std::vector,而不是每个数据成员的向量。
如果您认真对待数据库,请使用一个;不要重写自己的。

编辑1:排序
为了使排序更加容易,请超载>操作员:

struct Entry
{
  //...
  bool operator<(const Entry& other) const
  {
    // add comparison functionality, example:
    return GID < other.GID;
  }
}

现在,您可以使用:

对数据库进行排序
std::sort(database.begin(), database.end());

编辑2:其他排序
要使用不同的条件订购容器,您可以创建订购功能并将其传递给std::sort函数:

bool Order_By_Dname(const Entry& e1, const Entry& e2)
{
  return e1.Dname < e2.Dname;
}

您的排序变为:

std::sort(database.begin(), database.end(), Order_By_Dname);