i can detect the empty line in text but not getting how to delete it
please can you give me some tips how to delete that detected lines
#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
using namespace std;
int main()
{
// open input file
std::ifstream ifs( "in_f1.txt" );
std::fstream ofs( "out_f1.txt" );
char c;
char previous_c;
// squeeze whitespace
std::string word;
ifs >> word;
ofs << word;
while (ifs)
{
if (c==' ')
{
ofs.put(c);
while (c==' '&&ifs)
{
ifs.get (c);
;}
}
if (c=='\v')
{
previous_c=c;
while (c=='\v'&&ifs)
{
ifs.get (c);
;}
ofs.put(previous_c);
};
// read line
std::string line;
std::getline( ofs, line );
// append flag and remove 'empty lines'
int flag = 2;
while( getline( ofs, line ) )
{
if( line == " " )
{
flag = 2;
continue;
}
cout << line << " " << flag << endl;
flag = 0;
}
ifs.close();
ofs.close();
}}
you are looking in the output stream for an empty line, after you copy the characters to it.. A stream is not intended to be something we edit like a string, so stop thinking on it that way..
instead you need to add the logic before you put the characters into the stream.
the easiest approach is to have a temporary stream, that you copy from input to.
then for each line, copy the temporary stream to output stream, if and only if, it contains characters different from whitespace.
void remove_empty_lines(std::istream& in, std::ostream& out)
{
std::string line;
while (std::getline(in, line))
if (!line.empty())
out << line << '\n';
}
N.B. This will add a newline to the end of the file even if there isn't one in the original.
Related
I have a text file like this:
100,Nguyen Van A,2004
101,Tran Thi B,2004
102,Vo Van C,2005
103,Truong Thi D,2005
How can I add one blank space right after each "," into that file using C++?
I've tried using find() function but nothing worked.
svFile.open("list_student.txt");
while (getline(svFile, line, ','))
{
if (line.find(",", 0) != string::npos)
svFile << " ";
}
Two options, read and write the file character by character, or option 2, read the entire text file into a string and then perform your required changes and write the file back:
Option 1 (Character by Character):
char ch;
fstream fin("list_student.txt", fstream::in);
fstream fout("list_student_result.txt", fstream::out);
while (fin >> noskipws >> ch) {
fout << ch;
if (ch==',')
{
fout << ' ';
}
}
fout.close();
Option 2 (Read/Write entire file):
#include <iostream>
#include <fstream>
int main()
{
// Read the entire file
std::ifstream t("list_student.txt");
std::stringstream buffer;
buffer << t.rdbuf();
std::string myString = buffer.str();
size_t start = 0;
int pos = 0;
// Set your start character and replace with string here
std::string comma(",");
std::string replaceWith(", ");
// Replace the comma "," with ", " (and a space)
while ((pos = myString.find(comma, pos)) != std::string::npos) {
myString.replace(pos, comma.length(), replaceWith);
pos += replaceWith.length();
}
// Write the formatted text back to a file
std::ofstream out("list_student_result.txt");
out << myString;
out.close();
return 0;
}
I am trying to find and replace a line of data in a text file in c++. But I honestly have no idea where to start.
I was thinking of using
replaceNumber.open("test.txt", ios::in | ios::out | ios_base::beg | ios::app);
To open the file at the beginning and append over it but this doesn't work.
Does anyone know of a way to achieve this task?
Thanks
Edit: My text file is only one line and it contains a number for example 504. The user then specifies a number to subtract then the result of that should replace the original number in the text file.
Yes, you can do this using std::fstream, here's a quick implementation i whipped up real quick. You open the file, iterate over each line in the file, and replace any occurrences of your substring. After replacing the substring, store the line into a vector of strings, close the file, reopen it with std::ios::trunc, and write each line back to the empty file.
std::fstream file("test.txt", std::ios::in);
if(file.is_open()) {
std::string replace = "bar";
std::string replace_with = "foo";
std::string line;
std::vector<std::string> lines;
while(std::getline(file, line)) {
std::cout << line << std::endl;
std::string::size_type pos = 0;
while ((pos = line.find(replace, pos)) != std::string::npos){
line.replace(pos, line.size(), replace_with);
pos += replace_with.size();
}
lines.push_back(line);
}
file.close();
file.open("test.txt", std::ios::out | std::ios::trunc);
for(const auto& i : lines) {
file << i << std::endl;
}
}
You can use std::stringstream to convert the string read from the file to an integer and use std::ofstream with std::ofstream::trunc to overwrite the file.
#include <iostream>
#include <string>
#include <fstream>
#include <list>
#include <iomanip>
#include <sstream>
int main()
{
std::ifstream ifs("test.txt");
std::string line;
int num, other_num;
if(std::getline(ifs,line))
{
std::stringstream ss;
ss << line;
ss >> num;
}
else
{
std::cerr << "Error reading line from file" << std::endl;
return 1;
}
std::cout << "Enter a number to subtract from " << num << std::endl;
std::cin >> other_num;
int diff = num-other_num;
ifs.close();
//std::ofstream::trunc tells the OS to overwrite the file
std::ofstream ofs("test.txt",std::ofstream::trunc);
ofs << diff << std::endl;
ofs.close();
return 0;
}
I want to copy contents in a text file to a string or a *char. It would be better if I can copy the file content to an array of strings (each line an element of that array). This is my code:
int main() {
ifstream inFile;
inFile.open("index.in.txt"); //index.in has in each line a name and at the end there is a "."
char ab[11];
int q=0;
char *a[111];
if (inFile.is_open()) {
while (!inFile.eof()) {
inFile >> ab; //i think i don't understand this line correctly
a[q]=ab;
cout<<a[q]<<endl;
q++;
}
}
else{
cout<<"couldnt read file";
}
inFile.close();
cout<<"\n"<<ab<<endl; //it shoud be "." and it is
cout<<"\n"<<a[0]<<endl; //it should be "ion" but it gives me "."
return 0;
}
All values in the a array are equal to the last line which is dot
int main() {
ifstream inFile;
inFile.open("index.in.txt"); //index.in has in each line a name and at the end there is a "."
std::vector< std::string > lines;
std::string line;
if (inFile.is_open()) {
while ( getline( inFile, line ) ) {
lines.push_back( line );
}
}
...
now lines is a vector of string, each is a line from file
You are overwriting your only buffer everytime in inFile >> ab;
You read a line in buffer and save the address of buffer somewhere. Next time you read next line in the same buffer and save the exact same address as second line. If you read back your first line you will end up reading updated buffer i.e. last line.
You can change your code to
#include <vector>
#include <string>
#include <fstream>
using namespace std;
int main() {
ifstream inFile;
inFile.open("index.in.txt"); //index.in has in each line a name and at the end there is a "."
string ab; //char ab[11];
int q=0;
vector< string > a(111); //char *a[111];
if (inFile.is_open()) {
while (!inFile.eof()) {
inFile >> ab;
a[q]=ab;
cout<<a[q]<<endl;
q++;
}
}
else cout<<"couldnt read file";
inFile.close();
cout<<"\n"<<ab<<endl; //it shoud be "." and it is
cout<<"\n"<<a[0]<<endl; //it should be "ion" but it gives me "."
return 0;
}
Better use std::string and std::vector instead of arrays.
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
bool ReadFile(const std::string &sFileName,
std::vector<std::string> &vLines)
{
std::ifstream ifs(sFileName);
if (!ifs)
return false;
std::string sLine;
while (std::getline(ifs, sLine))
vLines.push_back(sLine);
return !ifs.bad();
}
int main()
{
const std::string sFileName("Test.dat");
std::vector<std::string> vData;
if (ReadFile(sFileName, vData))
for (std::string &s : vData)
std::cout << s << std::endl;
return 0;
}
In order to read a line you MUST use std::getline. The >> operator will only read a word, that is a sequence of characters ended by a whitespace.
See: http://en.cppreference.com/w/cpp/string/basic_string/getline
I have a program that basically reads a text file and counts the number of occurrences of each word on each line. Everything works properly when reading from a text file using an ifstream, however, if a file name is not entered on the command line, I need to read from stdin instead.
I use the following to open and read in the file currently:
map<string, map<int,int>,compare> tokens;
ifstream text;
string line;
int count = 1;
if (argc > 1){
try{
text.open(argv[1]);
}
catch (runtime_error& x){
cerr << x.what() << '\n';
}
// Read file one line at a time, replacing non-desired char's with spaces
while (getline(text, line)){
replace_if(line.begin(), line.end(), my_predicate, ' ');
istringstream iss(line);
// Parse line on white space, storing values into tokens map
while (iss >> line){
++tokens[line][count];
}
++count;
}
}
else{
while (cin) {
getline(cin, line);
replace_if(line.begin(), line.end(), my_predicate, ' ');
istringstream iss(line);
// Parse line on white space, storing values into tokens map
while (iss >> line){
++tokens[line][count];
}
++count;
}
Is there a way to assign cin to an ifstream and simply add an else statement if argc > 1 fails, using the same code afterwards instead of duplicating like this? I haven't been able to find a way to do this.
Make the reading part a function of its own. Pass either an ifstream or cin to it.
void readData(std::istream& in)
{
// Do the necessary work to read the data.
}
int main(int argc, char** argv)
{
if ( argc > 1 )
{
// The input file has been passed in the command line.
// Read the data from it.
std::ifstream ifile(argv[1]);
if ( ifile )
{
readData(ifile);
}
else
{
// Deal with error condition
}
}
else
{
// No input file has been passed in the command line.
// Read the data from stdin (std::cin).
readData(std::cin);
}
// Do the needful to process the data.
}
You cannot assign cin to an ifstream.
But you could reopen cin to some file.
Anyway, the better method would be modularising your code and just using a std::istream&.
I just put a easy way to let the program read file if given else use stdin, and close it properly.
#include <fstream>
#include <iostream>
#include <memory>
#include <string>
int main(int argc, char* argv[]) {
auto fp_deletor = [](std::istream* is_ptr) {
if (is_ptr && is_ptr != &std::cin) {
static_cast<std::ifstream*>(is_ptr)->close();
delete is_ptr;
std::cerr << "destroy fp.\n";
}
};
std::unique_ptr<std::istream, decltype(fp_deletor)> is_ptr{nullptr, fp_deletor};
if (argc > 2) {
std::cerr << "usage: " << argv[0] << "[input-file]";
return -1;
} else if (argc == 1) {
std::cerr << "using stdin as input.\n";
is_ptr.reset(&std::cin);
} else {
is_ptr.reset(new std::ifstream(argv[1]));
}
std::string line;
while (std::getline(*is_ptr, line)) {
// your logic....
}
// just return, unique_ptr manage the istream
return 0;
}
Wherever, there is a new line or ("\n") and a space (" ") immediately after the the new line, I want to disregard the "\n" and just print the space in my output, how could I do this?
This is an example:
newegg
bizrate
want to change it to :
newegg bizrate
I am confused since I guess I cannot do it by reading line by line! below is my rough code, which I don't know how to continue ...
Thanks a lot in advance.
ifstream file ("input.txt");
ofstream output("output.txt");
string line;
if(file.is_open())
{
while (!file.eof())
{
getline (file, line);
if (line.find("\n"+' ') != string::npos)
{
??
}
Do it like this. The function getline() will read till \n character
getline(file, line);
cout<<line;
while (!file.eof())
{
getline(file, line);
if (line[0]==' ')
{
cout <<" "<<line;
}
else
{
cout <<"\n"<<line;
}
}
The function getline() (documentation here) will read and throw away the \n character, so there's no need to search for it in the string.
Just do something like this:
bool first = true;
while (!file.eof())
{
getline(file, line);
// you may want to check that you haven't read the EOF here
if (!first)
{
cout << " ";
}
else
{
first = false;
}
cout << line;
}
You might want this:
#include <cctype>
#include <iostream>
#include <sstream>
int main() {
std::istringstream input(""
"newegg\n"
" bizrate\n"
"End");
std::string line;
while(std::getline(input, line)) {
while(std::isspace(input.peek())) {
std::string next_line;
std::getline(input, next_line);
line += next_line;
}
std::cout << line << '\n';
}
}
Please note: A test for EOF is likely wrong.