Changing values and storing new values in file

Pages: 12
Hi guys its just a simple code in which it has a fixed price in a file but I want to add more price with the exciting price so it can be the new price. I tried on it but i am stuck in changing the price and I am also stuck in changing the price in a file I want if I change the price then the price also change in the file too the price is written in the string and for to add more price I want to add a float type data but I am getting an error. Here is my code if anyone can help me.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include<iostream>
using namespace std;
string cost;
ifstream things("data.txt",ios::app|ios::in|ios::out);
while (things.ignore(21) && std::getline(things, cost))
{
main:
  system("cls");
  system("color 5f");
  cout << "cost Is    " << cost;
  cout<<"\nEnter 1 For add More Money With The Existing Cost";
  string adds;
  cin>>adds;
  if(adds=="1")
  {
     float add;
     cout<<"Add cost:  ";
     cin>>add;
     cost=add+cost;
     goto main;
  }
}
Hello adeel zamann,

First off your code will not compile or run.

You are missing header files and the "main" function"

"main:" is a label for a "goto" statement not the main function and you should avoid using the "goto" statement if at all possible. Using loops work much better.

If your decimal values are small a "float" may work, but these days a "double" is the preferred floating point choice.

Your program uses an input file. It is very helpful if you post the input file. If it is large then enough to demonstrate what it looks like and enough examples to demonstrate any problems that you are having.

I can see other parts of the code that may become a problem.

I will see what I can come up with and let you know.

Andy
If the file format is sequential with numbers as text representation, then you can't just 'add' or change content in the middle of the file. You need to read the existing data to a temp file until you get to the data you want to change, write the required new data to the temp file, copy the rest of the existing data to the temp file, delete the existing file and then rename the temp file to the existing file. This is not exactly trivial. You can add data to the end of an existing sequential file, but it should be in the same form as the existing so that it can be read the same.

It would be helpful if you showed a sample of the existing file and how it should be after it has been modified.
Hello adeel zamann,

If you are working from instructions or directions for this program please post them. It is not easy to understand from your code just what you are trying to do.

This is looking like a program that should be planed out before you start coding, so that you know what to code.

This is a quick work on your code, but it is not completely correct, but the comments do show some of the problems that you have.
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
#include<iostream>
#include <fstream>
#include <string>

//using namespace std;  // <--- Best not to use.
// The most recent post that is worth reading. http://www.cplusplus.com/forum/beginner/258335/

int main()
{
    std::string cost;

    std::ifstream things("data.txt");  // <--- 2nd parameters not needed and most likely ignored.

    while (things.ignore(21) && std::getline(things, cost))
    {
        system("cls");

        system("color 5f");

        std::cout << "cost Is    " << cost;
        std::cout << "\nEnter 1 For add More Money With The Existing Cost";

        std::string adds;  // <--- I would change this to "int choice"

        std::cin >> adds;

        if (adds == "1")  // <--- I would change this to "(choice == 1)"
        {
            double add;

            std::cout << "Add cost:  ";
            std::cin >> add;

            cost = add + cost;  // <--- Adding an double and a string.
        }
    }
}


Andy
Maybe you have something like this in mind to update the prices to the new price list.
If a particular price changes then just enter zero for the price increase.
You will have to come up with a way so you only update the current price list. There are many ways to do that.

Your 'adds' enter 1 is unnecessary.

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

using namespace std;

int main()
{
    fstream things_in("data_cost.txt", ios::in);
    if(!things_in.is_open())
    {
        cout << "Unable to open file\n";
        return -1;
    }
    
    
    fstream things_out("data_cost.txt", ios::app);
    if(!things_out.is_open())
    {
        cout << "Unable to open file\n";
        return -2;
    }
    
    
    double cost{0};
    double additional{0};
    
    while (things_in >> cost)
    {
        cout << "        Cost is: $" << cost << '\n';
        
        cout << "Additional cost: $";
        cin >> additional;
        
        cost = cost + additional;
        cout << "       New cost: $" << cost << '\n';
        
        things_out << cost << '\n';
    }
    
    things_in.close();
    things_out.close();
    
    return 0;
}


Test file - the first 3 are the original list, the new list is the 2nd 3

2.00
3.00
12.98
4.5
4.27
15


 Cost is: $2
Additional cost: $2.5
       New cost: $4.5
        Cost is: $3
Additional cost: $1.27
       New cost: $4.27
        Cost is: $12.98
Additional cost: $2.02
       New cost: $15
Program ended with exit code: 0


Hello adeel zamann,

While waiting for your reply I do have 1 question.

In regards to the input file is it given for you to use and if so is it unchangeable?

You wrote the line ifstream things("data.txt", ios::app | ios::in | ios::out);. the "ifstream" already implies that it is an input file and therefor "iso::app" does not apply to input files. "iso::in" is ignored because it is an "ifstream" and "iso::out" does not work on an input stream, so in the end everything after the "," is ignored.

I believe what you want is fstream things("data.txt", ios::app | ios::in | ios::out);, but you will need more to work with this.

Andy
Hello Andy
thank you for showing an interest to help me
Actually it's just a store program which have many things with their prices and these data are stored in a data file.

In the format of this bellow

 
while (things.ignore(21) && std::getline(things, cost))


I took string for the cost just for getline in a file

As it is easy to add two floats or integers data but we can't use the float and integers data in a getline for a file I am stuck with string I am sure that I have to convert string to the float to add the float value but I am stuck in changing I am trying but I am unable to do

Actually the price for everything is stored in a data file but with the time I am trying to change the old price to the new to add some more price with the exciting price or subtract some price from the existing price and the price get store in a data file too for future addition or subtraction from price.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include<iostream>
using namespace std;
string cost;
ifstream things("data.txt",ios::app|ios::in|ios::out);
while (things.ignore(21) && std::getline(things, cost))
{
main:
  system("cls");
  system("color 5f");
  cout << "cost Is    " << cost;
  cout<<"\nEnter 1 For add More Money With The Existing Cost";
  string adds;
  cin>>adds;
  if(adds=="1")
  {
     float add;
     cout<<"Add cost:  ";
     cin>>add;
     cost=add+cost;
     goto main;
  }
}
Hello againtry thank you for helping me

Actually what code you send me it's working fine but actually in a data file the data is stored in the format of
This
 
while (things.ignore(21) && std::getline(things, cost))


Your code is not following this format you code is following the format of the first word in a file

For example:-

In data file it's only written (2.1)
Your program will get this value and change this value and save it in a file

But if in a file has written (price is 2.1) then your code will not get this price

And as like that in my code
In a data file the price is stored in a format of this

 
while (things.ignore(21) && std::getline(things, cost))


Can you try and check it if you can help me.
@adeel
It’s great to know that you confirm my program is working fine.

I think your best bet now is to show us a sample of the data file.
Hello adeel zamann,

I understand the file format, but it does not show me what the actual file looks like. Using your while loop works for the file I created, but that does no mean what I created is the same as what you are using.

I have done some work rearranging your original code and managed to get it to work, but without the proper input file I am not sure if it will work for you right now.

You are correct. againtry's program does not work, but he neglected to mention that he redesigned your program along with the input file and did not post the directions of what his program should do.

Andy
Hello Andy and againtry


This is my full code
It has a option that user can add things with it's I'd and price and the I'd,price and thing name will store in a data file then I add 2 options that a user can edit the price and the price goes and store in the data file for future edits

I am unable to change the price and store the new price in the file also I want to delete the specific type of thing by give another option in the program but I didn't write it in the below program because I don't have idea that how to do 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
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#include<iostream>
#include<windows.h>
#include<limits>
#include<fstream>
using namespace std;
void SkipLine(std::istream &in)
{
    in.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
main()
{
	Main:
		system("cls");
		cout<<"Wellcome to the Mega Stor";
		cout<<"\nEnter 1 for add the thing\n\nEnter 2 for check or change in The price\n\n";
		string selection;
		cin>>selection;
		if(selection=="1")
		{
			add:
				system("cls");
				cout<<"\nWellcome to the Mega Stor";
				cout<<"\nAdd New Things";
				ofstream things("data.txt",std::ios::app);
				string name,price,id;
				cout<<"\nEnter Id: ";
				cin>>id;
				cout<<"\nEnter Name: ";
				cin>>name;
				cout<<"\nEnter price: ";
				cin>>price;
				things<<"Id Is     "<<id<<'\n';
				things<<"Name Is   "<<name<<'\n';
				things<<"Price Is  "<<price<<'\n';
				things<<'\n';
				things.close();
				system("cls");
				cout<<"\t"<<id<<" This Product is added in the data";
				Sleep(4*500);
				selection_in_add:
					cout<<"\n\tEnter 1 For To add Another Thing\n\tEnter 2 For To go To Menue\n";
					string selection_in_add;
					cin>>selection_in_add;
					if (selection_in_add=="1")
					{
						goto add;
					}
					else
					{
						if (selection_in_add=="2")
						{
							goto Main;
						}
						else
						{
							system("cls");
							cout<<"\tInvalid Selection";
							Sleep(5*400);
							goto selection_in_add;
						}
					}
		}
		else
		{
			if(selection=="2")
			{
				Find_Things:
				system("cls");
				cout<<"\nWellcome to the Mega Stor";
				cout<<"\nEnter Id Of The Specific Thing To Check The Price\n";
				string id,check_id,name,price;
				cin>>id;
				ifstream things("data.txt",std::ios::app);
				while (things.ignore(10) && std::getline(things, check_id) && things.ignore(10) && std::getline(things, name) && things.ignore(10) && std::getline(things, price))
				{
					if (id == check_id)
           			{
           				price_add_subtract:
                		system("cls");
						system("color 5f");
                		cout<<"\tId is: "<<id;
                		cout<<"\tThing is: "<<name;
                		cout<<"\tPrice is: "<<price<<"\n";
                		string price_add_subtract;               						
						cout<<"\n\tEnter 1 For Add Price\n\tEnter 2 For Subtract Price\n\tEnter 3 For Back\n\tEnter 4 For Go to Menue\n\t";
     	           		cin>>price_add_subtract;
        	        	if(price_add_subtract=="1")
                		{
            	    		float change_price,add_price;
                			cout<<"\n\tAmount To Add";
                			cin>>add_price;
                			change_price=std::stof(price);
                			change_price=add_price+change_price;
                			goto price_add_subtract;
						}
						else
						{
							if(price_add_subtract=="2")
							{
								float change_price,subtract_price;
                				cout<<"\n\tAmount For Subtract";
                				cin>>subtract_price;
                				change_price=std::stof(price);
                				change_price=change_price-subtract_price;
                				goto price_add_subtract;	
							}
							else
							{
								if(price_add_subtract=="3")
								{	
									goto Find_Things;
								}
								else
								{
									if(price_add_subtract=="4")
									{	
										goto Main;
									}
									else
									{
										system("color 6f");
										system("cls");
										cout<<"\t\tincorrect Selection\n";
										Sleep(5*400);
										goto price_add_subtract;
									}
								}
							}				
						}
            		}
            		SkipLine(things);
				}
				system("color 6f");
				system("cls");
				cout<<"\t\tincorrect Id\n";
				Sleep(5*400);
				goto Find_Things;
			}
			else
			{
				system("cls");
				cout<<"\nInvalid Selection";
				Sleep(5*400);
				goto Main;
			}
		}
}
@adeel, You need to change your data model - it’s no good - a csv model or two line per item model without desriptors is sufficient, simple and efficient :)
Hello adeel zamann,

I will start with your code is very hard to read. To that end it takes more time to straighten out your code and see what is happening.

So far I hae started with this:
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
#include <iostream>
#include <windows.h>
#undef min
#undef max
#include <limits>
#include <fstream>
#include <string>  // <--- Added. Used for "std::string" and "std::getline". Also need for the insertation and extraction operators. 

using namespace std;

constexpr DWORD SLEEP_TIME{ 2000 };

void SkipLine(std::istream &in)
{
    in.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}

int main()
{
Main:
    system("cls");

    cout << "Wellcome to the Mega Stor";
    cout << "\nEnter 1 for add the thing\n\nEnter 2 for check or change in The price\n\n";

    string selection;  // <--- A "char" or "int" would be better.

    cin >> selection;

    if (selection == "1")
    {
    add:
        system("cls");

        cout << "\nWellcome to the Mega Stor";
        cout << "\nAdd New Things";

        ofstream things("data.txt", std::ios::app);

        string name, id;  // <--- Changed.
        float price;  // <--- Changed.

        cout << "\nEnter Id: ";
        cin >> id;  // <--- "std::getline" may work better.

        //SkipLine();  // <--- Call function before using "std::getline".

        cout << "\nEnter Name: ";
        cin >> name;  // <--- Should use "std::getline" because the name may contain a space

        cout << "\nEnter price: ";
        cin >> price;

        things << id << ',' << name << ',' << price << '\n';

        //things << "Id Is     " << id << '\n';
        //things << "Name Is   " << name << '\n';
        //things << "Price Is  " << price << '\n';
        //things << '\n';

        things.close();

        system("cls");

        cout << "\t" << id << " This Product is added in the data";

        Sleep(SLEEP_TIME);

        //  Code removed for brevity.
    }
    else if (selection == "2")
    {
        //  Code removed for brevity.
    }
    else
    {
        system("cls");

        cout << "\nInvalid Selection";

        Sleep(SLEEP_TIME);

        goto Main;
    }
}

The space between "include" and the "<" is not really needed, but it does make it easier to read.

When you include the header files "window.h" and "limits" you need to follow the "windows.h" with the 2 "#undef"s, so that "limits" can define "min" and "max" in the way it needs to. I have not found any better way to do this, mostly because I so not use "windows.h" that often. I usually use std::this_thread::sleep_for(std::chrono::seconds(3)); // <--- Needs header files chrono" and "thread". In this case the (3) means 3 seconds and only whole numbers are used. Another option is std::this_thread::sleep_for(std::chrono::milliseconds(3000)); // <--- Needs header files chrono" and "thread". Where 1000 equals 1 second. This is also more portable than using "Sleep()".

A problem with defining "selection" as a string is that you could accidently or on purpose enter more than just 1 or 2 then your if statements would never be equal.

Line 54 would be a better way to write to the file which would make it much easier to read the file. Also writing to the file"Id Is " is more a waste of time and storage space for something that is not needed.

Line 71. Although there is no "else if" in C++ and there is nothing wrong with the way you did it. Most often line 71 is written this way. It works just the same and makes the code easier to read and follow.

Then if "selection" is not 1 or 2 you reach the "else" at line 75.

In the code not shown the "else if" statements should look like what I did.

A note: The "goto" statements should be replaced with either a "do/while" or "while" loop. The "goto" statement is useful in rare cases, but should not be part of normal programming.

While working I did have a thought. You could define a struct:
1
2
3
4
5
6
struct Product
{
    std::string s_id;
    std::string s_name;
    float price{};
};

Read the file into the struct and store it in a vector or array. The vector would be better if you have studied that. This way it is easier to use the vector or array to deal with any changes and just write the vector or array to the input file overwriting what is there with the new information. This would be easier than trying to move the file pointer around to change the price, unless you have to read and write to 1 file.

Andy
Hello adeel zamann,

Sorry I was interrupted and forgot this.

With the change I made the file would look like this:

123456,wigit,2.53


This becomes easier to read when the time comes.

Andy
Hello Andy

Thank you so much for showing your interest in my problem
But my question is still same like I am unable to change the price or how to do it and store the price in the data file too

I am not familiar with vector as I don't know how to use vector so does it have a different way beside vector
And to change the price and store it in the data file too
Last edited on
to change the price and store it in the data file too
It's hard to believe, but to change a text file, you have to rewrite the entire file. So to change the price of one item, you need to do something like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
open temp file
open data file
for each record in data file {
    if (it matches the one that you need to change) {
        write the updated record to the temp file
    } else {
        write the original record to the temp file.
    }
}

close the temp file and the data file
delete the data file
rename the temp file to the data file


Your code may work, but the structure could be improved. I'd think of it like this:
- main contains a loop that prints the main menu, gets the users selection and calls a function for each selection (except perhaps the selection to quit, which just sets a flag to exit the loop).

After you have the menu basics working, write a pair of functions: one that reads a single record from a stream (which will be the data file) and one that writes a record to a stream (that will also be the data file). Test these out. You want to make sure that you can read and write multiple records to/from a stream.

You could test that out and then write the functions that each option calls. Note that some options invoke submenus.
It doesn't have any way to store a data in file without rewrite the entire file?
Of course you can use a single file.

There are better ways to do it though, but you cut those off. <maps>'s are specifically designed to handle and search through this sort of data. Or you could use c-style arrays if you 'don't know' <vector>'s

But all of that can be automated using none of that and just a single file - you just have to keep track of the list's count and where the latest price list occurs. sooner or later STL containers will become a valuable resource ...

However, unless you are fixated on sleep's, this work's
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<fstream>

using namespace std;

struct Thing
{
    int ID;
    string name;
    double price;
};

int main()
{
    fstream things_in("data_cost.txt", ios::in);
    if(!things_in.is_open())
    {
        cout << "Unable to open file\n";
        return -1;
    }
    
    fstream things_out("data_cost.txt", ios::app);
    if(!things_out.is_open())
    {
        cout << "Unable to open file\n";
        return -2;
    }
    
    double additional{0};
    char comma{','};
    
    Thing temp;
    while (
           things_in >> temp.ID  >> comma>> temp.price >> comma &&
           (getline(things_in, temp.name))
           )
    {
        cout << temp.ID << ' ' << temp.name << '\n';
        
        cout << "        Cost is: $" << temp.price << '\n';
        
        cout << "Additional cost: $";
        cin >> additional;
        
        temp.price += additional;
        cout << "       New cost: $" << temp.price << "\n\n";
        
        things_out << temp.ID << ',' << temp.price << ',' << temp.name << '\n';
    }
    
    things_in.close();
    things_out.close();
    
    return 0;
}


cost_data.txt

101,2.00,Widget typeAA
307,3.00,tripod with 3 legs
213,12.98,door



1 Widget typeAA
        Cost is: $2
Additional cost: $0
       New cost: $2

7 tripod with 2 legs
        Cost is: $3
Additional cost: $1
       New cost: $4

13 door
        Cost is: $12.98
Additional cost: $3
       New cost: $15.98

Program ended with exit code: 0


EDIT: typo fixed: things_in >> temp.ID >> comma>> temp.price >> comma &&
Last edited on
And the new data file becomes:


101,2.00,Widget typeAA
307,3.00,tripod with 3 legs
213,12.98,door
1,3,Widget typeAA
7,5,tripod with 3 legs
13,15.98,door
It doesn't have any way to store a data in file without rewrite the entire file?
You can change parts of a file without rewriting the whole thing. The problem is that when you change a text file, you usually are changing the entire file, or at least the data from the change to the end of the file.

Consider this text file:
This is a test.

Now change it to:
This's a test.

To the human, it seems like you've made a small change, but keep in mind that a file is just a sequence of bytes. Let's compare the two files:
T h i s   i s   a   t e s t .
T h i s ' s   a   t e s t .

If you compare the corresponding bytes in the sequence, you see that only the first 4 bytes remain unchanged. That means you have to rewrite everything else.
Pages: 12