One way to do this is to continually refine your program so that it solves more and more of your initial problem. In other words:
Difficulty: This is not a completely easy problem, as we'll see, in part because towns' names are not always a single word, take "East New Market", for example.
Well, first of all, the basic structure of the program should be clear:
int main()
{
// Open census data file
// Read in (and ignore!) header information
// Loop over each row
{
// Process row
}
return 0;
}
We'll use this as a starting point.
tempdata that contains our
data. Eventually our program should allow the user to specify the data file,
but we'll worry about that later. Let's start off easy. With this assumption,
our program becomes:
int main()
{
// Open census data file
ifstream fin("tempdata");
// Read in (and ignore!) header information
// Loop over each row
{
// Process row
}
return 0;
}
For example, our file tempdata looks as follows:
Accident town 325 325 325 325 322 323 319 318 316 316 314 312Note that we first come to the town name, "
Accident" and
"town". Then there are 12 pieces of information to be read in (and
ignored).
int main()
{
// Open census data file
ifstream fin("tempdata");
// Read in (and ignore!) header information
// Loop over each row
{
/***** Process row **************/
// Read name of city/town/village
// Print name if town
// Read (and ignore) 7 entries
}
return 0;
}
Finally, we arrive at this, which is a
complete working program that we can compile and test on our
simplified input. It seems to work.
Baltimore city 620961 620770 620915 620410 622895 622391 623587 622522 616226 610481 602443 593490and it works like a champ. However, it fails for something like this:
Bel Air town 10120 10100 10149 10188 10254 10242 10181 10106 10054 10027 10042 10119Why does it fail? It fails because our program tacitly assumed that a town's name would be a single word, and that's not the case here.
So we need to keep reading in words, stopping when we read in town
or city or CDP or village. So we might
modify that piece of our code to look like this:
...
// Read name of city/town/village
string t;
fin >> t;
while(t != "town" && t != "city" && t != "village")
{
fin >> t;
}
// Print name if town
if (t == "town")
cout << ??? << endl;
tempdata only contains one row. In other
words, lets deal with several rows of data.
The key here is going to be determining that there is no more data to read.
There's a trick to this: If you read in from an ifstream object
and you come to the end of the file, the ifstream object goes into
an error state.
istream is cast to a
bool, it goes to false if it's in an error state, and true
otherwise. So all we have to do is place the
fin >> sthat reads in the first string of a line was successful.
Estimates-Base", and that it
only occurs in that one place. We can keep reading in strings until we read
the string "Estimates-Base"! Then, we can ignore 10 years in the header. This is pretty simple, it looks
something like this:
...
// Read in (and ignore!) header information
string kill;
while( (fin >> kill) && (kill != "Estimates-Base") )
{
// do nothing: ignore header info
}
for(int i=0; i<10; i++)
fin >> kill;
...
// User enters file name
string filename;
cout << "Enter name of input file: ";
cin >> filename;
// Open census data file
ifstream fin(filename);
if (!fin)
{
cout << "Error opening file!" << endl;
return 0;
}
An finally, here is a complete program!
John Jeffery Jones m040101 85, 95, 22, 54; Sandra Smith m040201 99, 98; Xavier Xenon Junior m050400 78, 80, 82, 84, 86, 88, 90;For this input, your program would print out
Sandra Smith had the highest average.A good way to approach this problem would be to write three successive programs:
Jones m040101 85 Smith m040201 99 Xenon m050400 78
John Jeffery Jones m040101 85 Sandra Smith m040201 99 Xavier Xenon m050400 78Hint: Remember that if
S is an object
of type string and c is an
object of type char, then c + S
is the string object you get by tacking the
character c onto the beginning of S.