I am very new to C++ and am taking a beginners course in college. We have a project due this coming tues. and I am stuck, I was wondering if you could please help me.

Background on proj:
I am working in the circulation dept of a magazine, and it is time to send out this month's magazines.

What I am supposed to do:
This program is supposed to read in a master file of subscribers, produce labels that will be organized into 4 groups, and then print out an updated subscriber file that will remove all the expired subscribers.

These are the criteria for the labels:

1. labels for all the subscriptions which have not expired and do not end this month
2. labels for all the subscriptions which expire this month i.e. have an expiration date equal to the first line in the input file.
3. labels for all the subscriptions which have expired
4. a list of all subscriptions which have not expired.

The master file looks like this:
07/10
John Brown 2020 K St. Ste 300 Washington, DC 2005208/12
Mary Poppins5678 Lexington Ave. New York, NY 1001207/10
Micky Mouse 1234 Buena Vista Dr.Los Angeles, FL 2000507/09
Bernard Shaw 62 Magnolia Ave. Dublin, Ireland 9932407/11
Joe-AllennMikleshevs76799 Congress Ave. Rowlings, Wyoming 6655407/10
Gloria Stephenson77665 La Salle St. Arlington, Virginia 2200107/11
Pamela Herby 89765 North Star St.Denver, Colorado 3322407/10
Zermillo Frankel 788 51st Street San Fransisco, CA 9001107/09
Betty White 33216 23rd Street Chicago, Illionis 4567807/12
Donald Duck 3344 Duck Pond Ln. Kansas City, MO 6532106/08
Alan Smith 1232 Cedar Avenue Rockville, MD 2084707/11
Jane Alexander 93473 Rainbow Ave. Raleigh, NC 2761407/10

where the first name (1-10), last name (11-20), address (21-40), city and state (41-50), 5 digit zip code (61-65), and expiration date (66-70...given in dd/dd which is year and then month) are given in columns.

This is what I have for the compiler to read in the txt file:

#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int main(){
string line;
ifstream myfile ("hw2.dat.txt"); //hw2 is the txt file which has the master file information
if (myfile.is_open())
{
while(! myfile.eof())
{
getline (myfile, line);
cout << line << endl;
}

myfile.close();
}

All this does is copy the master file and prints it the same way that I have it printed in this message.

However, after that I am not sure how to get the compiler to read the master file, line for line. I am thinking that the compiler is supposed to take each of those lines, make it into an array, and then read columns 66-70 and check it against the user-inputted year/month. But I don't know how to do that.

I know this is long, but could you please guide me as to what I should do? I am pretty desperate since my project is due tuesday and I would appreciate any help.

Thanks so much

Hello,

Firstly, you need to surround your code with [code]

[/code] tags.

You shouldn't be using eof to control file input because it has a bug.

To read in a line use getline or something like that.

oh sorry about not surrounding my code with the tags, i will do it next time.

I used the eof because that is what cplusplus.com told me to do haha, i dont know anything about a bug.

ive never used getline, but looking at the function in my programming book, it says:
getline(cin, s, c) reads the characters from cin into s until c is encountered. so in my code would 'myfile' be the cin and 'line' be the array that the master file is being stored in?

if I am thinking about it correctly, does that mean that all of that data is right now in an array called 'line'? and so I could search for the elements in columns 66-70 to see if that value is greater than/less than/equal to the date that the user inputs?

The program is reading the file line by line as written. What it looks like you need to do is figure out a way to parse (break it up into definable chunks) each line. I think you can do it with the getline() version for C strings if you want.

Once you have the date string you will be able to compare that string with the first line of the file for equality, greater than or less than using strcmp() which is used to compare to C style strings.

Use getline like this

streamName.getline(stringToReadInto, maxNumberOfChars to read, delimiting char);

to read in the first name it would be something like this:

char firstName[11];
myfile.getline(firstName, 10, ' ');

You'll have to run a test program to determine whether it would be 10 or 11 as the second parameter of getline(), because I always forget whether you have to account for the null char or not. I don't think so, but you can find out.

So now I made my code look like:

int main(){
	string line;
	ifstream myfile ("hw2.dat.txt");
	if (myfile.is_open())
	{
		/*while(! myfile.eof())
		{
			getline (myfile, line);
			cout << line << endl;
		}

	myfile.close();
	}*/

	char firstName[11];
	myfile.getline(firstName, 10, ' ');
	cout << firstName << endl;
	}
	else cout << "Unable to open file";

but when I do that it will only print out:
07/10
Jo

why is that the output?

First, you can forget about my suggestion to use strcmp() to compare dates, it won't work. Sorry.

As to your last post, I'm guessing a liitle now, but here goes. The first line in the file is the date with a newline char after it that you don't see when reading the file. That would add up to 6 char. Then, on the next line the first word is John of which the first to letters are Jo. How does this relate to the code you wrote? To start out with you called getline() and told it to put information found at the start of the file into the variable firstName. Then you printed whatever was put in firstName to the screen. If the amount of information stored in firstName would be up 9 char plus the null terminating char added by getline() unless it finds the space character first, and there's no apparent space character on the first line or in John, then it almost makes sense since the output is 7/10 on one line and Jo on the next. I suspect if I had memorized all the exquisite details of getline() I could give you a more accurate description of what's happening, though I think this is a pretty accurate description of what's happened.

To correct it, read in the first line outside the loop and store it in it's own string. Then use a loop to read in the rest of the file.

Just winging it now, but if all you want to know is the date and the rest of the line you can basically ignore, then eventhough the characters that make up the date may not always be in range 66-71 (for example, the second line of the file as posted only has 56 char if I counted right), they are always the last 5 char of the line. So you could always find it by determining the length of the line, count backwards five and get it that way.

Here's how it might go
char line[80];
myfile.getline(line, 80);

The newline char in the line will be removed/ignored by getline() and getline will put a null terminating char at index equal to strlen(line). Find it by doing this:

int end = strlen(line);
if(line[end] == '\0')
cout << "true";

Now:
line[end - 5] will be 0
line[end - 4] will be 8
line[end - 3] will be /
line[end - 2] will be 1
line[end - 1] wil be 2

If that's all you need to do, that is you don't need to create a label with name on separate line from address, etc, then this might work to get it.

Thank you so much for your time and the informative post.

So I did not use getline() completely. I did some research online and thought that using substrings would be better. This is what my code looks like right now:

#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int main(){
	string s, s1, s2, s3, s4, s5, s6, s7, date;
	string yy, mm;
	char slash;
	ofstream outfile, expired, expiring, valid;
	outfile.open("expired.txt");
	outfile.open("expiring.txt");
	outfile.open("valid.txt");
	ifstream myfile;
	myfile.open("hw2.dat.txt");
	
	getline(myfile,date);
	yy = date.substr(0,2);
	mm = date.substr(3,2);
	
	cout << yy << mm << endl;

	while(! myfile.eof())
	{	
	getline(myfile,s);
	cout << s << endl;
	s1 = s.substr(0,9);
	cout << s1 << endl;
	s2 = s.substr(10,9);
	cout << s2 << endl;
	s3 = s.substr(20,19);
	cout << s3 << endl;
	s4 = s.substr(40,19);
	cout << s4 << endl;
	s5 = s.substr(60,5);
	cout << s5 << endl;
	s6 = s.substr(65,2);
	cout << s6 << endl;
	s7 = s.substr(68,2);
	cout << s7 << endl;
	
	if (s6 < yy){
		cout << "expired" << endl;
		expired.txt << "s1 s2 s3 s4 s5 s6" << endl;
	}
	else if (s6 == yy && s7 < mm){
		cout << "expired2" << endl;
		//write to expired file s1 s2 s3 s4 s5 s6 s7;
	}
	else if (s6 == yy && s7 == mm){
		cout << "expiring" << endl;
		//	write to expiring  file s1 s2 s3 s4 s5 s6 s7;
	}
	else		
		cout << "OK" << endl;
	//write to valid file s1 s2 s3 s4 s5 s6 s7;
	




	}
	
	return 0;

}

This code will run, however it will say that there is an unexpected error with runtime after it finishes running. Is there something wrong with my compiler or does the program have a bug?

I have two other questions also, if you could help me.

My first question is how do I put the seperated strings into three text documents, one for the expired, expiring, and not expired. As you can see in my code, I tried doing it but I don't think I did it right.

Also, I need to have an output which updates the subscriber list, getting rid of the expired subscribers.

Could you please guide me on how I should do that?

Thanks again so much for your time.

The runtime error is likely a bug in your program. Add thesd lines

int len = s.length();
cout << len << endl;
cin.get();

after this line:

cout << s << endl;

That should pause the program at let you see the output during runtime. It should pause the first time after reading in the second line of the file, as confirmed by cout << s << endl;. If len is less than 70 then the substr() approach won't work because there aren't 70 char in the string, meaning trying to access any memory beyond len will result in runtime error because memory beyond len doesn't belong to s. It's not a syntax error so the compiler won't catch it. It's an error only at runtime when you try to access memory not reserved for the variable you are working with. If len is 70 for every line read in, then the substr() approach should work okay, I would think.

To output to multiple files use multiple streams. You declared multiple output streams okay, but in the code below you only opened one, outfile:

outfile.open("expired.txt");
outfile.open("expiring.txt");
outfile.open("valid.txt");

I expect you should do this instead:

expired.open("expired.txt");
expiring.open("expiring.txt");
valid.open("valid.txt");

Then when you want to write to that file you call the stream name, not the file name. This (trying to open multiple files with the same stream) could be a runtime error, too, but I think it's more likely to be the len problem, though you'll be able to figure it out for yourself by debugging as I described.

At first glance, to update the subscriber list I would overwrite the original file with the contents of the valid file once the original file has been completely read in.

This article has been dead for over six months. Start a new discussion instead.