This is my current code:
std::vector <OrderBookEntry> entries;
std::ifstream csvFile{ csvFilename };
std::string line;
if (csvFile.is_open()) {
while (std::getline(csvFile, line)) {
try {
std::stringstream ss(line);
OrderBookEntry obe = stringsToOBE(tokenise(line, ','));
entries.push_back(obe);
}
catch (const std::exception& e) {
std::cout << "CSVReader::readCSV bad data" << std::endl;
}
}//end of while loop
}
std::cout << "CSVReader::readCSV read " << entries.size() << " entries" << std::endl;
return entries;
}
OrderBookEntry::OrderBookEntry(double _price,
double _amount,
std::string _timestamp,
std::string _product,
OrderBookType _orderType,
std::string _username)
: price(_price),
amount(_amount),
timestamp(_timestamp),
product(_product),
orderType(_orderType),
username(_username)
{
}
example of csv file:
Hi all, I have a csvfile (1 mill+) rows and i am trying to read and store the entries faster. Currently it takes a bit of time before my program is able to read the data and run.
How do i read the csvFile quicker? Thanks!
Difficult to answer.
Please see below a solution that can create a test file with 1 million records.
I then make only the input buffer bigger, without any further optimization.
Then, all lines of the test file are read and parsed in 2.6seconds.
The question is now: Is this fast or is this slow? Please comment.
#include <iostream>
#include <fstream>
#include <string>
#include <unordered_map>
#include <iomanip>
#include <array>
#include <random>
#include <vector>
#include <chrono>
#include <algorithm>
#include <iterator>
const std::array<std::string, 3> OTString{ "bid","offer","trade" };
enum class OrderType : int { bid, offer, trade, invalid };
const std::unordered_map<std::string, OrderType> OrderTypeMap{ {OTString[0],OrderType::bid}, {OTString[1],OrderType::offer}, {OTString[2],OrderType::trade} };
OrderType getOrderType(std::string& ot) {
if (const auto it = OrderTypeMap.find(ot); it != OrderTypeMap.cend())
return it->second;
else
return OrderType::invalid;
}
const std::string testFileName{ "test.txt" };
void createTestFile() {
unsigned ms{};
unsigned second{};
unsigned minute{};
std::random_device rd; // Will be used to obtain a seed for the random number engine
std::mt19937 gen(rd()); // Standard mersenne_twister_engine seeded with rd()
std::uniform_real_distribution<> dis1(0.01, 1);
std::uniform_real_distribution<> dis2(1.0, 1000.0);
std::string product{"AAAAAAAAAAAA"};
if (std::ofstream ofs{ testFileName }; ofs) {
ofs << std::setfill('0') << std::right;
for (std::size_t row{}; row < 1'000'000; ++row) {
ofs << std::setw(2) << minute << ':' << std::setw(2) << second << ':' << ms << ','
<< product << ',' << OTString[row%3] << ',' << dis1(gen) << ',' << dis2(gen) << '\n';
++product[product.length() - 1];
for (std::size_t i{ product.length() - 1 }; i > 0; --i)
if (product[i] > 'Z') {
product[i] = 'A';
++product[i - 1];
}
else
break;
if (row % 100 == 0) {
++ms;
if (ms > 9) {
ms = 0;
++second;
if (second > 59) {
second = 0;
++minute;
}
}
}
}
}
else
std::cerr << "\n\n*** Error: Could not open file '" << testFileName << "' for writing.\n\n";
}
// For measuring durations
struct Timer {
std::chrono::time_point<std::chrono::high_resolution_clock> startTime{};
long long elapsedTime{};
void start() { startTime = std::chrono::high_resolution_clock::now(); }
void stop() { elapsedTime = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - startTime).count(); }
friend std::ostream& operator << (std::ostream& os, const Timer& t) { return os << t.elapsedTime << " ms "; }
};
constexpr std::size_t IOBufSize = 5'000'000;
char ioBuf[IOBufSize];
struct OrderBookEntry {
std::string timestamp{};
std::string product{};
OrderType orderType{};
double amount{};
double price{};
friend std::istream& operator >> (std::istream& is, OrderBookEntry& obe) {
std::string ot{}; char c;
std::getline(is >> std::ws, obe.timestamp, ',');
std::getline(is >> std::ws, obe.product, ',');
std::getline(is >> std::ws, ot, ',');
is >> obe.amount >> c >> obe.price;
obe.orderType = getOrderType(ot);
return is;
}
};
int main() {
//createTestFile();
std::vector<OrderBookEntry> obe{};
obe.reserve(1'500'000);
if (std::ifstream ifs{ testFileName }; ifs) {
// To speed up reading of the file, we will set a bigger input buffer
ifs.rdbuf()->pubsetbuf(ioBuf, IOBufSize);
Timer t; t.start();
std::copy(std::istream_iterator<OrderBookEntry>(ifs), {}, std::back_inserter(obe));
std::cout << "\nRecords read: "<< obe.size() << '\n';
t.stop();
std::cout << t << '\n';
}
else
std::cerr << "\n\n*** Error: Could not open file '" << testFileName << "' for reading.\n\n";
}
Related
The code is supposed to be able to count the characters in total then count each time they appear within a text file. I tried building a struct that makes an array which is an integer and char array at the same time so that I can have the counting in the same place as my array. But now I am stuck. I've looked online a lot but cannot find what I need to help me. Anyone got some advice? Also in the code if you see anything that should be changed I appreciate the tips! I am newer at c++ so go easy on me please.
Structs, multiple arrays, searching internet for answers
#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
struct letters {
int count;
char letter;
};
constexpr int SIZE = 10000;
std::string fileName, word;
int count = 0, charCount = 0;
int Alphabet[26];
letters chars[];
void getFileName(std::string& fileName);
int countWords(int& count, std::string& fileName, std::string word);
int countChar(int& charCount, std::string& fileName, letters chars[]);
void sortChars(letters chars[SIZE], int SIZE);
int main()
{
getFileName(fileName);
countWords(count, fileName, word);
countChar(charCount, fileName, chars);
sortChars(chars, SIZE);
return 0;
}
void getFileName(std::string& fileName)
{
std::cout << "Please enter the name of the file followed by the type (ex: text.txt) : " << std::endl;
std::getline(std::cin, fileName);
}
int countWords(int& count, std::string& fileName, std::string word)
{
count = 0;
std::ifstream infile(fileName);
while (infile >> word) {
count++;
}
std::cout << count << std::endl;
return count;
}
int countChar(int& charCount, std::string& fileName, letters chars[])
{
std::ifstream infile(fileName);
while (infile >> chars->letter) {
count++;
}
std::cout << charCount;
return charCount;
}
void sortChars(letters chars[SIZE], int SIZE)
{
int i = 0;
std::ifstream infile(fileName);
while (infile >> chars[i].letter) {
for (int i = 0; i <= chars->count; i++) {
if (infile == chars[i].letter) {
chars[i].count++;
}
}
}
}
void printCount()
{
std::cout << count << std::endl;
std::cout << charCount << std::endl;
std::ifstream infile(fileName);
}
The struct should count the number of times 'A' or 'a', should be able to convert to one case, but I can do this after it counts one or the other. My tester file is in all lowercase so that would be a good place to start.
Even bigger hint, use a std::unordered_map to count the characters:
#include <cstdlib> // EXIT_FAILURE
#include <cctype> // std::isupper(), std::tolower()
#include <string> // std::string<>, std::getline()
#include <unordered_map> // std::unordered_map<>
#include <iostream> // std::ifstream
#include <fstream> // std::cout, std::cerr
int main()
{
std::string file_name;
if (!std::getline(std::cin, file_name)) {
std::cerr << "Input error. :(\n\n";
return EXIT_FAILURE;
}
std::ifstream is{ file_name };
if (!is.is_open()) {
std::cerr << "Couldn't open \"" << file_name << "\" for reading. :(\n\n";
return EXIT_FAILURE;
}
std::size_t num_words = 0;
std::unordered_map<char, std::size_t> char_counts;
for (std::string word; is >> word; ++num_words) {
for (auto ch : word) {
if (std::isupper(ch))
ch = std::tolower(ch);
++char_counts[ch];
}
}
for (auto const &count : char_counts)
std::cout << "'" << count.first << "': " << count.second << '\n';
std::cout << "Number of words: " << num_words << "\n\n";
} // when control reaches the end of main() without encountering a return-statement
// it has the same effect as return 0;
If you insist on splitting that few lines of code up into functions:
#include <cstdlib> // EXIT_FAILURE
#include <cctype> // std::isupper(), std::tolower()
#include <string> // std::string<>, std::getline()
#include <unordered_map> // std::unordered_map<>
#include <iostream> // std::ifstream
#include <fstream> // std::cout, std::cerr
std::string get_file_name()
{
std::cout << "Filename: ";
std::string file_name;
if (!std::getline(std::cin, file_name))
std::cerr << "Input error. :(\n\n";
return file_name;
}
std::ifstream open_file(std::string file_name)
{
std::ifstream file{ file_name };
if (!file.is_open())
std::cerr << "Couldn't open \"" << file_name << "\" for reading. :(\n\n";
return file;
}
std::size_t get_file_stats(std::istream &is, std::unordered_map<char, std::size_t> &char_counts)
{
std::size_t num_words = 0;
for (std::string word; is >> word; ++num_words) {
for (auto ch : word) {
if (std::isupper(ch))
ch = std::tolower(ch);
++char_counts[ch];
}
}
return num_words;
}
int main()
{
std::string file_name{ get_file_name() };
if (!file_name.length())
return EXIT_FAILURE;
std::ifstream is{ open_file(file_name) };
if (!is.is_open())
return EXIT_FAILURE;
std::unordered_map<char, std::size_t> counts;
std::cout << "Number of words: " << get_file_stats(is, counts) << "\n\n";
for (auto const &count : counts)
std::cout << "'" << count.first << "': " << count.second << '\n';
}
everyone!
I'm new to C++, alas I make silly mistakes.
This is a snippet of a .txt-file's content:
<tag attr1="value1" attr2="value2" ... >
What I'm trying to accomplish is parsing through the .txt-file, generating the following output:
Tag: tag
name: attr1
value: value1
name: attr2
value: value2
What I've done so far didn't work (my problem is the delimiters):
#include<iostream>
#include <sstream>
#include <string>
#include <vector>
#include <fstream>
using namespace std;
struct tagline{
string tag;
string attributeN;
string attributeV;
};
int main(){
vector<tagline> information;
string line;
tagline t;
ifstream readFile("file.txt");
while(getline(readFile,line)){
stringstream in(line);
getline(in,t.tag);
getline(in,t.attributeN,'=');
getline(in,t.attributeV,'"');
information.push_back(t);
}
vector<tagline>::iterator it = information.begin();
for(; it != information.end(); it++){
cout << "Tag: " << (*it).tag << " \n"
<< "name: " << (*it).attributeN << " \n"
<< "value: " << (*it).attributeV << " \n";
}
return 0;
}
All I get is a plain display of the snippet as it's formatted in the .txt-file:
<tag attr1="value1" attr2="value2" ... >
I would be happy if someone could help. Thank you!
This would be better handled using an HTML/XML parser (depending on what your file actually contains).
That being said, you are not parsing the lines correctly.
Your first call to getline(in,t.tag); is not specifying a delimiter, so it reads the entire line, not just the first word. You would have to use getline(in, t.tag, ' '); instead.
Also, your tags can have multiple attributes, but you are only reading and storing the first attribute, ignoring the rest. You need a loop to read all of them, and a std::vector to store them all into.
Try something more like this instead:
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <fstream>
using namespace std;
struct tagattribute {
string name;
string value;
};
struct tagline {
string tag;
vector<tagattribute> attributes;
};
int main() {
vector<tagline> information;
string line;
ifstream readFile("file.txt");
while (getline(readFile, line)) {
istringstream in(line);
tagline t;
tagattribute attr;
in >> ws;
char ch = in.get();
if (ch != '<')
continue;
if (!(in >> t.tag))
continue;
do
{
in >> ws;
ch = in.peek();
if (ch == '>')
break;
if (getline(in, attr.name, '=') &&
in.ignore() &&
getline(in, attr.value, '"'))
{
t.attributes.push_back(attr);
}
else
break;
}
while (true);
information.push_back(t);
}
vector<tagline>::iterator it = information.begin();
for(; it != information.end(); ++it) {
cout << "Tag: " << it->tag << "\n";
vector<tagattribute>::iterator it2 = it->attributes.begin();
for(; it2 != it->attributes.end(); ++it2) {
cout << "name: " << it2->name << "\n"
<< "value: " << it2->value << "\n";
}
cout << "\n";
}
return 0;
}
Live demo
Alternatively, consider writing some custom operator>> to help with the parsing, eg:
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <fstream>
using namespace std;
struct tagattribute {
string name;
string value;
};
istream& operator>>(istream &in, tagattribute &attr)
{
getline(in, attr.name, '=');
in.ignore();
getline(in, attr.value, '"');
return in;
}
struct tagline {
string tag;
vector<tagattribute> attributes;
};
istream& operator>>(istream &in, tagline &t)
{
tagattribute attr;
in >> ws;
char ch = in.get();
if (ch != '<')
{
in.setstate(ios_base::failbit);
return in;
}
if (!(in >> t.tag))
return in;
do
{
in >> ws;
ch = in.peek();
if (ch == '>')
{
in.ignore();
break;
}
if (!(in >> attr))
break;
t.attributes.push_back(attr);
}
while (true);
return in;
}
int main() {
vector<tagline> information;
string line;
ifstream readFile("file.txt");
while (getline(readFile, line)) {
istringstream in(line);
tagline t;
if (in >> t)
information.push_back(t);
}
vector<tagline>::iterator it = information.begin();
for(; it != information.end(); ++it) {
cout << "Tag: " << it->tag << "\n";
vector<tagattribute>::iterator it2 = it->attributes.begin();
for(; it2 != it->attributes.end(); ++it2) {
cout << "name: " << it2->name << "\n"
<< "value: " << it2->value << "\n";
}
cout << "\n";
}
return 0;
}
Live demo
Well, I would try to do something like this using this wonderful answer:
struct xml_skipper : std::ctype<char> {
xml_skipper() : ctype(make_table()) { }
private:
static mask* make_table() {
const mask* classic = classic_table();
static std::vector<mask> v(classic, classic + table_size);
v[','] |= space;
v['"'] |= space;
v['='] |= space;
v['<'] |= space;
v['>'] |= space;
return &v[0];
}
};
Then, what you can do is just keep reading:
ifstream readFile("file.txt");
while(getline(readFile,line)){
istringstream in(line);
in.imbue(std::locale(in.getloc(), new xml_skipper));
in >> t.tag >> t.attributeN >> t.attributeV;
information.push_back(t);
}
//...
Do note that this will break if values or attribute names have whitespaces.
If you want something more serious, you will need to write lexer, syntax tree builder and semantics tree builder.
Full code
#include<iostream>
#include <sstream>
#include <string>
#include <vector>
#include <fstream>
#include <sstream>
using namespace std;
struct tagline{
string tag;
string attributeN;
string attributeV;
};
struct xml_skipper : std::ctype<char> {
xml_skipper() : ctype(make_table()) { }
private:
static mask* make_table() {
const mask* classic = classic_table();
static std::vector<mask> v(classic, classic + table_size);
v[','] |= space;
v['"'] |= space;
v['='] |= space;
v['<'] |= space;
v['>'] |= space;
return &v[0];
}
};
int main(){
vector<tagline> information;
string line;
tagline t;
std::istringstream readFile{"<tag attr1=\"value1\" attr2=\"value2\" ... >"};
while(getline(readFile,line)){
istringstream in(line);
in.imbue(std::locale(in.getloc(), new xml_skipper));
in >> t.tag >> t.attributeN >> t.attributeV;
information.push_back(t);
}
vector<tagline>::iterator it = information.begin();
for(; it != information.end(); it++){
cout << "Tag: " << (*it).tag << " \n"
<< "name: " << (*it).attributeN << " \n"
<< "value: " << (*it).attributeV << " \n";
}
}
Live on Wandbox.
If your input may vary within the boundaries of the xml specification, an XML-parser might be a better approach than parsing the string "manually".
Just to show how this could look like, see the following code. It is based on tinyxml2, which just requires to include a single .cpp / .h-file in your project. You could - of course - also use any other xml libraries; this is just for demonstration purpose:
#include <iostream>
#include "tinyxml2.h"
using namespace tinyxml2;
int main()
{
const char* test = "<tag attr1='value1' attr2 = \"value2\"/>";
XMLDocument doc;
doc.Parse(test);
XMLElement *root = doc.RootElement();
if (root) {
cout << "Tag: " << root->Name() << endl;
const XMLAttribute *attrib = root->FirstAttribute();
while (attrib) {
cout << "name: " << attrib->Name() << endl;
cout << "value : " << attrib->Value() << endl;
attrib = attrib->Next();
}
}
}
I am trying to read from a .csv file. There are two functions below, one for writing and one for reading.
The file contains a simple table:
date,first,second
1 a one
2 b two
3 c three
4 c four
For some reason, the statement while(file_stream.read(&c,1)); does not read anything. It stops at the first character and I'm dumbfounded as to why. Any clues?
#include <iostream>
#include <sstream>
#include <fstream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <string>
#include <cstdlib>
using namespace std;
std::string filename;
std::string line_string;
ifstream file_stream;
stringstream ss;
vector< vector<string> > vec;
char c;
void read_file()
{
filename = "test.csv";
cout << filename << endl;
file_stream.open(filename.c_str(),ios::out|ios::binary);
if(file_stream.fail())
{
cout << "File didn't open" << endl;
return;
}
if(file_stream.is_open())
cout << "file opened" << endl;
while(file_stream.read(&c,1)); // this isn't working
{
cout <<"char c is: " << c;
ss << noskipws << c;
}
file_stream.close();
cout << "string is: " << ss.str() << endl;
//get each line
int counter = 0;
vector<string> invec;
while(getline(ss,line_string,'\n'))
{
string header_string;
stringstream header_stream;
header_stream << line_string;
while(getline(header_stream, header_string,','))
{
invec.push_back(header_string);
}
invec.push_back(header_string);
vec.push_back(invec);
invec.clear();
counter++;
}
}
void test_output()
{
for(int i = 0; i < vec.size();i++)
{
for(int in = 0; in < vec[0].size(); in++)
cout << vec[i][in] << " ";
cout << endl;
}
}
int main()
{
read_file();
test_output();
}
Look very very carefully at the line that is not working:
while(file_stream.read(&c,1)); // this isn't working
{
cout <<"char c is: " << c;
ss << noskipws << c;
}
The ; character at the end of the while statement does NOT belong! You are running a no-body loop that does not terminate until read() fails, and THEN your code enters the bracketed block to output the last character that was successfully read (if any).
You need to remove that erroneous ; character:
while(file_stream.read(&c,1)) // this works
{
cout <<"char c is: " << c;
ss << noskipws << c;
}
Now, the real question is - why are you reading the input file character-by-character into a std::stringstream in the first place? You can use std::getline() with the input std::ifstream directly:
#include <iostream>
#include <sstream>
#include <fstream>
#include <vector>
#include <string>
std::vector< std::vector<std::string> > vec;
void read_file()
{
std::string filename = "test.csv";
std::cout << filename << std::endl;
std::ifstream file_stream;
file_stream.open(filename.c_str(), ios::binary);
if (!file_stream)
{
std::cout << "File didn't open" << std::endl;
return;
}
std::cout << "file opened" << std::endl;
//get each line
std::vector<std::string> invec;
std::string line;
int counter = 0;
if (std::getline(file_stream, line))
{
std::istringstream iss(line);
while (std::getline(iss, line, ','))
invec.push_back(line);
vec.push_back(invec);
invec.clear();
++counter;
while (std::getline(file_stream, line))
{
iss.str(line);
while (iss >> line)
invec.push_back(line);
vec.push_back(invec);
invec.clear();
++counter;
}
}
}
void test_output()
{
if (!vec.empty())
{
for(int in = 0; in < vec[0].size(); ++in)
std::cout << vec[0][in] << ",";
std::cout << std::endl;
for(int i = 1; i < vec.size(); ++i)
{
for(int in = 0; in < vec[i].size(); ++in)
std::cout << vec[i][in] << " ";
std::cout << std::endl;
}
}
}
int main()
{
read_file();
test_output();
}
I'm completely new to C++ and currently I'm trying to read very basic text file which look like this:
Dr John Doe
British
2
Soccer
Swimming
and my expected output should look like:
My information
Name: John Doe
Nationality: British
I have 2 hobbies:
1. Soccer
2. Swimming
My header file:
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <cstdlib>
#include <ctime>
#include <vector>
using namespace std;
const int MAX = 80;
const int MAXNO = 5;
enum Title {Miss, Mrs, Mr, Dr, Unknown};
struct Date
{
int day;
int month;
int year;
};
struct MyInfo
{
char name [MAX];
char national [MAX];
int noOfHobbies;
char hobby [MAXNO][MAX];
};
void getMyInfo (fstream& , char[] , MyInfo&);
void displayMyInfo (MyInfo);
My functions:
#include "Lab_1.h"
void getMyInfo (fstream& afile,char fileName[], MyInfo& x) {
afile.open (fileName);
if (!afile)
{
cout << "Binary file " << fileName << " opened for creation failed" << endl;
exit (-1);
}
cout << "\n" << "Begin reading of " << fileName << endl;
string line;
while(getline(afile, line))
{
afile >> x.national;
afile >> x.noOfHobbies;*/
if (afile >> x.name >> x.national >> x.noOfHobbies) {
cout << "Name: " << x.name << ", "
<< "National: " << x.national << ", "
<< "noOfHobbies: " << x.noOfHobbies << ", "
<< endl;
}
}
}
void displayMyInfo (MyInfo x) {
}
My main function:
#include "Lab_1.h"
int main () {
fstream afile;
MyInfo x;
string fileName;
getMyInfo(afile,"textfile.txt",x);
//displayMyInfo(x);
afile.close ();
}
The above code output nothing because I just put everything I understand over the forum with similar question. Since I'm already stuck for 1 day even though I've already done a lot of research but most of them suggest to use vector which I'm not familiar with at this moment, so can someone give me a solution to this problem? Thank you very much for your help in advance.
Random act of madness kindness:
Live On Coliru
#include <fstream>
#include <set>
struct Person {
std::string name;
std::string nationality;
std::set<std::string> hobbies;
friend std::istream& operator>>(std::istream& is, Person& into) {
size_t n = 0;
if (getline(is, into.name) &&
getline(is, into.nationality) &&
is >> n && is.ignore(1024, '\n'))
{
while (n--) {
std::string hobby;
if (getline(is, hobby))
into.hobbies.insert(hobby);
else
is.setstate(std::ios::failbit);
}
}
return is;
}
};
#include <iostream>
int main() {
std::ifstream ifs("input.txt");
Person p;
if (ifs >> p) {
std::cout << "My information\n";
std::cout << p.name << "\n";
std::cout << p.nationality << "\n";
std::cout << "I have " << p.hobbies.size() << " hobbies:\n";
size_t counter = 0;
for(auto const& hobby : p.hobbies) {
std::cout << ++counter << ". " << hobby << "\n";
}
} else {
std::cerr << "Parse failure\n";
}
}
I have a text file-> info.txt which contains the follow Id,games,amount
info.txt
1,left4dead,50
2,warcraft3,60
I know how to extract the details using vectors with my codes shown below.
stock.h
#ifndef stock_stock_h
#define stock_stock_h
#include <iostream>
class stock {
public:
stock() {
columnOneText = " ";
columnTwoText = " ";
}
stock(std::string columnOneText,
std::string columnTwoText
);
std::string getColumnOne();
std::string getColumnTwo();
void setItemId(std::string columnOneText);
void setItemDescription(std::string columnTwoText);
private:
std::string columnOneText, columnTwoText;
};
#endif
main.cpp
#include "stock.h"
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <vector>
using namespace std;
stock::stock(string columnOneText,
string columnTwoText)
{
setItemId(columnOneText);
setItemDescription(columnTwoText);
};
string stock::getColumnOne() {
return columnOneText;
}
string stock::getColumnTwo() {
return columnTwoText;
}
void stock::setItemId(string columnOneText) {
this->columnOneText = columnOneText;
}
void stock::setItemDescription(std::string columnTwoText) {
this->columnTwoText = columnTwoText;
}
int main(){
vector<stock> itemDetails;
string line;
string columnOneText;
string columnTwoText;
ifstream readFile("info.txt");
while(getline(readFile,line)) {
stringstream iss(line);
getline(iss, columnOneText,',');
getline(iss, columnTwoText, ',');
//consturctor
stock splitedColumns(columnOneText,
columnTwoText
);
itemDetails.push_back(splitedColumns);
}
readFile.close();
cout << "this is column One in text file" << endl;
for (int i =0; i<itemDetails.size(); i++) {
cout << itemDetails[i].getColumnOne() << " " << endl;
}
cout << "this is column Two in text file" << endl;
for (int i =0; i<itemDetails.size(); i++) {
cout << itemDetails[i].getColumnTwo() << " " << endl;
}
}
what I don't really know is how to extract the details using arrays instead of using vectors.
I have tried this but it doesn't seem to work
string line;
string columnOneText;
string columnTwoText;
string columnOneTextArray[7];
while(getline(readFile,line)) {
stringstream iss(line);
getline(iss, columnOneText,',');
getline(iss, columnTwoText, ',');
for(int i=0; i<8; i++) {
columnOneTextArray[i] = columnOneText;
cout << columnOneTextArray[i];
}
}
You guys might ask why do I want to do it in arrays instead of using vector,
I just curious and exploring how it can be done using arrays.
You problem can be solved in a lot simpler manner by using struct definitions in addition to using vectors (your use of classes is a bit of overkill, IMHO):
#include <fstream>
#include <iostream>
#include <cstdlib>
#include <vector>
#include <sstream>
//this utilizes a more idiomatic naming convention as opposed to `columnX`
typedef struct Stock {
int id;
std::string games;
int amount;
} Stock;
//Syntactic sugar for easier output
std::ostream& operator << (std::ostream& in, const Stock& stock) {
in << stock.id << " " << stock.games << " " << stock.amount;
return in;
}
int main() {
std::string filename = "info.txt";
std::fstream ifile;
std::vector <Stock> inventory;
Stock stock_t;//a temporary Stock variable
std::string temp;
ifile.open(filename.c_str(), std::ios::in);
if (!ifile.is_open()) {
std::cerr << "There was a problem opening the input file: \"" << filename << "\"\n";
exit(1);
}
while (ifile >> temp) {
std::istringstream iss(temp);
int column = 0;
//break each constituent line by using the comment as a delimiter:
while(std::getline(iss, temp, ',')) {
if (column == 0) {
stock_t.id = std::atoi(temp.c_str());
}
else if (column == 1) {
stock_t.games = temp;
}
else if (column == 2) {
stock_t.amount = std::atoi(temp.c_str());
}
++column;
}
inventory.push_back(stock_t);
}
for (int i = 0; i < inventory.size(); ++i) {
std::cout << inventory[i] << "\n";
}
ifile.close();
return 0;
}
Which outputs:
1 left4dead 50
2 warcraft3 60