I'm trying to initialize a file with 100 empty records with the code below:
void initializeInventory() {
std::ofstream out("hardware.dat", std::ios::binary);
Hardware h;
for (int i = 0; i < 100; ++i) {
h.ID = i;
h.name = "try"; // std::string();
h.quantity = 0;
h.price = 0;
h.notes = "try2"; //std::string();
out.write(reinterpret_cast<const char*>(&h), sizeof(Hardware));
}
out.close();
}
But when I try to print them out, it always print only 25 elements or crashes.
This is the function to print out elements:
void readInventory() {
std::ifstream in("hardware.dat", std::ios::in);
std::cout << std::setiosflags(std::ios::left) << std::setw(4) << "ID"
<< std::setw(16) << "Name"
<< std::setw(11) << "Quantity"
<< std::setw(10) << std::resetiosflags(std::ios::left)
<< "Price"
<< std::setw(50) << "Notes" << '\n';
Hardware h;
while (!in.eof()) {
in.read(reinterpret_cast<char*>(&h), sizeof(Hardware));
//if (!in.eof())
printOut(std::cout, h);
}
in.close();
}
void printOut(std::ostream &output, const Hardware& h) {
output << std::setiosflags(std::ios::left) << std::setw(4) << h.ID
<< std::setw(16) << h.name
<< std::setw(11) << h.quantity
<< std::setw(10) << std::setprecision(2)
<< std::resetiosflags(std::ios::left)
<< std::setiosflags(std::ios::fixed | std::ios::showpoint )
<< h.price
<< std::setw(50) << h.notes << '\n';
}
I also noted that if I increase the number of cycles in the for (I tried putting 400 instead of 100) the file hardware.dat seems to grow, so I thought that should be a problem in the print function. Any idea? Is there something I'm missing?
Thanks in advance.
It would be the best to overload the operator <<
friend ostream& operator<<(ostream& out, const Hardware& h) // output
{
out << "(" << h.id() << ", " << h.whatever() << ")";
return out;
}
and read the file line by line to the Hardware object.
By the way, overloading the input operator >> is also possible.
Related
This is my main function
int main()
{
const string filename = "ass10data.txt"; // use your filename here
ifstream fin(filename.c_str());
if (!fin)
{
cerr << "Unable to open " << filename << endl;
exit(1);
}
string buffer;
Quadrilateral* ptrQuad;
while (getline(fin,buffer))
{
// Process only valid input
if (buffer.size() > 1)
{
ptrQuad = createQuadrilateralFromString(buffer);
cout << *ptrQuad << endl;
delete ptrQuad;
}
}
fin.close();
}
This is the overloaded insertion operator
ostream& operator<<(ostream&out, Quadrilateral *pointerQuad)
{
if (pointerQuad->getType() == "rectangle")
{
out << "Rectangle: sides " << pointerQuad->getFirst() << " and " << pointerQuad->getSecond() << " area=" << pointerQuad->area();
out << " perimeter=" << pointerQuad->perimeter();
return out;
}
else if(pointerQuad->getType() == "square")
{
out << "Square: side "<< pointerQuad->getFirst() << " area="<< pointerQuad->area();
out << " perimeter=" << pointerQuad->perimeter();
return out;
}
else if(pointerQuad->getType() == "parallelogram")
{
out << "Parallelogram: sides " << pointerQuad->getFirst() << " and " << pointerQuad->getSecond() << " area=" << pointerQuad->area();
out << " perimeter=" << pointerQuad->perimeter();
return out;
}
else if(pointerQuad->getType() == "rhombus")
{
out << "Rhombus: side "<< pointerQuad->getFirst() << " area="<< pointerQuad->area();
out << " perimeter=" << pointerQuad->perimeter();
return out;
}
else
return out;
}
I'm getting an error message saying "no match for 'operator<<' (operand types are 'std::ostream {aka std::basic_ostream}' and 'Quadrilateral')" and I can't figure out why.
The insertion operator should take a const reference to the Quadrilateral, not a pointer to it:
ostream& operator<<(ostream&out, Quadrilateral const &pointerQuad)
Of course, that means your function should use the value syntax, not the pointer one too.
if (pointerQuad.getType() == "rectangle")
{
out << "Rectangle: sides " << pointerQuad.getFirst() << " and " << pointerQuad.getSecond() << " area=" << pointerQuad.area();
out << " perimeter=" << pointerQuad.perimeter();
return out;
}
[...]
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
I have a very simple program where I ask the user if they want to print to screen or a file. Rather than create two sets of output sections, I thought I could switch a stream to either cout or an ofstream and then output to that stream. However, I'm getting screen output no matter what.
ostream &out = cout;
do
{
cout << "Write to file (f) or screen (s)?";
cin >> yes_or_no;
} while (yes_or_no != 'f' && yes_or_no !='s');
if (yes_or_no=='f')
{
ofstream out;
out.open("Report.txt");
cout << "Writing report to Report.txt" << endl;
system("pause");
}
out << "Day: Current Value ROI" << endl;
out << "------------------------------------------" << endl;
out << setw(5) << 0;
out << "$" << setw(20) << setprecision (2) << fixed << initial_value;
out << setw(12) << "1.00" << endl;
for (int day = 1 ; day < number_of_days ; day++)
{
current_value = generateNextStockValue(current_value, volatility, trend);
out << setw(5) << day;
out << setw(20) << setprecision (2) << fixed << current_value;
out << setw(12) << setprecision (2) << fixed << current_value / initial_value;
out << endl;
}
You could put all the writing logic inside a function, and let the caller decide which output stream to write to:
void do_the_stuff(std::ostream& os)
{
// write to os
os << "blah blah" ....
}
then
if (yes_or_no=='f')
{
ofstream out("Report.txt");
do_the_stuff(out);
} else {
do_the_stuff(std::cout);
}
I'm trying to display a text file data into columns using a class structure and getline() function to read through the textfile and the dump the data into a vector class. But it seems that the program didn't even run to my 'while' loop then quitting the program. The textfile is not empty.
Below is my code:
void ScrambleWordGame::displayScoreChart() {
//open file
fstream readScoreChart("ScoreChart.txt");
string line = "";
//vector to store data in
vector<personResult> perResult;
personResult person;
//while file is open, do stuff
if(readScoreChart.is_open())
{
//check through the file
readScoreChart.seekp(0,ios::end);
//get the size of the file's data
size_t size = readScoreChart.tellg();
if(size == 0)
cout << "No results yet. Please TRY to win a game. AT LEAST~" << endl;
else
{
//create the 1st row with 4 column names
cout << left
<< setw(20) << "Player Name "
<< setw(20) << "Winning Time "
<< setw(20) << "No. Of Attempts "
<< setw(20) << "Game Level " << endl;
//fill the second line with dashes(create underline)
cout << setw(70) << setfill('-') << "-" << endl;
//read the file line by line
//push the 1st line data into 'line'
cout << getline(readScoreChart,line);
while(getline(readScoreChart,line))
{
//create stringstream n push in the entire line in
stringstream lineStream(line);
//reads the stringstream and dump the data seperated by delimiter
getline(lineStream,person.playerName,':');
getline(lineStream,person.winningTime,':');
getline(lineStream,person.noOfAttempts,':');
getline(lineStream,person.gameLvl);
//sort the results based on their timing
//sort(perResult.begin(),perResult.end(),pRes);
//display the results
cout << left
<< setfill(' ')
<< setw(25) << person.playerName
<< setw(22) << person.winningTime
<< setw(17) << person.noOfAttempts
<< setw(16) << person.gameLvl
<< endl;
}
}
}
readScoreChart.close();
}
Edit: Example of the TextFile
Joel:3:1:1
Mary:5:2:2
John:25:3:1
Your file pointer is at the end of the file after your first seek. You need to reposition it to the beginning of the file.
if(size == 0)
{
cout << "No results yet. Please TRY to win a game. AT LEAST~" << endl;
}
else
{
readScoreChart.seekp(0,ios::begin);
// all you other stuff
}
You need to seek back to the beginning of the file to be able to read. Better still, just don't seek to the end in the first place.
I'd re-structure the code a bit -- write an operator>> to read a record from a file, and an operator<< to write a record to a file.
class person {
std::string name;
std::string winning_time;
std::string num_attempts;
std::string level;
public:
bool operator<(person const &other) const {
return std::stoi(winning_time) < std::stoi(other.winning_time);
}
friend std::istream &operator>>(std::istream &in, person &p) {
std::string buffer;
std::getline(in, buffer);
std::istringstream is(buffer);
std::getline(is,p.name,':');
std::getline(is,p.winning_time,':');
std::getline(is,p.num_attempts,':');
std::getline(is,p.level);
return in;
}
friend std::ostream &operator<<(std::ostream &os, person const &p) {
return os << std::setw(25) << p.name
<< std::setw(22) << p.winning_time
<< std::setw(17) << p.num_attempts
<< std::setw(16) << p.level;
}
};
With those in place, the rest gets quite a bit simpler:
void show_header(std::ostream &os) {
cout << left
<< setw(20) << "Player Name "
<< setw(20) << "Winning Time "
<< setw(20) << "No. Of Attempts "
<< setw(20) << "Game Level " << "\n";
std::cout << std::string(70, '-');
}
void game::displayScoreChart(){
std::ifstream in("ScoreChart.txt");
// read the data:
std::vector<person> people{std::istream_iterator<person>(in),
std::istream_iterator<person>()};
if (people.empty()) {
std::cout << "No scores yet."
return;
}
// sort it by winning time:
std::sort(people.begin(), people.end());
show_header(std::cout);
// display it:
for (auto const &p : people)
std::cout << p << "\n";
return 0;
}
As a simple replacement if you don't have a C++11 compiler, an stoi can be written something like this:
int stoi(std::string in) {
return strtol(in.c_str(), NULL, 10);
}
I have a class that's supposed to write to a gml file defined below. The class has one method that does the writing. If I call the function, I get a core dump when the main function returns. I can create objects of the class with no problem, it only happens when the write function is called. The function also returns with no error and the rest of the program runs.
GML Writer:
class GMLWriter {
public:
void write(List<User*> usr, const char* filename);
};
void GMLWriter::write(List<User*> usr, const char* filename)
{
cout << "Filename: " << filename << endl;
ofstream outfile;
outfile.open(filename);
if (!outfile.is_open())
cout << "Couldn't open the file..." << endl;
outfile << "graph [\n";
// Write user data
for (int n = 0; n < usr.size(); n++) {
cout << "Writing node..." << endl;
outfile << "node [\n";
outfile << "id " << usr[n]->getID() << "\n";
outfile << "name \"" << usr[n]->getName() << "\"\n";
outfile << "age " << usr[n]->getAge() << "\n";
outfile << "zip " << usr[n]->getZip() << "\n";
outfile << "]\n";
}
// Write associations
for (int n = 0; n < usr.size(); n++) {
List<int> tList = usr[n]->getFriends();
cout << "Writing edge..." << endl;
//List<int> tempL = usr[n]->getFriends();
for (int i = 0; i < tList.size(); i++) {
outfile << "edge [\n";
outfile << "source " << usr[n]->getID() << "\n";
outfile << "target " << tList[i] << "\n";
outfile << "]\n";
}
}
outfile << "]"; // end graph
cout << "End function" << endl;
outfile.close();
}
User simply contains the variables to write to the file, and those methods work fine.
I've spent hours with this in a debugger and haven't been able to find the problem. Any help would be greatly appreciated.
Thanks!
Try looking at the core dump: http://www.network-theory.co.uk/docs/gccintro/gccintro_38.html