Priming Read Issue

I have this program that is placeing output into an outside text file, and it's working just fine (unless our reference file "register.txt" has a \n at the end of the file). I know I need to use a priming read to control this situation for a \n at the end of the file, but I'm not quite sure how to use it in this situation.

Thanks for any assistance! Below is the main part of my code that includes this issue.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
int main()
{
	const string REGISTER = "REGISTER.txt";    
	const string VEHICLES = "VEHICLES.txt";
	const string HOUSEHOLDS = "HOUSEHOLDS.txt";
	
	
	int id_num;
	char vehicle_type;
	string license_plate;
	int model_year;
	double msrp;
	double ownership_tax;
	double registration_charge;
	char ch;
	double sum;
	
	ifstream register_file;
	ofstream vehicle_file;
	ofstream households_file;
	
	register_file.open(REGISTER.c_str());
	vehicle_file.open(VEHICLES.c_str());
	households_file.open(HOUSEHOLDS.c_str());
	
	
	do
	{   
		sum = 0;
		                                      
		register_file >> id_num;
		
		do
		{
			
			register_file >> vehicle_type;
			register_file >> license_plate;
			register_file >> model_year;
			register_file >> msrp;
			
			calcTax(msrp, model_year, vehicle_type, ownership_tax, 
			registration_charge);                                   
					
			vehicle_file << fixed << setprecision(2) << vehicle_type << ' ' 
						 << license_plate << ' '	<< registration_charge 
						 << endl;
			
			ch = register_file.peek();
			
			sum += registration_charge;
						        
		} while(register_file && (ch != '\n'));
		
		households_file << fixed << setprecision(2) << id_num << ' ' 
						<< sum << endl;
					
	
	} while(register_file && (ch == '\n'));
   		
	register_file.close();
   	vehicle_file.close();
	
		
    cout << endl << endl;
    system("PAUSE");
    return 0;
}
Perhaps something like this. Use a while loop rather than do-while and test the condition of the input file after attempting to read an item.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
    while (register_file >> id_num)
    {   
        sum = 0;
        
        while (register_file >> vehicle_type)
        {
            register_file >> license_plate;
            register_file >> model_year;
            register_file >> msrp;

            calcTax(msrp, model_year, vehicle_type, ownership_tax, 
                registration_charge);
                    
            vehicle_file << fixed << setprecision(2) 
                         << vehicle_type << ' ' 
                         << license_plate << ' ' 
                         << registration_charge 
                         << endl;
            
            sum += registration_charge;                                
        }
        
        households_file << fixed << setprecision(2) 
                        << id_num << ' ' 
                        << sum << endl;
    }
I know I need to use a priming read to control this situation for a \n at the end of the file, but I'm not quite sure how to use it in this situation.


What you need to do is ensure your data extraction was successful before using the data you extracted. Also, consider not using the C-style of declaring every variable at the beginning of a function and limit them to smaller scopes when possible.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <string>
#include <fstream>
#include <iomanip>
#include <iostream>

using namespace std ;

void calcTax( double, int, char, double, double ) ;

int main()
{
    const string REGISTER = "REGISTER.txt";    
    const string VEHICLES = "VEHICLES.txt";
    const string HOUSEHOLDS = "HOUSEHOLDS.txt";
  
    ifstream register_file(REGISTER.c_str());
    ofstream vehicle_file(VEHICLES.c_str());
    ofstream households_file(HOUSEHOLDS.c_str()) ;

    int id_num ;
    while ( register_file >> id_num )
    {   
        char vehicle_type ;
        std::string license_plate ;
        int model_year ;
        double msrp ;

        double sum = 0;

        while ( register_file >> vehicle_type && register_file >> license_plate &&
                register_file >> model_year && register_file >> msrp )
        {
            double registration_charge, ownership_tax ;

            calcTax(msrp, model_year, vehicle_type, ownership_tax, 
                registration_charge);                                   

            vehicle_file << fixed << setprecision(2) << vehicle_type << ' ' 
                << license_plate << ' '	<< registration_charge 
                << endl;

            sum += registration_charge;
        }

        households_file << fixed << setprecision(2) << id_num << ' ' 
            << sum << endl;
    }

    cout << endl << endl;
}
This works fine when I have one line, but let's say that my "REGISTER.txt" file has multiple lines for each household. I want it to reproduce this loop everytime a new line is started. But, once you reach end of the file (whether it's after the final data extracted or it's another line in the data) I want it to stop the loop.
Last edited on
@cire: when you said
consider not using the C-style of declaring every variable at the beginning of a function and limit them to smaller scopes when possible

I realize the importance of this in general as you mentioned, but does this apply even in while-loops like where you declared the char variable vehicle_type inside the loop? Might that lead to unnecessary overhead during runtime to have the program re-declaring the variable every iteration of the while-loop, or am I off in left field? Please let me know, I'm curious.
Let me show you my entire code thus far, since I still can't figure it out. (By the way, i declare every variable at the beginning because it's a requirement of my class).

So, my text file "REGISTER.txt" says:

1
2
3
4
111111 A ABC123 2012 36666 A XYZ789 2005 15555
222222 A DDD333 1999 22222
333333 A FFF888 2000 12345 M BBB888 2000 9988 M GHW888 1990 7711
//<this is end of file on new line>// 


My code in whole:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#include <iostream>               
#include <cstdlib>                              
#include <iomanip>                               
#include <fstream>
#include <string>

using namespace std;

double calcTax(double, int, char, double, double&);

const double AUTO_ROAD_FEE = 24;
const double MOTORCYCLE_ROAD_FEE = AUTO_ROAD_FEE/2;
const double LICENSE_FEE = .0025;
const int CURRENT_YEAR = 2013;

int main()
{
	const string REGISTER = "REGISTER.txt";    
	const string VEHICLES = "VEHICLES.txt";
	const string HOUSEHOLDS = "HOUSEHOLDS.txt";
	
	
	int id_num;
	char vehicle_type;
	string license_plate;
	int model_year;
	double msrp;
	double ownership_tax;
	double registration_charge;
	char ch;
	double sum;
	double total_collected;
	int count;	
	
	ifstream register_file;
	ofstream vehicle_file;
	ofstream households_file;
	
	register_file.open(REGISTER.c_str());
	vehicle_file.open(VEHICLES.c_str());
	households_file.open(HOUSEHOLDS.c_str());
	
	
   	cout << "Household   Vehicles     Total" << endl;
   	cout << "ID Number   Registered   Charges" << endl;
   	cout << "---------   ----------   -----------" << endl;
   	
  	
	do
	{   
		
		sum = 0;
		count = 0;		
		register_file >> id_num;
		                                    		
		do
		{
			
			register_file >> vehicle_type;
			register_file >> license_plate;
			register_file >> model_year;
			register_file >> msrp;
			
			calcTax(msrp, model_year, vehicle_type, ownership_tax, 
			registration_charge);                                   
					
			vehicle_file << fixed << setprecision(2) << vehicle_type << ' ' 
						 << license_plate << ' ' << setw(10) << registration_charge 
						 << endl;
					 
			ch = register_file.peek();
			
			sum += registration_charge;
			count += 1;	
			
		} while(register_file && (ch != '\n'));	     
					
		cout << fixed << setprecision(2) << setw(9) << id_num << setw(8) 
			 << count << setw(9) << "$" << setw(10) << sum << endl;
		
		total_collected += sum;

	}while(register_file && (ch == '\n'));

 	register_file.close();  	
	vehicle_file.close();
   	   	
	cout << "                         -----------" << endl;
	cout << "Total County Collected   $" << setw(10) << total_collected;
		
    cout << endl << endl;                               
    system("PAUSE");    
    return 0;
}

double calcTax(double msrp, int model_year, char vehicle_type, double ownership_tax,
double& registration_charge)
{
	int yearsOld = CURRENT_YEAR - model_year;
	
	//cars
	const double TAX1 = (.03*msrp)-((.0015*msrp)*yearsOld); 
	const double TAX2 = (.0275*msrp)-((.0012*msrp)*yearsOld);
	const double TAX3 = (.025*msrp)-((.0009*msrp)*yearsOld);
	const double TAX4 = 20;
	//motorcycles
	const double TAX5 = (.025*msrp)-((.0009*msrp)*yearsOld); 
	const double TAX6 = (.0225*msrp)-((.0009*msrp)*yearsOld);
	const double TAX7 = (.02*msrp)-((.0009*msrp)*yearsOld);
	const double TAX8 = 10;
	
	if(vehicle_type == 'A')
	{
		
		if(yearsOld <= 5)
			ownership_tax = TAX1;
		else if(yearsOld > 5 && yearsOld <= 10)
			ownership_tax = TAX2;
		else if(yearsOld > 10 && yearsOld <= 15)
			ownership_tax = TAX3;
		else
			ownership_tax = TAX4;	
			
		registration_charge = ownership_tax + AUTO_ROAD_FEE +
		                      (LICENSE_FEE*msrp);
	}
	else
	{
		
		if(yearsOld <= 5)
			ownership_tax = TAX5;
		else if(yearsOld > 5 && yearsOld <= 10)
			ownership_tax = TAX6;
		else if(yearsOld > 10 && yearsOld <= 15)
			ownership_tax = TAX7;
		else
			ownership_tax = TAX8;
		
		registration_charge = ownership_tax + MOTORCYCLE_ROAD_FEE +
							  (LICENSE_FEE*msrp);
	}
	
	
}


Output receiving:

Household   Vehicles     Total
ID Number   Registered   Charges
---------   ----------   -----------
   111111       2        $   1501.97
   222222       1        $    355.11
   333333       3        $    380.20
   333333       1        $     41.28
                         -----------
Total County Collected   $   2278.55


Output desired:

Household   Vehicles     Total
ID Number   Registered   Charges
---------   ----------   -----------
   111111       2        $   1501.97
   222222       1        $    355.11
   333333       3        $    380.20
                         -----------
Total County Collected   $   2237.27
Here's one way:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <sstream>

    // replace your nested loops with:

    std::string line ;
    while ( std::getline(register_file, line) && line.length() )  // retrieve all of a single line from the file.
    {                                                                             // and if it isn't empty:
        sum = 0 ;
        count = 0 ;

        std::istringstream is(line) ;                                     // convert the line into a stream
        is >> id_num ;

        while ( is >> vehicle_type >> license_plate >> model_year >> msrp )
        {
            calcTax(msrp, model_year, vehicle_type, ownership_tax, registration_charge) ;
            vehicle_file << fixed << setprecision(2) << vehicle_type << ' '
                         << license_plate << ' ' << setw(10) << registration_charge
                         << endl ;

            sum += registration_charge ;
            ++count ;
        }

        std::cout << fixed << setprecision(2) << setw(9) << id_num << setw(8)
            << count << setw(9) << '$' << setw(10) << sum << endl ;

        total_collected += sum ;
    }


Also, your code should not compile since you tell the compiler that calcTax will return a value but it does not. total_collected should be initialized to 0. In your code, it is not initialized to any meaningful value. There is no reason for ownership_tax to be a parameter to calcTax since it should be a local-to-calcTax variable in its current implementation.
Everything which Cire has put is valid, I don't have anything serious to add.

However, purely as a matter of readability, I found the unnecessary parentheses get in the way in several places. For example this:
1
2
3
4
    //cars
    const double TAX1 = (.03*msrp)-((.0015*msrp)*yearsOld); 
    const double TAX2 = (.0275*msrp)-((.0012*msrp)*yearsOld);
    const double TAX3 = (.025*msrp)-((.0009*msrp)*yearsOld);

it might look better like this:
1
2
3
4
    //cars
    const double TAX1 = 0.03   * msrp  -  0.0015 * msrp * yearsOld;
    const double TAX2 = 0.0275 * msrp  -  0.0012 * msrp * yearsOld;
    const double TAX3 = 0.025  * msrp  -  0.0009 * msrp * yearsOld;

(multiplication and division take precedence over addition and subtraction).
Thank you for the information Chervil and Cire.

So, I tried using a "return registration_charge" in my function, but it isn't returning for some reason. This is why I swapped it out for a pass parameter. Why is it not returning the value back to the main function when i try to use return?
So, I tried using a "return registration_charge" in my function, but it isn't returning for some reason. This is why I swapped it out for a pass parameter. Why is it not returning the value back to the main function when i try to use return?

Did the call look something like the following when you were attempting to return a value?

registration_charge = calcTax(msrp, model_year...);

In other words, did you do something with the value returned?
That answered my question. Ugh. The little things, right? Haha.

Thanks!
Topic archived. No new replies allowed.