c++ how to remove/replace the last line of a file? - c++

How do I remove/replace the last line of a file in C++? I looked at these questions:
Deleting specific line from file, Read and remove first (or last) line from txt file without copying
. I thought about iterating to the end of the file and then replacing the last line but I'm not sure how to do that.

Find the position of the last occurrence of '\n' in the file content. If the file ends with '\n', i.e there is no more data after the last '\n', then find the position of the previous occurrence of '\n'. Use resize_file to truncate files at the found position or just replace the content after the found position.

#include <fstream>
#include <string>
using namespace std;
int main() {
ifstream fin("input.txt");
ofstream fout("output.txt");
while (!fin.eof()) {
string buffer;
getline(fin, buffer);
if (fin.eof()) {
fout << "text to replace last line";
} else {
fout << buffer << '\n';
}
}
fin.close();
fout.close();
}
Also you can read and store all your input file, modify and then write it:
#include <fstream>
#include <vector>
#include <string>
using namespace std;
int main() {
// read
ifstream fin("input.txt");
vector<string> lines;
while (!fin.eof()) {
string buffer;
getline(fin, buffer);
lines.push_back(buffer + '\n');
}
fin.close();
// modify
lines[lines.size() - 1] = "text to replace last line";
// write
ofstream fout("output.txt");
for (string line: lines) { // c++11 syntax
fout << line;
}
fout.close();
}

Related

C++ Weird File Line Read

I'm new to C++ programming and trying to figure out a weird line read behavior when reading a line from a text file. For this specific program, I have to wait for the user to press enter before reading the next line.
If I hard code the file name, the file read starts at line 1 as expected:
#include <iostream>
#include <fstream>
using namespace std;
int main(void) {
ifstream in_file;
in_file.open("test.txt");
// read line by line
string line;
while (getline(in_file, line)) {
cout << line;
cin.get();
}
in_file.close();
return 0;
}
I compile with g++ -Wall -std=c++14 test1.cpp -o test1 and get:
$ ./test
This is line one.
**user presses enter**
This is line two.
**user presses enter**
This is line three.
etc. etc.
But when I add in the option to have the user type in a file name, the line read starts at line 2:
#include <iostream>
#include <fstream>
using namespace std;
int main(void) {
string filename;
cin >> filename;
ifstream in_file;
in_file.open(filename);
// read line by line
string line;
while (getline(in_file, line)) {
cout << line;
cin.get();
}
in_file.close();
return 0;
}
The same compile command gives me:
$ ./test2
test.txt
This is line two.
**user presses enter**
This is line three.
**user presses enter**
This is line four.
etc. etc.
Am I missing something here? I have no idea why it starts reading at line 2 when I add in the code to specify a file name. Am I not finishing the cin statement properly or something?
Thanks!
by default cin operator>> reads data up to the first whitespace characte and whitespace characte is not extracted reference. So if you read file name like this cin>>file; file variable will contains only first part of your string without whitespace. So that when reading you do not have such problems use getline
#include <iostream>
#include <fstream>
#include <sstream>
using namespace std;
int main(void) {
string filename;
getline(cin, filename, '\n');
ifstream in_file;
in_file.open(filename);
// read line by line
string line;
while (getline(in_file, line)) {
cout << line;
cin.get();
}
in_file.close();
return 0;
}
This implementation of the code should work. You just needed to add cin.ignore() to ignore the remaining characters on the line until you hit either the end of the line(EOL) or the end of the file(EOF). The function also takes in 2 parameters, which are the maximum number of characters to ignore and the character to ignore. link to the use of cin.ignore(). Hope that this helps :)
#include <iostream>//basic
#include <fstream>//file
using namespace std;
int main(){
//set file name
string file="";
cout<<"file name: ";
cin>>file;
//create/write to file
ofstream out_file;
out_file.open(file);
out_file<<"test 1\ntest 2\ntest 3";
out_file.close();
//read file
ifstream in_file;
in_file.open(file);
string line;
cin.ignore();//clear buffer
while(getline(in_file,line)){
cout<<line;
cin.get();
}
in_file.close();
system("pause");
return 0;
}

Finding certain characters in a line of string

I want to be able to a string that contains certain characters in a file that contains one string per line.
#include <iostream>
#include <fstream>
#include <string>
int main(){
string line;
ifstream infile;
infile.open("words.txt");
while(getline(infile, line,' ')){
if(line.find('z')){
cout << line;
}
}
}
That's my attempt at finding all the string that contains the character z.
The text file contains random strings such as
fhwaofhz
cbnooeht
rhowhrj
perwqreh
dsladsap
zpuaszu
so with my implementation, it should only print out the strings with the character z in it. However, it seems to be reprinting out all the contents from the text file again.
Problem:
In your file the strings aren't separated by a space (' ') which is the end delimiter, they are separated by a end of line ('\n'), that is a different character. As a consequence, in the first getline everything goes to line. line contains all the text in the file, including z's, so all the content is printed. Finally, the code exits the while block after running once because getline reaches the end of the file and fails.
If you run this code
#include <iostream>
#include <fstream>
#include <string>
int main(){
std::string line;
std::ifstream infile;
infile.open("words.txt");
while(getline(infile, line,' ')){
std::cout << "Hi";
if(line.find('z')){
std::cout << line;
}
}
}
"Hi" will be only printed once. That is because the while block is only executed once.
Additionaly, see that line.find('z') won't return 0 if not match is found, it will return npos. See it running this code (As it says here):
#include <iostream>
#include <fstream>
#include <string>
int main(){
std::string line;
std::ifstream infile;
infile.open("words.txt");
while(getline(infile,line)){
std::cout << line.find('z');
if(line.find('z')){
std::cout << line << "\n";
}
}
}
Solution:
Use getline(infile,line) that is more suitable for this case and replace if(line.find('z')) with if(line.find('z') != line.npos).
while(getline(infile,line)){
if(line.find('z') != line.npos){
std::cout << line << "\n";
}
}
If you need to put more than one string per line you can use the operator >> of ifstream.
Additional information:
Note that the code you posted won't compile because string, cout and ifstream are in the namespace std. Probably it was a part of a longer file where you were using using namespace std;. If that is the case, consider that it is a bad practice (More info here).
Full code:
#include <iostream>
#include <fstream>
#include <string>
int main(){
std::string line;
std::ifstream infile;
infile.open("words.txt");
while(getline(infile,line)){
if(line.find('z') != line.npos){
std::cout << line << "\n";
}
}
}
getline extracts characters from the source and stores them into the variable line until the delimitation character is found. Your delimiter character is a space (" "), which isn't present in the file, so line will contain the whole file.
Try getline(infile, line, '\n') or simply getline(infile, line) instead.
The method find returns the index of the found character, where 0 is a perfectly valid index. If the character is not found, it returns npos. This is a special value whcih indicates "not found", and it's nonzero to allow 0 to refer to a valid index. So the correct check is:
if (line.find('z') != string::npos)
{
// found
}

Reading a text file C++

I'm trying to retrieve certain lines from a text file. I'm using:
#include <iostream>
#include <fstream>
using namespace std;
void parse_file()
{
std::ifstream file("VampireV5.txt");
string str= "Clan";
string file_contents;
while (std::getline(file, str))
{
file_contents += str;
file_contents.push_back('\n');
}
cout << file_contents;
file.close();
}
int main()
{
parse_file();
return 0;
}
I want to get that one and only line containing "Clan" until '\n'. I've tried to add an if inside the while loop but it is not returning anything.
Is there a way to make it get 1 line at once?
Your code is almost correct as in: It reads the file line by line and appends the contents to your string.
However since you only want that one line, you also need to check for what you are looking for.
This code snippet should give you only the line, which starts with the word 'Clan'.
If you want to check, whether the string is anywhere on the line, consider checking for != string::npos.
void parse_file()
{
std::ifstream file("VampireV5.txt");
string str;
string file_contents;
while (std::getline(file, str))
{
if (str.find("Clan") == 0)
{
file_contents += str;
file_contents.push_back('\n');
}
}
cout << file_contents;
file.close();
}

C++ Inserting a new line after a specific character in a text file

I am looking for a way to search for a specific character in a text file and add a new-line after every ;
It's a pretty big document (2,7MB) if that matters.
You can't insert new characters into the middle of an existing file, only append to the end. You will have to create a new file, copying characters from the old file to the new file, inserting new characters as needed. For example:
#include <string>
#include <fstream>
int main()
{
std::ifstream inFile("input.txt");
if (!inFile.is_open())
{
std::cerr << "Failed to open input file";
return 1;
}
std::ofstream outFile("output.txt");
if (!outFile.is_open())
{
std::cerr << "Failed to create output file";
return 1;
}
std::string line;
while (std::getline(inFile, line, ';'))
{
outFile << line;
if (!inFile.eof())
outFile << ";\n";
}
return 0;
}
As SomeProgrammerdude points out in the comments, inserting into an existing file isn't really feasible and one of your options is to read it all into a single std::string and write back into the same text file.
Here is an example implementation. We read a charter at a time and check if it is a semicolon, and add a newline after every semicolon. Notice the reserve part, although advised, it is not mandatory:
#include <string>
#include <fstream>
#include <stdexcept>
int main()
{
std::fstream f("test.txt", std::ios::in);
if (!f.is_open()) {
throw std::runtime_error("Failed to open file");
}
std::string contents;
contents.reserve(10000); // reserve some space for better efficiency
char ch;
while (f.get(ch)) {
contents.push_back(ch);
if (ch == ';')
contents.push_back('\n');
}
f.close();
f.open("test.txt", std::ios::out);
if (!f.is_open()) {
throw std::runtime_error("Failed to open file");
}
f << contents;
f.close();
return 0;
}
Input:
line line line line; line line line line; line line line; line line
Output:
line line line line;
line line line line;
line line line;
line line
Note the leading spaces before lines. This is because we appended '\n' after every ';', did not replace the spaces.

How to display a file in c++?

I need someone to edit that code so that i could display a file!!
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
string data; //enter a data as a string
ifstream datafile; // input datafile as ifstream
datafile.open("test.txt"); // open test file
}
Unfortunately you didn't specify how you want to read and display the file. Thus I made the assumption that output should go to std::cout. In the attached proposal there are two possibilities to read: line-by-line as you would read the file in any text editor or each word separately in a new line (input separated by White spaces, i.e. blanks, Tabulators or line breaks).
#include <iostream>
#include <fstream>
#include <string>
int main()
{
std::string data; //enter a data as a string
std::ifstream datafile; // input datafile as ifstream
datafile.open("Source.cpp"); // open test file
// read line by line
while (std::getline(datafile, data))
{
std::cout << data << std::endl;
}
/*
// read each word (separated by white spaces)
while (!datafile.eof())
{
datafile >> data;
std::cout << data << std::endl;
}
*/
datafile.close();
return 0;
}
There is no error handling in. If the file does not exist or any other occurs no exceptions will be caught.