std::string::find() not working with std::string as argument - c++

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.

Related

How to find out particular word in a string

Problem : I am getting Problem while pass string and find out word in that string.
I have tried below code:
if(string.find("Z03"))
{
// field exists
return true;
}
String :Z030000000057
Here's what I'm trying to do:
if(string.find("Z03"))
{
// field exists
return true;
}
when i pass string in message like ";Z030000000057" then its enter in the loop but when i simply pass "Z030000000057" its go into loop.
Kindly help me for this.
find() returns the index of the first occurrence, or string::npos. Your if is testing if find() returned zero (i.e. first occurrence at beginning of string) or not (i.e. search string occurs later, or not at all).
You are probably looking for...
if ( string.find( "Z03" ) != std::string::npos )
{
// field exists
return true;
}
...which perhaps could be shortened to...
return ( string.find( "Z03" ) != std::string::npos );
...if neither the true nor the false branch do anything else.
Check the documentation on the 'find' method: http://en.cppreference.com/w/cpp/string/basic_string/find
The method returns position of the first character of the found substring or std::string::npos if the substring is not found.
Regarding your examples:
std::string s("Z030000000057");
if(s.find("Z03"))
{
// execution DOES NOT goes here because find returns 0 as found position
}
s = ";Z030000000057";
if(s.find("Z03"))
{
// execution goes here because find returns 1 as found position
}
The correct code would be:
if (s.find("Z03") != std::string::npos)
{
// field exists
}
I recommend using cppreference for further checking standard functions, it's very useful.

string.find() doesn't return -1

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/

Check several signals in one String C++

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:
'([^()!&|;])'

Having trouble getting GET variables from url

I'm having trouble with this algorithm to extract the get variables from a url and print them each on a new line like:
x=y
z=hello
etc. but instead it prints a seemingly random section of the url with no newlines to the file. There must be a logic error of some kind but i just can't spot it.
for(i_m=0;i_m<len_m;i_m++) {
if(var_m[i_m]=='&') {
fwrite(var_m+offset_m, 1, amp_m, echo_out);
fputc('\n',echo_out);
offset_m+=amp_m;
amp_m=0;
}
amp_m++;
}
any help appreciated.
EDIT:
thank you everyone for your comments, I corrected that error Guss but to no avail. I thought up another algorithm, since I can't use c++ strings in this one
while((i_m=(strchr(var_m,'&')-var_m))>0) {
var_m[i_m]='\n';
}
Which would change each of the & to a newline, and then I could just write var_m to the file, but for some reason this gives me a buffer overflow.
void StringExplode(std::string &str, const std::string &separator, std::vector<string>* results){
int found;
found = str.find_first_of(separator);
while(found != string::npos){
if(found > 0){
results->push_back(str.substr(0,found));
}
str = str.substr(found+1);
found = str.find_first_of(separator);
}
if(str.length() > 0){
results->push_back(str);
}
}
your accounting of offset_m and amp_m seems to be wrong. Take for example the simple string "a&b&c" - your code should have outputed from that the text:
a
b
c
but if you trace through the code you will see that when you get to the first & then offset_m=0 and amp_m=1 and you'd print a - which is Ok but when you get to the second & then offset_m=1 and amp_m=2 which would actually print &b and at no point you'd print the last element.
Using a simple string splitting algorithm like mysqlforums suggested is a common way to handle this task, but I believe you should be able to come up with a simple loop algorithm that will get you what you need. think about it again and try to run through the algorithm in your head (or using pen and paper) to try to understand how it works - I'm sure you'll get it!
If you're still having problems, post something here and I'll try to help again.

CString extract file path

Hey I'm trying to extract the file path but the problem is that I'm stuck in an infinite loop don't understand why. Please have a look at my code.
CString myString(_T("C:\\Documents and Settings\\admin\\Desktop\\Elite\\Elite\\IvrEngine\\dxxxB1C1.log"));
int pos = myString.Find(_T("\\"));
while (pos != -1)
{
pos = myString.Find(_T("\\"), pos); // it keeps returning 2
}
CString folderPath = myString.Mid(pos);
Now the problem is that, Find() returns 2 the first time I run, but then in the while loop it keeps returning 2, why is the function unable to find the rest '\' ? So now I'm in an infinite loop :(.
It sounds like Find includes the character at the position you give it when searching. So if you give it the position of a character that matches the search, then it will return that same position.
You probably need to change it to:
pos = myString.Find(_T("\\"), pos + 1);
your code will never work! When the while loop finished, the contend of pos can not be used.
Here is a solution which will work:
CString folderPath;
int pos = myString.ReverseFind('\\');
if (pos != -1)
{
folderPath = myString.Left(pos);
}
You can fix the code (see the pos + 1 answers) but I think that you should use _splitpath_s instead which was intended for this kind of operations.
CString::Find always returns the first occurence of the character you're searching for. So it keeps finding the the first "\\" which is at index 2 infinitely since you're searching from 2 which includes that "\\"
I can understand your initial implementation, as the behaviour of CString::Find() seem to have changed over time.
Take a look at the MSDN docs for MFC implementation shipped with VC6 here and at the current implementation here. Especially look at the differences of the description of the 2nd offset parameter.
The solution to your problem is, as already stated above, to add 1 to the search offset of the successive Find() calls. You can also search for single chars (or wchar_ts) like that:
myString.Find(_T('\\'), pos+1);
EDIT:
BTW, take a look at the Path* familly of functions exposed by the shlwapi.dll, declared in shlwapi.h. Especially the PathRemoveFileSpec function might be of interest to you.
in MFC, example to get folder which including executable file:
char ownPth[MAX_PATH];
// Will contain exe path
HMODULE hModule = GetModuleHandle(NULL);
if(NULL == hModule){
return __LINE__;
}
// When passing NULL to GetModuleHandle, it returns handle of exe itself
GetModuleFileName(hModule,ownPth, (sizeof(ownPth)));
modulePath = (LPCSTR)ownPth;
modulePath = modulePath.Left(modulePath.ReverseFind(_T('\\')));
return 0;