Trying to read two files in the same time - c++

I am playing with threads but I don't know why this code doesn't work properly. It has to read two files(the names of the files come from keyboard) and then show the contents in the console. Could you tell me where is the problem?
#include<iostream>
#include<fstream>
#include<thread>
#include<string>
#include<vector>
using namespace std;
mutex mtx;
class eu
{
string filename;
string buffer;
public:
eu() {};
void citire(string filename)
{
this->filename = filename;
ifstream f(filename);
while (f.eof())
{
string ceva;
f >> ceva;
buffer = buffer + ceva;
}
f.close();
}
/*void operator()() it doesn't work either in this way
{
this->citire(filename);
}*/
friend ostream &operator<<(ostream& os, eu&n);
//~eu();
};
ostream& operator<<(ostream& os, eu&n)
{
os << n.buffer;
return os;
}
//threads.push_back(std::thread(&C::increase_member,std::ref(bar),1000));
int main()
{
vector<thread>instante;
string nume;
eu n;
for (int i = 0; i <2; i++)
{
cin >> nume;
instante.push_back(thread(&eu::citire, n, nume));
}
for (auto& th : instante) th.join();
cout << n;
}

Related

C++ Exception "Access violation reading location"

#include <iostream>
#include <fstream>
using namespace std;
struct review {
string text;
string date;
};
void getRegistry(int i) {
review* reg = new review;
ifstream file;
file.open("test.txt", ios::binary);
if (file) {
file.seekg(i * sizeof(review), ios::beg);
file.read(reinterpret_cast<char*>(reg), sizeof(review));
cout << reg->text;
file.close();
}
delete reg;
}
void generateBinary()
{
ofstream arq("test.txt", ios::binary);
review x;
x.text = "asdasdasd";
x.date = "qweqweqwe";
for (int i = 1; i <= 1000000; i++)
{
arq.write(reinterpret_cast<const char*>(&x), sizeof(review));
}
arq.close();
}
int main() {
generateBinary();
getRegistry(2);
return 0;
}
Hello, I'm trying to make a program which writes several "reviews" to a binary file, then reads a certain registry. The program seems to work, but, in the end, it always throws an exception: "Exception thrown at 0x00007FF628E58C95 in trabalho.exe: 0xC0000005: Access violation reading location 0xFFFFFFFFFFFFFFFF." How can I solve this? Thank you!
The problem is that you can't read/write std::string objects they way you are. std::string holds a pointer to variable-length character data that is stored elsewhere in memory. Your code is not accounting for that fact.
To be able to seek to a specific object in a file of objects the way you are attempting, you have to use fixed-sized objects, eg:
#include <iostream>
#include <fstream>
#include <cstring>
using namespace std;
struct review {
char text[12];
char date[12];
};
void getRegistry(int i) {
ifstream file("test.txt", ios::binary);
if (file) {
if (!file.seekg(i * sizeof(review), ios::beg)) throw ...;
review reg;
if (!file.read(reinterpret_cast<char*>(&reg), sizeof(reg))) throw ...;
cout << reg.text;
}
}
void generateBinary()
{
ofstream arq("test.txt", ios::binary);
review x = {};
strncpy(x.text, "asdasdasd", sizeof(x.text)-1);
strncpy(x.date, "qweqweqwe", sizeof(x.date)-1);
for (int i = 1; i <= 1000000; ++i) {
if (!arq.write(reinterpret_cast<char*>(&x), sizeof(x))) throw ...;
}
}
int main() {
generateBinary();
getRegistry(2);
return 0;
}
Otherwise, to deal with variable-length data, you need to (de)serialize each object instead, eg:
#include <iostream>
#include <fstream>
#include <cstdint>
using namespace std;
struct review {
string text;
string date;
};
string readStr(istream &is) {
string s;
uint32_t len;
if (!is.read(reinterpret_cast<char*>(&len), sizeof(len))) throw ...;
if (len > 0) {
s.resize(len);
if (!is.read(s.data(), len)) throw ...;
}
return s;
}
void skipStr(istream &is) {
uint32_t len;
if (!is.read(reinterpret_cast<char*>(&len), sizeof(len))) throw ...;
if (len > 0) {
if (!is.ignore(len)) throw ...;
}
}
void writeStr(ostream &os, const string &s) {
uint32_t len = s.size();
if (!os.write(reinterpret_cast<char*>(&len), sizeof(len)) throw ...;
if (!os.write(s.c_str(), len)) throw ...;
}
review readReview(istream &is) {
review r;
r.text = readStr(is);
r.date = readStr(is);
return r;
}
void skipReview(istream &is) {
skipStr(is);
skipStr(is);
}
void writeReview(ostream &os, const review &r) {
writeStr(is, r.text);
writeStr(is, r.date);
}
void getRegistry(int i) {
ifstream file("test.txt", ios::binary);
if (file) {
while (i--) skipReview(file);
review reg = readReview(file);
cout << reg.text;
}
}
void generateBinary()
{
ofstream arq("test.txt", ios::binary);
review x;
x.text = "asdasdasd";
x.date = "qweqweqwe";
for (int i = 1; i <= 1000000; ++i) {
writeReview(arq, x);
}
}
int main() {
generateBinary();
getRegistry(2);
return 0;
}
The operator sizeof (review) does not return the length of containing strings. This is due to the fact that string class contain pointers to real strings, which are located in a separated location of the memory, allocated dynamically. You should use explicitly the length of strings, and write explicitly the strings instead of the class. Same thing with reading from file. Read strings first, then attribute to review.

Trying to implement my own << and >> streaming operators to operate on my Grid object

My task is to overload my own "<<" and ">>" streaming operators to read and write values from and into my Grid. I am not sure how to implement this with my SaveGrid and LoadGrid. I've read multiple tutorials on overloading operators and this is what I got so far.
I have already implemented friends of the class but I am not sure how to implement them in my grid.cpp.
friend ostream& operator<<(ostream& out, Grid& grid);
friend istream& operator>>(istream& in, Grid& grid);
Looking for some suggestions on how I can implement this so I can read in and out with my existing methods using my overloaded operators with something like cout << grid and cin >> grid, I apologise that I have not articulated this very well but any advice at all is appreciated.
Grid.cpp
#include "Grid.h"
#include<iostream>
#include<fstream>
using namespace std;
void Grid::LoadGrid(const char filename[])
{
ifstream newStream;
newStream.open(filename);
for (int y = 0; y < 9; y++)
{
for (int x = 0; x < 9; x++)
{
newStream >> m_grid[y][x];
}
}
}
void Grid::SaveGrid(const char filename[])
{
ofstream newStreamOut(filename);
for (int y = 0; y < 9; y++)
{
for (int x = 0; x < 9; x++)
{
newStreamOut << m_grid[y][x] << " ";
}
newStreamOut << endl;
}
}
ostream& operator<<(ostream& out, Grid& grid)
{
grid.SaveGrid(out);
return out;
}
istream& operator>>(istream& in, Grid& grid)
{
grid.LoadGrid(in);
return in;
}
Grid.h
#pragma once
#include<ostream>
using namespace std;
class Grid
{
public:
Grid() {};
~Grid(){};
friend ostream& operator<<(ostream& out, Grid& grid);
friend istream& operator>>(istream& in, Grid& grid);
void LoadGrid(const char filename[]);
void SaveGrid(const char filename[]);
private:
int m_grid[9][9];
};
main.cpp
#include <iostream>
#include "Grid.h"
using namespace std;
int main(int args, char** argv)
{
Grid grid;
grid.LoadGrid("Grid1.txt");
grid.SaveGrid("OutGrid.txt");
system("pause");
}
Move the logic from your LoadGrid and SaveGrid functions (all the stuff that operates on the filestream that you open) into your >> and << functions. Also add const for the objects you're not supposed to change.
ostream& operator<<(ostream& out, const Grid& grid) // grid should be const
{
for (int y = 0; y < 9; y++)
{
for (int x = 0; x < 9; x++)
{
out << grid.m_grid[y][x] << " ";
}
out << endl;
}
return out;
}
Then your LoadGrid and SaveGrid functions are just helpers that call the stream operators, but take care of opening the filestream.
void Grid::SaveGrid(const char filename[]) const // *this should be const
{
ofstream newStreamOut(filename);
newStreamOut << *this;
}
Except now you can output your Grid to any other ostream you want:
std::cout << my_grid << "\n";
Afterwards, do the same for the istream side.

Reading a file into a vector of class objects

I have given it a few tries based on what I've read on numerous forums and books I have here. More details about this assignment here with more code from it: Click- another question from StackOverflow
What exactly I need to do is create a file with CHotel objects and insert them in this vector m_hoteli.
As to why it isn't working, it is either not reading the string from the file and it's not filling the vector at all.
This is my file:
"Marina" 5 500
"Tulip" 4 400
"BlackSea" 3 300
"SwissBell" 5 600
class CComplex:CHotel
{
protected:
string m_complex;
vector<CHotel> m_hoteli;
public:
CComplex(){};
CComplex(string filename, string nComplex)
{
fstream file("filename.txt", ios::in);
CHotel temp(" ",0,0);
while (file >> temp)
{
m_hoteli.push_back(temp);
}
/* Second try:
m_complex = nComplex;
fstream in;
in.open(filename, ios::in);
string s;
while (getline(in, s))
{
CHotel h1(s);
m_hoteli.push_back(h1);
}
Third try:
m_complex = nComplex;
ifstream iStream(filename);
if (iStream.good())
{
copy(istream_iterator<CHotel>(iStream), istream_iterator<CHotel>(), back_inserter(m_hoteli));
}
}
*/
}
That's the CHotel code:
class CHotel : public CTurist
{
protected:
string hName;
int stars;
int beds;
map<CTurist, unsigned> Turisti;
public:
unsigned Sum = 0;
int br = 0;
CHotel(){};
CHotel(string hName2, int zvezdi, int legla)
{
hName = hName;
stars = zvezdi;
beds = legla;
}
friend istream& operator>>(std::istream& is, CHotel& e)
{
is >> e.hName >> e.stars >> e.beds;;
return is;
}
I just do this in the main: CComplex c1("filename.txt", "Complex1");
You are not using the filename parameter in the CComplex constructor, other than that your code should work.
fstream file(filename, ios::in);
Do you know how to step debug? Here is some info on debugging
Here is your full code, the only change is the filename parameter and the file should now be placed in c:\temp.
#include <iostream>
#include <string>
#include <map>
#include <vector>
#include <fstream>
using namespace std;
class CTurist
{
protected:
string tName;
int age;
public:
CTurist() {};
CTurist(string name, int age2)
{
tName = name;
age = age2;
}
bool operator<(const CTurist& e) const
{
return age < e.age;
}
friend ostream& operator<<(ostream& os, const CTurist&& e);
friend ifstream& operator>>(ifstream& is, CTurist&& e);
};
class CHotel : public CTurist
{
protected:
string hName;
int stars;
int beds;
map<CTurist, unsigned> Turisti;
public:
unsigned Sum = 0;
int br = 0;
CHotel() {};
CHotel(string hName2, int zvezdi, int legla)
{
hName = hName;
stars = zvezdi;
beds = legla;
}
friend istream& operator>>(std::istream& is, CHotel& e)
{
is >> e.hName >> e.stars >> e.beds;;
return is;
}
};
class CComplex :CHotel
{
protected:
string m_complex;
vector<CHotel> m_hoteli;
public:
CComplex() {};
CComplex(string filename, string nComplex)
{
fstream file(filename, ios::in);
CHotel temp(" ", 0, 0);
while (file >> temp)
{
m_hoteli.push_back(temp);
}
}
};
int main()
{
CComplex c1("C:\\temp\\file.txt", "Complex1");
system("pause");
return 0;
}
Try putting a breakpoint in main and step through your program with f11 and f10

I'm freeing memory twice - C++

I have done this program where I check if my 'date' class is correct. The problem is that when I run my test program, it returned my the following error:
Error in `./bin/test': double free or corruption (fasttop): 0x00000000019c07c0 *
The job of this class is read and store a 'date'(a year) and a few events (allocated in a string array). For example, a object of this class would be: 1998 EVENT1 EVENT2 EVENT3.
Operator >> reads the next format:1908#Fantasmagorie#The Taming of the Shrew#The Thieving Hand#The Assassination of the Duke of Guise#A Visit to the Seaside
Well, my problem is that I'm deleting some pointer twice or freeing some memmory twice, I have tried a lot of things but I don't know how to fix it (as you can see on my code, I have already tried to set all pointers to 0 when I delete them.):
Date class .h
#ifndef _date_HISTORICA_
#define _date_HISTORICA_
#include <iostream>
#include <string>
#include <cassert>
using namespace std;
class date{
private:
int year;
int eventsNum;
int reserved;
string * str;
void resize(int r);
public:
date();
//date(int a, string *s, int n);
date(const date& d);
~date();
int getAge();
void addEvent(string& s);
friend ostream& operator<<(ostream& os, const date& d);
friend istream& operator>>(istream& is, date& d);
};
#endif
Date Class Code:
#include<iostream>
#include<string>
#include<fstream>
#include<sstream>
#include<date.h>
using namespace std;
void date::resize(int r)
{
assert(r>=0);
if(r!=this->reserved)
{
if(r!=0)
{
string * aux = new string[r];
if(this->reserved>0)
{
int min=this->reserved<r?this->reserved:r;
for(int i=0; i<min; i++)
aux[i]=this->str[i];
delete[] this->str;
this->str=NULL;
}
this->str=aux;
this->reserved=r;
if(this->reserved<this->eventsNum)
this->eventsNum=this->reserved;
} else
{
if(this->reserved>0)
{
delete[] this->str;
this->str=NULL;
}
this->year=0;
this->eventsNum=0;
this->reserved=0;
}
}
}
date::date() : year(0), eventsNum(0), reserved(0), str(0){}
date::date(const date& d)
{
this->year=d.year;
this->eventsNum=d.eventsNum;
this->reserved=d.reserved;
this->str=new string[this->reserved];
for(int i=0; i<this->eventsNum; i++)
this->str[i]=d.str[i];
}
date::~date()
{
this->year=0;
this->eventsNum=0;
this->reserved=0;
if(this->str)
delete[] this->str;
this->str=NULL;
}
int date::getAge(){return this->year;}
ostream& operator<<(ostream& os, const date& d)
{
os << d.year;
for(int i=0; i<d.eventsNum; i++)
os << '#' << d.str[i];
os << endl;
return os;
}
void date::addEvent(string& s){
if (this->eventsNum == this->reserved){
if (this->eventsNum==0)
resize(1);
else
resize(2*this->reserved);
}
this->str[eventsNum]=s;
eventsNum++;
}
istream& operator>>(istream& is, date& d)
{
string line; char c;
is >> d.year >> c;
getline(is, line);
int n=1;
for(int i=0; i<line.length(); i++)
if(line[i]=='#')
n++;
d.eventsNum=n;
d.reserved=d.eventsNum;
delete[] d.str;
d.str=NULL;
d.str=new string[n];
stringstream ss(line);
for(int i=0; i<n; i++)
getline(ss, d.str[i], '#');
return is;
}
Test Program Class:
#include<iostream>
#include<fstream>
#include<cronologia.h>
#include<date.h>
using namespace std;
int main(int argc, char * argv[]){
cout << "STATE: IN PROGRESS" << endl;
cout << "TEST: (2)" << endl;
date d;
ifstream f("./data/name.txt");
while(f >> d)
{
cout << d;
}
date d1;
cin >> d1;
d=d1;
cout << d << endl;
}
Example file (wich should be read by date clas):
1900#Sherlock Holmes Baffled#The Enchanted Drawing
1901#Star Theatre#Scrooge, or, Marley's Ghost
1902#A Trip to the Moon
1903#The Great Train Robbery#Life of an American Fireman
1904#The Impossible Voyage
1905#Adventures of Sherlock Holmes; or, Held for Ransom
1906#The Story of the Kelly Gang#Humorous Phases of Funny Faces#Dream of a Rarebit Fiend
1907#Ben Hur#L'Enfant prodigue
1908#Fantasmagorie#The Taming of the Shrew#The Thieving Hand#The Assassination of the Duke of Guise#A Visit to the Seaside
Im so sorry for my English!!! :,(
Since there is no assignment overloading in your code, in the line
d=d1;
All the members of d1 will be copied to a new object d by value. Hence there will be two copies of the object date which have the same reference value in their member str. Those two will eventually get out of scope and both will be destructed. The first one will free the allocated memory while the other will try to free that same reference and that is why you get the error.
You need a copy assignment operator:
void swap(date& other)
{
using std::swap;
swap(year, other.year);
swap(eventsNum, other.eventsNum);
swap(reserved, other.reserved);
swap(str, other.str);
}
date::date(const date& d) : year(other.year), eventsNum(other.eventsNum), reserved(other.reserved), str(new string[other.reserved])
{
for(int i = 0; i < this->eventsNum; i++)
this->str[i] = d.str[i];
}
date& date::operator = (const date& d)
{
swap(*this, d);
return *this;
}
Might also be nice to provide a move constructor..

usage of istream in class constructor c++

I have a text file that contains a list of students and their marks and looks like this:
Name_of_student 78 4; 98 5; 90 5; 63 3;
...
I have an assignment to create a class that will read and store that data. This is what I've done so far.
group.h
class Subject {
public:
Subject(int mark0, int mark1);
Subject();
int get_m0() { return mark0; }
int get_m1() { return mark1; }
private:
int mark0;
int mark1;
};
class Student {
public:
Student(string name);
Student();
vector<Subject>my_marks;
string get_name() { return name; }
private:
string name;
};
class Reading
{
public:
Reading(vector<Student>, istream& );
istream& read_student();
private:
vector<Student>group;
istream& is;
};
text.cpp
Subject::Subject(int m0, int m1) :
mark0(m0), mark1(m1) {}
Subject::Subject() :
mark0(1), mark1(1) {}
Student::Student(string n0) :
name(n0) {}
Student::Student() :
name("null") {}
Reading::Reading(vector<Student>group0, istream& is0) :
group(group0), is(is0) {}
istream& Reading::read_student()
{
string n;
is >> n;
if (!is) return is;
Student st = Student(n);
for (int i = 0; i < 4; ++i)
{
int m0, m1;
is >> m0 >> m1;
char ch;
is >> ch;
Subject sub = Subject(m0, m1);
st.my_marks.push_back(sub);
}
group.push_back(st);
return is;
}
It compiles, but refuses to read anything.
int main()
{
ifstream ifs("text");
if(!ifs) error("can`t open input file");
vector<Student> group;
Readding r(group, ifs);
r.read_student();
cout << group.size();
}
And what it shows:
0
If anyone has any ideas I'd appreciate it.
In Reading::read_student(), you are filling up the member variable Reading::group. You are not filling up the function variable group in main.
Use:
int main()
{
ifstream ifs("text");
vector<Student> group;
Readding r(group, ifs);
r.read_student();
cout << r.group.size();
// ^^^^^^^^ access the member variable of r.
}
If you want the function variable group to be filled up, Reading needs to store a reference to the input group.
class Reading
{
public:
Reading(vector<Student> & , istream& );
// ^^^^^^ Take a reference as input
istream& read_student();
private:
vector<Student>& group;
// ^^^^^^ store a reference
istream& is;
};
What i have changed:
group.h
class Reading
{
public:
Reading( istream& );
vector<Student>group;
istream& read_student();
private:
istream& is;
};
text.cpp
Reading::Reading(istream& is0) :
is(is0) {}
int main()
{
ifstream ifs("text");
if(!ifs) error("can`t open input file");
Readding r(ifs);
r.read_student();
cout << r.group.size();
}
And now it works all correct!!!