reading from a binary file to a 2D array

Hi! My program manages the type of occupants within an office building. Office building has floors 0-4 and 8 offices per floor (A-H); for example, office 4A is on the 5th floor of office A. The program works properly, except for reading the saved binary file to my 2D array. When I input the correct filename, the program loads what is saved in the file but crashes right after. I'm not able to cut down my program enough to allow for a workable program, so I'll give you the functions that I believe have the issues. I have tried everything I know of. Please help. Thank you.
MAIN:
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
#include <iostream>                  // for user I/O
#include <fstream>                   // for file streams
#include <iomanip>                   // for fixed, setw and setprecision
#include <cctype>                    // for toupper()
#include <string>

using namespace std;

// declare enumerated type globally
enum occupantType {EMPTY, LAWYER, PARALEGAL, ASSISTANT};

//global constants
const int FLOOR_ROW = 5; 
const int OFFICE_COL = 8; 
const string BUILDING_FILE = "BUILDING.BIN";

// typedef aliases
typedef int officeBuilding[FLOOR_ROW][OFFICE_COL];

//prototypes
bool readFile(officeBuilding);										
void writeFile(officeBuilding);									
void initializeArray(officeBuilding);							
char mainMenu();														 
int calculateCurrentStat(officeBuilding);							
char convertNumberToLetter(int);									
int convertLetterToNumber(char);									
int optionPrompts(int&, char&, char&);								
int occupantType();													
void displayEmptyOffices(officeBuilding);						
int displayOccupiedOffices(officeBuilding);							
string displayOccupantType(int);									
void newOccupancyMessage(string, int, char, char, officeBuilding);  
//**************************************************************************
int main()
{
	//variables	
	officeBuilding buildingArray;	
	int officeCount = 0;			
	bool results;					
	bool exitLoop = false;			
	bool validatedRequest = true;	
	char choice;					
	int flrNum, 				
		enumType,				
		officeNum,				
		total;						
	char officeLetter;				
	string occupantName;			
    
	results = readFile(buildingArray);	//read BUILDING.BIN file
	total = calculateCurrentStat(buildingArray);  //calculates and returns the individual types 
	
	while(choice != 'D' && choice != 'd')
	{
		
		choice = mainMenu();					
		//if all offices are empty and choice is 1 or 2, display error and re-prompt menu
		if (total == 0)							
		{
			while (choice == '1' || choice == '2')
			{
				cout << endl;
				cout << "*** ERROR! ALL OFFICES ARE EMPTY. TRY AGAIN ***" << endl << endl;
				choice = mainMenu();			
			}
		}
		
		if (choice == 'D' || choice == 'd')	//if choice is 'D' exit the loop
		{
			cout << "Saving data to file BUILDING.BIN" << endl;
			writeFile(buildingArray);		//function to save data to binary file
			return 1;
		}														
				
		cout << endl;
		choice = static_cast<int>(choice);	//change status of choice from char to int
		if(choice == '3')
		{
			//validation functions
			do
			{				
				displayEmptyOffices(buildingArray);					//displays all empty offices
				//displays option 3 questions (floor number, column letter, and occupant type)
				enumType = optionPrompts(flrNum, officeLetter, choice);	 
				officeNum = convertLetterToNumber(officeLetter);	//converts the office letter to a numeric value
			}while (!validatedRequest);	//loops until correct number and office letter are entered
					
			//display functions
			buildingArray[flrNum][officeNum] = enumType;			//adds the occupant type to the 2D array (enumerated type)
			occupantName = displayOccupantType(enumType);			//occupantName becomes the string value of the enumerated type name
			newOccupancyMessage(occupantName, flrNum, officeLetter, choice, buildingArray);  //displays new occupant message
			total =calculateCurrentStat(buildingArray);	//re-calculates and displays all current status in the array
		}
	}	
	cin.ignore();
	return 0;
}
//*****************************************************************************************************************
bool readFile(officeBuilding buildingArray)
{
	//variables
	string filename;
	bool exitLoop = true;
	int floor;
	int office;
	int numCount;
	
	//reading from input binary file for inBuildingData
	ifstream inBuildingData;
	inBuildingData.open(BUILDING_FILE.c_str(), ios::binary | ios::in);
	//prompt
	cout << endl << "Enter data filename: ";
    cin >> filename;

	// verification that file exists 
	if (filename != BUILDING_FILE)
	{
		cout << "Data file: " << filename << ". Does not exist." << endl;
		cout << "Program will continue to main menu." << endl << endl;
		initializeArray(buildingArray);
	}   	
  	else 									// read all data into 2D array
	{  		
			for (int floor= 0; floor < 5; floor++)
			{
				for (int office= 0; office < 8; office++) 
     				inBuildingData.read( reinterpret_cast<char*>(&buildingArray[floor][office]), sizeof(officeBuilding) );
		 	} 
	//		inBuildingData.read( reinterpret_cast<char*>(&buildingArray), 40 * sizeof(officeBuilding) );
		//	if (inBuildingData) // no error state,// so 100 numbers successfully read
		//	numCount = 40;
		//	else // read error occurred
		//	{ 
		//	numCount = (inBuildingData.gcount() / sizeof(int));
		//	inBuildingData.clear(); // reset file stream
		//	}
    }  
         
    inBuildingData.close();  
 
	return exitLoop;
}
//*****************************************************************************************************************
void writeFile(officeBuilding buildingArray)
{
	//writing to the binary file OUT_BUILDING.BIN
	ofstream outBuildingData;
	outBuildingData.open(BUILDING_FILE.c_str(), ios::binary | ios::out);

	//variables	
	int floor = 0, 
	    office = 0; 
	
	if (outBuildingData.is_open())
	{		
		for (int floor; floor < 5; floor++)
		{
			for (int office= 0; office < 8; office++) 
     			outBuildingData.write( reinterpret_cast<char*>(&buildingArray[floor][office]), sizeof(officeBuilding) );
		} 
		cout << "Data has been successfully saved. Goodbye!" << endl;
	}
	else
		cout << "Unable to open file!" << endl;
    		 
    outBuildingData.close(); 
	return;	
}

Last edited on
This is odd:
1
2
3
4
5
6
7
	inBuildingData.open(BUILDING_FILE.c_str(), ios::binary | ios::in);
	//prompt
	cout << endl << "Enter data filename: ";
    cin >> filename;

	// verification that file exists 
	if (filename != BUILDING_FILE)
You open the file and then let the user guess what file name it was?


Since you do not check whether the file could be opened buildingArray remains uninitialized (or whatever it was before the call to readFile(...)) if not. That might lead to a crash.

There are more problems:

Line 54: Since choice is uninitialized it could be anything including 'D' or 'd'.
Line 77: What are you trying to do there? It is actually useless.

Instead of using magic numbers you should use (partially existing) named constants.
Sorry for the confusion. My program is almost 700 lines long, I can see why you would get confused, with so much of the program not included. I wish I could include the whole program.

line 15 is the filename. The user is supposed to already have the filename. It's kind of like a password. If correct filename, than it reads the data to a 2D array and then proceeds to the main menu. If incorrect, than it initializes all offices to empty and proceeds to the main menu.

As far as checking whether the file could be opened, I thought the if-else statement on line 117 did that. if (filename != BUILDING_FILE) --- can't be opened ELSE --- can be opened.

line 54 if user inputs 'D' than goto function writeFile to save data to binary file; afterwards the program will exit.

line 77: This is more of an experiment. I forgot to delete it. It is useless.

I'm not sure what you mean by magic numbers?

Sorry I overlooked this.

Magic number:

https://en.wikipedia.org/wiki/Magic_number_%28programming%29

Here: Unnamed numerical constants

Do you still have problems or is this solved?
1
2
3
4
5
for (int floor= 0; floor < 5; floor++)
{
	for (int office= 0; office < 8; office++) 
     		inBuildingData.read( reinterpret_cast<char*>(&buildingArray[floor][office]), sizeof(officeBuilding) );
}


Not sure if it's happening here, but I'm pretty sure the size of incorrect.

Try replace the whole loop to

inBuildingData.read(reinterpret_cast<char*>(buildingArray), sizeof(buildingArray));
Topic archived. No new replies allowed.