The problem I'm having is with overloading the >> operator so that I could read data from a file directly into a class's member data. Everytime I run through the program, it just crashes. when I look through the debugger, it brings me to some page of crazy code.

So far, I've managed to make everything in my program work except just that.

I have no clue why this segment of code won't work.

Atlas::Atlas(char * file)
{
	ifstream inputFile(file);
	db = new Database(file);

	inputFile >> *db; // gives me problems :\
//	db->fillDatabase();
	inputFile.close();
}

Here's the complete code:

#include <iostream>
#include <cstring>
#include <fstream>

#include "state.h"
#include "database.h"
#include "formatheader.h"
#include "atlas.h"

using std::cout;
using std::cin;
using std::ostream;

//////////////////////////  program start  ///////////////////////////////////////
int main(void)
{
	const int max = 81;
	char filename[max];
	char stateInput[max];
	char name[max];
	char cap[max];
	int year, popRank;
	int index;
	Atlas * pA;

	//////// set up Atlas object and print its data ////////
	cout << "Enter filename or hit ENTER: ";
	cin.getline(filename, max);
	
	if ( strlen(filename) == 0)
		pA = new Atlas;
	else
		pA = new Atlas(filename);

	cout << *pA;  // print information of all states in the database

	////// create a state to replace an existing state in the database //////
	cout << "Enter new information for state, comma separated: ";
	cin.getline(stateInput, max);
		
	Format::parse(stateInput, name, &year, cap, &popRank);  // new Format function
	State s(name, year, cap, popRank);
	cout << "This is the new information for the state: ";
	cout << s;
	
	cout << "Enter index of state to be replaced: ";
	cin >> index;
	cin.ignore(100, '\n');

	pA->replace(index, s);
	cout << *pA;

	// add code you already have in lab 3 to search in the database for 
	// the new state and print it
	// you should print the new state in the database, not the state s above
	cout << "Enter state name or press ENTER to stop: ";
	cin.getline(stateInput, max);

	while ( stateInput[0] )
	{
		const State foundState = pA->getState( Format::fixString(stateInput) );

		if ( strcmp(foundState.getName(), "none") == 0 &&
			 strcmp(foundState.getCap(), "none") == 0 )
			cout << stateInput << " was not found!\n";
		else
		{
			cout << "State: " << Format::upperCase(foundState.getName()) << '\n';
			cout << "Year: " << foundState.getYear() << '\n';
			cout << "Capital: " << Format::upperCase(foundState.getCap()) << '\n';
			cout << "Population Ranking: " << foundState.getPopRank() << '\n';
		}
		cout << "\nEnter a state name or press ENTER to stop>: ";
		cin.getline(stateInput, max);
	}

	cout << "Have a nice day!\n";
	
	return 0;
}

#ifndef	DATABASE_H
#define DATABASE_H

#include "state.h"

using std::ifstream;

class Database
{
public:
	Database(char * file = "states.txt");
	Database(const Database & arg);
	~Database() { delete [] list; delete [] filename; }
	int getCount() { return count; }
	State * getList() { return list; }
	void deleteDatabase ();
	void fillDatabase ();
	friend ifstream &operator>>(ifstream &in, Database & obj);
private:
	State * list;		// array of states
	int count;			// total count of states
	char * filename;	// input filename
};

#endif

#include <iostream>
#include <cstring>
#include <fstream>

#include "state.h"
#include "database.h"

using std::cout;
using std::cin;
using std::ifstream;

//////////////////////  Database functions  ////////////////////////////////
// Constructor
Database::Database(char * file) : count(5)
{
	// open input file and check for open success
	if ( ifstream inputFile(file) )
	{
		// allocate memory for Database struct and check for success
		// allocate memory for filename field and initializes with filename
		if ( filename = new char[strlen( file ) + 1] )
			strcpy( filename, file );
		else
			cout << "Not enough memory!" << '\n';
		
		// initialize list field by allocating memory for array of 10 states 
		// and check for success
		if ( list = new State[5] ) {}			
		else
			cout << "Not enough memory!" << '\n';

		// close input file
		inputFile.close();
	}
	else
	{
		cout << "File not found!" << '\n';
		exit(0);
	}
}

Database::Database(const Database & arg) : count(arg.count)
{
	if ( filename = new char[strlen( arg.filename ) + 1] )
		strcpy( filename, arg.filename );
	else
		cout << "Not enough memory!\n";

	if ( list = new State[count])
		for ( int cnt = 0; cnt < count; cnt++)
			list[cnt] = arg.list[cnt];
	else
		cout << "Not enough memory!\n";
}

//fillDatabase - reads info from file and stores in array of State structs
//input: pointer to Database struct
//return: nothing
void Database::fillDatabase ()
{
	char name[80];	// temp variables
	int year;
	char cap[80];	// input data
	int popRank;

	char array[100]; // temporary storage for file input

	// open file from filename field of db
	// don't need to check for file open success because initDatabase already checked
	ifstream inputFile( filename );
	
	// loop through all the states
	for ( int cnt = 0; cnt < count; cnt++ )
	{
	    // read and parse one line of file into 4 input data fields
		if ( !inputFile.eof() )
		{
			inputFile.getline( array, 100 );

			if ( sscanf( array, "%[^,], %d, %[^,], %d",	name, &year, cap, 
				&popRank ) == 4 )
			{
				// if tempState is created successfully from the 4 input data
				State tempState(name, year, cap, popRank);
				list[cnt] = tempState;
			}
			else
			{
				cout << "Error with file!" << '\n';
				return;
			}
		}
	}
 
 	// close file
 	inputFile.close();
}

ifstream &operator>>(ifstream &in, Database & obj)
{
	char name[80];
	int year;
	char cap[80];
	int popRank;

	char array[100];
	ifstream inputFile( in );

	for (int cnt = 0; cnt < obj.count; cnt++)
	{
		if ( !inputFile.eof() )
		{
			inputFile.getline( array, 100 );

			if ( sscanf( array, "%[^,], %d, %[^,], %d",	name, &year, cap, 
				&popRank ) == 4 )
			{
				State tempState(name, year, cap, popRank);
				obj.list[cnt] = tempState;
			}
			else
				cout << "Error with file!" << '\n';
		}
	}

	inputFile.close();

	return in;
}

#ifndef STATE_H
#define STATE_H

#include <iostream>

using std::ostream;

class State
{
public:
	State(char * tempName = "none", int tempYear = 0, char * tempCap = "none", int tempPopRank = 0);
	State( const State & arg );
	~State() { delete [] name; delete [] cap; }
	int findState(char * stateName) const;
	char * getName() const { return name; }
	int getYear() const { return year; }
	char * getCap() const { return cap; }
	int getPopRank() const { return popRank; }
	void changeName(char * tempName);
	void changeCap(char * tempCap);
	void changeYear(int tempYear) { year = tempYear; }
	void changePopRank(int tempPopRank) { popRank = tempPopRank; }
	// overloaded operators
	friend ostream &operator<<(ostream &out, State const & obj);
	State & operator=(const State & tempState);
private:
	char * name;	// state name
	int year;		// year of entry into the union
	char * cap;		// state capital
	int popRank;	// population ranking
};

#endif

#include <iostream>
#include <cstring>

#include "state.h"

using std::cout;
using std::cin;

State::State(char * tempName, int tempYear, char * tempCap, int tempPopRank) : year(tempYear), popRank(tempPopRank)
{
	char * stateName;
	char * capital;
   // if memory allocation is successful, store name
	if ( stateName = new char[strlen( tempName ) + 1 ] )
	{
		strcpy( stateName, tempName );
  		name = stateName;
	}
	else
	   cout << "Not enough memory!" << '\n';
   
	// if memory allocation is successful, store capital
	if ( capital = new char[strlen( tempCap ) + 1 ] )
	{
		strcpy( capital, tempCap );
		cap = capital;
	}
	else
		cout << "Not enough memory!" << '\n';
}

State::State( const State & arg ) : year(arg.year), popRank(arg.popRank)
{
	name = new char[strlen(arg.name) + 1];
	strcpy(name, arg.name);

	cap = new char[strlen(arg.cap) + 1];
	strcpy(cap, arg.cap);
}

////////////////////////  State functions  //////////////////////////////
int State::findState(char * stateName) const
{
	if ( strcmp( stateName, name ) == 0 )
		return 1;
	else
		return 0;
}

void State::changeName(char * tempName)
{
	name = new char[strlen(tempName) + 1];
	strcpy( name, tempName );
}

void State::changeCap(char * tempCap)
{
	cap = new char[strlen(tempCap) + 1];
	strcpy( cap, tempCap );
}

State &State::operator=(const State & tempState)
{
	name = new char[strlen(tempState.name) + 1];
	strcpy ( name, tempState.name );

	year = tempState.year;

	cap = new char[strlen(tempState.cap) + 1];
	strcpy( cap, tempState.cap );

	popRank = tempState.popRank;
	
	return *this;
}

ostream &operator<<(ostream &out, State const & obj)
{
	out << obj.name << ' ';
	out << obj.year << ' ';
	out << obj.cap << ' ';
	out << obj.popRank << '\n';

	return out;
}

#ifndef FORMAT_H
#define FORMAT_H

class Format
{
public:
	static char * fixString(char * string);
	static char * upperCase(char * string);
	static void parse(char * input, char * name, int * year, char * cap, int * popRank);
};

#endif

#include <iostream>
#include "formatheader.h"

using std::cout;

char * Format::fixString(char * string)
{
	// capitalize the first letter of the sentence
	string[0] = toupper( string[0] );	

	for (int cnt = 1; cnt < (strlen(string) + 1); cnt++)
		if ( isalpha( string[cnt] ) )
			string[cnt] = tolower( string[cnt] );	// set to lower case
		else if ( string[cnt] == ' ' )
		{
			++cnt;							// move to the beginning of the next word
			string[cnt] = toupper( string[cnt] );	// capitalize
		}
	return string;
}

char * Format::upperCase(char * string)
{
	for (int cnt = 0; cnt < (strlen(string) + 1); cnt++)
		if ( isalpha( string[cnt] ) )
			string[cnt] = toupper( string[cnt] );
	return string;
}

void Format::parse(char * input, char * name, int * year, char * cap, int * popRank)
{
	sscanf( input, "%[^,], %d, %[^,], %d", name, year, cap, popRank );
}

#ifndef	ATLAS_H
#define ATLAS_H

#include "database.h"
#include "state.h"

class Atlas
{
public:
	Atlas(char * file = "states.txt");
	~Atlas() { delete db; }
	void replace(int index, State const & s);
	State getState(char * stateName) const;
	// overloaded operators
	friend ostream &operator<<(ostream &, Atlas const & obj);
private:
	Database * db;
};

#endif

#include <iostream>
#include <fstream>
#include "atlas.h"
#include "database.h"
#include "state.h"

using std::ifstream;
using std::ios_base;

Atlas::Atlas(char * file)
{
	ifstream inputFile(file);
	db = new Database(file);

	inputFile >> *db;
//	db->fillDatabase();
	inputFile.close();
}

void Atlas::replace(int index, State const & s)
{
	State * tempState = db->getList();

	delete [] tempState[index].getName();
	delete [] tempState[index].getCap();
	
	tempState[index].changeName(s.getName());
	tempState[index].changeYear(s.getYear());
	tempState[index].changeCap(s.getCap());
	tempState[index].changePopRank(s.getPopRank());
}

State Atlas::getState(char * stateName) const
{
	State * tempState = db->getList();

	for (int cnt = 0, found = 0; cnt < db->getCount() && !found; cnt++)
		found = tempState[cnt].findState( stateName );

	if ( found )
		return State( tempState[cnt - 1] );
	else
		return State();
}

ostream &operator<<(ostream &out, Atlas const & obj)
{
	out << " State name      Year     Capital      Pop. rank\n";
	out << "------------------------------------------------\n";

	for (int cnt = 0; cnt < obj.db->getCount(); cnt++)
	{
		out.setf(ios_base::left);
		out.width(17);
		out << obj.db->getList()[cnt].getName();

		out.setf(ios_base::left);
		out.width(8);
		out << obj.db->getList()[cnt].getYear();

		out.setf(ios_base::left);
		out.width(18);
		out << obj.db->getList()[cnt].getCap();

		out.setf(ios_base::left);
		out.width(2);
		out << obj.db->getList()[cnt].getPopRank() << '\n';
	}

	return out;
}

states.txt file

Connecticut,1788,Hartford,29
Maine,1820,Augusta,40
Massachusetts,1788,Boston,13
New Hampshire,1788,Concord,41
Rhode Island,1790,Providence,43
Vermont,1791,Montpelier,49
Delaware,1787,Dover,45
Maryland,1788,Annapolis,19
New Jersey,1787,Trenton,10
New York,1788,Albany,3
Pennsylvania,1787,Harrisburg,6
Alabama,1819,Montgomery,23
Arkansas,1836,Little Rock,32
Florida,1845,Tallahassee,4
Georgia,1788,Atlanta,9
Kentucky,1792,Frankfort,26
Louisiana,1812,Baton Rouge,24
Mississippi,1817,Jackson,31
Missouri,1821,Jefferson City,17
North Carolina,1789,Raleigh,11
South Carolina,1788,Columbia,25
Tennessee,1796,Nashville,16
Virginia,1788,Richmond,12
West Virginia,1863,Charleston,37
Illinois,1818,Springfield,5
Indiana,1816,Indianapolis,14
Iowa,1846,Des Moines,30
Kansas,1861,Topeka,33
Michigan,1837,Lansing,8
Minnesota,1858,St. Paul,21
Nebraska,1867,Lincoln,38
North Dakota,1889,Bismarck,11
Ohio,1803,Columbus,7
South Dakota,1889,Pierre,46
Wisconsin,1848,Madison,20
Arizona,1912,Phoenix,18
New Mexico,1912,Santa Fe,36
Oklahoma,1907,Oklahoma City,28
Texas,1845,Austin,2
Alaska,1959,Juneau,47
California,1850,Sacramento,1
Colorado,1867,Denver,22
Hawaii,1959,Honolulu,42
Idaho,1890,Boise,39
Montana,1889,Helena,44
Nevada,1864,Carson City,35
Oregon,1859,Salem,27
Utah,1896,Salt Lake City,34
Washington,1889,Olympia,15
Wyoming,1890,Cheyenne,50

ok i figured the problem out. It turns out that I opened the same file twice..

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.