Click here to Skip to main content
15,845,744 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
please program crashes at the very end of my program after the system("pause") line.

What I have tried:

#include<iostream>
#include<fstream>
#include<string>
#include<vector>
#include<iterator>
using namespace std;
void eatline() { while(cin.get()!= '\n')continue;
}

 struct sal {
	string x;
	int y;
 };
void writedata(string & name, int x)
{
	 fstream file;
	 file.open("info.dat", ios::out | ios::app | ios::binary);
	if (file.is_open())
	{
		sal l = {
			name,
			x
		};
		file.write(reinterpret_cast<char *>(&l), sizeof(l));
		file.close();
	}
}
void red(vector<sal> & p)
{
	vector<sal>::iterator r = p.begin();
	for (r=p.begin();r!=p.end();r++)
		cout << (*r).x << " " << (*r).y << endl;
}
int main()
{
	long idea;
	string name1;
	cout << "Enter the name of the pupil" << endl;
	while (getline(cin, name1) && name1[0]!='\0')
	{
		cout << "Enter the amount of school fees paid\n";
		cin >> idea;
		eatline();
		writedata(name1, idea);
		cout << "Enter the name of the next pupil(press enter to quit)\n" << endl;
	}
	
	cout << "These are the names and school fess of the pupils you entered\n";
	ifstream fin;
	fin.open("info.dat",ios::in|ios::binary);
	sal k;
	vector<sal>j;
	while (fin.read(reinterpret_cast<char *>(&k), sizeof k))
	{
		j.push_back(k);
	}
	fin.close();
	red(j);
	system("pause");
	return 0;
}
Posted
Updated 29-Mar-17 0:47am
v3

You are writing and reading dynamic objects (std::string) to / from a file without handling the dynamic data. This won't work.

The std::string object does not contain the string itself but only a pointer to allocated memory. Depening on the target build (32 or 64 bit), sizeof(std::string) will be 4 or 8 (and sizeof(sal) will be 8 or 16).

What you are doing is writing these pointers to a file and reading them back again. But then the pointers are not pointing to valid memory locations anymore and you get an access violation.

If you want to store such data in a file, you have to write the size (string length) first and then store the string content. Upon reading, read the length, provide a buffer with that length, read the string into that buffer, and copy it to a std::string.

Untested example:
C++
void writeSal(fstream & file, const sal & s)
{
    // Get the length
    size_t len = s.name.length();
    // Write length
    file.write(reinterpret_cast<const char *>(&len), sizeof(len));
    // Write string content
    file.write(s.name.c_str(), len);
    // Write y
    file.write(reinterpret_cast<const char *>(&s.y), sizeof(s.y));
}

void readSal(fstream & file, sal & s)
{
    size_t len;
    file.read(reinterpret_cast<char *>(&len), sizeof(len));
    char *buf = new char[len + 1];
    file.read(buf, len);
    buf[len] = '\0';
    s.name = buf;
    delete [] buf;
    file.read(reinterpret_cast<char *>(&s.y), sizeof(s.y));
}
 
Share this answer
 
It may be urgent to you, but it isn't to us. All that your stressing the urgency does is to make us think you have left it too late, and want us to do it for you. This annoys some people, and can slow a response.

Then you just dump your code on us, and can't even be bothered to format it: you aren't making any friends here, you know...

We can't help you here: we have no access to the info.dat file you are reading and that contains the data that is causing you a problem.

So, its going to be up to you.
Put a breakpoint on the first line in the function, and run your code through the debugger. Then look at your code, and at your data and work out what should happen manually. Then single step each line checking that what you expected to happen is exactly what did. When it isn't, that's when you have a problem, and you can back-track (or run it again and look more closely) to find out why.

Sorry, but we can't do that for you - time for you to learn a new (and very, very useful) skill: debugging!
 
Share this answer
 
Comments
Osikwemen 26-Mar-17 7:45am    
well sorry about the formatting issh, really don't know how to format code on the site but will improve as time goes on. for the program the debugger shows the problem is at the return 0 line. so I don't know the cause of that.
[no name] 26-Mar-17 7:55am    
The function is declared 'void writedata(string & name, int x)'. Void means that you don't return a value at all. Just delete the return 0; line and try again. I only wonder why the compiler does accept this at all.
Osikwemen 1-Apr-17 3:45am    
The declaration of void is not for the main function so it doesn't affect it
[no name] 1-Apr-17 4:02am    
It would have been too easy that way. I must have looked at the wrong function.
As Jochen Arndt said, you are not saving the string correctly, and, as a result, it isn't read correctly either. More importantly, at the end of the program, the destructor of that string is called, assuming a correctly initialized string - and at that point it crashes.

Your problem starts with reinterpret_cast : my advice on that is:
1. as a general rule, never cast anything to a different type. If types don't match, then the most likely reason is that (a) your variable(s) weren't defined with the correct type to start with, or (b) the variable or function that you try to use with your variable wasn't defined with the right type. Try to fix that, if possible.
2. If you must cast, use const_cast, dynamic_cast, or static_cast - whichever is appropriate.
3. If neither of the above works, rewrite your program to avoid the cast altogether, or at worst can get away with case 2. above.

Using reinterpret_cast is a surrender: you give up on static typing and all the advantages that come with it, replacing it with managing bytestreams. This can work, but only if you fully understand the format of the actual data, and have full control of it's management. In this case, you have neither.

Based on this, my suggestion is to solve that problem according to case 3. above: rewrite your program, i. e. the parts that deal with writing and reading the data. There are other functions that are fully capable of writing and reading std::string objects, so do use those, not binary output functions:

C++
void write_sal(fstream& f, const sal& s) {
   f << s.name << endl << s.y <<endl;
}
sal read_sal(fstream& f) {
   sal s;
   f >> s.name >> s.y;
   return s;
}


There. No casting required. I haven't tested it: the additional endl that I added to the output may not be needed, you might need to test that.

P.S.:
The streaming operator operator>>(std::basic_string&) will only read up to the first whitespace. So, if your input might contain whitespace characters, use the function std::basic_istream::getline() instead:
C++
sal read_sal(fstream& f) {
   sal s;
   std::getline(f, s.name);
   f >> s.y;
   return s;
}

Now, if your sal object is { "What do you get if you multiply six by nine?" , 42 }, then the first version will only read { "What", 0 } , whereas the above modifiation will correctly read the full text and number.

P.P.S.:
I should mention that mixing different methods to read or write from/to streams can cause problems, because they may use different methods of synchronization. Therefore, to be safe, it would be better to change that last read function like this:
C++
sal read_sal(fstream& f) {
   sal s;
   std::getline(f, s.name);
   std::string sy;
   std::getline(f, sy);
   s.y = std::stoi(sy);
   return s;
}

See std::getline - cppreference.com[^]
 
Share this answer
 
v4

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900