.txt file question

Hey all, I have a big program project that I'm working on that's supposed to do the following: "The multiple mailings option of your menu should read a text file named Mailings.txt and display to the console all the information that was displayed in Project 2 for each mailing in the file. When the user selects the multiple mailings option, the mailing labels should be created and displayed for every mailing in the file without the user needing to do anything else. The Mailings.txt file contains 5 mailings, but your program must be able to process an identically formatted file with any number of mailings.
If a user selects the multiple mailings option, your program should calculate and display the total cost of all the postage in the text file. After displaying all the mailing labels, display the total amount of postage owed. Format the total cost of the postage in dollars and cents."

My problem is, I've never used, displayed, opened, ect any file of any kind. I just learned about this. You can see at the very bottom of the program I have so far what I'm trying to do, I just don't know exactly what next step to take. Not only do I need to be able to display multiple different shipping labels should the user input more than one, I also have to have the program calculate the total postage cost. I've worked at this program for a little while now as you can see and my head is kinda bogging down now, between the writing and the tons of reading haha.
Here's the code 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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
  //This program formats a shipping label with a pseudo barcode for printing and placing on a package.
#include<iostream>
#include<string>
#include<fstream>
using namespace std;

int main()
{
	int input; //To hold user mailing choice input. 
	string name, streetAddress, city, state, zipcode; //To hold user location input information.
	int number; //To hold the user number input information.
	const double cost1=0.49, cost2=0.98, cost3=2.54, addCharge1=0.22, addCharge2=0.20; //To hold the given constants.
	const int singleMail=1, multiMail=2, quitMail=3
	double weight; //To hold user input data.
	
	//Gather user input data.
	do
	{
		//Display Menu
		cout<<"Mailing Options Menu:\n\n";
			<<"1. Single Item Mailing\n";
			<<"2. Multiple Item Mailing\n";
			<<"3. Quit Program\n";
		cin>>input;
		
		//Validate the user's input.
		while (input<singleMail||input>quitMail)
		{
			cout<<"Invalid input, please enter a valid input:";
			cin>>input;
		}
		
		//Response to user's input.
		switch (input)
		{
			case singleMail:
				cout<<"Please enter your name:";
				getline(cin, name);
				cout<<"Please enter your street address:";
				getline(cin, streetAddress);
				cout<<"Please enter your city:";
				getline(cin, city);
				cout<<"Please enter your state:";
				getline(cin, state);
				cout<<"Please enter your zipcode:";
				cin>>zipcode;
				cout<<"Please enter 1 for letter, 2 for envelope or 3 for parcel:";
				cin>>number;
				cout<<"Please enter item's weight in ounces:";
				cin>>weight;
				
				//Calculate the cost of the item based off of type and weight.
				if (number==1&&weight<=1)
					cout<<"******************************"<<cost1<<"\n\n";
				else if (number==1&&weight>1)
					cout<<"******************************"<<cost1+(weight*addCharge1)<<"\n\n";
				else if (number==2&&weight<=1)
					cout<<"******************************"<<cost2<<"\n\n";	
				else if (number==2&&weight>1)
					cout<<"******************************"<<cost2+(weight*addCharge1)<<"\n\n";
				else if (number==3&&weight<=3)	
					cout<<"******************************"<<cost3<<"\n\n";
				else if (number==3&&weight>3)
					cout<<"******************************"<<cost3+(weight*addCharge2)<<"\n\n";
				else 
					cout<<"Invalid input, restart program."<<endl;
					
				//The following will output the address information based off the user input.
				cout<<name<<endl;
				cout<<streetAddress<<endl;
				cout<<city<<", "<<state<<" "<<zipcode<<"\n\n";
				
				//The following converts the user input zipcode into a barcode.
				string result;
				char digit;
				int checkSum;
				{
   				if (digit == '0')
        			result= "||:::";
   				else if (digit == '1')
       				result= ":::||";
   				else if (digit == '2')
       				result= "::|:|";
   				else if (digit == '3')
     	    		result= "::||:";
  				else if (digit == '4')
   	    			result= ":|::|";
  				else if (digit == '5')
            		result= ":|:|:";
   				else if (digit == '6')
        			result= ":||::";
    			else if (digit == '7')
        			result= "|:::|";
    			else if (digit == '8')
        			result= "|:::|";
   				else if (digit == '9')
        			result= "|:|::";
    			else
        			result= "Invalid";
        		}
        		
        		result=zipcode;
        		checkSum=(zipcode%10)
        		
        		cout<<"| "<<zipcode<<checkSum<<" |"; //Displays barcode.
        		
        	case multiMail:
        		ofstream outputFile;
        		int numberOfMailings //To hold user input amount of items being mailed. 
        		double postage //To hold cost of postage
        		
        		//Get number of items being sent.
        		cout<<"How many seperate items are you sending today?";
        		cin>>numberOfMailings;
        	
        		//Open a file named Mailings.txt
        		outputFile.open("Mailings.txt");
        		
        		//Get the info for each item being mailed and write it to the file. 


Thanks to any and all help in advance.

Hello cmangum3,

While I look at the code maybe you could post the input file that you are using? It does help.

Andy
Hey Handy Andy,

So the input file is supposed to ask for user input, getting the type of item to be mailed, name, address, city, state and zipcode. Then it calculates the cost of postage followed by a barcode in the format as seen below:

**************************$0.93

Larry Smith

122 Main Street

Charlotte NC 23499

|::|:|::||::|::||:|::|:|::::||:|

My input system for getting all this info and displaying it is found in lines 36-105.
Hello cmangum3,

When I first started working with file streams I developed this code. One reason was to make it easier to use by always using the same variable name for the input file. The other reason was to make it generic so all I had to do is add the file name in the first line.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
std::string iFileName{ "Mailings.txt" };

std::ifstream inFile;

inFile.open(iFileName);

if (inFile.is_open())
{
	std::cout << "\n File " << iFileName << " is open" << std::endl;
	std::this_thread::sleep_for(std::chrono::seconds(2));  // <--- Needs header files chrono" and "thread".
}
else
{
	std::cout << "\n File " << iFileName << " did not open" << std::endl;
	std::this_thread::sleep_for(std::chrono::seconds(3));  // <--- Needs header files chrono" and "thread".
	exit(1);
}

As you become more familiar with working with file streams you will come to learn how this code can be shortened.

The program that you write generally looks in the sub directory that contains the ".cpp" files for the program. When you open a file for output you can find that sub directory.

Now when you get the input file stream opened and working you will need to decide if you want to read the file and store the information or if you just need to read the file and process what is there.

I do not know if there is anything beyond line 119, but I do know it is at least missing the closing braces.

Just a suggestion, I like to put my variables defined as "const" at the beginning. In this case it would be the beginning of main or at the beginning of the file like where the line using namespace std; is that is best not to use. This way these constant variable are at the beginning where they are easy to find when they need to be changed. Also I, as many other do, is to use capital letters for the variable name. This way you know it is defined as a constant and it can not be changed.

As with any program work in small steps or parts, get it working and move on the the next. Once you get the input file working the output will be much easier.

You have a good start with your output file, but it could use some work.

Hope that helps,

Andy
Hello cmangum3,

That is great for getting user input, but I meant what does the file "Mailings.txt" look like. Half of the battle of reading a file is knowing what is in the file and how it is laid out.

Andy
Yes it helped a little bit, but I'm still confused as to how to have the info input into the file.

This is what I've now added to it. But my question is, do I have to prompt the user to re-input all the information for a new package, address, ect for each package they want to add to the file?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
case multiMail:
        		ofstream outputFile; //File stream object.
        		
				//Get number of items being sent.
        		cout<<"How many seperate items are you sending today?";
        		cin>>numberOfMailings
        		
        		//Open the given file.
				outputFile.open("Mailings.txt");
        		
        		//Get the info for each item being mailed and write it to the file.
        		for (int count=2; count<=numberOfMailings; count++)
        		{
        			cout<<"Enter the mailing info for address"<<count<<": ";
        			
				}


So do I now prompt the user to do this now?:

cout<<"Please enter your name:";
getline(cin, name);
cout<<"Please enter your street address:";
getline(cin, streetAddress);
cout<<"Please enter your city:";
getline(cin, city);
cout<<"Please enter your state:";
getline(cin, state);
cout<<"Please enter your zipcode:";
cin>>zipcode;
cout<<"Please enter 1 for letter, 2 for envelope or 3 for parcel:";
cin>>number;
cout<<"Please enter item's weight in ounces:";
cin>>weight;

//Calculate the cost of the item based off of type and weight.
if (number==1&&weight<=1)
cout<<"******************************"<<cost1<<"\n\n";
else if (number==1&&weight>1)
cout<<"******************************"<<cost1+(weight*addCharge1)<<"\n\n";
else if (number==2&&weight<=1)
cout<<"******************************"<<cost2<<"\n\n";
else if (number==2&&weight>1)
cout<<"******************************"<<cost2+(weight*addCharge1)<<"\n\n";
else if (number==3&&weight<=3)
cout<<"******************************"<<cost3<<"\n\n";
else if (number==3&&weight>3)
cout<<"******************************"<<cost3+(weight*addCharge2)<<"\n\n";
else
cout<<"Invalid input, restart program."<<endl;

//The following will output the address information based off the user input.
cout<<name<<endl;
cout<<streetAddress<<endl;
cout<<city<<", "<<state<<" "<<zipcode<<"\n\n";

//The following converts the user input zipcode into a barcode.
string result;
char digit;
int checkSum;
{
if (digit == '0')
result= "||:::";
else if (digit == '1')
result= ":::||";
else if (digit == '2')
result= "::|:|";
else if (digit == '3')
result= "::||:";
else if (digit == '4')
result= ":|::|";
else if (digit == '5')
result= ":|:|:";
else if (digit == '6')
result= ":||::";
else if (digit == '7')
result= "|:::|";
else if (digit == '8')
result= "|:::|";
else if (digit == '9')
result= "|:|::";
else
result= "Invalid";
}

result=zipcode;
checkSum=(zipcode%10)

cout<<"| "<<zipcode<<checkSum<<" |"; //Displays barcode.

I feel like there's something big I'm missing but again, I'm very new to this and to be honest, my professor has kinda left me on my own, providing little to know pointers. So I'm pretty much forced to figure this stuff out on my own, but I have a due date. This wouldn't be hard if I didn't work a job and have other classes, I just simply don't have time to fool around for hours on end and figure it out myself. This is all part of my big delima XD

Hello cmangum3,

When I strarted working with the program I found something missing on line 13. This will be a compiler error to figure out.

lines 38 - 40 all end with ';'s you do not need.

Line 103 mod only works on "int"s you are trying to use this on a string. You will eithe need to store this number as an "int" or change it to an "int" before you do the "% 10".

Lines 109 and 110 has the same problem as line 13.

The do/while is missing the while in what you posted.

The other errors I will have to work on tomorrow. Also I will work on the new code tomorrow.

Like I said earlier, small steps. It looks like a lot of the program is done and you just need to finish what you do not have.

Hope that helps,

Andy
Hello cmangum3,

I noticed in an earlier message you said:
So the input file is supposed to ask for user input
No the input file provides information so you do not have to ask the user for input.

The problems I see in the last bit of code for case "multiMail" line 6 has a problem the fact that line 9 is indented gives you a hint that there is a problem above line 9. I do not know if you are using an IDE or which one, but the better ones should tell you of a problem before you compile the program and a compile of the code will tell you of any problems that need fixed. You need to compile the program begore you post the code. This way you can put any error messages in your message that you do not understand.

Yes in case "multiMail" you will have to prompt the user for information and the rest. What you should be doing is putting the code that is used more than once into functions. This way in the case statements all yo have to do is call the function.

For the function that would get the user input all the variables need should be passed by reference, so that changes to these variables will be reflected back to where they are defined.

In "multiMail" you have opened an out put file to use, but you never make use of this file nor do I see where you close the file stream. "cout" writes to the screen not to your output file which would be "outputFile <<". You can open your files in the case statements, but it would be better to open these files at the beginning of main and close them just before the final "return" statement. This way the files are available while the program is running especially the output file. The input file can be closed when you are done reading the file.

When you have code, as with the code you have not between code tags, this is a good indication that it should be in one or more functions. And the basic idea of the function is that it does one thing which may or may not return something.

I have a little to work with I will see what I can come up with.

Hope that helps,

Andy
Hello cmangum3,

I have been working with your program and have changed some things around then I went to reread the requirements of the program and after reading the first line:
"The multiple mailings option of your menu should read a text file named Mailings.txt and display to the
console all the information that was displayed in Project 2 for each mailing in the file.
I realized that the "multiMail" case is all wrong.

As it says I need to know what the "Mailings.txt" file looks like to know if what I have that reads the file is correct and I have no idea what was done in "Project 2", i.e., what did the output look like? You are asking for help on this project based on what was done in the previous project , but failed to show what was done in "Project 2", so I have nothing to go by which makes it hard to advise on what you should do here.

I find that if you break up the requirements of the program like this:
"The multiple mailings option of your menu should read a text file named Mailings.txt and display to the
console all the information that was displayed in Project 2 for each mailing in the file.

When the user selects the multiple mailings option, the mailing labels should be created and displayed for
every mailing in the file without the user needing to do anything else.

The Mailings.txt file contains 5 mailings, but your program must be able to process an identically formatted
file with any number of mailings.

If a user selects the multiple mailings option, your program should calculate and display the total cost
of all the postage in the text file.

After displaying all the mailing labels, display the total amount of postage owed.
Format the total cost of the postage in dollars and cents."
it helps to understand the smaller parts that need to be done.

I believe that what you did for the single case is OK, but this is what I did to change it around:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
case singleMail:
	GetUserInput(name, streetAddress1, streetAddress2, city, state, zipCode, number, weight);

	//Calculate the cost of the item based off of type and weight.
	CalculateWeight(number, weight);

	//The following will output the address information based off the user input.
	PrintInfo(name, streetAddress1, streetAddress2, city, state, zipCode, number, weight);

	//The following converts the user input zipCode into a barcode.
	checkSum = (std::stoi(zipCode) % 10);
	result = CreateBarCode(zipCode + std::to_string(checkSum));

	//result = zipCode;  // <--- Overwrites the return value of the previous function.

       //Displays barcode.
	std::cout << "| " << result << " | " << zipCode << checkSum << " |";
 
	break;  // <--- This was missing in both cases. 

As you can see I have taken most of the code and put it into functions to make them easier to use in multiple places.

The prototypes for these functions are:
1
2
3
4
5
6
7
void GetUserInput(std::string& name, std::string&streetAddress1, std::string&streetAddress2,
	std::string& city, std::string& state, std::string& zipCode, int& number, double& weight);
std::string CreateBarCode(const std::string zipCode);
double CalculateWeight(const int number, const double weight);
int MainMenu();
void PrintInfo(const std::string& name, const std::string&streetAddress1, const std::string&streetAddress2,
	const std::string& city, const std::string& state, const std::string& zipCode, const int number, const double weight);

These are the functions I created to streamline the program. If you need help understanding or creating these functions let me know.

Now I am going to scrap what is in the "multiMail" case and start over.

Hope that helps,

Andy
Oh gotcha, I'm sorry for not adding Project 2 requirements.
They are as follows:

"The postage due is based on whether the mailing is a letter, a large envelope or a parcel. Prompt the user for the type of item they are mailing and the weight of the item. Use the following criteria to calculate the postage and display it on the mailing label as shown in the Sample Output.
Postage for letters is $0.49 for letters weighing one ounce or less. An additional $0.22 per ounce is added for every ounce (or part of an ounce) over one ounce. For example, a letter that weighs 2.1 ounces will cost $0.49 + (2 * $0.22) = $0.93 to mail.
Postage for large envelopes is $0.98 for envelopes weighing one ounce or less. An additional $0.22 per ounce is added for every ounce (or part of an ounce) over one ounce. For example, a large envelope that weighs 0.5 ounces will cost $0.98 to mail.
Postage for parcels is $2.54 for parcels weighing three ounces or less. An additional $0.20 per ounce is added for every ounce (or part of an ounce) over three ounces. For example, a parcel that weighs 5.5 ounces will cost $2.54 + (3 * $0.20) = $3.14 to mail."

So essentially, the requirements are to ask the user to enter item type (letter, parcel, envelope) then enter their name, address, city, state, zipcode. The program then calculates the cost of postage based off the input, displays the shipping name and address, then uses the user input zipocde to print a barcode at the bottom. The output has to look like this:


**************************$0.93

Larry Smith

122 Main Street

Charlotte NC 23499

|::|:|::||::|::||:|::|:|::::||:|

Now what's different in project 3 (this project) is that it needs to include this plus a menu option for multi mailing. (As explained above). On top of this, it needs to calculate total cost of postage if the user has multiple items being shipped. The output format that was given as an example looks like this:

Welcome to the Mailing Label Printing System

1 – Single Mailing

2 – Multiple Mailings

3 -- Quit

Enter your choice: 1

Enter name : Larry Smith

Enter street address: 122 Main Street

Enter city: Charlotte

Enter state: NC

Enter zip code: 23499

Enter 1 for letter, 2 for envelope, 3 for parcel: 1

Enter weight in ounces: 2.1



**************************$0.93

Larry Smith

122 Main Street

Charlotte NC 23499

|::|:|::||::|::||:|::|:|::::||:|


1 – Single Mailing

2 – Multiple Mailings

3 -- Quit

Enter your choice: 2


**************$2.94

Ann Perkins

217 Lowell Drive

Pawnee IN 47408

|:|::||:::|:|::|||:::|::|:|:::||


**************$1.42

Ron Swanson

3657 White Bridge Road

Eagleton IN 47320

|:|::||:::|::||:::|:|||::::|::||

ect..... ect....

Ok I read through your program prototypes and they seem to make sense. We haven't relly learned how to use the "void" function though if I recall correctly. So I'm not sure what that's about.

To make sure I'm understanding this right, case singleMail example you gave streamlines the user input so I don't have to repeat it and it shortens the overall program right? So I should replace my case singleMail part with that format?
Hello cmangum3,

OK seeing the requirements for "Project 2" helps. Is see in "2" all you needed to do is get input from the user and display it on the screen. Simple enough. Now you are being asked to expand the last program to include reading a file.

The case for "singleMail" is OK and works. You should have just picked that up from the last program. I had to do some adjusting in the case to have everything come out correctly.

For the "multiMail" case I scraped what you had and started over with what I had to work with.

Let me emphasize this differently
"The multiple mailings option of your menu should read a text file named Mailings.txt and display to the
console all the information that was displayed in Project 2 for each mailing in the file.
Without this file anything I tell you about reading this file is likely to be wrong. When you have to read a file the first thing you have to know is what the file looks like. It makes a difference on how you write the code to read the information.

All the type "void" means is that the function do not return anything. Other than that it has no special meaning here.

To make sure I'm understanding this right, case singleMail example you gave streamlines the user input so I don't have to repeat it and it shortens the overall program right? So I should replace my case singleMail part with that format?
You do not have to, but it does clean up the case to use C++ more as it was designed for. In the end it is up to you based on what you know at this point and what you want to learn and do. I believe that some of the things I have showed you are likely to be far beyond what you know. No worries I will explain what you so not understand.

I do not think I have said much about the "singleMail" case. In your original code the first part getting the user input is OK and works. The next part to calculate the postage I did this way:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
double CalculatePostage(const int number, const double weight)
{
	double postage{};

	if (number == 1 && weight <= 1.0)
		postage = cost1;
	else if (number == 1 && weight > 1.0)
		postage = cost1 + (weight * addCharge1);
	else if (number == 2 && weight <= 1.0)
		postage = cost2;
	else if (number == 2 && weight > 1.0)
		postage = cost2 + (weight * addCharge1);
	else if (number == 3 && weight <= 3.0)
		postage = cost3;
	else if (number == 3 && weight > 3.0)
		postage = cost3 + (weight * addCharge2);
	else
		std::cout << "\nInvalid input, restart program." << std::endl;

	std::cout << "\n*****************************$" << postage << "\n\n";

	return postage;
}

The function definition starts out with "double" this is the return value type. Next I changed the name of the function to better describe what the function does This is not necessary, but helps. In the () are the parameters passed to the function. They start with "const" so the compiler knows that they can not be changed and if you try the compiler will consider this an error and stop. I changed the if/else if statements to use it in a way that makes more sense. The last "cout" statement I changed the last '*' to the '$' because I like it better. You can change that back if you need to.

After printing out the name address etc. you will have to create your bar code. I changed the order to this:
1
2
checkSum = (std::stoi(zipCode) % 10);
result = CreateBarCode(zipCode + std::to_string(checkSum));

because if I remember correctly you need to add the "checkSum" to the "zipCode" before you create the bar code. As you can see I had to change the "zipCode" to an "int" before doing the "% 10" then in the next line I had to change "checkSum" ot a string before adding it "zipCode" to sent the new string to the "CreateBarCode" function.

Next is the line to print the bar code, zip code and the check sum number.

The last line of the case is a "break" statement to exit the switch. Otherwise the next case will execute.

For the "multiMail" case I scraped what you had and started over. This is what I came up with:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
case multiMail:
	while (ReadFile(inFile, name, streetAddress1, streetAddress2, city, state, zipCode, number, weight))
	{
		totalPostage += CalculatePostage(number, weight);

		PrintInfo(name, streetAddress1, streetAddress2, city, state, zipCode, number, weight);

		checkSum = (std::stoi(zipCode) % 10);
		result = CreateBarCode(zipCode + std::to_string(checkSum));

		std::cout << "| " << result << " | " << zipCode << checkSum << " |"; //Displays barcode.
	}

	std::cout << "\n\n Total postage is $" << std::setw(5) << totalPostage << std::endl;

	break;
case quitMail:
	cont = false;
	break;

The while condition is likely strange to you. It is not that hard to understand. The functions parameter is everything the the function will need to read the file. The function returns a bool, so the only return values are false or true. As long as the return value is true the while loop will keep reading the and processing the file. When the return value is false the while loop fails and your processing is done.

The next line calls the function to calculate the postage cost. The return value is a double and the "+=" adds each return value to the "totalPostage" variable.

Everything from "PrintInfo" to the closing brace of the while loop should make sense to you.

After the while loop I just printed the total postage of what was read from the file.

finishing with the break statement.

The last case statement I added.

Hope that helps,

Andy
Hey Handy Andy,

Thank you so very much for your time and dedication to this question, it means a lot.

Sorry for my periodic responses, I've just been busy, like I said, this class doesn't fit well at all with my other ones, or my day to day life haha

I'm working on putting it all together with the help and examples you provided and I'll get back to you as soon as I can, hopefully by later tonight.

Again, thank you so much for your time. I have learned more here than I probably have in class so that's a plus haha

Topic archived. No new replies allowed.