0

i have a data like this;

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

I am using that code to read file;

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;
}

My question is, how can i store that datas in a linked list? I create a node to store StockCode, Description and Quantity. How can i get the that columns data from buffer?

I can use only iostream, ctime,fstream, string libraries to solve that problems. No vector.

OSentrk
  • 58
  • 1
  • 1
  • 9
  • Which variable are you currently storing the information read in right now? – dinonugs Dec 22 '19 at 21:44
  • You need to read the file line by line and split it into tokens. Then parse the tokens and store the data in some data structure. That's too much for an answer, because [here](https://stackoverflow.com/questions/1120140/how-can-i-read-and-parse-csv-files-in-c) is a similiar question with extensive answer already. – Lukas-T Dec 22 '19 at 21:50
  • Imagine you get each line as the buffer capture a string, does there is any pattern or condition can be defined to split them? Such as stock code ,quality and description. Once it is done, each of these can be directed to specific node of linked list. P. S: You can define a dynamic object to temporary hold these splited data – Harrison Chong Dec 23 '19 at 07:13

1 Answers1

1

first of all, it is a shame that teachers forces people to use raw pointers and C-Style arrays in C++. And, to reinvent the wheel for a std::list.

I cannot even use a std::unique_ptr under the given include list. So, Lord forgive me for the following:

#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;
}

Ülease note. My linked list is not generic and has an empty element at the end. You may implement your own linked list or download one of the thousands of examples from the net.

A M
  • 14,694
  • 5
  • 19
  • 44