wont read input file, what's wrong?

Pages: 12
Look closely at your read loop. You appear to have some "weird" brace locations, note that that "x++" is not part of the while loop, it probably should be in the loop.


lol okay, i fixed that. it's working now but I'm getting garbage values for
Residential
and
Employee
but
Business
is outputting correctly?

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
#include <iostream>
#include <string>
#include <fstream>
using namespace std;

const int MAX_CUSTOMERS = 15;
struct Customer
{
	Customer() {
	}
	char customerType;
	int numOfBasicServConn, numOfPremChannels;
	double amountDue;
	string accountNumber;
};

int readFile(ifstream& fin, Customer cust[]);



int main()
{
	Customer cust[MAX_CUSTOMERS];

	ifstream fin("C:\\Users\\ryan\\Desktop\\inFile.txt");
	if (!fin)
	{
		cerr << "File failed to open!\n";
		return (1);
	}
	int numOfCustomers = readFile(fin, cust);

	for (int i = 0; i < numOfCustomers; ++i)
		cout << cust[i].customerType << " " << cust[i].accountNumber << " "
		<< cust[i].numOfBasicServConn << " " << cust[i].numOfPremChannels << " " << endl;
	
	Customer bo;
	cin.ignore(10000, '\n');
	cin.get();
	return 0;
}

int readFile(ifstream& fin, Customer cust[])
{
	int x = 0;

	while (x < MAX_CUSTOMERS && fin >> cust[x].customerType) {
		if (cust[x].customerType == 'B')
			fin >> cust[x].accountNumber >> cust[x].numOfBasicServConn >> cust[x].numOfPremChannels;
		else if (cust[x].customerType == 'R')
						fin >> cust[x].accountNumber >> cust[x].numOfPremChannels;
		else if (cust[x].customerType == 'E')
			fin >> cust[x].accountNumber;
		x++;
	}
		
	return x;
}
it's working now but I'm getting garbage values for

What do you mean by "garbage values" and what do you expect to be getting?

Edit: You don't retrieve all the data for all of the structure values, depending on the customer type, so since you didn't initialize the structure values you will get undetermined output when you try to print those values. Perhaps you should only be printing the values you actually read?


Last edited on
okay, ya sorry my post earlier wasn't very clear.

What do you mean by "garbage values"


input:

R12345 5


output:

R 12345 -869874865 5


so since you didn't initialize the structure values you will get undetermined output when you try to print those values.


One way of initializing the structure value is to use a constructor, correct? Please correct me if I'm wrong but I added what I believe is a default constructor in the struct, but for some reason that's all I did was add it to the struct itself.
I'm at work right now but would you mind giving me an idea of what my next step should be?
I need to add a function to compute the amountDue but I'm unsure if that should be my next step. Thank you.



Last edited on
Please correct me if I'm wrong but I added what I believe is a default constructor in the struct,

Yes, you did.
But it doesn't actually do anything.

You might change this:
1
2
    Customer() {
    }
to this:
1
2
3
    Customer() : customerType(' '), numOfBasicServConn(0),
        numOfPremChannels(0), amountDue(0.0) {
    }

(the std::string will already initialise to empty string).

But equally, jlb made a good suggestion, that you should only be printing the values you actually read.
Yes, you did. 
But it doesn't actually do anything


Is the reason why it doesn't do anything because I didn't do it correctly? And changing it to your suggestion:
Customer() : customerType(' '), numOfBasicServConn(0),
        numOfPremChannels(0), amountDue(0.0) {
    }


will actually implement the constructor?
Your code was correct in terms of syntax. But it wasn't correct in terms of what needed to be done, because it didn't alter any of the values.

Why not try it and see.
So, yep you were right. No surprise there. No more garbage values.

first three lines of input:
B12345 16 8
B12345 5 8
R12345 5


output:
B12345 16 8
B12345 5 8
R12345 0 5


So I need a function to compute the amountDue. It's getting closer. Taking me longer than I feel like it should have but I'm learning a lot.
Okay, i apologize for the long post but I want you guys to have the full instructions my professor posted and the picture of the example output file my professor posted.

#(professor instructions start)#
Rewrite the Programming Example page 236 in chapter 4 ( Cable Company Billing ).

Expected Program and Design:
1. Write a pseudo code before starting your program ( do not use SWITCH, replace it with IF structures )
1.1 Draw a flowchart for your program based on your pseudo code
2. Identify your constants
3. Your input will come from a text file of at least 15 customers
3.1 Input file format - customerType accountNumber baseConnection premiumChannels
       ( i.e residential example: R12345 5 , business example B12345 16 8, employee example EXYZ001  ) residence do not have premium channels

3.2 Add employee customers ( no base or premium channels need to be specified in input file )
4. Precision should be two decimal places
5. Calculate the running average for residential and business customer spending
6. Print all customer's bill to a single file and the end of the file you should have the average summary for each customer type.
6.1 Pay attention to details when you formatting your output

Note: Use all chapter concepts and make your final as a true representation of what we have learned this semester.

Turn in
program design ( pseudo code and/or flow chart )
input file
output file
.cpp file of your program ( make sure you include your header and comment your code )

Extra credit
Implement your program using arrays, covered in chapter 8, and user defined simple data types to hold customer data.


Professor's example of output file:


https://postimg.org/image/ktxtq4uir/

This is everything I have so far:

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
#include <iostream>
#include <string>
#include <fstream>

using namespace std;

//Named constants - residential customers
const double RES_BILL_PROC_FEES = 4.50;
const double RES_BASIC_SERV_COST = 20.50;
//Named constants - business customers
const double BUS_BILL_PROC_FEES = 15.00;
const double BUS_BASIC_SERV_COST = 75.00;
const double BUS_BASIC_CONN_COST = 5.00;
const double BUS_COST_PREM_CHANNEL = 50.00;
//Named constants - employee customers
const double EMP_BILL_PROC_FEES = 4.50;
const double EMP_BASIC_SERV_COST = RES_BASIC_SERV_COST * 0.8;
//Named constant - maximum customers
const int MAX_CUSTOMERS = 15;

struct Customer
{
	Customer() : customerType(' '), numOfBasicServConn(0), 
	numOfPremChannels(0), amountDue(0.0) {
	}
	char customerType;
	int numOfBasicServConn, numOfPremChannels;
	double amountDue;
	string accountNumber;
};

int readFile(ifstream& fin, Customer cust[]);
int compute_amountDue(ifstream& fin, Customer cust[]);

int main()
{
	Customer cust[MAX_CUSTOMERS];

	ifstream fin("C:\\Users\\ryan\\Desktop\\inFile.txt");
	if (!fin)
	{
		cerr << "File failed to open!\n";
		return (1);
	}
	int numOfCustomers = readFile(fin, cust);

	for (int i = 0; i < numOfCustomers; ++i)
		cout << cust[i].customerType << " " << cust[i].accountNumber << " "
		<< cust[i].numOfBasicServConn << " " << cust[i].numOfPremChannels << " " << endl;

	int amount = compute_amountDue(fin, cust);

	for (int i = 0; i < amount; ++i)
		cout << cust[i].amountDue << " " << endl;
	
	cin.ignore(10000, '\n');
	cin.get();
	return 0;
}

int readFile(ifstream& fin, Customer cust[])
{
	int x = 0;

	while (x < MAX_CUSTOMERS && fin >> cust[x].customerType) {
		if (cust[x].customerType == 'B')
			fin >> cust[x].accountNumber >> cust[x].numOfBasicServConn >> cust[x].numOfPremChannels;
		else if (cust[x].customerType == 'R')
						fin >> cust[x].accountNumber >> cust[x].numOfBasicServConn;
		else if (cust[x].customerType == 'E')
			fin >> cust[x].accountNumber;
		x++;
	}
		
	return x;
}

int compute_amountDue(ifstream& fin, Customer cust[])
{
	int i = 0;

	while (i < MAX_CUSTOMERS)
	{
		if (cust[i].customerType == 'B' && cust[i].numOfBasicServConn <= 10) 
			cust[i].amountDue = BUS_BILL_PROC_FEES + BUS_BASIC_SERV_COST
				+ cust[i].numOfPremChannels * BUS_COST_PREM_CHANNEL;
		
		else if (cust[i].customerType == 'B') 
			cust[i].amountDue = BUS_BILL_PROC_FEES + BUS_BASIC_SERV_COST
				+ (cust[i].numOfBasicServConn - 10)
				* BUS_BASIC_CONN_COST
				+ cust[i].numOfPremChannels * BUS_COST_PREM_CHANNEL;
		
		else if (cust[i].customerType == 'R') 
			cust[i].amountDue = RES_BILL_PROC_FEES + RES_BASIC_SERV_COST;
		
		else if (cust[i].customerType == 'E') 
			cust[i].amountDue = EMP_BILL_PROC_FEES + (RES_BASIC_SERV_COST * 0.8);
		i++;
	}
	return i;
}


I know I need to reformat the output, I'm just not quite sure how. Also, it's computing the
amountDue
correctly but not in the format it looks like he expects from the example picture. Any help would be appreciated.
I'm not sure that the example picture given by your professor is something you could really achieve - looks like he used Excel or some spreadsheet program to generate that, whereas you will be generating a text file. But if you ignore the colourful graphics, you might get most of that in a plain text file. The one part which won't work is the extra details in column 6. If you are to output those, they'll either appear one after the other, making a very long line, or dropped below onto separate lines.

Still, I'll put that aside for now, focus on the program.
There are a couple of comments on this function:
 
int compute_amountDue(ifstream& fin, Customer cust[])

It is receiving the ifstream as a parameter, but it doesn't use it. On the other hand the function does need to know how many customer records were read from the file, the program should not assume that exactly MAX_CUSTOMERS were read from the file.

Also, the function returns some sort of value, but I don't think it needs to - does it?


Maybe something like this (simplified view, rest of details unchanged):
1
2
3
4
5
6
7
void compute_amountDue(Customer cust[], int size)
{
    for (int i=0; i<size; i++)
    {
        // details omitted here
    }
}


And in main(),
these lines:
51
52
53
    int amount = compute_amountDue(fin, cust);

    for (int i = 0; i < amount; ++i)
would become
51
52
53
    compute_amountDue(cust, numOfCustomers);

    for (int i = 0; i < numOfCustomers; ++i)

Last edited on

int compute_amountDue(ifstream& fin, Customer cust[])

It is receiving the ifstream as a parameter, but it doesn't use it.


Okay, I think I get what you're saying. Basically, the parameter
ifstream& 
currently, goes unused. And actually isn't necessary because main already has access to the array??

Also, the function returns some sort of value, but I don't think it needs to - does it?


I was using jlb's post for the while loop in
readFile()
as an example for
compute_amountDue
. Can you please explain to me why this function is different and does not need to return any values? Is it because
compute_amountDue
is simply calculating? I hope I'm making sense.
Well, look at line 45
 
     int numOfCustomers = readFile(fin, cust);

The function returns a value which is very important, it tells the calling code how many records it succeeded in reading from the file.

On the other hand, the function compute_amountDue() does some calculation and stores the result back into the array, for example
85
86
    cust[i].amountDue = BUS_BILL_PROC_FEES + BUS_BASIC_SERV_COST
				+ cust[i].numOfPremChannels * BUS_COST_PREM_CHANNEL;

Since this function is doing lots of calculations for lots of different customers, which value should it return, if any? For example it might return the total amount for all the customers. But there's no need to invent a need just for the sake of it. If there is no purpose to be served, then just make the return type void (which means nothing is returned).

As it was, the previous version was returning i, when i was equal to MAX_CUSTOMERS. There was clearly no purpose in that. MAX_CUSTOMERS is already a global constant. Nor would there be any point in returning the value size, since size would have the value numOfCustomers and the main() function already has that information.

I suppose I'd say, if in doubt, keep things as simple as possible. If there later turns out to be something more required, you can always change things at that later time.
Chervil


I made your suggested adjustments. I'm curious, do you think I should change my code and use a vector instead of an array?
I'm curious, do you think I should change my code and use a vector instead of an array?

Your assignment specifically requires arrays, so you probably should stick with arrays for now.

Please post your current code.

Also look at this:
3. Your input will come from a text file of at least 15 customers

The above tells me that there may be more than 15 customers, are you sure it is okay to ignore any "extra" records?

Also look at this:
3. Your input will come from a text file of at least 15 customers

The above tells me that there may be more than 15 customers, are you sure it is okay to ignore any "extra" records?


I know, I'm a little concerned about that as well. That's why i was asking about vectors. Even though I haven't used a vector before except a couple of times yesterday just following a video on YouTube.

But you're probably right. I mean, for some reason, my class only covers chapters 1 through 8 in the textbook and I'm already using a struct and a constructor which weren't covered in chapters 1 - 8. But I would hope he wouldn't count off because I did extra research by consulting with you guys. Who knows, I'm kind of past that point now lol.

Anyways here's my current code:

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
#include <iostream>
#include <string>
#include <fstream>

using namespace std;

//Named constants - residential customers
const double RES_BILL_PROC_FEES = 4.50;
const double RES_BASIC_SERV_COST = 20.50;
//Named constants - business customers
const double BUS_BILL_PROC_FEES = 15.00;
const double BUS_BASIC_SERV_COST = 75.00;
const double BUS_BASIC_CONN_COST = 5.00;
const double BUS_COST_PREM_CHANNEL = 50.00;
//Named constants - employee customers
const double EMP_BILL_PROC_FEES = 4.50;
const double EMP_BASIC_SERV_COST = RES_BASIC_SERV_COST * 0.8;
//Named constant - maximum customers
const int MAX_CUSTOMERS = 15;

struct Customer
{
	Customer() : customerType(' '), numOfBasicServConn(0), 
	numOfPremChannels(0), amountDue(0.0) {
	}
	char customerType;
	int numOfBasicServConn, numOfPremChannels;
	double amountDue;
	string accountNumber;
};

int readFile(ifstream& fin, Customer cust[]);
void compute_amountDue(Customer cust[], int size);
void printCustomerInfo(Customer cust[], int numOfCustomers);

int main()
{
	Customer cust[MAX_CUSTOMERS];

	ifstream fin("C:\\Users\\ryan\\Desktop\\inFile.txt");
	if (!fin)
	{
		cerr << "File failed to open!\n";
		return (1);
	}
	int numOfCustomers = readFile(fin, cust);

	compute_amountDue(cust, numOfCustomers);

	printCustomerInfo(cust, numOfCustomers);
	
	cin.ignore(10000, '\n');
	cin.get();
	return 0;
}

int readFile(ifstream& fin, Customer cust[])
{
	int x = 0;

	while (x < MAX_CUSTOMERS && fin >> cust[x].customerType) {
		if (cust[x].customerType == 'B')
			fin >> cust[x].accountNumber >> cust[x].numOfBasicServConn >> cust[x].numOfPremChannels;
		else if (cust[x].customerType == 'R')
						fin >> cust[x].accountNumber >> cust[x].numOfBasicServConn;
		else if (cust[x].customerType == 'E')
			fin >> cust[x].accountNumber;
		x++;
	}
		
	return x;
}

void compute_amountDue(Customer cust[], int size)
{
		for (int i = 0; i < size; i++)
		{
		if (cust[i].customerType == 'B') 
			cust[i].amountDue = BUS_BILL_PROC_FEES + BUS_BASIC_SERV_COST
				+ cust[i].numOfPremChannels * BUS_COST_PREM_CHANNEL;
		
			if (cust[i].numOfBasicServConn >= 10) 
			cust[i].amountDue += (cust[i].numOfBasicServConn - 10) * 
				BUS_BASIC_CONN_COST;
		
		else if (cust[i].customerType == 'R') 
			cust[i].amountDue = RES_BILL_PROC_FEES + RES_BASIC_SERV_COST;
		
		else if (cust[i].customerType == 'E') 
			cust[i].amountDue = EMP_BILL_PROC_FEES + (RES_BASIC_SERV_COST * 0.8);
	}
}

void printCustomerInfo(Customer cust[], int numOfCustomers)
{
	for (int i = 0; i < numOfCustomers; ++i) {
		cout << cust[i].customerType << " " << cust[i].accountNumber << " "
			<< cust[i].numOfBasicServConn << " " << cust[i].numOfPremChannels << " "
			<< cust[i].amountDue << '\n';
	}
}
Last edited on
Example input file from prof:

B12345 16 8
B12345 5 8
R12345 5
EXYZ001
B12346 16 18
B12346 15 8
R12346 50
EXxZ002
B12347 6 38
B12347 15 +8
R12347 5
EKAZ008
B12348 6 28
B12348 12 0
R12345 +5
I'm already using a struct and a constructor which weren't covered in chapters 1 - 8. But I would hope he wouldn't count off because I did extra research by consulting with you guys.

Your assignment instructions specifically allow the use of structures/classes:
Extra credit
Implement your program using arrays, covered in chapter 8, and user defined simple data types to hold customer data.

User Defined simple data types is another definition of a structure.

I know, I'm a little concerned about that as well.

I'd just increase the MAX_CUSTOMERS value to a larger value, something like 100. The way your program is now structured you should be okay.

One comment you may want to use the same variable name in your functions when passing it to your functions, for better documentation.

I'd also recommend passing an istream/ostream to your functions, then you can pass any input or output stream not just an ifstream or ofstream.

You would just change the function prototype and function implementation to:
int readFile(istream& fin, Customer cust[]);
The function calls stay the same.

I'd also be careful using the absolute file name ("C:\\Users\\ryan\\Desktop\\inFile.txt") and instead place inFile.txt in the proper directory and just use the current directory ("inFile.txt") as it's location. If your instructor actually runs your program he probably won't have that directory on his system.



Your assignment instructions specifically allow the use of structures/classes:


User Defined simple data types is another definition of a structure.


Okay. Good to know lol.

One comment you may want to use the same variable name in your functions when passing it to your functions, for better documentation.


Okay, so i just changed
void compute_amountDue(Customer cust[], int size)
to
void compute_amountDue(Customer cust[], int numOfCustomers)


I'd also recommend passing an istream/ostream to your functions, then you can pass any input or output stream not just an ifstream or ofstream.


I made that change as well.


I'd also be careful using the absolute file name ("C:\\Users\\ryan\\Desktop\\inFile.txt") and instead place inFile.txt in the proper directory


hmmm, okay I'll see if I can find out how to change it to the proper directory


I'm going to post my latest code which includes your suggestions and one or two minor adjustments.

After reading the prof's instructions again, I'm a little concerned about number's 5 and 6. I know it's not you guy's job to interpret what my prof is saying; however, I'm a little confused about what he means by #5 (Calculate the running average.....). Obviously, I know what an average is. What confuses me is his example output file has nothing like that so I don't know how/where he wants it. Also, for #6 (and at the end of the file you should....), is that something different than calculating the running average? ▼

5. Calculate the running average for residential and business customer spending
6. Print all customer's bill to a single file and the end of the file you should have the average summary for each customer type


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
//Program: Cable Company Billing
//This program reads an input file comprised of local customers for a cable
//company. The program then calculates the customer's bill and outputs the 
//bill to a file. The program processes three types of customers: business,
//residential, and employee.

#include <iostream>
#include <string>
#include <fstream>
#include <iomanip>

using namespace std;

//Named constants - residential customers
const double RES_BILL_PROC_FEES = 4.50;
const double RES_BASIC_SERV_COST = 20.50;
//Named constants - business customers
const double BUS_BILL_PROC_FEES = 15.00;
const double BUS_BASIC_SERV_COST = 75.00;
const double BUS_BASIC_CONN_COST = 5.00;
const double BUS_COST_PREM_CHANNEL = 50.00;
//Named constants - employee customers
const double EMP_BILL_PROC_FEES = 4.50;
const double EMP_BASIC_SERV_COST = RES_BASIC_SERV_COST * 0.8;
//Named constant - maximum customers
const int MAX_CUSTOMERS = 100;

struct Customer
{
	Customer() : customerType(' '), numOfBasicServConn(0), 
	numOfPremChannels(0), amountDue(0.0) {
	}
	char customerType;
	int numOfBasicServConn, numOfPremChannels;
	double amountDue;
	string accountNumber;
};

int read_File(istream& fin, Customer cust[]);
void compute_amountDue(Customer cust[], int numOfCustomers);
void output(Customer cust[], int numOfCustomers, ostream& os);

int main()
{
	Customer cust[MAX_CUSTOMERS];

	ifstream fin("inFile.txt");
	if (!fin)
	{
		cerr << "File failed to open!\n";
		return (1);
	}

	int numOfCustomers = read_File(fin, cust);

	compute_amountDue(cust, numOfCustomers);

	ofstream os("outFile.txt");
	if (!os)
	{
		cerr << "Could not open output file!\n";
		return (1);
	}

	output(cust, numOfCustomers, os); 	
	
	cin.ignore(10000, '\n');
	cin.get();
	return 0;
}

int read_File(istream& fin, Customer cust[])
{
	int x = 0;

	while (x < MAX_CUSTOMERS && fin >> cust[x].customerType) {
		if (cust[x].customerType == 'B')
			fin >> cust[x].accountNumber >> cust[x].numOfBasicServConn >> cust[x].numOfPremChannels;
		else if (cust[x].customerType == 'R')
						fin >> cust[x].accountNumber >> cust[x].numOfBasicServConn;
		else if (cust[x].customerType == 'E')
			fin >> cust[x].accountNumber;
		x++;
	}
		
	return x;
}

void compute_amountDue(Customer cust[], int numOfCustomers)
{
		for (int i = 0; i < numOfCustomers; i++)
		{
			if (cust[i].customerType == 'B') {
				cust[i].amountDue = BUS_BILL_PROC_FEES + BUS_BASIC_SERV_COST
					+ cust[i].numOfPremChannels * BUS_COST_PREM_CHANNEL;

				if (cust[i].numOfBasicServConn >= 10)
					cust[i].amountDue += (cust[i].numOfBasicServConn - 10) *
					BUS_BASIC_CONN_COST;
			}
		else if (cust[i].customerType == 'R') 
			cust[i].amountDue = RES_BILL_PROC_FEES + RES_BASIC_SERV_COST;
		
		else if (cust[i].customerType == 'E') 
			cust[i].amountDue = EMP_BILL_PROC_FEES + (RES_BASIC_SERV_COST * 0.8);
		}
}

void output(Customer cust[], int numOfCustomers, ostream& os)
{
	for (int i = 0; i < numOfCustomers; ++i) {
		os << cust[i].customerType << " " << cust[i].accountNumber << " "
			<< cust[i].numOfBasicServConn << " " << cust[i].numOfPremChannels << " "
			<< fixed << setprecision(2) << '$' << cust[i].amountDue << '\n';
	}
}
Do I need to create another struct for the average?
Topic archived. No new replies allowed.
Pages: 12