CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 4 of 4

Thread: writing and reading to a binary file

  1. #1
    Join Date
    Jun 2015
    Posts
    7

    writing and reading to a binary file

    Hello,
    I have a program that keeps track of the amount and type of residence in an office building. The office building has 5 floors and 8 offices within each floor (40 total offices) I am using a 2D array called officeBuilding, and an enumerated type called occupantType. The program works fine but I can't seem to read/ write to my binary file. The following is my program. functions readFile and writeFile and my read/write to binary file. Any help would be appreciated. Thank you.

    Code:
    #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
    void display_header();												//header function
    bool readFile(ifstream&, officeBuilding, int&);						//function reads the data from a binary file to a 2D array
    void writeFile(ofstream&, officeBuilding, int, int, int);			//function writes data from a 2D array to a binary file
    void initializeArray(officeBuilding);								//intializes a 2D array to EMPTY for the first time running
    char mainMenu();													//displays the main menu and returns the users choice
    int menuValidation(char);											//validates the users choice from the main menu
    int validateNum(int);												//validates the users input for floor number and returns valid number
    char validateLetter(char);											//validates the users input for column letter and returns valid letter
    bool validateOriginalRequest(int, int, int, char, officeBuilding);	//validates the original request 
    int calculateCurrentStat(officeBuilding, int);						//calculates the total number of occupant types and individual types
    char convertNumberToLetter(int);									//converts an integer to a char(letter). Column number to letter
    int convertLetterToNumber(char);									//converts an char(letter) to a integer. letter number to column
    int optionPrompts(int&, char&, char&);										//displays the prompts for floor number, office letter, and occupant type
    int occupantType();													//displays the prompt for occupant type and returns to optionPrompts function
    void displayEmptyOffices(officeBuilding);							//display all empty offices in the 2D array (format: 4A). Occupied is display blank
    int displayOccupiedOffices(officeBuilding);							//display all occupied offices in the 2D array (format: 4A). Empty is displayed blank
    string displayOccupantType(int);									//converts occupant type(int) to the string value of that type and returns that value
    void newOccupancyMessage(string, int, char, char, officeBuilding);  //if users inputs an option that isn't valid, than output an error message.
    //**************************************************************************
    int main()
    {
    	//variables	
    	officeBuilding buildingArray;	//2D array
    	int officeCount = 0;			//total count for occupied offices in the binary file
    	bool results;					//readFile return
    	bool exitLoop = false;			//exits the main loop if true
    	bool validatedRequest = true;	//if true, the original request is valid
    	char choice;					//return value for user input from menu options
    	int numLawyer = 0, 				//individual counters for Lawyer
    		numParalegal = 0, 			//individual counters for paralegal
    		numAssistant = 0; 			//individual counters for assisant
    	int flrNum, 					//stores the floor number 
    		enumType,					//stores the occupant type (numeric)
    		officeNum,					//stores the office number
    		total;						//stores the total amount of occupants in the 2D array
    	char officeLetter;				//stores the office letter
    	string occupantName;			//stores the string name of enumType
        
    	//reading from input binary file for inBuildingData
    	ifstream inBuildingData;
    	inBuildingData.open(BUILDING_FILE.c_str(), ios::binary | ios::in);  
    	//writing to the text file OUT_BUILDING.BIN
    	ofstream outBuildingData;
    	outBuildingData.open(BUILDING_FILE.c_str(), ios::binary | ios::out);
    	
    	display_header();						//display header
    	initializeArray(buildingArray);			//initalize array to EMPTY
    	results = readFile(inBuildingData, buildingArray, officeCount);	//read BUILDING.BIN file
    	total = calculateCurrentStat(buildingArray, enumType);			//calculates and returns the individual types 
    	
    	while(choice != 'D' && choice != 'd')
    	{
    		
    		choice = mainMenu();					//returns the verified input from main menu
    		choice = menuValidation(choice);
    		
    		if (total == 0)							//if all offices are empty and choice is 1 or 2, display error and re-prompt menu
    		{
    			while (choice == '1' || choice == '2')
    			{
    				cout << endl;
    				cout << "*** ERROR! ALL OFFICES ARE EMPTY. TRY AGAIN ***" << endl << endl;
    				choice = mainMenu();			
    				choice = menuValidation(choice);
    			}
    		}
    		
    		if (choice == 'D' || choice == 'd')		//if choice is 'D' exit the loop
    		{
    			cout << "Saving data to file BUILDING.BIN" << endl;
    			writeFile(outBuildingData, buildingArray, flrNum, officeNum, enumType);	//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 == '1' || choice == '2')										
    		{			
    			//validation functions
    			do
    			{
    				displayOccupiedOffices(buildingArray);				//displays all occupied offices
    				enumType = optionPrompts(flrNum, officeLetter, choice);		//displays option 3 questions (floor number, column letter, and occupant type)
    				officeNum = convertLetterToNumber(officeLetter);	//converts the office letter to a numeric value
    				validatedRequest = validateOriginalRequest(flrNum, officeNum, enumType, choice, buildingArray);
    			}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, enumType);	//re-calculates and displays all current status in the array			
    		}
    		else
    		{
    			//validation functions
    			do
    			{				
    				displayEmptyOffices(buildingArray);					//displays all empty offices
    				enumType = optionPrompts(flrNum, officeLetter, choice);		//displays option 3 questions (floor number, column letter, and occupant type)
    				officeNum = convertLetterToNumber(officeLetter);	//converts the office letter to a numeric value
    				validatedRequest = validateOriginalRequest(flrNum, officeNum, enumType, choice, buildingArray);	
    			}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, enumType);	//re-calculates and displays all current status in the array
    		}
    	}	
    	cin.ignore();
    	return 0;
    }
    //*************************************************************************
    //*************************************************************************
    void display_header()
    {
    	cout << endl;
    	cout << "######################################################################\n"
    		    "This program will maintain data about the occupant type of employees\n"
    	        "in each office in the building. The data will be stored in a 2D array.\n"
    	        "######################################################################" << endl;
    	cout << endl << endl;
    }
    //*****************************************************************************************************************
    bool readFile(ifstream& inBuildingData, officeBuilding buildingArray, int& cnt)
    {
    	//variables
    	string filename;
    	bool exitLoop = true;
    	int tempFlr, tempOffice, tempType;
    	int count = 0;
    	int numCount ;
    	
    	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);
    		//exitLoop = false;
    	}
    	// calling different functions to compute and display the results   	
      	else 									// read all data into 2D array
    	{  
    		//while(inBuildingData)
    	//	{
    			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
    			}
    
        }  // end while
             
         	inBuildingData.close();  
     // }  // end else
    	return exitLoop;
    }
    //*****************************************************************************************************************
    void writeFile(ofstream& outBuildingData, officeBuilding buildingArray, int flr, int col, int type)
    {
    	
    	//variables	
    	int floor, office; 
    	
    	if (outBuildingData.is_open())
    	{
    		
    		for (int floor= 0; floor < 5; floor++)
    		{
    			for (int office= 0; office < 8; office++) 
         			outBuildingData.write( reinterpret_cast<char*>(&buildingArray[floor][office]), sizeof(officeBuilding) );
    		 } 
    
         	//outBuildingData.write(reinterpret_cast<char*>(&buildingArray), sizeof(officeBuilding));
    
    	}
    	else
    		cout << "Unable to open file!" << endl;
        		 
        outBuildingData.close(); 
    	return;
    	
    }
    //*****************************************************************************************************************
    void initializeArray(officeBuilding buildingArray)
    {
    	//variables	
    	int floor, office; 
    	
    	for (floor = 0; floor < FLOOR_ROW; floor++) 
        	for (office = 0; office < OFFICE_COL; office++) 
        		buildingArray[floor][office] = EMPTY;
          		 
    	return;
    }
    //*****************************************************************************************************************
    char mainMenu()
    {
    	//variables
    	char choice;	
    	
    	cout << endl;
    	cout << "**************************************************" << endl;
    	cout << "\t\t\tMain Menu" << endl<< endl;
    	cout << "\t1 - Change office from occupied to empty" << endl;
    	cout << "\t2 - Modify office occupant type" << endl;
    	cout << "\t3 - Change office from empty to occupied" << endl;
    	cout << "\tD - Done making modifications" << endl << endl;
    	cout << "***************************************************" << endl;
    	
    	cout << " Please enter menu choice (1, 2, 3, D): ";
    	cin >> choice;
    		
    	return choice;
    }
    //************************************************************************************************
    int menuValidation(char selection)
    {
    	while(selection) 
        {
            if( selection == 'D' || selection == 'd' ) 
    			return selection; 
    
            else if( selection > '0' && selection < '4' ) 
    			return selection; // if input is from 1-3
    
            else 
            {
            	cout << "ERROR! an invalid choice was entered. Enter new choice: " ; // bad input
    			cin >> selection;
    		}
        }
        return selection;
    }
    //************************************************************************************************
    int validateNum(int number)
    {
    	while(number)
    	{
    		if(number >= 0 && number <= 4)
    			return number;
    		else 
    		{
    			cout << "ERROR! an invalid entry was entered. Enter new number: " ; // bad input
    			cin >> number;
    		}
    	}
    	return number;
    }
    //************************************************************************************************
    char validateLetter(char letter)
    {
    	while(letter)
    	{
    		if(letter >= 'A' && letter < 'I')
    			return letter;
    		else
    		{
    			cout << "ERROR! an invalid entry was entered. Enter new letter: " ; // bad input
    			cin >> letter;
    			letter = toupper(letter);
    		} 
    	}
    	return letter;
    }
    //*****************************************************************************************************************
    bool validateOriginalRequest(int flr, int office, int type, char choice, officeBuilding buildingArray)
    {
    	bool verify;
    	
    	if(choice == '1' || choice == '2')
    	{
    		if (buildingArray[flr][office] != EMPTY)
    			verify = true;
    		else
    		{
    			cout << endl;
    			cout << "*** ERROR! Office is already empty. Please try again. ***" << endl;
    			verify = false;
    		}
    	}
    	else 
    	{
    		if (buildingArray[flr][office] == EMPTY)
    			verify = true;
    		else
    		{
    			cout << endl;
    			cout << "*** ERROR! Office is already occupied. Please try again. ***" << endl;
    			verify = false;
    		}	
    	}
    	return verify;
    }
    //*****************************************************************************************************************
    int calculateCurrentStat(officeBuilding buildingArray, int type)
    {
    	//variables
    	int row, col; 
    	int total = 0;
    	int cnt1 = 0,
    		cnt2 = 0,
    		cnt3 = 0;
    	
    	for (int row = 0; row < FLOOR_ROW; row++) 
          for (int col = 0; col < OFFICE_COL; col++)
          { 
        	  if (buildingArray[row][col] == LAWYER)
        	  	cnt1++;
        	  if (buildingArray[row][col] == PARALEGAL)
        	  	cnt2++;
        	  if (buildingArray[row][col] == ASSISTANT)
        	  	cnt3++;
    	  }
    	  total = cnt1 + cnt2 + cnt3;
    	  	
    	cout << endl; 
    	cout << "**************************************************" << endl;
    	cout << "  Current Office Status (40 total offices):  " << endl;
    	cout << setw(9) << cnt1 << " lawyers" << endl;
    	cout << setw(9) << cnt2 << " paralegals" << endl;
    	cout << setw(9) << cnt3 << " assistants" << endl;
    	cout << setw(9) << "---" << endl;
    	cout << setw(9) << total << " occupied offices" << endl;
    	cout << "***************************************************" <<endl;  
    	return total;
    }
    //*****************************************************************************************************************
    int optionPrompts(int& flr, char& office, char& option)
    {
    	//variables
    	int type;
    	
    	cout << "Enter the floor number (0-4): ";
    	cin >> flr;
    	validateNum(flr);						//validate flr
    	
    	cout << "Enter the office letter (A-H): ";
    	cin >> office;
    	office = toupper(office);
    	validateLetter(office);				   //validate office letter
    	
    	if (option == '1')
    		return type = 0;
    	
    	type = occupantType();	
    	
    	return type;
    }
    //************************************************************************************************
    int occupantType()
    {
    	//variables
    	int type;
    	
    	cout << "Enter the occupant type number" << endl;
        cout << "(0- Empty, 1- Lawyer, 2- Paralegal, or 3- Assistant): ";
    	cin >> type;
    	
    	if(type == 0)
    		type = EMPTY;
    	if(type == 1)
    		type = LAWYER;
    	if(type == 2)
    		type = PARALEGAL;
    	if(type == 3)
    		type = ASSISTANT;
    		
    	return type;
    }
    //************************************************************************************************
    char convertNumberToLetter(int column)
    {
    	//variables
    	
    	switch (column)
    	{
    		case 0:
    			column = 'A';
    			break;
    		case 1:
    			column = 'B';
    			break;
    		case 2:
    			column = 'C';
    			break;
    		case 3:
    			column = 'D';
    			break;
    		case 4:
    			column = 'E';
    			break;
    		case 5:
    			column = 'F';
    			break;
    		case 6:
    			column = 'G';
    			break;
    		default:
    			column = 'H';
    	}
    	return column;
    }
    //************************************************************************************************
    int convertLetterToNumber(char column)
    {
    	//variables
    	
    	switch (column)
    	{
    		case 'A':
    			column = 0;
    			break;
    		case 'B':
    			column = 1;
    			break;
    		case 'C':
    			column = 2;
    			break;
    		case 'D':
    			column = 3;
    			break;
    		case 'E':
    			column = 4;
    			break;
    		case 'F':
    			column = 5;
    			break;
    		case 'G':
    			column = 6;
    			break;
    		default:
    			column = 7;
    	}
    	return column;
    }
    //************************************************************************************************
    void displayEmptyOffices(officeBuilding buildingArray)
    {
    	//variables
    	int row, col;
    
    	for (int row = FLOOR_ROW -1; row >= 0; row--)	//for loop to display office floor and column letter
    	{
    		for (int col = 0; col < OFFICE_COL; col++)	
    		{
    			if (buildingArray[row][col] == EMPTY)						//if array is EMPTY display row and letter
    				cout << setw(7) << row << convertNumberToLetter(col) << setw(7); 
    			else														//if not EMPTY display nothing
    				cout << setw(7) << " " << " " << setw(7); 					
    		}     		
          	cout << endl;												 
    	}
    }
    //*****************************************************************************************************************
    int displayOccupiedOffices(officeBuilding buildingArray)
    {
    	//variables
    	int row, col;
    
    	for (int row = FLOOR_ROW -1; row >= 0; row--)	//for loop to display office floor and column letter
    	{
    		for (int col = 0; col < OFFICE_COL; col++)	
    		{
    			if (buildingArray[row][col] == EMPTY)						//if not EMPTY display nothing
    				cout << setw(7) << " " << " " << setw(7);
    			else														//if occupied display row and letter
    				cout << setw(7) << row << convertNumberToLetter(col) << setw(7); 					
    		}     		
          	cout << endl;												 
    	}
    }
    //************************************************************************************************
    
    string displayOccupantType(int name) 
    {
    	//variables
    	string select;
    	
    	switch (name)
    	{
    		case 0:
    			select = "Empty";
    			break;
    		case 1:
    			select = "Lawyer";
    			break;
    		case 2:
    			select = "Paralegal";
    			break;
    		case 3:
    			select = "Assistant";
    			break;
    		default:
    			select = "UNKNOWN";
    			
    	}
    	return select;
    }
    //*****************************************************************************************************************
    void newOccupancyMessage(string name, int flr, char col, char option, officeBuilding buildingArray)
    {
    	if (option == '1')
    	{
    		cout << endl;
    		cout << "Office " << flr << col << " is now empty." << endl;
    	}
    	else if(option == '2')
    	{
    		cout << endl;
    		cout << "Occupant in office " << flr << col << " has been changed to " << name << endl;
    	}
    	else
    	{
    		cout << endl;
    		cout << "Office " << flr << col << " is now being occupied by " << name << endl;
    	}
    }

  2. #2
    2kaud's Avatar
    2kaud is online now Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,189

    Re: writing and reading to a binary file

    Code:
    bool readFile(ifstream& inBuildingData, officeBuilding buildingArray, int& cnt)
    buildingArray is passed by value so changes made during the function are not present in the calling function. Consider
    Code:
    bool readFile(ifstream& inBuildingData, officeBuilding& buildingArray, int& cnt)
    which passes buildingArray by ref so that changes to buildingArray during the function are available to the calling function.

    The same point also applies to several other functions which alter argument data (eg initializeArray()).
    Last edited by 2kaud; October 12th, 2015 at 09:02 AM.
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++17 Compiler: Microsoft VS2019 (16.7.0)

  3. #3
    Join Date
    Jun 2015
    Posts
    7

    Re: writing and reading to a binary file

    Thank you for your comment. It makes sense to make the array passed by reference. I went ahead and changed those functions, but it still isn't saving. In main, the line with...
    Code:
    initializeArray(buildingArray);
    This function initializes the array all to empty. When I type in the correct file name, it brings up the initial array as all empty. On the other hand, when I comment out that line and run it again, it loads up the initial array with numerous offices as occupied. This also confuses me. If you could give me some details on where my program is messed up, I would greatly appreciate it. Thank you.

  4. #4
    2kaud's Avatar
    2kaud is online now Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,189

    Re: writing and reading to a binary file

    On the other hand, when I comment out that line and run it again, it loads up the initial array with numerous offices as occupied. This also confuses me.
    buildingArray is of type int [FLOOR_ROW][OFFICE_COL]. In c++ arrays are not initialised before use so the contents of the array after its definition are unknown and will likely vary each time the program is used. That is why in c++ variables should be initialised before use.

    In order to determine the issue with saving you should use the debugger to trace through the program to see where it is deviating from that expected. If you haven't used the debugger before now is the time to start to become familiar with it.
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++17 Compiler: Microsoft VS2019 (16.7.0)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  


Windows Mobile Development Center


Click Here to Expand Forum to Full Width




On-Demand Webinars (sponsored)