Console Application crashes on exit

As always .. Thanks for trying to help :-)

This application consist of two parts

Part one takes in quarterly sales figures and writes it to a file.
Part two reads that file and displays the sales figures.

The program works just fine except it crashes on exit of part 2
I read something about zero null pointers but can't see where it
could apply in my case

Any help is greatly appreciated.

Here is the code for part 1:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
/*Headers*/
#include <iostream>//needed 4 input/output
#include <iomanip>//needed to round
#include <string>//needed 4 strings
#include <fstream>//needed to write output into a file
using namespace std;//global namespace to avoid name clash
/*Structures*/
struct division
{
	string divisionName;
	double QSales[4];//array of doubles to hold sales figures	
};
//***Function Prototypes
division getValues(const string &name);
void displayValues(division);
//***C++ starting point
int main()
{	
	division d1,d2,d3,d4;//4 instances of structure division
	
	d1 = getValues("North");//name d1 in function call
	d2 = getValues("East");//name d2 in function call
	d3 = getValues("South");//name d3 in function call
	d4 = getValues("West");//name d4 in function call

	displayValues(d1);//function call to see what was typed in
	displayValues(d2);//               "
	displayValues(d3);//               "
	displayValues(d4);//               "

	ofstream output;//start ofstream with the name output
	output.open("salesReport.dat", ios::binary | ios::out);//open file or create if not exist
	//use binary format and overwrite existing data 
	output.write(reinterpret_cast<char *>(&d1), sizeof(d1));//write d1 to file 
	output.write(reinterpret_cast<char *>(&d2), sizeof(d2));//write d2 to file
	output.write(reinterpret_cast<char *>(&d3), sizeof(d3));//write d to file
	output.write(reinterpret_cast<char *>(&d4), sizeof(d4));//write d4 to file
	output.close();

	system("PAUSE");//press any key
	return 0;//exit
}
division getValues(const string &name)//function to fill sales array
{
	division div;
	div.divisionName = name;//temp variable for division names

	for (unsigned i=0; i < 4; ++i)//loop through all divisions and quarters
	{
		cout << name << endl;//put out division name
		cout << "Enter sales for quarter " << i+1 << ":\n "<<endl;//prompt for sales figures
		cin >> div.QSales[i];//take in sales figures
	}
	return div;//return values
}
void displayValues(division d)//display function to test what was enterd
{
	cout << "Division Name: " << d.divisionName<<endl;
	cout << "First quarter sales: " << d.QSales[0]<<endl;
	cout << "Second quarter sales: " << d.QSales[1]<<endl;
	cout << "Third quarter sales: " << d.QSales[2]<<endl;
	cout << "Fourth quarter sales: " << d.QSales[3]<<endl;
	cout << endl;
}


and here is the code for part 2:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
/*Headers*/
#include <iostream>//needed 4 input/output
#include <iomanip>//needed to round
#include <string>//needed 4 strings
#include <fstream>//needed to write output into a file
using namespace std;//global namespace to avoid name clash
/*Structures*/
struct division
{
	string divisionName;
	double QSales[4];//array of doubles to hold sales figures		
};
//***Function Prototypes
void displayValues(division);
//***C++ starting point
int main()
{	
	division d1,d2,d3,d4;//4 instances of structure division
	//open data file in binary format
	ifstream input("salesReport.dat",ios::binary |  ios::in);
	//read in data to be displayed
	input.read(reinterpret_cast<char *>(&d1), sizeof(d1));
	input.read(reinterpret_cast<char *>(&d2), sizeof(d2));
	input.read(reinterpret_cast<char *>(&d3), sizeof(d3));
	input.read(reinterpret_cast<char *>(&d4), sizeof(d4));
	input.close();
	//calls for display function 
	displayValues(d1);
	displayValues(d2);
	displayValues(d3);
	displayValues(d4);

	system("PAUSE");//press any key
	return 0;//exit
}
void displayValues(division d)//display function with structure type and argument
{
	cout << fixed << setprecision(2);//format output for money(2 digits after decimal)
	cout << "Division Name: " << d.divisionName<<endl;//display division name
	cout << "First quarter sales: $" << d.QSales[0]<<endl;//display sales figures for 1. quarter
	cout << "Second quarter sales: $" << d.QSales[1]<<endl;//display sales figures for 2. quarter
	cout << "Third quarter sales: $" << d.QSales[2]<<endl;//display sales figures for 3. quarter
	cout << "Fourth quarter sales: $" << d.QSales[3]<<endl;//display sales figures for 4. quarter
	cout << endl;//separator
}
You are trying to write and read and string as binary data, which won't work because a string is not a "plain-old data" type. For a program like this, you're better off just writing the data as text, though you could modify your saving code to save/load a char* to and from a string.
Thanks Zhuge for pointing that out.

I'm trying to adjust the code but it doesn't really work.

I changed the string to an char array like so:
1
2
3
4
5
struct division
{
	char divisionName[5];// 
	double QSales[4];//array of doubles to hold sales figures	
};

and the naming on lines 21 - 24 to:
1
2
3
4
strcpy(d1.divisionName, "North");//name d1 
strcpy(d2.divisionName, "East");//name d2 
strcpy(d3.divisionName, "South");//name d3 
strcpy(d4.divisionName, "West");//name d4  

but my getValues function doesn't like it
1
2
3
4
5
6
7
8
9
10
11
12
13
division getValues(const char &name)//function to fill sales array
{
	division div;
	div.divisionName = name;//temp variable for division names

	for (unsigned i=0; i < 4; ++i)//loop through all divisions and quarters
	{
		cout << i<<". division" << endl;//put out division name
		cout << "Enter sales for quarter " << i+1 << ":\n "<<endl;//prompt for sales figures
		cin >> div.QSales[i];//take in sales figures
	}
	return div;//return values
}


my changes broke the line
 
div.divisionName = name;//temp variable for division names 

I'm getting lost ... I'm still a greenhorn :-(
char divisionName[5];
Remember a character string such as "North" has a null terminator, so it requires one extra byte. divisionName needs to be at least 6 characters in length - though that sounds a bit short for a typical name. 20 to 30 characters might be more usual.

div.divisionName = name; - use strcpy().

Also be aware of strncpy() which is safer.
Thank you Chervil

I have to reconsider my approach, since I couldn't get it to work by replacing the string with a char array.
Topic archived. No new replies allowed.