is there any library or example for reading a csv file in C++ like the csv module in Python?
What I need is a function to read a csv file and put each column element of a row in a map with the header name as the key value.
I can answer myself. I wrote a CSVDict class.
#include <iterator>
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <string>
#include <map>
class CSVDict {
public:
CSVDict(std::string fileName, int headerRow) {
file = std::ifstream(fileName);
for (int i = 0; i < headerRow; i++){ readNextRow(file); }
m_header = m_data;
}
std::string const& operator[](std::size_t index) const {
return m_data[index];
}
std::string const& operator[](std::string index) const {
return m_dataMap.find(index)->second;
}
bool readNextRowMap() {
readNextRow(file);
if (!file) return false;
m_dataMap.clear();
auto it_data = m_data.begin();
for (auto it = m_header.begin(); it != m_header.end(); ++it) {
m_dataMap[*it] = *it_data;
++it_data;
}
return true;
}
private:
void readNextRow(std::istream& str) {
std::string line;
std::getline(str, line);
if (!str) return;
std::stringstream lineStream(line);
std::string cell;
m_data.clear();
while (std::getline(lineStream, cell, ';')) {
m_data.push_back(cell);
}
}
std::vector<std::string> m_data;
std::vector<std::string> m_header;
std::map<std::string, std::string> m_dataMap;
std::ifstream file;
};
int main()
{
CSVDict dict("1.csv", 2);
while (dict.readNextRowMap()) {
std::cout << dict[0] << " " << dict[1] << " " << dict[2] << " " << dict[3] << " " << dict[4] << " " << dict[5] << " " << dict[6] << "\n";
}
CSVDict dict1("1.csv", 2);
dict1.readNextRowMap();
std::cout << dict1["ipField"] << " " << dict1["mdBeamEnergy"] << " " << dict1["mdBeamCurrent"] << " " << dict1["mcoBeamSizeId"] << " " << dict1["mdGantryAngle"] << " " << dict1["miLayerNumber"] << "\n";
dict1.readNextRowMap();
std::cout << dict1["ipField"] << " " << dict1["mdBeamEnergy"] << " " << dict1["mdBeamCurrent"] << " " << dict1["mcoBeamSizeId"] << " " << dict1["mdGantryAngle"] << " " << dict1["miLayerNumber"] << "\n";
dict1.readNextRowMap();
std::cout << dict1["ipField"] << " " << dict1["mdBeamEnergy"] << " " << dict1["mdBeamCurrent"] << " " << dict1["mcoBeamSizeId"] << " " << dict1["mdGantryAngle"] << " " << dict1["miLayerNumber"] << "\n";
dict.readNextRowMap();
std::cout << dict[0] << " " << dict[1] << " " << dict[2] << " " << dict[3] << " " << dict[4] << " " << dict[5] << " " << dict[6] << "\n";
return 0;
}
Example csv file:
#VALUES;;;;;;
ipField;mdBeamEnergy;mdBeamCurrent;mcoBeamSizeId;mdGantryAngle;miLayerNumber;mbRoomSwitchingLayer
24.30815;172.152971;24.30815;4;65;1;1
24.30815;172.152971;24.30815;4;65;2;0
24.30815;172.152971;24.30815;4;65;3;0
24.30815;172.152971;24.30815;4;65;4;0
24.30815;172.152971;24.30815;4;65;5;0
24.30815;172.152971;24.30815;4;65;6;0
24.30815;172.152971;24.30815;4;65;7;0
24.30815;172.152971;24.30815;4;65;8;0
usage (see main function in example):
class constructor needs to have the csv filename and the csv header line number
every readNextRowMap gets the values of the next line in the csv file
you can address the values either by number index or by header name
downside:
csv file has to have a header line
Related
#define MYSQLPP_MYSQL_HEADERS_BURIED
#include <mysql++/mysql++.h>
#include <iostream>
#include "/home/sulli313/Project4/Film.h"
void Film::showList(){
std::cout << "\n-----------------------------------" << std::endl;
std::cout << " Query Application " << std::endl;
std::cout << "-----------------------------------" << std::endl;
std::cout << " 1 All letter name actors" << std::endl;
std::cout << " 2 First # PG-13 and Above" << std::endl;
std::cout << " 3 All active/inactive users by store" << std::endl;
std::cout << " 4 Actor Movie titles and ids" << std::endl;
std::cout << "-1 Exit" << std::endl;
std::cout << "-----------------------------------" << std::endl;
std::cout << ">> Enter your choice:" << std::endl;
}
void Film::showOne(){
mysqlpp::Connection myDB("cse278F2022", "localhost", "cse278F2022",
"raspberrySeltzer");
// Create a query
mysqlpp::Query query = myDB.query();
std::cout << "Please enter a Letter A-Z!" << std::endl;
std::string letter;
std::cin >> letter;
///////////////////////////////////Do this part/////////////////////////////////////////////
//if(letter)
query << "SELECT first_name, last_name "
<< "FROM actor "
<< "WHERE first_name "
<< "LIKE '" + letter + "%'";
// << "WHERE code = \"IST\"";
query.parse();
mysqlpp::StoreQueryResult result = query.store();
std::cout << "Here is your selection!\n" << std::endl;
std::cout << "--First/Last Names of Actors Whos First ";
std::cout << "Name Stars With " + letter + "--\n" << std::endl;
std::cout << std::left << std::setw(12) << "First Name" <<
std::setw(10) << "Last Name" << std::endl;
std::cout << "------------------------" << std::endl;
for (const auto & row : result) {
std::cout << std::left << std::setw(12) << row[0].c_str();
std::cout << std::setw(5) << row[1] << std::endl;
}
std::cout << "\n" << "to continue, press enter..." << std::endl;
showList();
}
void Film::showTwo(){
mysqlpp::Connection myDB("cse278F2022", "localhost", "cse278F2022",
"raspberrySeltzer");
//Selecting the second option's query
std::cout << "Please type a limit 1-30!" << std::endl;
std::string limit;
std::cin >> limit;
mysqlpp::Query query = myDB.query();
query << "SELECT title "
<< "FROM film "
<< "WHERE rating = 'PG-13' "
<< "OR rating = 'R' "
<< "OR rating = 'NC-17' "
<< "LIMIT " + limit + " ";
query.parse();
mysqlpp::StoreQueryResult result = query.store();
std::cout << "Here is your selection!\n" << std::endl;
std::cout << "--First "+ limit +" Titles PG-13 to NC-17--\n" << std::endl;
std::cout << std::left <<std::setw(20)<< "Title" << std::endl;
std::cout << "------------------------------" <<std::endl;
for (const auto & row : result) {
std::cout << std::left << std::setw(20) << row[0].c_str()<< std::endl;
}
std::cout << "\n" << "to continue, press enter..." << std::endl;
showList();
}
void Film::showThree(){
mysqlpp::Connection myDB("cse278F2022", "localhost", "cse278F2022",
"raspberrySeltzer");
//bind variable
std::cout << "Please type 1 for active and 0 for inactive!" << std::endl;
std::string active;
std::cin >> active;
if(active != "1" && active != "0"){
std::cout << "Wrong!" << std::endl;
std::cout << "Please type 1 for active and 0 for inactive!" << std::endl;
std::cin >> active;
}
//Selecting the second option's query
mysqlpp::Query query = myDB.query();
query << "SELECT Count(*) "
<< "FROM customer "
<< "WHERE active = '"+ active + "' "
<< "GROUP BY store_id";
query.parse();
mysqlpp::StoreQueryResult result = query.store();
std::cout << "Here is your selection!\n" << std::endl;
if(active == "1"){
std::cout << "--Count of All Active Users Grouped by Store Id--\n" << std::endl;
std::cout << std::left <<std::setw(20)<< "Active User Ids" << std::endl;
std::cout << "--------------------" <<std::endl;
} else {
std::cout << "--Count of All Inactive Users Grouped by Store Id--\n" << std::endl;
std::cout << std::left <<std::setw(20)<< "Inactive User Ids" << std::endl;
std::cout << "--------------------" <<std::endl;
}
for (const auto & row : result) {
std::cout << std::left << std::setw(20) << row[0].c_str()<< std::endl;
}
std::cout << "\n" << "to continue, press enter..." << std::endl;
showList();
}
void Film::showFour(){
mysqlpp::Connection myDB("cse278F2022", "localhost", "cse278F2022",
"raspberrySeltzer");
//bind variable
std::cout << "Please type an actor id that is 1-200!" << std::endl;
std::string act_id;
std::cin >> act_id;
//Selecting the second option's query
mysqlpp::Query query = myDB.query();
query << "SELECT film.title, film.film_id, film_actor.actor_id "
<< "FROM film, film_actor "
<< "WHERE film_actor.actor_id = "+ act_id +" "
<< "GROUP BY title "
<< "LIMIT 20";
query.parse();
mysqlpp::StoreQueryResult result = query.store();
std::cout << "Here is your selection!\n" << std::endl;
std::cout << "--First 20 Titles and IDs of Actor Id 25--\n" << std::endl;
std::cout << std::left <<std::setw(22)<< "Title" <<
std::setw(10)<< "Film_id" << std::setw(0)<<"Actor_id" << std::endl;
std::cout << "----------------------------------------" <<std::endl;
for (const auto & row : result) {
std::cout << std::left<<std::setw(22)<< row[0].c_str() << std::setw(10) << row[1] << std::setw(0) << row[2].c_str() << std::endl;
}
std::cout << "\n" << "to continue, press enter..." << std::endl;
showList();
}
#ifndef FILM_H
#define FILM_H
#include <iostream>
#include <string>
class Film {
public:
void showList();
void showOne();
void showTwo();
void showThree();
void showFour();
private:
};
#endif
// Copyright
// Purpose: Project 4
// Date 11/25/2022
// Author: Colton Sullivan
#define MYSQLPP_MYSQL_HEADERS_BURIED
#include <mysql++/mysql++.h>
#include <iostream>
#include "/home/sulli313/Project4/Film.h"
int main() {
int choice;
showList();
std::cin >> choice;
if (choice == -1) {
std::cout << "Bye!" << std::endl;
}
while (choice != -1) {
while ( choice > 4 || choice < -1 || choice == 0 ) {
std::cout << "The wrong choice!!!" << std::endl;
std::cout << "" << std::endl;
std::cout << "to continue, press enter...";
showList();
std::cin >> choice;
}
if ( choice == 1 ) {
showOne();
}
if ( choice == 2 ) {
showTwo;
}
if ( choice == 3 ) {
showThree;
}
if ( choice == 4 ) {
showFour;
}
std::cin >> choice;
if ( choice == -1 ) {
std::cout << "Bye!" << std::endl;
}
}
}
When trying to switch the original program to object oriented programming, I ran into the problem of the error "Invalid use of non-static member function" popping up for the showOne, showTwo, showThree, showFour and showList functions.
If there is a way to access the functions that are created in the Film.cpp/Film.h files and use them in the QueryApp.cpp file to run that as the main, please let me know.
I have tried switching it from Film::showOne, Film::showTwo...etc to showOne(); and Film::showOne(); but either the same Invalid use of non-static member function error will show or it will say that it has not be declared in this scope.
Your showSomething() functions are all member functions of the Film type. In particular, because they are not marked as static, they are non-static member functions. That means they operate on an instance of Film:
class C {
public:
void a(); // <- non-static member function
static void b(); // <- static member function
};
void foo() {
C::b(); // okay, doesn't need an object
C::a(); // not okay, needs an object
C object; // instance of C
object.a(); // okay
object.b(); // also okay
}
Typically you would give your object some state information or it raises the question why you have a non-static member function to begin with. If you don't need state, make them free functions (i.e., functions that are not member functions) or make them static.
In your case, I suppose it would be helpful to create a database connection in your Film's constructor so you can use the database member in all the functions that need a database connection to function.
Something like this:
class Film {
private:
mysqlpp::Connection myDB;
public:
Film() : myDB("x", "localhost", "y", "z") {}
// ...
};
I have following test example:
#include <iostream>
#include <vector>
void foo (std::vector<int> value) {
std::cout << "value "
<< &value
<< " "
<< value.data()
<< " "
<< value.size()
<< std::endl;
}
void foo2 (std::vector<int>&& rvalure_ref) {
std::cout << "rvalue_ref "
<< &rvalure_ref
<< " "
<< rvalure_ref.data()
<< " "
<< rvalure_ref.size()
<< std::endl;
}
int main() {
std::vector<int> value(5, 0);
std::cout << "init "
<< &value
<< " "
<< value.data()
<< " "
<< value.size()
<< std::endl;
foo(std::move(value));
std::cout << "done "
<< &value
<< " "
<< value.data()
<< " "
<< value.size()
<< std::endl;
}
The result of the code above is:
init 0x7ffed27c6450 0x56480bc1eeb0 5
value 0x7ffed27c6470 0x56480bc1eeb0 5
done 0x7ffed27c6450 0 0
Looks great:
Now, move to:
#include <iostream>
#include <vector>
void foo (std::vector<int> value) {
std::cout << "value "
<< &value
<< " "
<< value.data()
<< " "
<< value.size()
<< std::endl;
}
void foo2 (std::vector<int>&& rvalure_ref) {
std::cout << "rvalue_ref "
<< &rvalure_ref
<< " "
<< rvalure_ref.data()
<< " "
<< rvalure_ref.size()
<< std::endl;
}
int main() {
std::vector<int> value(5, 0);
std::cout << "init "
<< &value
<< " "
<< value.data()
<< " "
<< value.size()
<< std::endl;
foo2(std::move(value));
std::cout << "done "
<< &value
<< " "
<< value.data()
<< " "
<< value.size()
<< std::endl;
}
The result is:
init 0x7ffccc93a5c0 0x56124b3a8eb0 5
rvalue_ref 0x7ffccc93a5c0 0x56124b3a8eb0 5
done 0x7ffccc93a5c0 0x56124b3a8eb0 5
My problem is:
For the 1st case, it is perfectly called by "move semantics", and as you see, the ownership of the vector has been transfered to the function parameter. Finally, at "done", the data is null to verify the the vector at main() no longer owns the vector.
Now to explicitly claim the parameter is "rvalue reference", as case 2. As you see, actually it is like "call by (l)reference".
How can I figure out it?
I am trying to write a string to a binary file, to that effect I made this snippet:
std::string outname = filename.substr(0, filename.size() - 4) + std::string("_bin") + std::string(".sdf");
std::cout << "Writing results to: " << outname << "\n";
std::ofstream outfile(outname.c_str(), std::ofstream::binary);
std::stringstream ss;
ss << phi_grid.ni << " " << phi_grid.nj << " " << phi_grid.nk << std::endl;
ss << min_box[0] << " " << min_box[1] << " " << min_box[2] << std::endl;
ss << dx << std::endl;
for (unsigned int i = 0; i < phi_grid.a.size(); ++i)
{
ss << phi_grid.a[i] << std::endl;
}
outfile.write(ss.str().c_str(), ss.str().size());
outfile.close();
This however always writes to a text file, not a binary file. I don't udnerstand why, the flag is explicitely passed to the constructor.
I've recently started learning c++ and for the life of me, I can't seem to get the syntax of using ostream in a class and what arguments should I pass. Here's the code:
This is the class in question:
#include <iostream>
#include <string>
using namespace std;
class Pokemon{
friend ostream& operator<<(ostream&, Pokemon);
public:
string name, level, cp;
Pokemon(string x="Pikachu", string y="5", string z="1000"){
name = x;
level = y;
cp = z;
}
Pokemon name(){
return this->name;
}
Pokemon level(){
return this->level;
}
Pokemon cp(){
return this->cp;
}
Pokemon display_stats(){
cout << this-> name << "stats are:" << endl;
cout << " " << "Attack: 2716.05" << endl;
cout << " " << "Defence: 1629.63" << endl;
cout << " " << "HP: 1086.42" << endl;
}
};
template<typename TYPE> //i dont understand this and the things i've written down here are only based on samples i've seen
ostream& operator<<(ostream& os, Pokemon & c){
os << "The level of " << c.name << " is" << c.level << " with cp of " << c.cp;
}
As you could see, I already tried constructing the ostream thing but I don't really understand how it works. This is my main function:
int main()
{
Pokemon a, b, c, d;
a = Pokemon();
b = Pokemon("Weezing");
c = Pokemon("Nidoking", 100);
d = Pokemon("Mewtwo", 50, 5432.1);
cout << a << endl;
cout << b << endl;
cout << c << endl;
cout << d << endl;
cout << "Jessie: You are no match to me! Go " << b.name << "!" << endl;
cout << "Gary: Go lvl " << c.level << " " << c.name << "! Crush them" << endl;
cout << "Ash: " << a.name << " can do it even thouh he is only level " << a.level << endl;
cout << "Jessie: Hahaha! My " << b.name << " CP is " << b.cp << endl;
cout << "Gary: "<< c.name << " CP is " << c.cp << endl;
cout << "Ash: " << a.name << " CP is " << a.cp << endl;
cout << "Giovanni: Behold " << d.name << " is here." << endl;
d.display_stats();
return 0;
}
I'm getting errors of:
no instance of constructor "Pokemon::Pokemon" matches the argument list -- argument types are: (const char [9], int) //on line c = Pokemon("Nidoking", 100);
no instance of constructor "Pokemon::Pokemon" matches the argument list -- argument types are: (const char [7], int, double) //on line d = Pokemon("Mewtwo", 50, 5432.1);
All of your Pokemon class methods are returning the wrong type. And your main() is not calling any of the methods correctly at all.
Change your Pokemon class to look more like this:
#include <iostream>
#include <string>
using namespace std;
class Pokemon {
private:
string m_name;
int m_level;
double m_cp;
friend ostream& operator<<(ostream&, const Pokemon&);
public:
Pokemon(string x="Pikachu", int y=5, double z=1000) {
m_name = x;
m_level = y;
m_cp = z;
}
string name() const {
return m_name;
}
int level() const {
return m_level;
}
double cp() const {
return m_cp;
}
void display_stats() const {
cout << m_name << " stats are:" << endl;
cout << " " << "Attack: 2716.05" << endl;
cout << " " << "Defense: 1629.63" << endl;
cout << " " << "HP: 1086.42" << endl;
}
};
ostream& operator<<(ostream& os, const Pokemon &c) {
os << "The level of " << c.m_name << " is " << c.m_level << " with cp of " << c.m_cp;
return os;
}
And then change main() to look more like this:
int main()
{
Pokemon a;
Pokemon b("Weezing");
Pokemon c("Nidoking", 100);
Pokemon d("Mewtwo", 50, 5432.1);
cout << a << endl;
cout << b << endl;
cout << c << endl;
cout << d << endl;
cout << "Jessie: You are no match to me! Go " << b.name() << "!" << endl;
cout << "Gary: Go lvl " << c.level() << " " << c.name() << "! Crush them" << endl;
cout << "Ash: " << a.name() << " can do it even though he is only level " << a.level() << endl;
cout << "Jessie: Hahaha! My " << b.name() << " CP is " << b.cp() << endl;
cout << "Gary: " << c.name() << " CP is " << c.cp() << endl;
cout << "Ash: " << a.name() << " CP is " << a.cp() << endl;
cout << "Giovanni: Behold " << d.name() << " is here." << endl;
d.display_stats();
return 0;
}
Live Demo
As previous questions have been answered, the way to pass a std::ofstream object as a function argument seems to be to instead pass a reference: std::ofstream&.
Whilst this solution compiles, the resulting output is not equivalent to creating an std::ofstream object within the method then calling write().
The code below does not give the correct output:
In main.cpp:
std::ofstream file(path + "output.stubs");
stub->writeRaw(file); //stub is a pointer to an object of class Stub
file.close();
In Stub.cpp:
void Stub::writeRaw(std::ofstream& file) {
file.write((char*)this, sizeof(*this));
}
The correct output is given by both changing Stub.cpp to:
void Stub::writeRaw(void) {
std::ofstream file(path + "output.stubs");
file.write((char*)this, sizeof(*this));
file.close();
}
or writing the object to the file in main instead of calling a class method.
Any help on this behaviour would be greatly appreciated!
EDIT
Some context for the class Stub:
Stub.hpp
#pragma once
#include <iostream>
#include <ios>
#include <fstream>
#include "constants.hpp"
#include "DataTypes.hpp"
class Stub {
private:
StubHeader header;
StubIntrinsicCoordinates intrinsic;
StubPayload payload;
public:
Stub(void);
virtual ~Stub(void);
StubHeader getHeader(void);
StubIntrinsicCoordinates getIntrinsicCoordinates(void);
StubPayload getPayload(void);
void setHeader(StubHeader stub_header);
void setIntrinsicCoordinates(StubIntrinsicCoordinates stub_intrinsic);
void setPayload(StubPayload stub_payload);
void print(void);
void writeRaw(std::ofstream& file);
};
And the relevant data types are defined as follows:
struct StubHeader {
uint8_t bx;
uint8_t nonant;
};
struct StubIntrinsicCoordinates {
uint8_t strip;
uint8_t column;
int crossterm;
};
struct StubPayload {
bool valid;
int r;
int z;
int phi;
int8_t alpha;
int8_t bend;
uint8_t layer;
bool barrel;
bool module;
};
EDIT 2
The (toy) code to read the stub is as follows:
std::ifstream r(path + "output.stubs");
Stub s;
r.read((char*)&s, sizeof(s));
s.print();
Only one stub is written to the file as this was a test of functionality. The print function for the Stub class is as follows:
void Stub::print(void) {
std::cout << "----- Header -----" << '\n';
std::cout << "bx: " << std::dec << (int)header.bx << '\n';
std::cout << "nonant: " << std::dec << (int)header.nonant << '\n';
std::cout << "----- Intrinsic Coordinates -----" << '\n';
std::cout << "strip: " << std::dec << (int)intrinsic.strip << '\n';
std::cout << "column: " << std::dec << (int)intrinsic.column << '\n';
std::cout << "crossterm: " << std::dec << (int)intrinsic.crossterm << '\n';
std::cout << "----- Payload -----" << '\n';
std::cout << "valid: " << std::boolalpha << payload.valid << '\n';
std::cout << "r: " << std::dec << (int)payload.r << '\n';
std::cout << "z: " << std::dec << (int)payload.z << '\n';
std::cout << "phi: " << std::dec << (int)payload.phi << '\n';
std::cout << "alpha: " << std::dec << (int)payload.alpha << '\n';
std::cout << "bend: " << std::dec << (int)payload.bend << '\n';
std::cout << "layer: " << std::dec << (int)payload.layer << '\n';
std::cout << "barrel: " << std::boolalpha << payload.barrel << '\n';
std::cout << "module: " << std::boolalpha << payload.module << "\n\n";
}
EDIT 3
For completeness and transparency, please find below the exact code for main.cpp:
int main(int argc, char const *argv[]) {
Geometry g;
g.generateModuleLUTs();
g.generateCorrectionLUTs();
std::vector<std::array<Stub*, PAYLOAD_WIDTH> > all_stubs;
std::vector<Module> modules = g.getData();
for (int i = 0; i < LINK_NUMBER; i++) {
LinkGenerator link_gen;
LinkFormatter link_formatter(link_gen.run());
StubFormatter stub_formatter(link_formatter.run(), i);
std::array<Stub*, PAYLOAD_WIDTH> stubs = stub_formatter.run(modules);
CoordinateCorrector coordinate_corrector(stubs);
all_stubs.push_back(coordinate_corrector.run());
}
std::ofstream f(path + "output.stubs");
all_stubs[0][0]->writeRaw(f);
all_stubs[0][0]->print();
std::ifstream r(path + "output.stubs");
Stub s;
r.read((char*)&s, sizeof(s));
s.print();
return 0;
}
The bug in the code was that I was not calling file.close() before constructing the std::ifstream object to read the file again. This was the cause of the unexpected behaviour.
Writing a class to file using this seems to be valid, although it is important that you are careful and know exactly what you want to write to a file.
Thank you to everyone who commented and helped to answer this question!