I have a program that I need to be able to search a file with regex epressions and delete what regex has found. Here is the code I have been working on:
#include <boost/regex.hpp>
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include "time.h"
using namespace std;
class application{
private:
//Variables
boost::regex expression;
boost::smatch matches;
string line;
string pat;
int lineNumber;
string replace;
char time[9];
char date[9];
//Functions
void getExpression(){
cout << "Expression: ";
cin >> pat;
try{
expression = pat;
}
catch(boost::bad_expression){
cout << pat << " is not a valid regular expression\n";
exit(1);
}
}
void boostMatch(){
//Files to open
//Input Files
ifstream in("files/trff292010.csv");
if(!in) cerr << "no file\n";
//Output Files
ofstream out("files/ORIGtrff292010.csv");
ofstream newFile("files/NEWtrff292010.csv");
ofstream record("files/record.dat");
//time
_strdate_s(date);
_strtime_s(time);
lineNumber = 0;
while(in.peek() != EOF){
getline(in, line, '\n');
lineNumber++;
out << line << "\n";
if (regex_search(line, matches, expression)){
for (int i = 0; i<matches.size(); ++i){
record << "Date: "<< date << "Time: " << time << "\tmatches[" << i << "]: " << matches[i] << "\n\tLine Number: "<< lineNumber<< '\n\t\t' << line << '\n';
boost::regex_replace(line, expression, "");
newFile << line << "\n";
}
}else{
newFile << line << "\n";
}
}
}
public:
void run(){
replace = "";
getExpression();
boostMatch();
}
};
As you can see I was trying to use boost::regex_replace to just replace what was found with a blank space, but this did not work. The test I have been running is using [*] to find all the asterisks before some names in a list. Example *alice. The program does find the star but does not remove is to just alice
It seems like boost::regex_replace is returning a string instead of modifying the input. See the documentation for this method.
Try this instead:
newFile << boost::regex_replace(line, expression, "") << "\n";
Escape the * with a \ .
This is a fairly common issue,
http://bytes.com/topic/c/answers/166133-problem-boost-regex_replace
Maybe the above link helps
Related
trying to format with c++ getline function. The output puts everything at the first record number forename instead of where it should go.
Code:
#include <fstream>
#include <string>
#include <iostream>
using namespace std;
int main()
{
const int RANGE = 12;
string tab[RANGE];
int i = 0, j = 0;
ifstream reader("records.txt");
if (!reader)
{
cout << "Error opening input file" << endl;
return -1;
}
while (!reader.eof())
{
if ( ( i + 1) % 4 == 0)
getline( reader, tab[i++], '\n');
else
getline( reader, tab[i++], '\t');
}
reader.close();
i = 0;
while (i < RANGE)
{
cout << endl << "Record Number: " << ++j << endl;
cout << "Forename: " << tab[i++] << endl;
cout << "Surname: " << tab[i++] << endl;
cout << "Department: " << tab[i++] << endl;
cout << "Telephone: " << tab[i++] << endl;
}
return 0;
}
Contents of TXT file:
John Smith Sales 555-1234
Mary Jones Wages 555-9876
Paul Harris Accts 555-4321
Please run the code for yourself to understand what happens and put the txt file in the same folder as your code.
Hope someone can help me thanks.
See Why is iostream::eof inside a loop condition (i.e. while (!stream.eof())) considered wrong?.
Also, your final while loop should only output the strings that were actually read into the array, not the full array, if the file has less than 12 strings. But unless you can guarantee that your file never exceeds 12 strings, you should use std::vector instead of a fixed array.
Also, instead of alternating the getline() delimiter in a single loop, I would just use an outer loop to read whole lines only, and then separately read tab-delimited values from each line. And then store the values in an array/vector of struct instead of individually.
Try something more like this:
#include <fstream>
#include <sstream>
#include <string>
#include <iostream>
#include <vector>
using namespace std;
struct Person
{
string foreName;
string surName;
string department;
string phoneNumber;
};
int main()
{
ifstream reader("records.txt");
if (!reader)
{
cout << "Error opening input file" << endl;
return -1;
}
vector<Person> people;
string line;
while (getline(reader, line))
{
istringstream iss(line);
Person p;
getline(iss, p.foreName, '\t');
getline(iss, p.surName, '\t');
getline(iss, p.department, '\t');
getline(iss, p.phoneNumber, '\t');
people.push_back(p);
}
reader.close();
int j = 0;
for (Person &p : people)
{
cout << endl << "Record Number: " << ++j << endl;
cout << "Forename: " << p.foreName << endl;
cout << "Surname: " << p.surName << endl;
cout << "Department: " << p.department << endl;
cout << "Telephone: " << p.phoneNumber << endl;
}
return 0;
}
There are easier ways to separate words in an istream, namely C++ sring stream tools:
#include <fstream>
#include <iostream>
#include <sstream> //<-- string stream library
using namespace std; //<-- should not be used, use scope std::
int main() {
const int RANGE = 12;
string tab[RANGE];
string temp; //<--to store each field temporarily
int i = 0, j = 0;
ifstream reader("records.txt");
if (!reader) {
cout << "Error opening input file" << endl;
return -1;
}
while (getline(reader, temp)) { //<-- read one full line
stringstream ss(temp); // <-- input to a string stream
while(ss >> tab[i]){ // <-- passing strings to the string array one by one
i++;
}
}
reader.close();
i = 0;
while (i < RANGE) {
cout << endl << "Record Number: " << ++j << endl;
cout << "Forename: " << tab[i++] << endl;
cout << "Surname: " << tab[i++] << endl;
cout << "Department: " << tab[i++] << endl;
cout << "Telephone: " << tab[i++] << endl;
}
return 0;
}
The idea here was to mess as little as possible with your code, one thing I would advise is to use std::vector instead of normal fixed size arrays. Also, as it was said and linked, eof is very unreliable.
The source of your problem, I think, is explained in Why is iostream::eof inside a loop condition (i.e. `while (!stream.eof())`) considered wrong?.
You are reading into tab[12], tab[13], tab[13], and tab[14] due to that error. Of course, that leads to undefined behavior.
Change the loop to:
// Read the contents of the file line by line
std::string line;
while (getline( reader, line))
{
// Process each line's contents.
std::istringstream str(line);
getline(str, tab[i++], '\t');
getline(str, tab[i++], '\t');
getline(str, tab[i++], '\t');
getline(str, tab[i++], '\n');
}
Make sure to add
#include <sstream>
To be doubly sure that you are not using the array using out of bounds indices, add a check.
while ( i+4 < RANGE && getline( reader, line))
{
...
}
First, while (!reader.eof()) is not doing the right thing.
The immediate problem you see is caused by the fact that your file does not contain '\t', hence already the very first getline reads all the contents of the file into tab[0]. (At least thats what I got after 1-to-1 copying your file contents)
Your code is rather difficult, because you declare variables long before you use them and later reuse them. You have a fixed size array, but when there are more lines in the file your code will just crash. Also reading everything into a plain array of strings is making things complicated. Accessing forename or other fields requires you to compute the offset into the array. Better use a data structure:
struct file_entry {
std::string first_name;
std::string last_name;
std::string departure;
std::string phone;
};
Then you can define an input operator:
std::istream& operator>>(std::istream& in,file_entry& fe) {
return in >> fe.first_name >> fe.last_name >> fe.departure >> fe.phone;
};
And use a std::vector to store as many entries as there are in the file:
int main() {
std::string contents{"John Smith Sales 555-1234\n"
"Mary Jones Wages 555-9876\n"
"Paul Harris Accts 555-4321\n"};
std::stringstream reader{contents};
std::vector<file_entry> data;
std::string line;
while (std::getline(reader,line)) {
file_entry fe;
std::stringstream{line} >> fe;
data.push_back(fe);
}
for (const auto& fe : data) {
std::cout << "Forename: " << fe.first_name << '\n';
std::cout << "Surname: " << fe.last_name << '\n';
std::cout << "Department: " << fe.departure << '\n';
std::cout << "Telephone: " << fe.phone << '\n';
}
}
live example
PS you do not need to call close on the file, this is already done in its destructor. Not calling it explicitly has the benefit that the same code that works for a file stream also works for a stringstream.
So basically what I want to implement is that I have a text file and I have to find a specific word along with the location (location of line and where the word is on that line). how it could be implemented using basic knowledge of C++... I'm a newbie and haven't studies vector etc.Thanks for your help
fstream x;
x.open("file.txt);
while(getline(x,str)) {
//extract word from str and save in str1
if(reqWord == str1)
print("match found");
}`
This is kind of an advanced trick, but I suggest you try stringstream:
std::stringstream ss;
ss << str;
while(ss >> str1)
...
You can use find in order to search a specific occurrence of a search term. It will return the position of the first occurrence, otherwise npos if it's not on the current line.
Please find below a working example:
Edited - using regular expression with word boundary
#include <iostream>
#include <fstream>
#include <regex>
int main() {
std::cout << "Please input the file path" << std::endl;
std::string path;
std::cin >> path;
std::ifstream file(path.c_str());
if (file.is_open()) {
std::string search;
std::cout << "Please input the search term" << std::endl;
std::cin >> search;
std::regex rx("\\b" + search + "\\b");
int line_no = 1;
for (std::string line; std::getline(file, line); ++line_no) {
std::smatch m;
if (std::regex_search(line, m, rx)) {
std::cout << "match 1: " << m.str() << '\n';
std::cout << "Word " << search << " found at line: " << line_no << " position: " << m.position() + 1
<< std::endl;
break;
}
}
} else {
std::cerr << "File could not be opened." << std::endl;
return 1;
}
return 0;
}
I am trying to read string with spaces using getLine, but i am getting error "Error: The function "getLine" must have a prototype.". I am getting this error even after including using namespace std;
void buildAhardCodedSQL4()
{
cout << "Enter source : ";
getLine(cin,source);
}
Replace getLine(cin,source); with getline(cin,source);
For more information on how to use getline(), refer to the following: http://www.cplusplus.com/reference/string/string/getline/
read the manual:
http://en.cppreference.com/w/cpp/string/basic_string/getline
#include <string>
#include <iostream>
#include <sstream>
int main()
{
// greet the user
std::string name;
std::cout << "What is your name? ";
std::getline(std::cin, name);
std::cout << "Hello " << name << ", nice to meet you.\n";
// read file line by line
std::istringstream input;
input.str("1\n2\n3\n4\n5\n6\n7\n");
int sum = 0;
for (std::string line; std::getline(input, line); ) {
sum += std::stoi(line);
}
std::cout << "\nThe sum is: " << sum << "\n";
}
I try to find same lines between two text files.
while (getline (texta,str1)){
while (getline (textb,str2)){
cout<<str1<<str2<<endl;
}}
First while working very well but second one just read first part line of text and then quit. I've tried different textes but doesnt work.
If you want to look all code:
void similars(string text1,string text2){
string str1,str2;
ifstream texta(text1.c_str());
ifstream textb(text2.c_str());
if(texta.is_open() && textb.is_open()){
while (getline (texta,str1)){
while (getline (textb,str2){
cout<<str1<<str2<<endl;
}
}
}
else cout << "Unable to open file";
}
don't mix things those shouldn't do
consider this example:
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
void similars(string text1, string text2)
{
string str1, str2;
ifstream texta(text1.c_str(), ios::in);
ifstream textb(text2.c_str(), ios::in);
cout << "text1: " << endl << endl;
while(!texta.eof())
{
getline (texta, str1);
cout << str1 << endl;
}
cout << endl << endl;
texta.close(); // closing safely the file
cout << "text2: " << endl << endl;
while(!textb.eof())
{
getline (textb, str2, '\n');
cout << str2 << endl;
}
textb.close();
cout << endl;
}
int main()
{
system("color 1f");
string sText1 = "data1.txt";
string sText2 = "data2.txt";
similars(sText1, sText2);
system("pause");
return 0;
}
just create two text files with notepad or any text editor, rename them to "text1.txt", "text2.txt" and put some text in them and save and close. then run the program.
This currently reads a .txt file and sorts the contents. I'm trying to get it to write those sorted contents of the vector to a file. Currently it only writes one line, how can I can get it to put all lines in the new file? Thank you so much. -Kaiya
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <cmath>
#include <fstream>
using namespace std;
inline void keep_window_open() {char ch; cin>>ch;}
int main()
{
string line;
ifstream myfile("weblog.txt");
vector<string> fileLines;
//stack overflow example
if (!myfile) //test the file
{
cout << "Unable to open the file" << endl;
return 0;
}
while (getline(myfile, line))
{
fileLines.push_back(line);
//cout << line << '\n';
}
sort(fileLines.begin(), fileLines.end()); //sorting string vector
for (string &s : fileLines)
{
cout << s << " ";
ofstream newfile ("newfile.txt");
newfile << s << " ";
};
return 0;
}
ofstream newfile ("newfile.txt");
for (string &s : fileLines)
{
cout << s << " ";
newfile << s << " ";
};
Creating newfile for every loop iteration overwrites the content of the file, by default.
Either open newfile before the last loop, or open it in append mode within the loop.
It's because you are creating a new file in each iteration of your loop!
ofstream newfile("newfile.txt");
should be written before the loop.
ofstream newfile ("newfile.txt");
for (string &s : fileLines)
{
cout << s << " ";
newfile << s << " ";
};
ofstream newfile ("newfile.txt");
copy(fileLines.begin(), fileLines.end(), ostream_iterator<string>(newfile, " ") );
Here is my complete code that worked, thanks Xiaotian Pei for your help.
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <cmath>
#include <fstream>
using namespace std;
inline void keep_window_open() {char ch; cin>>ch;}
int main()
{
string line;
ifstream myfile("weblog.txt");
vector<string> fileLines;
if (!myfile) //test the file
{
cout << "Unable to open the file" << endl;
return 0;
}
while (getline(myfile, line))
{
fileLines.push_back(line);
}
sort(fileLines.begin(), fileLines.end()); //sorting string vector
ofstream newfile ("newfile.txt"); //write to new file
for (string &s : fileLines)
{
cout << s << " ";
newfile << s << " ";
}
return 0;
}