Problems of Replacing a string in txt file

Right now I am planning to replace the name if the user enter a correct ID. However,it create a new line for the replacing the new name instead in the text file.
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
cout << "Transfer name"<<endl;
cout << "Please enter ID" << endl;
cin>>ID;
		
		   		
 while(!inFile.eof())
   {	
    	getline (inFile,line);			
    	if (line == ID){
    	cout <<"ID is found!" << endl;		
    	cout <<"Please enter the new name " <<endl;
    	cin >> name1;
    	
    	cout <<"Name is updated: " << name1 <<endl;		
    	myfile << name1 << endl<<endl;
    	
    	
    	string Line;		//starting here i think is the problem
    	size_t len = name1.length();
    	
        	
        size_t pos = line.find(name);
        if (pos != string::npos){
				
        Line.replace(pos, len, name1);

       }
       else 
        break;

    	
    	break;
    
   }
   else {
   cout<< "There is no data\n";			
}
   		
    	}


In txtfile
1 (ID)
rhap (Planning to replace the name to rhap123)
rhap123 (Instead of replacing the old name, it creates a new line for the new name)
Last edited on
warning: line 6 is a bad approach. you can google the why, but the while eof approach does not always work as expected. Put the getline in the while is safer.

now for your bug: what is 'line' on code line 9 if you create it on line 18?!
line 19 is pointless, you do not need another variable to represent the length, and worse, if the length changed, the variable goes out of date but the string's length function is always current.

it is unclear what lines 19 to 27 are trying to do.
your code should look like this, if I understand you, in psudo code:

read the line.
is it the name?
if it is the name, get a new name.
write the new name to the file.
else, it is not the name, write the old line to the file (leaving it unchanged).
end loop

and that is it. the line with the name is modified, the other lines are intact, and nothing more needs to be done.

if name is not on a line by itself, and you need to replace it in many places, then instead of the above, it becomes:
get name and replacement name from user up front, out of the loop.
while(get a line)
does line contain name?
if so, replace name. (multiple times?!)
either way, replaced or not, write the line to the file
end loop

I am rusty on what replace functions we have; there may be one that replaces all instances in a line at one go, and if none, no change, getting rid of the condition and handling the case of 2 copies of name on the same line, which is not currently being handled.
Last edited on
However,it create a new line for the replacing the new name instead in the text file.

Normally you don't replace a "line" in a text file, you would re-write the text file with the desired information.

By the way you need to show more content, a small complete program would be best.

For example how did you open your output file?

By the way I would say that the line right above your "The problem is here" marker is probably part of the problem.

Lastly using eof() to control a "data entry" loop will usually cause problems as well. You should be using the actual read instead: while(getline(Stream, String)).
Based on jonnin the way you write is exactly what I want for the code.For jlb i will show you my full code of it. Yes i want to (rewrite/replaced) if possible. If possible, would like to see the code that you coded.

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

int main()
{
    
	string name, id ,name1;

	
	ofstream myfile;
	myfile.open("data.txt");

	ofstream outFile("data.txt");
    	ifstream readFile("data.txt");
	ifstream inFile("data.txt");

	cout << "Transfer name"<<endl;
    	cout << "Please enter new name" << endl;
    	cin>>name1;
		
		   		
    	while(!inFile.eof())
    	{
    		
    	getline (inFile,line);			
    	if (line == name){
    	cout <<"Name is found!" << endl;		
    	cout <<"Please enter the new name " <<endl;
    	cin >> name1;
    	
    	cout <<"Name is updated: " << name1 <<endl;		
    	myfile << name1 << endl<<endl;
    	
    	
    	string Line;						
    	size_t len = name1.length();
    	
        	
            	size_t pos = line.find(name);
            	if (pos != string::npos){
				
                	Line.replace(pos, len, name1);

                	}
            	else 
                	break;

    	
    	break;
    
   		}
   		else {
   			cout<< "There is no data\n";			
		   }
   			
    	}
return 0;
Last edited on
Why are you trying to open your files so many times. Normally you only open the same file once. You would close the open file before trying to re-open the file.

If you want a file that is open for both reading and writing then you should be using fstream.

Also note that by default an ofstream truncates the file when opening, meaning there will be nothing in that file.

So in your code you open the file for output, erasing the file contents, then you try to read from an empty file. Do you see any problem with this?

Edit: And as I said earlier, you can only replace characters, you can't add characters to a file (except at the end of the file). So if your "names" are not the same exact length you will probably end up with garbage, if your intended method did what you seem to want.

Last edited on
I think I would try something like this (incomplete):


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22


int main()
{    
  //get what to replace with what etc here...
    string filename = "data.txt";
    ifstream file(filename);
	string filedata;
	filedata.reserve(5000000); 
	filedata.assign(istream_iterator<char>(file), istream_iterator<char>());
	
	//while finds the string, replace it loop here until all done. I highly suggest 
//you .find on a string with space search_term space so it does not replace
//partial matches inside other words.  or look left/right to be sure its a match, 
//since you can't assume spaces, could be first/last word in line, how complex you need 
//this part?
	
	file.close()
	ofstream file2(filename);
	file2 << filedata;
	file2.close();	
}


if the files get huge, this will become stupidly slow, as it is kind of a brute force approach. if you want to deal with huge files, we can adjust it; I assumed you were dealing with relatively small files

anyway, as noted above, you need only open the file twice, once to read it, once to write it.
If dealing with huge files, you may need to read/write together, in which case you write to a new file, delete the old at the end, rename the new at the end, so its the same file to the user when done, but in the middle, you may need 2 (on disk) files.
Last edited on
Thanks for your advice jlb so that means i cannot change the name in the exact number of length right? Yes I am also having problem the file that keep deleting the content without my permission every time i close the system. Would like some of your assistance. Sorry i forgot to close the file at my code. Hope you notice.
Last edited on
If the names are exactly the same length, then yes you can replace the name in the "middle" of the file. However if they are not you need to copy the existing data into memory, make the modifications, then rewrite the information completely, usually to a different file.

If you don't want to delete the file contents when opening with an ofstream you need to use a stream mode that doesn't erase the contents.

On what stream should I use?
On what stream should I use?

What? The question doesn't make sense, please restate the question.
Also please post the input file contents, and what you're trying to input into the program.

Line (upper-case L) and line (lower-case l) are two entirely different variables, case DOES matter.

Where exactly are you creating line (lower-case l)? Nowhere in the code you've posted.

You use Line (upper-case L) to write out your changed data, but you modify the read data in line. You writing out a blank string every time!

Even if that is just a typo and wanted Line to be line (lower-case l) you are defining AFTER you try using it.

Not the most elegant way of finding and replacing text data in a file is:

1. Open the file for reading. Read each line and stuff that line into a container. Such as std::vector (if you can use one) or into a regular array that can hold std::strings. When the loop is done close the file.

2. Loop through the container, searching each line for what you want to replace. If/when found replace the value(s). There may be multiple instances that need changing.

3. Open the file for writing, setting the open flags so writing to the file will overwrite/replace the current contents. Loop through your container, writing out all the lines, modified or not. When the loop ends, close the file.

You've now found and replaced the strings or portions of strings you wanted to change. Crude, but it works. The only drawback to doing it this way is if you are wanting to change the contents of a file that is HUGE. What those limits are depends on a lot of factors. For learning purposes it is doubtful you will ever be required to deal with something like that.
Topic archived. No new replies allowed.