Click here to Skip to main content
14,664,481 members
Rate this:
Please Sign up or sign in to vote.
See more:
So for my program, I'm trying to use an array of structs to store a list of data from a separate txt. file. I figured out how to store each respective item into the appropriate array when I have a predetermined array size of 100. I created a while loop to try to prevent the data from being read into the arrays after there is no more data, but inserting a "count" variable and counting the number of iterations, but to no avail. Can anyone point me in the right direction of what's wrong with my loop based on the code below(I took out the count variable because whenever I use it, it messed up my output):


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

using namespace std;



struct Computer
{
	string Model;
	string Manu;
	int Price;
	string ARRAY1[100];
	string ARRAY2[100];
	int ARRAY3[100];
	
};

void getComputer(Computer&, ifstream&, ofstream&);

int main()
{
	Computer data;

	ifstream iFile;
	ofstream oFile;
	iFile.open("CompSys.txt");
	oFile.open("CompLog.txt");


	getComputer(data, iFile, oFile);
	
	iFile.close();
	oFile.close();
	return 0;


}

void getComputer(Computer& data, ifstream& iFile, ofstream& oFile)//, Computer& alldata)
{

	int Idx;
	
	int counter =100;

	while(iFile)
	{
	for( Idx = 0; Idx < counter; Idx++)
	
	{
	getline(iFile, data.Model, '\t');
	data.ARRAY1[Idx] = data.Model;
	
	getline(iFile, data.Manu, '\t');
	data.ARRAY2[Idx] = data.Manu;

	iFile >> data.Price;
	data.ARRAY3[Idx] = data.Price;

	}
	data.numItems = Idx;

	}
}



Below is the txt. that the cpp file reads from:

Professional AP500	Compaq	2337
Dimension 4100	Dell	1609
Dimension 8100	Dell	1808
Precision Workstation 620	Dell	2848
AMD Athlon Thunderbird	Explorer Micro	717
Profile 3cx	Gateway	1999
e-Vectra P2024T	Hewlett-Packard	2619
PowerMate VT300	NEC Computers	1160
PCV-RX270DS	Sony	1478
PCV-RX370DS	Sony	1699
Posted
Comments
Timberbird 22-Nov-11 1:48am
   
Maybe I misunderstood your question - do you actually use these lines:
int counter =100;
...
for( Idx = 0; Idx < counter; Idx++)
?
They force your program to attempt to read 100 lines from a file before a new check on file eof is done.
BTW, wouldn't it be better to use
while(!iFile.eof())?
CeePlusNewb 22-Nov-11 2:46am
   
The for loop was necessary to create the parameters for the arrays, but I'm having trouble with the middle argument. I only set it to 100 to be certain that there were enough cells in the array to hold the information. However, I want the program to stop filling the array's cell once it gets to the end of the txt. file.
Timberbird 22-Nov-11 4:05am
   
Then you should leave while cycle only, with file eof as an exit condition. Inside the loop you read new structure, add it to array and increase Idx value by one (it should be set to zero before loop). If Idx value reaches 100, you should also exit the while loop, like that:

int Idx=0;

while(!iFile.eof() and Idx<100)
{
// read data here
++Idx;
}

As to using arrays of fixed length - you should really consider replacing them with more convenient objects. std::list or std::deque from STL could help here.
CeePlusNewb 22-Nov-11 11:52am
   
That did the trick! thanks so much man. I appreciate it!

Rate this:
Please Sign up or sign in to vote.

Solution 1

You want to create a vector[^] (or some other container) of the struct. This way the struct can hold all the data, and only the data, of a single instance of a Computer.
See vector::end()[^] for an example of how to iterate through all the elements in the container


#include <fstream>
#include <iostream>
#include <iomanip>
#include <cmath>
#include <string>
#include <vector>
 
using namespace std;

//This holds the data for a single instance of a computer
struct Computer {
	string Model;
	string Manu;
	int Price;
};

//And this is the type of our collection, a vector of Computers
typedef vector<Computer> ComputerList;
 
void getComputer(Computer&, ifstream&, ofstream&);
 
int main() {
	ComputerList data;
 
	ifstream iFile;
	ofstream oFile;
	iFile.open("CompSys.txt");
	oFile.open("CompLog.txt");

	getComputer(data, iFile, oFile);
	
	iFile.close();
	oFile.close();
	return 0;
}
 
void getComputer(ComputerList& list, ifstream& iFile, ofstream& oFile) {
	int Idx;
	int counter =100;
	while(iFile) {
		for (Idx = 0; Idx < counter; Idx++) {
			Computer data;
			getline(iFile, data.Model, '\t');
			getline(iFile, data.Manu, '\t');
			iFile >> data.Price;
			list.push_back(data); //Add the computer to (the back/end) of the collection
		}
	}
}


This is just my changes yo your code, I have not tested it to make sure it works.
   
Rate this:
Please Sign up or sign in to vote.

Solution 2

In addition to what Andrew suggested:

1. don't mix getline() or similar functions alternating with input stream operators. It will just mess up your reading order since these functions behave differently. Maybe it works, maybe it doesn't. but if it doesn't, I promise it will be very tough to fix.

My suggestion is to use getline() without specifying a separator to get the entire line, then split it into individual tokens, see if you actually get the right number of tokens (and deal with the error if you don't), and then store them in your data structure.

You could do the same with an ifstream, only that you must be careful whether or not it will swallow the newline character (IIRC it doesn't!). If it does, you cannot test the number of arguments and must hope that the entire file is well-formatted and correct. If it doesn't you must test for it's presence and cut it from your input string.

2. Get rid of that for loop. If you start with the variant Andrew suggested in solution 1, then you can just erase the start and end lines of the for loop.
   

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)




CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100