读取和存储CSV数据

问题描述 投票:0回答:1

我有这样的数据;

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,描述和数量。我如何从缓冲区获取该列数据?

我只能使用iostream,ctime,fstream,字符串库来解决该问题。没有向量。

c++ csv buffer fstream
1个回答
0
投票

首先,老师强迫人们在C ++中使用原始指针和C-Style数组,这是很可耻的。并且,为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;
}

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

© www.soinside.com 2019 - 2024. All rights reserved.