wont read input file, what's wrong?

Pages: 12
I'm trying to input a file into an array. I'm not looking for the entire code or anything as this is a homework assignment and I want to figure it out myself. I'm stuck on inputting the file correctly. As you can see from the input file below, the first input character IS a character followed by five digits. Would the functions I have below work? I have to be able to separate the character (B) so that i can place it in [each row][first column] as you can see. Otherwise, I would input it as a string but it seems more difficult to then separate the character for what I need to do? I typed an example of what the array should look like below. I may be going at this completely wrong and I'm sorry if I'm not making any sense. I'm doing my best to explain it but I'm still new. Any help would be greatly appreciated.

input file

B34568 15 8
1
2
3
  void getCustomerType(char customerType[]);

  void getData(int data[]);

custType accountNumber numServCon numChannels amountDue
B 56893 15 7 476.23
B 53246 23 4 545.67
R 23562 3 206.34
E 23562 34.55
Last edited on
An easy way would be to create a struct/class to deal with customers.
1
2
3
4
5
6
struct Customer
{
    char type;
    int accountNumber, numServCon, numChannels;
    double amountDue;
};


Then you can just do
void getData( Customer cust[], int size );

Though, I'd recommend using a vector rather than an array, so you can have an arbitrary amount of customers.
I'm trying to input a file into an array.

An array of what? You have multiple types in your file what type of variables are you planning to use?

What have you tried. If you use the correct data types this should be fairly easy using the extraction operator.

ps. Please don't open multiple topics for the same problem.
Sorry, I was trying to explain it more thoroughly in my second post and show what the output should look like. I won't do that again though. I see the example of my output came out well :/ lol. Thanks for the help. I was looking at trying to use structs; however, the class I'm taking only covers chapters 1 - 8 and structs don't start until chapter 9 so I'm assuming my professor doesn't want me to use structs. But if I have to then I will.
jlb - the arrays will be [5][5] with the variables from my messed up looking output example. Like I said I'm still new, so trying to answer what I think you're asking in words can be quite difficult for me. But I get extra credit for using user defined simple data types to hold the customer data. So I was thinking something like:

1
2
3
4
5
6
7
enum customerData {BUSINESS, RESIDENTIAL, EMPLOYEE};

customerData account;

string account;

inFile >> 


but obviously this isn't declaring any arrays. Sorry I'm being so vague.
Well if you actually started to write the program you would see that that approach is incorrect. You can't have a variable of two different types in the same scope (both customerData and string are types).

I'd start easier, you have 5 pieces of data, so define 5 variables of the proper types for the particular part of the file.

For example the last element in your file appears to be a floating point value, so create a variable with a floating point type where you can store that value.



Hmmm. Okay, I'm a little confused because this is the example in my book and I was thinking it would work similarly for my assignment:

1
2
3
enum courses {ALGEBRA, BASIC, PASCAL, CPP};

courses registered;

(then it explains how to read these values using two variables of type char)

and then goes on to say,
"You can also use the string type to input value in the variable registered. For example, the following code accomplishes this:"

1
2
3
4
5
6
7
8
9
10
string course;
cin >> course;
if (course == "algebra")
    registered = ALGEBRA;
else if (course == "BASIC")
    registered = BASIC;
else if (course == "pascal")
    registered = PASCAL;
else if (course == "cpp"
    registered = CPP;


but either way, you're probably right and I need to start with something easier.

For example the last element in your file appears to be a floating point value, so create a variable with a floating point type where you can store that value.

float amountDue[5][5];

does that work? I think where I'm getting stuck is when I remember that I'm trying to create an array and I also want functions to read the data. So instead of taking it step by step, I keep thinking about the big picture and it's causing me to doubt what I'm doing. If that makes sense.
can someone please tell me if I'm on the right track here? I'd really appreciate it

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
#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;
const double RES_COST_PREM_CHANNEL = 7.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 - number of customers
const int NO_OF_CUSTOMERS = 15;

struct Customer
{
	char customerType;			//customer's type
	int accountNumber, numOfBasicServConn, numOfPremChannels;	//customer's account, service connections, and channels	
	float amountDue;				//customer's amount due
};

//function prototype - reads and stores customer's type and initializes rest of array to zero
void initialize(ifstream& inFile, Customer list[], int listSize)
{
	int index;
	
	for (index = 0; index < listSize; index++)
	{
		inFile >> list[index].customerType;			//get customer's type

		list[index].accountNumber = 0;
		list[index].numOfBasicServConn = 0;
		list[index].numOfPremChannels = 0;
		list[index].amountDue = 0;
	}
}
For example the last element in your file appears to be a floating point value, so create a variable with a floating point type where you can store that value.

float amountDue[5][5];

Why the two dimensional array? Also unless you have "special" requirements you should prefer using a double over a float. Also as a first go, avoid the array. Once you can properly break apart one "line" it is easy to move to vectors or arrays. So start easier. Start by creating your main() function, and declare the proper variables (single instances) that you will need to read the stream.

So instead of taking it step by step, I keep thinking about the big picture and it's causing me to doubt what I'm doing.

Knowing the "big picture" is important but you need to be able to reduce that "big picture" to simple discrete steps. Part of the allure of functions is to be able to break the problem down into small parts, in this case start by reading one line and parsing that one line into the proper type of variables, and verifying that you did these steps correctly.

Hmmm. Okay, I'm a little confused because this is the example in my book and I was thinking it would work similarly for my assignment:

That's all well and good, however you tried to use the same variable name for both your enum instance and a string instance, that will not work. A variable can only have one type.

Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//function prototype - reads and stores customer's type and initializes rest of array to zero
void initialize(ifstream& inFile, Customer list[], int listSize)
{
	int index;
	
	for (index = 0; index < listSize; index++)
	{
		inFile >> list[index].customerType;			//get customer's type

		list[index].accountNumber = 0;
		list[index].numOfBasicServConn = 0;
		list[index].numOfPremChannels = 0;
		list[index].amountDue = 0;
	}
}


Why are you initializing all the rest of the variables to zero? Why not continue to read the rest of the file into the rest of the variables instead?

Also what happens if there are more or less records than listSize?


Where is your main()? If you have a complete program you can compile and run the program to see what problems there are. You need to compile early and often fixing any warnings or errors as you go along.


Last edited on
Okay, is what I just posted using the struct incorrect? I believe what you are saying is that I'm not comfortable enough yet to be trying to implement functions, arrays, structs, etc., so I should start small rather than overwhelming myself?

in this case start by reading one line and parsing that one line into the proper type of variables, and verifying that you did these steps correctly.

input file
B12345 16 8

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
using namespace std;

int main()
{
	ifstream inFile;
	string customerType;

	inFile.open("\\Users\\ryan\\Desktop\\inFile.txt");
	if (inFile.fail())
	{
		cout << "Could not open input file." << endl;
	}
	getline(inFile, customerType);
	cout << " " << customerType << endl;
	system("pause");
	return 0;
}


now to parsing that line into the proper type of variables. hmmmm
okay i just saw your last response. well because I'm taking bits and pieces from examples in the book lol and the example for structs read one piece of information, stored it and initialized everything else to zero. And then created the other functions for the rest of the data.
Okay this is what I have so far after using your suggestions. I believe it's now reading all of the variables. Sorry, brain is kind of fried right now. I know what i just did but now I'm having trouble figuring out what my next step is. Suggestions please?


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
#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;
const double RES_COST_PREM_CHANNEL = 7.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 - number of customers
const int NO_OF_CUSTOMERS = 15;

struct Customer
{
	char customerType;			//customer's type
	int accountNumber, numOfBasicServConn, numOfPremChannels;	//customer's account, service connections, and channels	
	float amountDue;				//customer's amount due
};

//function prototype -  reads and stores customer's data
void readData(ifstream& inFile, Customer list[], int listSize);

int main()
{
	ifstream inFile;
	string inputFile;

	Customer customerList[NO_OF_CUSTOMERS];

	inFile.open("\\Users\\ryan\\Desktop\\inFile.txt");
	if (inFile.fail())
	{
		cout << "Could not open input file." << endl;
	}
	getline(inFile, inputFile );
	cout << " " << inputFile << endl;
	system("pause");
	return 0;
}



//function definition for readData
void readData(ifstream& inFile, Customer list[], int listSize)
{
	int index;

	for (index = 0; index < listSize; index++)
	{
		inFile >> list[index].customerType			//get customer's type
			>> list[index].accountNumber
			>> list[index].numOfBasicServConn
			>> list[index].numOfPremChannels
			>> list[index].amountDue;
	}
}
Soooo I didn't even call the function in main huh.....
Also what happens if there are more or less records than listSize?

Would it be better if I used a while loop rather than for? If so, my textbook says for numeric data - the EOF-controlled while loop is better. And for text - the eof function is better. Do you find that this is the case? My input file contains both, granted only one character but still: B12345 16 8. My question is which one do you suggest I use, or am I completely off base with the while loop?
If so, my textbook says for numeric data - the EOF-controlled while loop is better. And for text - the eof function is better. Do you find that this is the case?

No, I find using a while loop that uses the actual read operation better. Also since you're using arrays instead of the much safer std::vector you need to also insure that you don't try to read more than the size of the array will allow.

Something more like:

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


using namespace std;


const int MAX_CUSTOMERS = 15;

struct Customer
{
	char customerType;			//customer's type
	int accountNumber, numOfBasicServConn, numOfPremChannels;	//customer's account, service connections, and channels
	double amountDue;				//customer's amount due
};

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

int main()
{
    Customer cust[MAX_CUSTOMERS];

    // Use the constructor to open the file instead of calling the open() function whenever possible.
    ifstream fin("\\Users\\ryan\\Desktop\\inFile.txt");
    if(!fin)
    {
        cerr << "File failed to open!\n";
        return(1); // Stop the program because of error.
    }
    int numberCustomers = readFile(fin, cust);

    // You'll probably want to print all the information to verify that you read the file correctly.
    for(int i = 0; i < numberCustomers; ++i)
        cout << cust[i].customerType << " " << cust[i].accountNumber << " "
             << cust[i].amountDue << endl;
}

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

    // Limit the loop to the size of the array, and stop processing when you get a read error, usually eof.
    while(counter < MAX_CUSTOMERS && fin >> cust[counter].customerType
                                         >> cust[counter].accountNumber
                                         >> cust[counter].numOfBasicServConn
                                         >> cust[counter].numOfPremChannels
                                         >> cust[counter].amountDue)
    {
        counter++;
    }


    return counter;  // This is the actual number of customers read.
}
Okay, thanks a lot man. I'm going to look into using a vector and take some of your other suggestions. I'm sure I'll have more questions. Thanks again
can someone please tell me what i've done incorrectly that it won't output my file of:

B12345 16 8


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

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

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 << " "
		<< cust[i].amountDue << endl;
	
	return 0;
}

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

	while (x < MAX_CUSTOMERS && fin >> cust[x].customerType
		>> cust[x].accountNumber
		>> cust[x].numOfBasicServConn
		>> cust[x].numOfPremChannels
		>> cust[x].amountDue)
	{
		x++;
	}
	return x;
}
It looks like your file doesn't contain all of the fields you're trying to read so the read operation fails and nothing is inserted into your array.



First check the value of numOfCustomers after reading the file, use a debugger or add a cout message.

When I tried it, the value was zero. So something is going wrong in the readFile() function.

A quick glance at the data:
B12345 16 8
and then at the file input statement shows a mismatch. There is nothing in the file to be read into the variable cust[x].amountDue, hence the fin fail flag is set, meaning the statement x++; is not executed because the while condition is false.

As a temporary hack to see what would happen, I tried this:
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
int readFile(ifstream& fin, Customer cust[])
{
    int x = 0;

    while (x < MAX_CUSTOMERS && fin >> cust[x].customerType
        >> cust[x].accountNumber
        >> cust[x].numOfBasicServConn
        >> cust[x].numOfPremChannels
//      >> cust[x].amountDue
        )
    {
        x++;
    }
    return x;
}

With line 46 commented out, I got this output:
B 12345 16 8 1.4822e-323

The last figure is the uninitialised variable.

This isn't a solution, but a way of looking at what is happening.

If different records have different items present, then limit the part read inside the while loop to that which should always be there, and read the rest as required inside the function body.
Last edited on
I'm not sure why but I thought that it would just print 0.0 for cust[x].amountDue but obviously it doesn't work like that. I added some if/else and removed
amountDue
from the function. I just tried all of the inputs my prof posted as an example and it's returning bits and pieces of the last three input lines?

input:
B12345 16 8
B12345 5 8
R12345 5
EXYZ001
B12346 16 18
B12346 15 8
R12346 50
EXxZ002
B12347 6 38
B12347 05 +8
R12347 5
EKAZ008
B12348 6 28
B12348 12 0
R12345 +5
EABC004


output:
E ABC004 12 5


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

const int MAX_CUSTOMERS = 15;
struct 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;
	
	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;
}
Pages: 12