读取和存储 CSV 数据

Read and Store CSV Data

我有这样的数据;

InvoiceNo;StockCode;Description;Quantity;InvoiceDate;UnitPrice;CustomerID;Country
A;B;C;D;E;F;G;H
A2;B2;C2;D2;E2;F2;G2;H2
.
.
.
A500000;B500000;C500000;D500000;E500000;F500000;G500000;H500000

我正在使用该代码读取文件;

std::ifstream is("myData.csv", std::ifstream::binary);
if (is) {
    is.seekg(0, is.end);
    int length = is.tellg();
    is.seekg(0, is.beg);

    char* buffer = new char[length];
    std::cout << "Reading " << length << " characters... ";
    is.read(buffer, length);

    if (is) {
        std::cout << "all characters read successfully.";

    }
    else
        std::cout << "error: only " << is.gcount() << " could be read";
    is.close();
    delete[] buffer;
}

我的问题是,如何将这些数据存储在链表中?我创建了一个节点来存储 StockCode、Description 和 Quantity。 我怎样才能从缓冲区中获取那列数据?

我只能使用 iostream、ctime、fstream、string 库来解决这些问题。没有向量。

首先,老师强迫人们在 C++ 中使用原始指针和 C 风格数组是一种耻辱。并且,为 std::list.

重新发明轮子

我什至无法在给定的包含列表下使用 std::unique_ptr。所以,上帝原谅我以下几点:

#include <iostream>
#include <fstream>
#include <string>

constexpr size_t NumberOfInvoiceDataEntries = 8;

// Make reading easier
// Lord forgive me for using plain C-Style arrays
using InvoiceDataEntry = std::string[NumberOfInvoiceDataEntries];

// Split line into columns
void splitLine(const std::string& csvLine, InvoiceDataEntry csvColumns) {

    // Initialize all needed value
    size_t columnIndex{ 0U }; size_t startPos{ 0U }; size_t i = 0U;

    // Iterate over all characters in the string
    do {
        // If we found semicolon or end of string, then we copy the sub-string
        if (csvLine[i] == ';' || i == csvLine.size()) {

            // Copy to column array.
            csvColumns[columnIndex++] = csvLine.substr(startPos, i - startPos);;
            startPos = i + 1;
        }
        ++i;
    } while (i <= csvLine.size());
}

struct InvoiceData {
    // Our data
    InvoiceDataEntry data{};

    // Overwrite inserter operator for easier input
    friend std::istream& operator >> (std::istream& is, InvoiceData& id) {
        if (std::string line{}; std::getline(is, line) && !line.empty()) {
            splitLine(line, id.data);
        }
        return is;
    }

    // Overwrite extractor operator for easier output
    friend std::ostream& operator << (std::ostream& os, const InvoiceData& id) {
        return os << "\nInvoice No:   " << id.data[0] << "\nStock Code:   " << id.data[1] << "\nDescription:  " << id.data[2]
            << "\nQuantity:     " << id.data[3] << "\nInvoice Date: " << id.data[4] << "\nUnit Price:   " << id.data[5]
            << "\nCustomer ID:  " << id.data[6] << "\nCountry:      " << id.data[7] << "\n";
    }
};

struct LinkedListInvoiceData {

    // Destructor: clean up newed memory
    ~LinkedListInvoiceData() { delete next; }

    void add(const InvoiceData& id) {

        // Search end of linked list
        LinkedListInvoiceData* current = this;
        while (current->next != nullptr)
            current = current->next;

        // Assign new invoice data.
        current->invoiceData = id;
        current->next = new LinkedListInvoiceData();
    }

    void print() {

        LinkedListInvoiceData* current = this;
        while (current != nullptr) {
            std::cout << current->invoiceData;
            current = current->next;
        }
        return;
    }

private:
    LinkedListInvoiceData* next{ nullptr };
    InvoiceData invoiceData{};
};

const std::string fileName("r:\myData.csv");

int main() {  

    // Open file and check if it is open
    if (std::ifstream ifs(fileName); ifs) {

        // The linked list with the invoice data
        LinkedListInvoiceData llid{};

        // Read all lines of file
        for (InvoiceData id; ifs >> id; ) 
            llid.add(id);
        // Print complete linked list
        llid.print();
    }
    return 0;
}

Ü租约。我的链接列表不是通用的,末尾有一个空元素。您可以实现自己的链表或从网上下载数以千计的示例之一。