I'm almost finished with this program but the problem I'm having is with freeing the memory I allocated. Particularly in the area where I have pointers to strings.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/////////////// user defined data /////////////////////
struct State
{
char * name; // state name
int year; // year of entry into the union
char * cap; // state capital
int popRank; // population ranking
};
struct Database
{
struct State * list; // array of states
int count; // total count of states
char * filename; // input filename
};
/////////////// function prototypes ////////////////////
struct Database * initDatabase (char * filename);
void deleteDatabase (struct Database * db);
void fillDatabase (struct Database * db);
void insertDatabase (struct Database* db, int index, struct State * state);
void printDatabase (struct Database * db);
int initState (struct State * state, char * name, int year, char * cap, int popRank);
void deleteState (struct State * state);
void copyState (struct State * from, struct State * to);
void printState (struct State * state);
////////////////////////// program start ///////////////////////////////////////
int main(void)
{
struct Database * db;
if (db = initDatabase("states.txt")) // allocate memory for Database struct,
// then initialize fields of Database struct
{
fillDatabase(db); // read from file
printDatabase(db); // print data
deleteDatabase(db); // free memory in Database struct
free(db); // free Database struct itself
return 0;
}
else // not successful
{
return 1;
}
}
////////////////////// Database functions ////////////////////////////////
//initDatabase - allocates memory for Database struct and initializes
// each field
//input: input filename
//return: pointer to Database struct if success
// NULL if fail
struct Database * initDatabase (char * filename)
{
FILE * fpIn;
struct Database * db;
struct State * states;
char * string;
// open input file and check for open success
if ( ( fpIn = fopen( filename, "r" ) ) )
{
// allocate memory for Database struct and check for success
if ( db = ( struct Database * )malloc( sizeof( struct Database ) ) )
{
// allocate memory for filename field and initializes with filename
if ( string = ( char * )malloc( sizeof( char ) * strlen( filename ) ) )
{
strcpy( string, filename );
db->filename = string;
}
else
{
printf("Not enough memory!\n");
exit(0);
}
// initialize count field to 50
db->count = 50;
// initialize list field by allocating memory for array of 50 states
// and check for success
if ( states = ( struct State * )malloc( sizeof( struct State ) * 50 ) )
{
db->list = states;
}
else
{
printf("Not enough memory!\n");
exit(0);
}
}
}
else
{
printf("Error with file!\n");
exit(0);
}
// close input file
fclose( fpIn );
return db;
}
//deleteDatabase - frees allocated memory inside a Database struct
//input: pointer to Database struct
//return: nothing
void deleteDatabase (struct Database * db)
{
while ( db->list )
{
deleteState( db->list );
db->list++;
}
}
//fillDatabase - reads info from file and stores in array of State structs
//input: pointer to Database struct
//return: nothing
void fillDatabase (struct Database * db)
{
struct State tempState; // temp State struct to store data from file
char name[80]; // temp variables
int year; // to store
char cap[80]; // input data
int popRank; // from file
int index = 0; // index into array of State structs
FILE *fpIn;
int cnt;
// open file from filename field of db
// don't need to check for file open success because initDatabase already checked
fpIn = fopen( db->filename, "r" );
// loop through all the states
for ( cnt = 0; cnt < db->count; cnt++ )
{
// read and parse one line of file into 4 input data fields
if ( fscanf( fpIn, "%[^,], %d, %[^,], %d", name, &year, cap, &popRank ) == 4 )
{
// if tempState is created successfully from the 4 input data
if ( initState (&tempState, name, year, cap, popRank) )
{ // then copy tempState data into array of states at the current index
insertDatabase (db, index, &tempState);
}
index++;
}
else
{
printf("Error reading file!\n");
exit(0);
}
}
// close file
fclose( fpIn );
}
//insertDatabase - copy state data from tempState into appropriate place in array
//input: pointer to Database struct
// current index in array
// pointer to tempState containing state data
//return: nothing
void insertDatabase (struct Database * db, int index, struct State * state)
{
// set pCurrent to location to be inserted in array
struct State *pCurrent = db->list + index;
// copy from state to pCurrent
copyState (state, pCurrent);
return;
}
//printDatabase - print data of state array
//input: pointer to Database struct
//return: nothing
void printDatabase (struct Database * db)
{
int i;
printf (" State name Year Capital Pop. rank\n");
printf ("------------------------------------------------\n");
for (i = 0; i < db->count; i++)
printState(db->list+i);
return;
}
//////////////////////// State functions //////////////////////////////
//initState - initializes a State struct with input data
//input: pointer to State struct
// name, year, capital, and population rank of state
//return: true for success
// false for fail
int initState (struct State * state, char * name, int year, char * cap, int popRank)
{
char * stateName;
char * capital;
// if memory allocation is successful, store name
if ( stateName = ( char * )malloc( sizeof( char ) * strlen( name ) ) )
{
strcpy( stateName, name );
state->name = stateName;
}
else
{
printf("Not enough memory!\n");
return 0;
}
// store year
state->year = year;
// if memory allocation is successful, store capital
if ( capital = ( char * )malloc( sizeof( char ) * strlen( cap ) ) )
{
strcpy( capital, cap );
state->cap = capital;
}
else
{
printf("Not enough memory!\n");
return 0;
}
// store population ranking
state->popRank = popRank;
return 1;
}
//deleteState - frees allocated memory inside a State struct
//input: pointer to State struct
//return: nothing
void deleteState (struct State * state)
{
free( state->name );
free( state->cap );
free( state );
}
//copyState - copies contents between two State structs
//input: pointer to source State struct
// pointer to destination State struct
//return: nothing
void copyState (struct State * from, struct State * to)
{
to->name = from->name;
to->year = from->year;
to->cap = from->cap;
to->popRank = from->popRank;
}
//printState - displays State data
//input: pointer to State struct
//return: nothing
void printState (struct State * state)
{
printf ("%-17s%-8d%-18s%2d\n", state->name, state->year, state->cap, state->popRank);
return;
}
The data from the file is read as state, year, capital, and population ranking.
Can't help much but I'm sure others would greatly appreciate it if you used the [code=c] tag.
I'm almost finished with this program but the problem I'm having is with freeing the memory I allocated. Particularly in the area where I have pointers to strings.
And? What do you want us to do? Read every line of the code and tell you any errors we find?
Tell us any compilation errors. If it compiles, tell us the program output. Then say what you were expecting. Show the lines (or the whereabouts) of where this occurs. In this case, it would also be helpful if you showed us the file you're trying to read.Can't help much but I'm sure others would greatly appreciate it if you used the [code=c] tag.
He doesn't have to as long as he tells us what is wrong with the code.
never mind i figured out the problem(s)
I think I'm having a similar problem. Any chance you could describe how you fixed this problem? Or, what the problem was?
I think I'm having a similar problem. Any chance you could describe how you fixed this problem? Or, what the problem was?
Most memory problems boil down to the program either trying to access/free memory that it didn't allocate (resulting in crashes/segmentation faults), or not freeing memory after the software is finished using it (resulting in memory leaks). Since everyone's code is different, please start a new thread with the exact issue you're experiencing.