I want to search a position in one string which isn't equal to "(",")","!","&","|",";". If I use if(str[1] != "!" && str[1] != "(" ...), it is too long... is there something I can use to make this simple?
I think you're talking about find_first_not_of. str.find_first_not_of("!(...").
string badChars = "!()&|;";
if ( badChars.find(str[1]) == string::npos )
{
}
Edit: I think I misunderstood the problem. As Michael Krelin pointed out, find_first_not_of is probably what you want here.
Any regex engine can match that via:
'([^()!&|;])'
Related
I have got a queue fifo type (first in, first out) with strings in it. Every string is sentence. I need to find a word in it, and show it on console. The problem is, that when i used str.find("word") it can showed sentence with "words".
Add white space and some symbols like ".,?!" = str.find("word ") etc. but its not a solution
if (head != nullptr)
do {
if (head->zdanie_kol.find("promotion") != string::npos ||
head->zdanie_kol.find("discount") != string::npos ||
head->zdanie_kol.find("sale") != string::npos ||
head->zdanie_kol.find("offer") != string::npos)
cout << head->zdanie_kol << endl;
} while (head != nullptr);
For example, i got two sentences, one is correct, another one is not.
Correct:
We have a special OFFER for you an email database which allows to contact eBay members both sellers and shoppers.
Not Correct:
Do not lose your chance sign up and find super PROMOTIONS we prepared for you!
The three simplest solutions I can think of for this are:
Once you get the result simply check the next character. If it's a whitespace or '\0', you found your match. Make sure to check the character before too so you don't match sword when looking for word. Also make sure you're not reading beyond the string memory.
Tokenize the string first. This will break the sentence into words and you can then check word by word to see if it matches. You can do this with strtok().
Use regular expression (e.g. regex_match()) as mentioned in the comments. Depending on the engine you choose, the syntax may differ, but most of them have a something like "\\bsale\\b" which will match on word boundary (see here for more information).
Here is a solution, using std::unordered_set and std::istringstream:
#include <unordered_set>
#include <string>
#include <sstream>
//...
std::unordered_set<std::string> filter_word = {"promotion", "discount", "sale", "offer"};
//...
std::istringstream strm(head->zdanie_kol);
std::string word;
while (strm >> word)
{
if (filter_word(word).count())
{
std::cout << head->zdanie_kol << std::endl;
break;
}
}
//...
If you had many more words to check instead of only 4 words, this solution seems easier to use since all you have to do is add those words to the unordered_set.
I have a rudimentary program I'm trying to implement that asks for a URL of a .pdf file and then downloads it and shows it through Xming. First, I want to check to make sure the user actually put in a URL with 'http://' at the front and 'pdf' or 'PDF' at the end. I suppose this might be a typical problem from someone coming from Python, but how do I check end of the string the user inputs. Using the method below (which I used with my Python-oriented-brain) I get a
Range error: -3
So how do ACTUAL C++ programmers accomplish this task? Please and thank you.
if (file[0]=='h' && file[1]=='t' && file[2]=='t' && file[3]=='p' && file[4]==':'
&& file[5]=='/' && file[6]=='/' && (file[-3]=='p' || file[-3]=='P')
&& (file[-2]=='d' || file[-2]=='D') && (file[-1]=='f' || file[-1]=='F'))
In C++ you cant access negative indizies.
You would have to manually calculate the position of the laste element:
int s = file.size();
(file[s-3]=='p' || file[s-3]=='P')
&& (file[s-2]=='d' || file[s-2]=='D')
&& (file[s-1]=='f' || file[s-1]=='F')
I'm assuming that file is a C++ - string, if its not you have to use a other way to get the length
You could also simplify your code by using build in string-functions:
int s = file.size();
if (s > 10 && file.find("http://") == 0 && file.substr(s-3, 3) == "PDF") //...
Or just use Regex like another comment suggested (probably the nicest way)
There are probably quite a few C++ programmers who have a bool endsWith(std::string const& input, std::string const& suffix) function in their toolkit.
It's easy to write this in a non-performing way. Calling substr is a common cause of this. A regex is even less performant. Here's one implementation that avoids temporaries and copies:
bool endsWith(std::string const& input, std::string const& suffix)
{
if (input.size() < suffix.size()) return false; // "a" cannot end in "aa"
return std::equal(begin(suffix), end(suffix), end(input)-suffix.size());
}
Another solution is to use Regex.
regex url("http//\w*pdf",icase);
Or you can use regex:
#import <regex>
using namespace std;
...
std::string str = "http://www.example.com/myFile.PDF";
std::regex rx("http(s)?:(www\.)?.+/[pP][dD][fF]");
return regex_match(str.begin(), str.end(), rx)
..
Where:
"http(s)? - matches http or https
(www\.)? - matches a single or 0 apparitions of www. such as 'www.example.com' or 'example.com'
.+/ - matches any character
/[pP][dD][fF] - the end of url can by any combination of small and capital letters that form whe word 'pdf'
You can check out more here and here
There's a bunch of different ways using various string methods. If you really cared about performance you could benchmark the various ways. Here's an example with find & substr.
#include <algorithm>
#include <string>
std::string file = "http://something.pdf";
std::transform(file.begin(), file.end(), file.begin(), ::tolower); // lowercase the data, see http://stackoverflow.com/questions/313970/stl-string-to-lower-case
if (file.find("http://") == 0 && (file.substr(file.length() - 3) == "pdf")) {
// valid
}
I've run across something that does not make much sense to me when using std::string::find() I'm hoping that someone here is able to spot my error:
std::string testString = "PFAIL";
std::string response = "PFAIL\n";
if( response.find(testString) != std::string::npos )
{
//do something
}
This code NEVER hits the //do something comment for some reason. Any ideas?
Edited: I meant that it never hits the //do something code block, which it should and it does if I express it the following way:
if( response.find( testString.c_str() ) != std::string::npos )
{
// do something
}
Maybe you should consider using straight logic in your if statements:
if( response.find(testString) == std::string::npos )
This logical expression could potentialy confuse you less. If the return value of find equals to std::string::npos then the string in testString variable has not been found in your response string.
Edited: i had the logic in answer the wrong way.
Your condition is the wrong way around from what you appear to be expecting. npos is returned if nothing is found. Since the response clearly contains the test, npos won't be returned and the body of the if will be entered.
The code below is simple. As I know, if string::find() didn't find matches it returns -1. But for some reasons the code below doesn't work. Everytime I run this code I get endless loop. Thank you for help!
#include <string>
#include <iostream>
using namespace std;
int main()
{
string text;
text = "asdasd ijk asdasd";
string toReplace = "ijk";
cout<<text<<endl;
int counter = 0;
while ( text.find(toReplace) != -1)
counter++;
cout<<counter<<endl;
system("pause");
}
Aside from the other answers which are completely correct, I just wanted to add that your while loop would have produced an endless loop anyway. For example:
while(text.find(toReplace) != std::string::npos)
counter++;
will be an endless loop because it will keep trying to find the toReplace string in text and it will always find it (that's because find starts from the beginning of the string each time). This is probably not what you intended.
std::string::find returns std::string::npos if the searched substring is not found, not -1. The exact value of npos is implementation-defined, so use npos, as in
while ( text.find(toReplace) != std::string::npos)
Come to think of it, find couldn't return -1 even if it wanted to because the return type of find is specified to be std::size_t which is an unsigned type.
Additionally, find will always search for the first occurrence of the substring, no matter how many times you call it. If you want to iterate through all the occurrences you should use the overload of find which takes a second parameter - the position from which to start searching.
Whoever told you this or wherever you read it, it lied to you.
If std::string::find fails, it returns std::string::npos, which is not -1.
You should check the documentation about such things, when you're not sure.
So, your while will be something like:
while ( std::string::npos != text.find(toReplace) )
Regarding your comment:
UPDATE: I tried to use while ( text.find(toReplace) != string::npos ) but I still get endless loop :( – user2167403 10 secs ago
You should really learn to read the documentation. Use a variable to store the last result of std::string::find (different from std::string::npos) and use std::string::find's second parameter - pos ( by passing value - last_match_position + 1).
Omitting the second parameter, std::string::find always starts from the beginning of the string, which causes the endless loop.
In the code snippet you provided text variable contains substring "ijk" which is stored in the toReplace variable. As long as in while cycle neither text or toReplace variables are changed, find method will always return not a -1 value which is the condition for while cycle to continue.
As already metioned in other comments you should check not for -1 but for std::string::npos.
It does help to read the manual page (string::npos is the answer).
See http://www.cplusplus.com/reference/string/string/find/
I am not good with c++ and I cannot find this anywhere, please apologize me if it is a bad question. I have a pointer and I want to know if some names store in this pointer begins with some specific string. As in python something like (maybe it is a bad example):
if 'Pre' in pointer_name:
This is what I have:
double t = 0;
for (size_t i =0; i < modules_.size(); ++i){
if(module_[i].name() == "pre"){ // here is what I want to introduce the condition
if (modules_[i].status() == 2){
std::cout << module_[i].name() << "exists" << std::endl;
}
}
}
The equivalent of Python 'Pre' in string_name is:
string_name.find("Pre") != std::string::npos // if using string
std::strstr(pointer_name, "Pre") // if using char*
The equivalent of Python string_name.startswith('Pre') ("begins with some specific string") is:
string_name.size() >= 3 && std::equal(string_name.begin(), string_name.begin() + 3, "Pre"); // if using string
string_name.find("Pre") == 0 // less efficient when it misses, but shorter
std::strncmp(pointer_name, "Pre", 3) == 0 // if using char*
In two of those cases, in practice, you might want to avoid using a literal 3 by measuring the string you're searching for.
Check std::string::find, there are enough good examples. If you are using c-style string, use strstr.
You can use the algorithm header file to do most of things usually one liners in python.
In this case though it might be just easier to use string find method .
If your name variable is of type std::string then you can use name().compare("Pre") == 0 for string comparison.
EDIT: Seems I misunderstood the question, for contains you can use string find, as other said.
Using C style strings, char * is not recommended in C++. They are error prone.