Well I did really awful on this assignment *hangs head* Now we've been given assignment 2 and it seems equally as difficult!
Printable View
Well I did really awful on this assignment *hangs head* Now we've been given assignment 2 and it seems equally as difficult!
As you have now been assessed on your assignment 1, have you been given a 'model answer' by the course tutors so that you can see how it could have been done?
Nope. Just the next assignment. This week we are learning arrays. I've already gotten my assignment and am ready to start working on it. *deep breath* More time to work on it this week! That way I can get help easier!!
It's pretty similar to my last assignment actually.
Taking a quick look through the code, there are some very basic errors.
This routine is to obtain data from a file. However you are passing these parameters by value so any change you make to them in the function will not be reflected in the calling routine. If you want changed values to be available in the calling routine then you need to pass by reference likeCode:int getData(int houseID, int vehicleYear, int originalCost, string vehicleClass, string licensePlate)
Code:int getData(int& houseID, int& vehicleYear, int& originalCost, string& vehicleClass, string& licensePlate)
There are two issues with this. Firstly == is used as the equality comparision and secondly character constants are placed within ' '. What this statement does is assigns the value of variable A to the variable vechicleClass and tests whether this value is non-zero. You useCode:if (vehicleClass = A)
orCode:if (vechicleClass == 'A')
if comparing against a string instead of a char.Code:if (vechicleClass == "A")
whilst syntactically correct, it doesn't do what you think it will. It first compares 5 with vehicleAge which gives either a 0 or a 1. It then compares this 1 or 0 with 10. As it is always less than 10, this statement is always true. You need to writeCode:else if (5 < vehicleAge <= 10)
Code:else if (vechicleAge > 5 && vechicleAge <= 10)
Those make a lot of sense!
I had figured out the vehicleClass == 'A' one. But I didn't know about the else if or the int&.
My new assignment that I'll be starting on tonight (when I'm not on a work computer) is
1. Read in a file of vehicle type and registration cost.
2. Sort that into an array. 1 for Autos and 1 for Motorcycles,
3. Calculate the highest registration cost, the lowest, and the average for each array.
4. Array size of 500 - produce an error if more than 500 lines.
5. Output to screen number of vehicles registered, high, low and average for each array.
So I'm thinking that instead of getData, I need to use getline() so that it reads a line at a time. Then have a loop to read the next line. Test something like, if (char == '\n'). Would that work?
Then for the array, I should just be able to make one of size 499 (to store 500 vehicles) and then I'm not sure how but search it for the high and low.
Am I even in the right direction?? o_O
To help your studies, the code below is one possible version for your first assignment. I'm not sure about the calculation formulaes though.
For the registration.txt file containingCode:#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
#include <map>
using namespace std;
const string dataname = "REGISTER.txt";
const string vehname = "VECHICLES.txt";
const string housename = "HOUSEHOLDS.txt";
struct datarec {
string houseid;
int vehyear;
int orgcost;
string vehclass;
string license;
double tax;
double licfee;
};
struct houserec {
double fee;
int no;
};
typedef map<string, houserec> dmap;
typedef dmap::const_iterator cidmap;
bool getData(ifstream& ifs, datarec& data);
void calculateFees(datarec& data);
void showData(const datarec& data);
void writeDataVehicles(ofstream& ofs, const datarec& data);
void writeDataHouseholds(ofstream& ofs, const string& house, double fee);
bool getData(ifstream& ifs, datarec& data)
{
static string oldid;
ifs >> data.houseid;
if (data.houseid == "A" || data.houseid == "M") {
//Got multiple vehicle for 1 houseid
data.vehclass = data.houseid;
data.houseid = oldid;
ifs >> data.license >> data.vehyear >> data.orgcost;
} else
ifs >> data.vehclass >> data.license >> data.vehyear >> data.orgcost;
oldid = data.houseid;
calculateFees(data);
return ifs.good();
}
void writeDataVehicles(ofstream& ofs, const datarec& data)
{
ofs << data.vehclass << setw(8) << data.license << setprecision(2) << fixed << setw(8) << right << data.licfee << endl;
}
void writeDataHouseholds(ofstream& ofs, const string& house, double fee)
{
ofs << house << setprecision(2) << fixed << setw(8) << right << fee << endl;
}
void calculateFees(datarec& data)
{
const int vehicleAge = 2014 - data.vehyear;
data.licfee = 0.0025 * data.orgcost;
if (data.vehclass == "A") {
if (vehicleAge <= 5) {
data.tax = (0.03 * data.orgcost) - ((0.015 * data.orgcost) / vehicleAge);
} else {
if (vehicleAge > 5 && vehicleAge <= 10) {
data.tax = (0.0275 * data.orgcost) - ((0.012 * data.orgcost) / vehicleAge);
} else {
if (vehicleAge > 10 && vehicleAge <= 15) {
data.tax = (0.025 * data.orgcost) - ((0.009 * data.orgcost) / vehicleAge);
} else {
data.tax = 20.00;
}
}
}
} else {
if (data.vehclass == "M") {
if (vehicleAge <= 5) {
data.tax = (0.025 * data.orgcost) - ((0.009 * data.orgcost) / vehicleAge);
} else {
if (vehicleAge > 5 && vehicleAge <= 10) {
data.tax = (0.0225 * data.orgcost) - ((0.009 * data.orgcost) / vehicleAge);
} else {
if (vehicleAge > 10 && vehicleAge <= 15) {
data.tax = (0.02 * data.orgcost) - ((0.009 * data.orgcost) / vehicleAge);
} else {
data.tax = 10.00;
}
}
}
} else {
data.tax = 0;
}
}
}
void showData(const datarec& data)
{
cout << data.houseid << " " << data.vehclass << " " << data.license << " " << data.vehyear << " " << data.orgcost << " " << data.tax << " " << data.licfee << endl;
}
int main()
{
ifstream dataIn(dataname.c_str());
if (dataIn.is_open() == false) {
cout << "The file " << dataname << " cannot be opened.\n";
return 1;
}
ofstream vehOut(vehname.c_str());
if (vehOut.is_open() == false) {
cout << "The file " << vehname << " cannot be opened.\n";
return 2;
}
ofstream houseOut(housename.c_str());
if (houseOut.is_open() == false) {
cout << "The file " << housename << " cannot be opened.\n";
return 2;
}
datarec data;
dmap house;
while (getData(dataIn, data)) {
//showData(data);
writeDataVehicles(vehOut, data);
house[data.houseid].fee += data.licfee;
house[data.houseid].no++;
}
for (cidmap it = house.begin(); it != house.end(); ++it) {
writeDataHouseholds(houseOut, it->first, it->second.fee);
cout << it->first << setw(4) << it->second.no << setprecision(2) << fixed << setw(8) << right << it->second.fee << endl;
}
return 0;
}
This produces for file vehicles.txtCode:111111 A ABC123 2012 36666 M XYZ789 2005 15555
222222 A DDD333 1999 22222
and for households.txtCode:A ABC123 91.67
M XYZ789 38.89
A DDD333 55.56
and displays on the screenCode:111111 130.55
222222 55.56
which is think is what was required.Code:111111 2 130.55
222222 1 55.56
For reading data from a file, look at the getData() function in the sample code I posted and how I used that function in main().
There is an STL function sort() that will do the sort for you. See http://www.cplusplus.com/reference/algorithm/sort/
If you just want to calculate the highest, lowest and average for different vechicle types, there is no need to read the data into arrays. You want a struct containing high, low, average, total, numreg and then a 2 element array of this struct (for types A and M ) or even better use a map like in my example program. As you read in each line from the file, just update high, low, total, numreg for the appropriate array and then at the end calculate the average. Then just output the required info. Simples!:D
Well, 2kaud's suggestion is more efficient than reading into an array and then repeatedly looping over the array to obtain the results that you want. This is a good. On the other hand, it couples together the distinct operations to obtain each result, which can be a bad since you cannot reuse the code to say, only find the highest.Quote:
Originally Posted by spideyflygirl90
I would start by producing a simple program that just loops reading the data from the file and displaying it on the screen (see my sample program for an idea of one way of doing it). That was the first version of the example I posted above. Once that worked OK I then extended the program in stages. Each stage was tested first before the next stage was added. This way you always have a working program - one that doesn't do all it's supposed to, but working nevertheless. Once you have a program that you know reads the data OK, then you can add code that puts it in an array. Test that. Then sort the array and test that. Then add code to find highest etc etc etc. The important point is that at every stage you have a working program that does what's it's supposed to at that stage in the design.Quote:
I'm trying to get an idea of where to start before I get home from work and actually start
If you have a go and post some code here, we'll provide guidance but won't produce the code for you as this is a marked assessment. See http://forums.codeguru.com/showthrea...ork-assignmentCode:Do {
Design
code
test
debug
} while program-not-correct
Good luck!:thumb:
So I'm trying to do it piece by piece, starting with opening the file. However, it's giving me an error that says "Cannot find or open the PDB file".
Here's the very basic code I have so far. I'm wondering I guess, does the VEHICLES.txt have to be saved somewhere specific? Or linked to in some special way?
Code:#include<iostream>
#include<iomanip>
#include<fstream>
#include<string>
using namespace std;
void main()
{
char vehicleClass;
string licensePlate;
float registrationFee;
ifstream infile;
infile.open("VEHICLES.txt");
while (infile >> vehicleClass >> licensePlate >> registrationFee)
{
cout << "The file was successfully opened." << endl;
}
}
The PDB file (Program Database) holds debugging and project state information that allows incremental linking of a Debug configuration of your program. A PDB file is created when you build with /ZI or /Zi (for C/C++). See http://msdn.microsoft.com/en-us/libr...=vs.90%29.aspxQuote:
However, it's giving me an error that says "Cannot find or open the PDB file".
This message is an issue with the way the project has been set up. Have a look at
http://social.msdn.microsoft.com/For...?forum=vsdebug
Re your program. main() should be defined as
VEHICLES.txt needs to exist in the same folder as the program if you don't specify a folder location. A way to open a file and test if was opened properly is like this from my previous exampleCode:int main()
When you define the file variable, you can specifiy the file name as wellCode:ifstream infile("VEHICLES.txt");
if (infile.is_open() == false) {
cout << "The file VEHICLES.txt cannot be opened.\n";
return 1;
}
cout << "The file was successfully opened." << endl;
while (infile >> vehicleClass >> licensePlate >> registrationFee)
{
//process data
}
http://www.cplusplus.com/reference/f...ream/ifstream/
Using .open() is OK but as you know the name of the file when you define the file variable IMO specifying the name then is easier than having a separate .open() statement.
The class function .is_open() returns true if there is a valid file opened to the file variable. If the open failed it returns false. As the program is concerned with file processing, the rest of the program is invalid if the file hasn't been opened OK. Another way of coding this could be
This way there is only 1 entry and 1 exit point to the function - rather than 2 exits as in the previous example.Code:ifstream infile("VEHICLES.txt");
int retval = 0;
if (infile.is_open() == true)
{
cout << "The file was successfully opened." << endl;
while (infile >> vehicleClass >> licensePlate >> registrationFee)
{
//process data
}
} else {
cout << "The file VEHICLES.txt cannot be opened.\n";
retval = 1;
}
return retval;
}
stream extraction (infile >> vehicleClass ...) returns a NULL if there is a problem performing the extraction (see http://www.cplusplus.com/reference/i...perator%3E%3E/). Hence the while condition is true if the extraction is successfull and is false if there is an error with the extraction and the while loop then terminates. The extraction can fail for three reasons 1) end-of-file has been reached 2) the characters extracted could not be interpreted as a valid value of the appropriate type (trying to read an int and finds an 'A' 3) an error occured during the extraction and data couldn't be read. See http://www.cplusplus.com/reference/ios/ios/good/
Update:
So I figured out the major reason why I was struggling so much! My computer has a bug! Ahh!! I've been needing a new laptop for school, picked it up yesterday, ran the codes I have finished so far for my assignment this week and they worked!
What a relief.
So I have my openfile and getdata functions figured out! working on sort data and displayresults!
I'm stuck again, maybe someone can help ;-P
I wrote my openFile function and tested it, worked just fine! I put a cout statement to verify that it worked. It displayed perfectly. Then I moved it into it's own function instead of main, called it from main, and now it won't display the cout statement. It just gives me a return 0 value. Here's my code: I have extra #include statements for my following code but I haven't gotten that far yet.
Code:#include<iostream>
#include<iomanip>
#include<fstream>
#include<string>
#include<sstream>
using namespace std;
int main()
{
// declare the needed variables
char vehicleClass;
string licensePlate;
float registrationFee;
ifstream inFile;
int openFile();
}
int openFile(ifstream& inFile)
{
// open the file
inFile.open("VEHICLES.txt");
if (!inFile) // checks for error while opening
{
cout << "Cannot open the input file. "
<< "The program terminates." <<endl;
}
else
{
cout << "The file was opened successfully." << endl;
}
}