I really don't know what is wrong that my regex is not matching.
I tried two codes:
Code1 (NOT MATCH):
I am pushing from file to vector<string> cn;
//FILE
ifstream file(params.file_name);
string line;
// read each line of the file
while ( getline(file, line) ){
istringstream iss(line);
string token;
unsigned int loopCsv = 0;
while (getline(iss, token, ';')){ //when ";" separate cn;uid;mail
if (loopCsv == 0)
cn.push_back(token); //cn
if (loopCsv == 1)
uid.push_back(token); //uid
if (loopCsv == 2)
mail.push_back(token); //mail
loopCsv++;
if (loopCsv == 3) //after 3 (cn,uid,mail) repeat
loopCsv=0;
}
}
then trying regex:
cout << "There is Neruda Jakub: " << cn[286] << endl;
regex regexX(".*Jakub", std::regex::ECMAScript | std::regex::icase);
bool match = regex_search(cn[286], regexX);
if (match)
cout << "MATCH!" << endl;
I am getting output:
There is Neruda Jakub: Neruda Jakub
but no match. I have also tried adding some symbols around cn[286] if there isn't any space |Neruda Jakub| and there isn't
Code2 (MATCH):
vector<string> someVctr;
someVctr.push_back("Neruda Jakub");
regex regexX(".*Jakub", std::regex::ECMAScript | std::regex::icase);
bool match = regex_search(someVctr[0], regexX);
if (match)
cout << "MATCH!" << endl;
without problem, I will get MATCH!
I will be grateful for any help you can provide.
From the comments, it looks like the file was encoded as utf-16. The simple fix for all of this is to replace all the char streams and strings with char16_t (or wchar_t on Windows)
basic_string<char16_t> cn;
basic_string<char16_t> uid;
basic_string<char16_t> mail;
//FILE
basic_ifstream<char16_t> file(params.file_name);
basic_string<char16_t> line;
// read each line of the file
while ( getline(file, line) ){
basic_istringstream<char16_t> iss(line);
basic_string<char16_t> token;
unsigned int loopCsv = 0;
while (getline(iss, token, ';')){ //when ";" separate cn;uid;mail
if (loopCsv == 0)
cn.push_back(token); //cn
if (loopCsv == 1)
uid.push_back(token); //uid
if (loopCsv == 2)
mail.push_back(token); //mail
loopCsv++;
if (loopCsv == 3) //after 3 (cn,uid,mail) repeat
loopCsv=0;
}
}
cout << "There is Neruda Jakub: " << cn[286] << endl;
basic_regex<char16_t> regexX(".*Jakub", std::regex::ECMAScript | std::regex::icase);
bool match = regex_search(cn[286], regexX);
if (match)
cout << "MATCH!" << endl;
Related
I have a file map.txt:
Montreal|Quebec,Toronto|30,40
New York|Boston,Philadelphia,Scranton|20,10,50
I want to assign the first part before the "|" to cityString, the second part to edgesString and the third part to costString. Then, I will use boost to split the strings into corresponding vectors, and assign these vectors to a custom CityNode Object.
This is my code:
string cityString;
string edgesString;
string costString;
vector<string> edgesVector;
vector<string> costVector;
vector<CityNode> cities;
int i = 0;
bool used = true;
string line;
ifstream myfile(this->fileName);
if (myfile.is_open())
{
while (getline(myfile, line))
{
cout << cityString << "|" << edgesString << "|" << costString << "\n"; // read line of file
boost::split(edgesVector, edgesString, [](char c) {return c == ','; }); //split edgesString into vector delimiter: ','
boost::split(costVector, costString, [](char c) {return c == ','; }); // split costString into vector delimiter: ','
//ASSIGN VARIABLES
cities[i].setValues(cityString, edgesVector, costVector);
i++;
}
myfile.close();
}
else cout << "Incorrect file format";
return cities;
when I call
cout << cities[0].getName();
I get
||
||
instead of "Montreal" as I want. I think the error is the way I read the variables from the file but I don't know how to fix it. Please help.
Try something more like this instead:
string edgesString;
string costString;
string line;
vector<string> edgesVector;
vector<string> costVector;
vector<CityNode> cities;
ifstream myfile(this->fileName);
if (myfile.is_open())
{
while (getline(myfile, line))
{
istringstream iss(line);
getline(iss, cityString, "|");
getline(iss, edgesString, "|");
getline(iss, costString);
cout << cityString << "|" << edgesString << "|" << costString << "\n"; // display line from file
auto onComma = [](char c){ return c == ','; };
boost::split(edgesVector, edgesString, onComma); //split edgesString into vector delimiter: ','
boost::split(costVector, costString, onComma); // split costString into vector delimiter: ','
//ASSIGN VARIABLES
CityNode city;
city.setValues(cityString, edgesVector, costVector);
cities.push_back(city);
}
myfile.close();
}
else
cout << "Cannot open file";
return cities;
So for what i understand, there is multiple things here :
First the actual content of your file is stored into the line variable.
This variable seems to be never used after. Hence, your vectors are not set.
Then the output on the console is the result of the 'cout << cityString << "|" << edgesString << "|" << costString << "\n";` statement, since you never affect any value to those variables they are "empty strings". And because there is 2 line in your file, with the while statement you end up with :
||
||
Also I think you can split without using boost.
with this code you have the proper output :
boost::split(lineVect, line,[](char c) { return c == '|'; });
cout << lineVect[0] << "|" << lineVect[1] << "|" << lineVect[2] << "\n";
boost::split(edgesVector, lineVect[1], [](char c) { return c == ','; }); //split edgesString into vector delimiter: ','
boost::split(costVector, lineVect[2], [](char c) { return c == ','; }); // split costString into vector delimiter: ','
//ASSIGN VARIABLES
cities[i].setValues(lineVect[0], edgesVector, costVector);
i++;
My problem is rather simple yet I can't get my head around it.
I was searching through the internet of course, but all solutions I found were using std::vectors and I'm not allowed to use them.
I have the following string:
std::string str "Tom and Jerry";
I want to split this string using space as a delimiter, and then assign the three words into three different strings.
//this is what I am trying to achieve
std::string substr1 = "Tom";
std::string substr1 = "and";
std::string substr1 = "Jerry";
This is how I am splitting the string by the space as a delimiter:
std::string buf;
std::string background;
std::stringstream ss(str);
while (ss >> buf) {
if (buf == " ")
background = buf; // don't really understand that part
std::cout << "splitted strings: " << buf << std::endl;
}
But I have no idea when and how should I assign the splitted strings into the substr1, substr2, substr3. Would anyone explain how should I throw in the strings assignment part into this?
I have tried some weird stuff like:
std::string substr1, substr2, substr3;
int counter = 1;
while (ss >> buf) {
if (buf == " ")
background = buf; // don't really understand that part
counter = 1;
if (counter == 1) {
substr1 = buf;
std::cout << "substr1 (Tom): " << substr1 << std::endl;
counter++;
}
else if (counter == 2) {
substr2 = buf;
std::cout << "substr2 (and): " << substr2 << std::endl;
counter++;
}
else if (counter == 3) {
substr3 = buf;
std::cout << "substr3 (Jerry): " << substr3 << std::endl;
counter++;
}
Thanks.
You can simply do ss >> substr1; ss >> substr2; ss >> substr3;. The >> operator works exactly with spaces as separator.
Code
in "while" ,when coming a space ,make it a substring before the space and the "tom and jerry" has 2 space so it was splitted to two words. ss>>buf means input "ss"'s string to buf. so if there comes a spce it can store the word before space.
So I want to get a specific part from every line of the input file.
So far I got this:
ifstream fin("text.txt");
string line;
while (getline(fin, line)) {
if (line.find("Set") == 0)
{
istringstream sin1(line.substr(line.find("path1=") + 1));
sin1 >> path1;
istringstream sin2(line.substr(line.find("path2=") + 1));
sin2 >> path2;
}
}
From what I understood the (line.substr(line.find("VAR_CAL_PATH2=") + 1)) part will take whatever it's after "path1=" and will put it into path1, I guess I got it wrong. My input file has two lines:
Set path1="somepath"
Set path2="someotherpath"
When the while loop ends I get path1="Set" and path2="someotherpath" but what I want is path1="somepath" and path2="someotherpath"
As #Jordfräs says, find() returns the position of the start of the string.
When you try to parse the path2 value, you overwrite the value of path1.
The code with these fixes:
const string path1field = "path1=";
const string path2field = "path2=";
string path1 = "", path2 = "";
ifstream fin("text.txt");
string line;
while (getline(fin, line))
{
if (line.find("Set") != string::npos)
{
size_t path1pos = line.find(path1field);
size_t path2pos = line.find(path2field);
if (path1pos != string::npos)
{
istringstream sin1(line.substr(path1pos + path1field.length()));
sin1 >> path1;
}
if (path2pos != string::npos)
{
istringstream sin2(line.substr(path2pos + path2field.length()));
sin2 >> path2;
}
}
}
cout << "path1: " << path1 << endl;
cout << "path2: " << path2 << endl;
The find() function in std::string returns the position of the start of the string. Adding 1 will point to the start + 1, not the position after the string you search for.
There is plenty of good documentation of the standard library available, e.g., http://en.cppreference.com/w/cpp/string/basic_string/find
Another (more general) solution for string variables could be:
ifstream fin("text.txt");
string line;
const vector<string> pathsNames={"path1=", "path2="};
vector<string> paths(pathsNames.size());
while (getline(fin, line)) {
if (line.find("Set") == 0)
{
for(std::vector<string>::size_type x=0; x<pathsNames.size(); x++){
if(line.find(pathsNames[x])!=string::npos){
paths[x]=line.substr(line.find(pathsNames[x]) + pathsNames[x].length());
break;
}
}
}
}
//print results
for(std::vector<string>::size_type x=0; x<pathsNames.size(); x++){
cout << pathsNames[x] << paths[x] << endl;
}
I want to make a factory class which creates and loads objects in from a file;
however when I try to read in a int from the file it appears to return a incorrect number.
std::ifstream input;
input.open("input.txt");
if (!input.is_open()){
exit(-1);
}
int number;
input >> number;
cout << number;
input.close();
When I enter a number in the input.txt file it shows: -858993460.
Changing the number doesn’t make a difference and when I use cin instead of ifstream it works like it should. I'm probably just missing something really stupid, but I can't figure it out.
Edit: Using getLine() works like it should. I guess there is a problem using >>.
Here is another solution to open a file a read it line by line:
string line;
ifstream myfile("input.txt");
if (myfile.is_open())
{
while ( getline (myfile,line) )
{
cout << line << '\n'; // Use this to verify that the number is outputed
// Here you can transform your line into an int:
// number = std::stoi(line);
}
// myfile.close(); Use this if you want to handle the errors
}
else cout << "Unable to open file";
If you don't want to read line by line, just remove the while
...
getline(myfile,line);
number = std::stoi(line);
...
Read multiple numbers in one line
Image that your input file is like this:
1, 2.3, 123, 11
1, 2
0.9, 90
Then, you can use this piece of code to read all the numbers:
string line;
ifstream myfile("input.txt");
string delimiter = ", ";
if (myfile.is_open())
{
while ( getline (myfile,line) )
{
cout << "Reading a new line: " << endl;
size_t pos = 0;
string token;
while ((pos = line.find(delimiter)) != string::npos) {
token = line.substr(0, pos);
cout << token << endl; // Instead of cout, you can transform it into an int
line.erase(0, pos + delimiter.length());
}
}
}
else cout << "Unable to open file";
The output will be:
Reading a new line:
1
2.3
123
11
Reading a new line:
1
2
Reading a new line:
0.9
90
New solution that may work =)
I didn't test this, but it works apparently:
std::ifstream input;
double val1, val2, val3;
input.open ("input.txt", std::ifstream::in);
if (input >> val1 >> val2 >> val3) {
cout << val1 << ", " << val2 << ", " << val3 << endl;
}
else
{
std::cerr << "Failed to read values from the file!\n";
throw std::runtime_error("Invalid input file");
}
To check the IO, see http://kayari.org/cxx/yunocheckio.html
I want to start of by saying that I am still learning and some might think that my code looks bad, but here it goes.
So I have this text file we can call example.txt.
A line in example.txt can look like this:
randomstuffhereitem=1234randomstuffhere
I want my program to take in the numbers that are next to the item= and I have started a bit on it using the following code.
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
string word;
int main()
{
ifstream readFile("example.txt", ios::app);
ofstream outfile("Found_Words.txt", ios::app);
bool found = false;
long int price;
cout << "Insert a number" << endl;
cout << "number:";
cin >> number;
system("cls");
outfile << "Here I start:";
while( readFile >> word )
{
if(word == "item=")
Here is the problem; first of all it only searchs for "item=" but to find it, it cannot be included with other letters. It has to be a standalone word.
It wont find:
helloitem=hello
It will find:
hello item= hello
It has to be separated with spaces which is also a problem.
Secondly I want to find numbers next to the item=. Like I want it to be able to find item=1234 and please note that 1234 can be any number like 6723.
And I dont want it to find what comes after the number, so when the number stops, it wont take in anymore data. Like item=1234hello has to be item=1234
{
cout <<"The word has been found." << endl;
outfile << word << "/" << number;
//outfile.close();
if(word == "item=")
{
outfile << ",";
}
found = true;
}
}
outfile << "finishes here" ;
outfile.close();
if( found = false){
cout <<"Not found" << endl;
}
system ("pause");
}
You can use a code like this:
bool get_price(std::string s, std::string & rest, int & value)
{
int pos = 0; //To track a position inside a string
do //loop through "item" entries in the string
{
pos = s.find("item", pos); //Get an index in the string where "item" is found
if (pos == s.npos) //No "item" in string
break;
pos += 4; //"item" length
while (pos < s.length() && s[pos] == ' ') ++pos; //Skip spaces between "item" and "="
if (pos < s.length() && s[pos] == '=') //Next char is "="
{
++pos; //Move forward one char, the "="
while (pos < s.length() && s[pos] == ' ') ++pos; //Skip spaces between "=" and digits
const char * value_place = s.c_str() + pos; //The number
if (*value_place < '0' || *value_place > '9') continue; //we have no number after =
value = atoi(value_place); //Convert as much digits to a number as possible
while (pos < s.length() && s[pos] >= '0' && s[pos] <= '9') ++pos; //skip number
rest = s.substr(pos); //Return the remainder of the string
return true; //The string matches
}
} while (1);
return false; //We did not find a match
}
Note that you should also change the way you read strings from file. You can either read to newline (std::getline) or to the end of stream, like mentioned here: stackoverflow question