I need to read data from CSV file which is updated every second with a new data in the same cell and row.
What i mean is following :
For example i have 1 in the first row and cell then i have already 2 etc. But everything is changed in the same row and column.
struct Node
{
double number;
}
void readData(vector<Node>&Values)
{
Node Data;
ifstream file("file.csv");
if (file.good())
cout << "file ok";
file >> Data.number;
Values.push_back(Data);
}
int main()
{
vector<Node>Values;
while (true)
{
readData(Values);
_sleep(1000);
}
}
The problem i have is that it reads every second the new data but it saves in the vector the same number from the beginning. If the number was 1, it will save the same number hundreds times even if the number has been changed 10 times.
What should i change in the read file to work with the data which can be updated because the csv file is opened and updated, i can not close it?
I am pretty sure that it can be done the problem i did not find any solution in the internet.
Thank you in advance!
I would simplify the code as such;
double ReadData()
{
double val;
ifstream file("file.csv");
if (!file.good())
{// Check if valid, return Error Code
return 0;
}
file >> val;
return val;
}
int main()
{
vector<double> values;
while (true)
{
double retVal = ReadData();
if (retVal == 0)
{// Whatever you defined the error code as
break;
}
values.push_back(retVal);
_sleep(1000);
}
}
and if you really want the structure I'd just return the data and add it to the structure in the main loop.
Change from _sleep(1000) to _sleep(150
Related
I'm in the middle of making a binary search tree that stores Items of type MechPart, which stores an int quantity and a string code. The MechParts are generated by reading from a text file and storing their data. A separate text file called MonthlyUpdate.txt is used to read a list of MechParts in the tree and then update their quantities. For example:
MechPart A0001's quantity = 12
MonthlyUpdate.txt says A0001's quantity = 6
Run an update function that finds A0001 in the tree
Replace it with the updated quantity value of 6 (12 - 6).
Here's the two functions that perform this task:
void DBInterface::updateFromFile(string f_Name)
{
ifstream file (f_Name.c_str());
string line;
MechPart tmp_mp;
if (file.is_open())
{
std::getline(file, line);
while (std::getline (file, line))
{
std::istringstream iss (line);
int q=0;
int pos=0;
pos = line.find('\t',0); //find position of blank space
string tmp_str = line.substr(0,pos); //create a substring
string tmp_str1 = line.substr((pos+1), string::npos);
stringstream ss (tmp_str1);
ss >> q;
tmp_mp.set_code(tmp_str); //set code
tmp_mp.set_quantity(q);
MechPart currentQuantity;
currentQuantity = tree.quantitySearch(tree.getRoot(), tmp_mp);
tmp_mp.set_quantity((currentQuantity.get_quantity()) + q);
tree.update(tree.getRoot(), tmp_mp);
cout << "Current node data: " << tmp_mp.get_code() << " | " << tmp_mp.get_quantity() << endl;
}
}
and BSTree.template:
template <typename Item>
Item BSTree<Item>::quantitySearch(BTNode<Item>* q_ptr, Item obj)
{
if (q_ptr == NULL)
{
//POINTER IS NULL
}
else if (q_ptr->data() == obj)
{
return q_ptr->data();
}
else if (obj > q_ptr->data())
{ //WORK ON RIGHT SIDE
quantitySearch(q_ptr->get_right(), obj);
}
else
{
//work on left side
quantitySearch(q_ptr->get_left(), obj);
}
}
The search goes through the tree and locates a MechPart with the same part name code as the parameter and then returns that MechPart.
I've been running the code through GDB debugger. I have it displaying currentQuantity.get_quantity() to validate the returned MechPart's quantity is correct, however i am getting very large numbers for some reason. What is also confusing me is that in the MechPart constructor it assigns a value of 0 to quantity.
Eventually the updateFromFile() function gives me a segmentation fault, so something is very wrong here but I can't work out what as yet.
Recursive functions need to return their recursive calls back up to their caller for them to work properly. Look at the classic factorial example of recursion:
int factorial(int n) {
if (n == 1) {
return 1;
}
else {
return n*factorial(n-1);
}
}
As others have pointed out, your quantitySearch function only returns q_ptr->data() but never returns the return value from the recursive quantitySearch calls. I would start there and I would strongly suggest adding in cout statements in the recursive function to get a complete picture of what's happening "under the hood"
The purpose of the following short program is to search through a binary file (that contains details of different trains) for a particular train (whose number is accepted from the user) and then rewrite a blank record at that location.
That is, I wish to 'delete' that train record.
The problem is that the program goes into an infinite loop and repeatedly writes blank records to the binary file, thereby resulting in an enormous 2 GB .dat file being created.
#include<iostream.h>
#include<fstream.h>
struct train {
int train_no;
char train_name[50], source[20], dest[20];
int n_AC1, n_AC2, n_ACC, n_FC, n_SLC, n_SS; // variables for no of seats
train() { //default constructor
train_no = 0;
n_AC1=0, n_AC2=0, n_ACC=0, n_FC=0, n_SLC=0, n_SS=0;
strcpy(train_name, "/0");
strcpy(source, "/0");
strcpy(dest, "/0");
}
//member functions to accept and display the above values
};
void remove_train(fstream &f) {
train t, blank;
int tno, found = 0;
do {
cout<<"Enter the train no: ";
cin>>tno;
if(tno <=0)
cout<<"Invalid train number. Please re-enter."<<endl;
}
while(tno <=0);
f.seekg(0L, ios::beg);
f.read((char*)&t, sizeof(train));
while(!f.eof() && !found) {
if(t.train_no == tno) {
found = 1;
f.seekp(-sizeof(train), ios::cur);
f.write((char*)&blank, sizeof(train));
cout<<"Train number "<<tno<<" has been deleted!"<<endl;
}
else
f.read((char*)&t, sizeof(train));
}
if(found == 0)
cout<<"ERROR: train not found."<<endl;
}
int main() {
fstream f("Trains.dat", ios::binary | ios::in | ios::out);
remove_train(f);
cin.ignore();
cin.get();
}
When the above program is executed, after I input the train number as '1', the only observable output is "Train number 1 has been deleted", following which the program goes into the aforementioned infinite loop.
This doesn't seem to be an isolated issue; whenever I try to move back by one record and
then write a blank record anywhere in the Railway Reservation project that this code is a part of, the same problem ensues. For instance, if it is a passenger record I wish to overwrite, this is the relevant code fragment that seems to be causing the issue:
f.seekp(-1L*sizeof(passenger), ios::cur);
f.write((char*)&p, sizeof(passenger));
MAJOR EDIT: The problem was fixed when I replaced -sizeof(train) with -110L (which is the byte size of the 'train' structure)! Any idea why this is the case?
I must say I am at a loss to find a fault in your code. I've run a copy of it and it worked as expected.
There are a few minor errors (for instance it will fail if your data file does not exist) and the code could certainly be improved (your usage of f.eof() is somewhat awkward), but nothing that can explain the behaviour you're describing.
Here is the exact version I'm running right now. Except for a bit of extra code to create a dummy data file and a few debug outputs, I don't see any difference with yours.
Maybe you could try to compile it and see if it fails in your environment?
#include<iostream>
#include<fstream>
#include <string.h>
using namespace std;
struct train {
int train_no;
char train_name[50], source[20], dest[20];
int n_AC1, n_AC2, n_ACC, n_FC, n_SLC, n_SS; // variables for no of seats
train() { //default constructor
train_no = 0;
n_AC1=0, n_AC2=0, n_ACC=0, n_FC=0, n_SLC=0, n_SS=0;
strcpy(train_name, "");
strcpy(source, "");
strcpy(dest, "");
}
//member functions to accept and display the above values
};
void remove_train(fstream &f) {
train t, blank;
int tno, found = 0;
do {
cout<<"Enter the train no: ";
cin>>tno;
if(tno <=0)
cout<<"Invalid train number. Please re-enter."<<endl;
}
while(tno <=0);
cout<<"deleting train "<<tno<<endl;
f.seekg(0L, ios::beg);
f.read((char*)&t, sizeof(train));
while(!f.eof() && !found) {
cout<<f.tellp()<<endl;
if(t.train_no == tno) {
found = 1;
f.seekp(-sizeof(train), ios::cur);
cout<<"delete "<<f.tellp()<<"/"<<f.tellg()<<endl;
f.write((char*)&blank, sizeof(train));
cout<<"Train number "<<tno<<" has been deleted!"<<endl;
}
else
{
cout<<"read "<<f.tellg()<<endl;
f.read((char*)&t, sizeof(train));
}
}
if(found == 0)
cout<<"ERROR: train not found."<<endl;
else
cout<<"done"<<endl;
}
void create_trains(int n)
{
fstream f("Trains.dat", ios::binary | ios::out);
train t;
for (int i = 1 ; i <= n ; i++)
{
t.train_no = i;
f.write((char*)&t, sizeof(train));
}
}
int main() {
create_trains (10);
fstream f("Trains.dat", ios::binary | ios::in | ios::out);
remove_train(f);
cin.ignore();
cin.get();
}
Newbie question! I've started a small project that loads integer values from a file into an array. (The array needs to be accessed at random which is why i've chosen an array and not a vector.)
To load the data values from the file I've created a Load/Save class. The load function reads the first line of the file which gives us the total number of entries the array needs to have, then it will fill the array with the rest of the values in that file.
This load object is only created temporarily, I want to give the data to the program and then delete the object.
What is the best way to achieve this? should I create the array in main() and pass the load object a reference, in which case how can I create the array so it can be re-sized for the amount of data that needs loading..?
here is the load/save class:
class FileIOClass {
public:
FileIOClass();
int ReadFile(char*);
private:
};
this is the cpp code for the class:
FileIOClass::FileIOClass() {
}
int FileIOClass::ReadFile(char* file_name) {
string line;
ifstream file;
file.open(file_name, ios::in);
cout << "Loading data...\n";
int num_x, num_y, array_size;
bool machine_header = false;
if (file.is_open()) {
while(getline(file, line)) {
if (line.size() && machine_header == false) {
// Load machine header information
file >> num_x;
file >> num_y;
file >> array_size;
machine_header = true; // machine header has now been read, set this to true.
}
else {
// this is where i want to load the data from the file into an array.
// the size of the array should be equal to the value in array_size.
}
}
cout << "Loading complete!\n";
}
else {cout<<"File did not open!\n";}
file.close();
return 0;
}
and here is the main.cpp so far:
int main(int argc, char** argv)
{
FileIOClass data_in;
data_in.ReadFile(argv[1]);
return 0;
}
there will be several other classes that will process the data thats contained in the array.
I bet there are a load of odd newbie mistakes in this code - please feel free to point them out, better to learn these things now.
Thanks all!
Ian.
Somthing like this might be good:
vector<int> myVector(array_size);
for(int i=0; file && i<array_size; i++) {
file >> myVector[i];
}
As long as you've already decided on using a class to read the file, storing the data within the class seems reasonable. add a member to this class to store the data:
class FileIOClass {
public:
FileIOClass();
int ReadFile(char*);
unsigned int operator [](int i) const {return m_data[i];}
int size(void) { return m_data.size(); }
private:
std::vector<int> m_data;
};
and insert data into this member in your ReadFile method:
while(getline(file, line)) {
int pos = 0;
if (line.size() && machine_header == false) {
// Load machine header information
file >> num_x;
file >> num_y;
file >> array_size;
m_data.resize(array_size);
machine_header = true; // machine header has now been read, set this to true.
}
else {
file >> m_data[pos++];
// this is where i want to load the data from the file into an array.
// the size of the array should be equal to the value in array_size.
}
}
notice that I overloaded the [] operator, so you can use your class like this:
int main(int argc, char** argv)
{
FileIOClass data_in;
data_in.ReadFile(argv[1]);
if (data_in.size() >= 1)
cout << data_in[0];
return 0;
}
The array needs to be accessed at random which is why i've chosen an array and not a vector.
C++ vectors allow efficient random access (they are arrays under the hood). Use std::vector unless you have profiled your code and found them inefficient for what you are doing.
This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
I'm learning c++ and am working on a program that keeps giving me a 'pointer being freed was not allocated' error. It's a grocery store program that inputs data from a txt file, then user can enter item# & qty. I've read through similar questions but what's throwing me off is the 'pointer' issue. I would appreciate if someone could take a look and help me out. I'm using Netbeans IDE 7.2 on a Mac.
I'll just post the whole piece I have so far. Thx.
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;
class Product
{
public:
// PLU Code
int getiPluCode()
{
return iPluCode;
}
void setiPluCode( int iTempPluCode)
{
iPluCode = iTempPluCode;
}
// Description
string getsDescription()
{
return sDescription;
}
void setsDescription( string sTempDescription)
{
sDescription = sTempDescription;
}
// Price
double getdPrice()
{
return dPrice;
}
void setdPrice( double dTempPrice)
{
dPrice = dTempPrice;
}
// Type..weight or unit
int getiType()
{
return iType;
}
void setiType( int iTempType)
{
iType = iTempType;
}
// Inventory quantity
double getdInventory()
{
return dInventory;
}
void setdInventory( double dTempInventory)
{
dInventory = dTempInventory;
}
private:
int iPluCode;
string sDescription;
double dPrice;
int iType;
double dInventory;
};
int main ()
{
Product paInventory[21]; // Create inventory array
Product paPurchase[21]; // Create customer purchase array
// Constructor to open inventory input file
ifstream InputInventory ("inventory.txt", ios::in);
//If ifstream could not open the file
if (!InputInventory)
{
cerr << "File could not be opened" << endl;
exit (1);
}//end if
int x = 0;
while (!InputInventory.eof () )
{
int iTempPluCode;
string sTempDescription;
double dTempPrice;
int iTempType;
double dTempInventory;
InputInventory >> iTempPluCode >> sTempDescription >> dTempPrice >> iTempType >> dTempInventory;
paInventory[x].setiPluCode(iTempPluCode);
paInventory[x].setsDescription(sTempDescription);
paInventory[x].setdPrice(dTempPrice);
paInventory[x].setiType(iTempType);
paInventory[x].setdInventory(dTempInventory);
x++;
}
bool bQuit = false;
//CREATE MY TOTAL VARIABLE HERE!
int iUserItemCount = 0;
do
{
int iUserPLUCode;
double dUserAmount;
double dAmountAvailable;
int iProductIndex = -1;
//CREATE MY SUBTOTAL VARIABLE HERE!
while(iProductIndex == -1)
{
cout<<"Please enter the PLU Code of the product."<< endl;
cin>>iUserPLUCode;
for(int i = 0; i < 21; i++)
{
if(iUserPLUCode == paInventory[i].getiPluCode())
{
dAmountAvailable = paInventory[i].getdInventory();
iProductIndex = i;
}
}
//PLU code entry validation
if(iProductIndex == -1)
{
cout << "You have entered an invalid PLU Code.";
}
}
cout<<"Enter the quantity to buy.\n"<< "There are "<< dAmountAvailable << "available.\n";
cin>> dUserAmount;
while(dUserAmount > dAmountAvailable)
{
cout<<"That's too many, please try again";
cin>>dUserAmount;
}
paPurchase[iUserItemCount].setiPluCode(iUserPLUCode);// Array of objects function calls
paPurchase[iUserItemCount].setdInventory(dUserAmount);
paPurchase[iUserItemCount].setdPrice(paInventory[iProductIndex].getdPrice());
paInventory[iProductIndex].setdInventory( paInventory[iProductIndex].getdInventory() - dUserAmount );
iUserItemCount++;
cout <<"Are you done purchasing items? Enter 1 for yes and 0 for no.\n";
cin >> bQuit;
//NOTE: Put Amount * quantity for subtotal
//NOTE: Put code to update subtotal (total += subtotal)
// NOTE: Need to create the output txt file!
}while(!bQuit);
return 0;
}
iUserItemCount is never initialised. You're invoking undefined behaviour when you use it as an index.
Because you work with statically allocated arrays you probably stumbled upon writing after the end of the array.
You state that the file has exactly 21 entries but what happens with the eof condition? If you read the last entry, the stream still doesn't have the eof bit set. This only happens when you try to read and there is nothing.
After the 21st entry, the loop still continues because the eof bit is not set. It reads garbage information and tries to store it into paInventory[21], but the array was only 21 in size.
//after last read x=21 and eof not set
while (!InputInventory.eof () )
{
//first read causes eof to be set
InputInventory >> iTempPluCode >> sTempDescription >> dTempPrice >> iTempType >> dTempInventory;
//Accessing paInventory[21] here which causes your error
paInventory[x].setiPluCode(iTempPluCode);
//...//
}
#include<iostream>
#include<windows.h>
#include<string>
#include<fstream>
using namespace std;
class linklist //linked list class
{
struct main_node;
struct sub_node;
struct main_node // main node that only have head pointers in it
{
sub_node *head;
main_node()
{ head=NULL; }
};
main_node array[26];
struct sub_node
{
double frequency;
string word;
sub_node *next;
sub_node()
{ frequency=1; word=""; next=NULL; }
};
public:
void add_node(string phrase)
{
char alphabat1=phrase[0];
if(isupper(alphabat1))
{
alphabat1=tolower(alphabat1);
}
if(!isalpha(alphabat1))
return;
sub_node*temp = new sub_node;
temp->word = phrase;
sub_node*current = array[alphabat1-97].head;
if(current == NULL)
array[alphabat1-97].head = temp;
else
{
while(current -> next != NULL && phrase != current-> word)
{ current= current->next; }
if(current->word == phrase)
current->frequency++;
else
current->next = temp; //adding words to linklist
}
}
void display()
{
for(int i=0;i<26;i++)
{
sub_node *temp=array[i].head;
cout<<char(i+97)<<" -> ";
while(temp!=NULL)
{
cout<<temp->word<<" ("<<temp->frequency<<") ";
temp=temp->next;
}
cout<<"\n";
}
}
void parsing_documents(char *path)
{
char token[100];
ifstream read;
read.open(path);
do
{
read>>token; // parsing words
add_node(token); //sending words to linked list
}
while(!read.eof());
read.clear();
read.close();
}
void reading_directory()
{
// code to read multiple files
HANDLE hFile; // Handle to file
WIN32_FIND_DATA FileInformation; // File information
char tempPattern[90];
strcpy(tempPattern,"*.txt");
hFile = ::FindFirstFile(tempPattern, &FileInformation);
long count=0;
if(hFile != INVALID_HANDLE_VALUE)
{
do
{
count++;
cout<<"."<<count;
this->parsing_documents( FileInformation.cFileName);
}
while(TRUE == ::FindNextFile(hFile, &FileInformation));
}
::FindClose(hFile);
}
};
void main()
{
linklist member;
member.reading_directory();
member.display();
}
I am working on a project in which I have to read more than 50,000 text files parse their words and save them in a linked list in a sorted manner , i have made the code in C++. it's working quite efficiently but I have one problem in this regard that it is not reading the files correctly sometimes 3000 sometimes 4000. I have searched for it a lot but i couldn't succeed to find my fault . . here is my code in C++
if any body help me in this regard i would be very thankful
!read.eof() only checks for end of file, not errors reading the file, such as a networked mounted file system not being ready, disk error, or lack of permission to read the file. You should check for all failures, with while(read) which has an overloaded operator to check everything for you. So, if the file fails, you stop trying to read from it. You should also check the status before trying to read from the file. As such, while(read) { ... } is preferable to the do/while loop. After the loop, you might issue a warning or error to the user of you did not reach the end of file !read.eof() so they can investigate that specific file.
Try to avoid char * and char [] as much possible as this is highly error prone. You have a char[100]. What happens if the string is longer than 100 characters? read >> token may overwrite the stack -- such as to damage the ifstream read.
Consider using std::list<sub_node> to avoid having to re-invent and re-debug the wheel? You would no longer need the next pointer as std::list already does that for you. This would leave far less code to debug.