Vectors in C++ Files - c++

Within this function, I am passing multiple files. It was implemented with arrays before, and now I need to convert all of the arrays to vectors. The issue I have is when I read in from the files, it does not stop. Why??
void readIn(ifstream &iFile, vector<string> &itemName, vector<double> &itemPrice, vector<double> &quantity)
{
int x = 0;
string str;
string nTemp;
double pTemp;
int qTemp;
while(!iFile.eof())
{
getline(iFile, nTemp);
iFile.ignore();
itemName.push_back(nTemp);
iFile >> pTemp;
itemPrice.push_back(pTemp);
iFile >> qTemp;
quantity.push_back(qTemp);
cout << itemName.size() << " " << itemPrice.size() << " " << quantity.size() << endl;
}
readIn(appIn, appName, appPrice, appquantity);
readIn(drinkIn, drinkName, drinkPrice, driquantity);
readIn(entreeIn, entreeName, entreePrice, entquantity);
readIn(dessertIn, desName, desPrice, dessquantity);
This is the function and calls. Not sure why when outputting the item name, item price and quantity sizes, it just continually reads in values.

Expanding your code to an executable example:
#include <vector>
#include <string>
#include <fstream>
#include <iostream>
using namespace std;
void readIn(ifstream &iFile, vector<string> &itemName, vector<double> &itemPrice,
vector<double> &quantity)
{
int x = 0;
string str;
string nTemp;
double pTemp;
int qTemp;
while(!iFile.eof())
{
getline(iFile, nTemp);
iFile.ignore();
itemName.push_back(nTemp);
iFile >> pTemp;
itemPrice.push_back(pTemp);
iFile >> qTemp;
quantity.push_back(qTemp);
cout << itemName.size() << " " << itemPrice.size() << " " << quantity.size()
<< endl;
}
}
int main () {
vector<string> nam;
vector<double> price,quantity;
ifstream in;
in.open("data_adamp.txt");
readIn(in,nam,price,quantity);
}
Given ...
$ cat data_adamp.txt
animal a 1 2
beach b 3 4
cart c 4 5
dog d 6 7
... compiling with (GCC version 6.4.0):
$ gcc adamp.cpp -lstdc++ -oadamp
... lets me run:
$ ./adamp
... which does indeed never stop.
One way to solve this problem is to tokenize each line and convert the two rightmost fields to doubles and the rest to the record name, e.g. (using the approach in the highest-ranked answer to How do I iterate over the words of a string?):
#include <vector>
#include <string>
#include <fstream>
#include <iostream>
#include <sstream>
#include <vector>
#include <iterator>
using namespace std;
// See the highest-scoring answer to https://stackoverflow.com/questions/236129/how-do-i-iterate-over-the-words-of-a-string/236803#236803
template<typename Out>
void split(const std::string &s, char delim, Out result) {
std::stringstream ss(s);
std::string item;
while (std::getline(ss, item, delim)) {
*(result++) = item;
}
}
std::vector<std::string> split(const std::string &s, char delim) {
std::vector<std::string> elems;
split(s, delim, std::back_inserter(elems));
return elems;
}
void readIn(ifstream &iFile, vector<string> &itemName, vector<double> &itemPrice,
vector<double> &quantity)
{
string nTemp;
double pTemp;
int qTemp;
string line;
while(getline(iFile,line))
{
char delim = ' ';
vector<string> s = split(line,delim);
istringstream ss;
ss.str(s.back());
ss >> qTemp;
s.pop_back();
ss.str(s.back());
ss.clear();
ss >> pTemp;
s.pop_back();
nTemp = "";
for (int i = 0; i < s.size(); i++)
{
if (i > 0) nTemp.append(" ");
nTemp.append(s[i]);
}
itemName.push_back(nTemp);
itemPrice.push_back(pTemp);
quantity.push_back(qTemp);
cout << nTemp << "++" << pTemp << "++" << qTemp << endl;
}
}
int main () {
vector<string> nam;
vector<double> price,quantity;
ifstream in;
in.open("data_adamp.txt");
readIn(in,nam,price,quantity);
}

Related

C++ program to perform operations using a text file

item,price,qty,ordno,trdno
abc,54,2,123,32
xyz,34,2,345,21
item: string (char[])
price,qty (int)
ordno (long long)
trdno (int)
Make a structure for above mentioned fields
Make a vector (array, or any other container type) to hold multiple instances of this structure
1: Read file
2: read line, split values
3: initialize above mentioned structure object
4: add this object of structure to container
5: when whole file is read.. iterate over the container and print each elements values (serialno, orderno, tradeno, price, qty, item)
I tried this and it is not working-
#include<bits/stdc++.h>
using namespace std;
struct item {
string name;
double price;
int quantity;
int order_no;
int trd_no;
};
int main()
{
int n;cin>>n;
string str, T;
ifstream read("input.txt");
while(getline(read,str))
{
cout<<str<<endl;
}
stringstream X(str); // X is an object of stringstream that references the S string
cout<<endl;
while (getline(X, T, ','))
{
cout << T << endl; // print split string
}
read.close();
return 0;
}
For the code that you are showing, you misplaced just one '}' after the first while. So the code will read in the first while-loop all lines of the file and is then empty. And, then you try to split the lines. This can of course not work.
If you move the closing bracket to in front of read.close(); then your code will work. Like this:
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
using namespace std;
struct item {
string name;
double price;
int quantity;
int order_no;
int trd_no;
};
int main()
{
int n; cin >> n;
string str, T;
ifstream read("input.txt");
while (getline(read, str))
{
cout << str << endl;
stringstream X(str); // X is an object of stringstream that references the S string
cout << endl;
while (getline(X, T, ','))
{
cout << T << endl; // print split string
}
}
read.close();
return 0;
}
Caveat: this will not work, if the source file contains the header row! You can read this and throw it away, if needed.
If we follow the instruction of your homework, line by line, and assume that the first line contains header rows, then we would do like the following.
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
struct Item {
std::string name;
double price;
int quantity;
long long order_no;
int trd_no;
};
int main()
{
std::vector<Item> items;
std::string str, T;
std::ifstream read("input.txt");
// Read first line and ignore it
std::getline(read, str);
while (std::getline(read, str))
{
std::istringstream X(str);
Item tempItem;
getline(X, T, ',');
tempItem.name = T;
getline(X, T, ',');
tempItem.price = std::stod(T);
getline(X, T, ',');
tempItem.quantity = std::stoi(T);
getline(X, T, ',');
tempItem.order_no = std::stoll(T);
getline(X, T, ',');
tempItem.trd_no = std::stoi(T);
items.push_back(tempItem);
}
read.close();
for (const Item& item : items)
std::cout << item.name << ' ' << item.price << ' ' << item.quantity << ' '
<< item.order_no << ' ' << item.trd_no << '\n';
}
And, with a little bit more advanced C++, where we especially keep data and methods in a class, we could do the following:
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include <iomanip>
#include <algorithm>
#include <iterator>
// The item
struct Item {
std::string name{};
double price{};
int quantity{};
long long order_no{};
int trd_no{};
// Overwrite extraction operator for easier stream IO
friend std::istream& operator >> (std::istream& is, Item& i) {
char c;
return std::getline(is >> std::ws, i.name, ',') >> i.price >> c >> i.quantity >> c >> i.order_no >> c >> i.trd_no;
}
// Overwrite inserter for easier output
friend std::ostream& operator << (std::ostream& os, const Item& i) {
return os << "Name: " << i.name << "\tPrice: " << i.price << "\tQuantity: " << i.quantity << "\tOrder no: " << i.order_no << "\tTRD no: " << i.trd_no;
}
};
// The Container
struct Data {
std::vector<Item> items{};
// Overwrite extraction operator for easier stream IO
friend std::istream& operator >> (std::istream& is, Data& d) {
// Read header line and ignore it
std::string dummy; std::getline(is, dummy);
// Delete potential old data
d.items.clear();
// Read all new data from file
std::copy(std::istream_iterator<Item>(is), {}, std::back_inserter(d.items));
return is;
}
// Overwrite inserter for easier output
friend std::ostream& operator << (std::ostream& os, const Data& d) {
std::copy(d.items.begin(), d.items.end(), std::ostream_iterator<Item>(os, "\n"));
return os;
}
};
int main()
{
// Open file and check, if it could be opened
if (std::ifstream sourceFileStream("input.txt"); sourceFileStream) {
// Define container
Data data{};
// Read and parse complete source file and assign to data
sourceFileStream >> data;
// Show result
std::cout << data;
}
else std::cerr << "\n\nError: Could not open source file:\n\n";
}

split a set of data into different category

I have a .txt file which is a set of data (2000 lines) example shown below
Time,Price ($),Volume,Value ($),Condition
10/10/2013 04:57:27 PM,5.81,5000,29050.00,LT XT
10/10/2013 04:48:05 PM,5.81,62728,364449.68,SX XT
10/10/2013 04:10:33 PM,5.81,451,2620.31,
10/10/2013 04:10:33 PM,5.81,5000,29050.00,
How do i split them into chunks of each category? Example:
Volume - (whole data of volume)
Price - (whole data of price)
I understand that need to use delimiter to split but i don't know how to go about it (would need a little push on codings).
I'm using vectors to store these set of data by line.
Any help will be appreciated. Thanks
#include<iostream>
#include<fstream>
#include<string>
#include<vector>
#include<sstream>
//#include "Header.h"
using namespace std;
int main()
{
//open file
ifstream inFile("Course_of_sale.txt", ifstream::in);
// if can read
if (inFile.good())
{
std::vector<string> strVector;
//create vector
string line;
//read and push to back
while (getline(inFile, line))
{
getline(inFile, line);
strVector.push_back(line);
}
vector<string>::iterator it;
for (it = strVector.begin(); it < strVector.end(); it++)
{
cout << *it << endl;
}
stringstream ss(line);
string field;
while (getline(ss, field, ','))
{
getline(inFile, line);
strVector.push_back(line);
}
cout << "\nSize : " << strVector.capacity() << " elements \n";
}
system("Pause");
Currently only managed to do a read from file.(and this code is copied from SO)
This was my attempt.
#include <iostream>
#include <sstream>
#include <fstream>
#include <vector>
#include <string>
struct entry {
int time;
double price;
int volume;
double value;
std::string condition;
entry(const int ti, const double pr, const int vo, const double va, const std::string &co):
time{ ti }, price{ pr }, volume{ vo }, value{ va }, condition{ co }
{ }
};
std::vector<std::string> &split(const std::string &str, const char delim, std::vector<std::string> &ret) {
std::stringstream ss(str);
std::string tmp;
while (std::getline(ss, tmp, delim))
ret.push_back(tmp);
return ret;
}
int main(int argc, char **argv) {
std::vector<entry> vec;
std::ifstream file("test.txt");
std::string line;
std::vector<std::string> str;
while (std::getline(file, line)) {
std::vector<std::string>().swap(str);
split(line, ',', str);
std::string tmp{ "" };
if (str.size() > 4)
std::string tmp(str.at(4));
entry e(
std::stoi(str.at(0)),
std::stod(str.at(1)),
std::stoi(str.at(2)),
std::stod(str.at(3)),
tmp
);
vec.push_back(e);
}
system("pause");
return 0;
}
It's only fault tolerant if you leave off the condition.

C++ reading from data from text file

I have the following data:
$GPVTG,,T,,M,0.00,N,0.0,K,A*13
I need to read the data, however there are blanks in between the commas, therefore I am not sure how I should read the data.
Also, how do I select GPVTG only for a group of data? For example:
GPVTG,,T,,M
GPGGA,184945.00
GPRMC,18494
GPVTG,,T,,M,0
GPGGA,184946.000,3409
I have tried using:
/* read data line */
fgets(gpsString,100,gpsHandle);
char type[10] = "GPVTG";
sscanf(gpsString," %GPVTG", &type);
if (strcmp(gpsString, "GPTVG") == 0){
printf("%s\n",gpsString);
}
Thats what i'd do
#include <iostream>
#include <vector>
#include <sstream>
#include <fstream>
#include <string>
using namespace std;
vector<string> &split(const string &s, char delim, vector<string> &elems) {
stringstream ss(s);
string item;
while (getline(ss, item, delim)) {
elems.push_back(item);
}
return elems;
}
vector<string> split(const string &s, char delim) {
vector<string> elems;
split(s, delim, elems);
return elems;
}
int main()
{
ifstream ifs("file.txt");
string data_string;
while ( getline( ifs, data_string ) )
{
//i think you'd want to erase first $ charachter
if ( !data_string.empty() ) data_string.erase( data_string.begin() );
//now all data put into array:
vector<string> data_array = split ( data_string, ',' );
if ( data_array[0] == "GPVTG" )
{
//do whatever you want with that data entry
cout << data_string;
}
}
return 0;
}
Should handle your task. All empty elements will be empty "" strings in array. Ask if you need anything else.
Credits for split functions belong to Split a string in C++? answer.
How about this
#include <istream>
#include <sstream>
class CSVInputStream {
public:
CSVInputStream(std::istream& ist) : input(ist) {}
std::istream& input;
};
CSVInputStream& operator>>(CSVInputStream& in, std::string& target) {
if (!in.input) return in;
std::getline(in.input, target , ',');
return in;
}
template <typename T>
CSVInputStream& operator>>(CSVInputStream& in, T& target) {
if (!in.input) return in;
std::string line;
std::getline(in.input, line , ',');
std::stringstream translator;
translator << line;
translator >> target;
return in;
}
//--------------------------------------------------------------------
// Usage follow, perhaps in another file
//--------------------------------------------------------------------
#include <fstream>
#include <iostream>
int main() {
std::ifstream file;
file.open("testcsv.csv");
CSVInputStream input(file);
std::string sentence_type;
double track_made_good;
char code;
double unused;
double speed_kph;
char speed_unit_kph;
double speed_kmh;
char speed_unit_kmh;
input >> sentence_type >> track_made_good >> code;
input >> unused >> unused;
input >> speed_kph >> speed_unit_kph;
input >> speed_kmh >> speed_unit_kmh;
std::cout << sentence_type << " - " << track_made_good << " - ";
std::cout << speed_kmh << " " << speed_unit_kmh << " - ";
std::cout << speed_kph << " " << speed_unit_kph << std::endl;;
}
This separates the comma separation from the reading of the values, and can be reused on
most other comma separated stuff.
If you want use C++ style code based on fstream:
fin.open(input);
cout << "readed";
string str;
getline(fin, str); // read one line per time

getline() with delim not working as intended

I'm trying to split this a string with a comma as a delimeter. I put a string "Smith,Erdos,William" and it just outputs "William" but not Smith and Erdos. There must be something wrong here that I just can't see, can anyone help?
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
int main() {
int numScenarios(0);
int numPapers(0);
int numWriters(0);
std::vector<std::string> paperTitles (1);
std::vector<std::string> paperAuthors (1);
std::vector<std::string> splitAuthors (1);
std::string token;
std::string input;
std::cin >> numScenarios;
std::cin >> numPapers >> numWriters;
for (int i(0); i < numPapers; ++i) {
std::getline(std::cin,input);
std::istringstream iss(input);
while(getline(iss,token,','));
{
std::cout << token << std::endl;
}
//paperTitles.push_back(input);
//input = '\0';
}
for (int i(0); i < numWriters; ++i) {
getline(std::cin,input);
paperAuthors.push_back(input);
input = '\0';
}
return 0;
}
while(getline(iss,token,',')); // <== look closely

how to insert data from a text file into an array of struct

I need to read data from a text file, and insert the data in an array of struct. The data file is in the following format:
productname price quantity
my main concern is to read the product name, which consist of one, and two words. Should I approach product name as a c-string or as a string literal?
any help appreciated
#include <iostream>
#include <fstream>
using namespace std;
const int SIZE = 15; //drink name char size
const int ITEMS = 5; //number of products
struct drinks
{
char drinkName[SIZE];
float drinkPrice;
int drinkQuantity;
};
int main()
{
//array to store drinks
drinks softDrinks[ITEMS];
//opening file
ifstream inFile;
inFile.open("drinks.txt");
char ch;
int count = 0; //while loop counter
if(inFile)
{
while(inFile.get(ch))
{
//if(isalpha(ch)) { softDrinks[count].drinkName += ch; }
//if(isdigit(ch)) { softDrinks[count].drinkPrice += ch; }
cout << ch;
}
cout << endl;
count++;
}
else
{
cout << "Error opening file!\n";
system("pause");
exit(0);
}
system("pause");
return 0;
}
Since you ask for "any help", here's my view: Forget everything you wrote, and use C++:
#include <fstream> // for std::ifstream
#include <sstream> // for std::istringstream
#include <string> // for std::string and std::getline
int main()
{
std::ifstream infile("thefile.txt");
std::string line;
while (std::getline(infile, line))
{
std::istringstream iss(line);
std::string name;
double price;
int qty;
if (iss >> name >> price >> qty)
{
std::cout << "Product '" << name << "': " << qty << " units, " << price << " each.\n";
}
else
{
// error processing that line
}
}
}
You could store each line of data in a std::tuple<std::string, int, double>, for example, and then put those into a std::vector as you go along.