I'm currently making a DLL with a collection of code snippets that I find myself commonly using. I have made a search functin that checks if one string is inside of another string. I have also added a vector choice in the case that I want to search many strings.
In the header:

static DATAEDITING_API bool Contains(std::string target, std::string source);

static DATAEDITING_API bool Contains(std::string target, std::vector<std::string> source);

static DATAEDITING_API bool Contains(std::string target, std::string source, bool sensitive);

static DATAEDITING_API bool Contains(std::string target, std::vector<std::string> source, bool sensitive);

Now the problem is that the following code snippet always returns true. The Contains(std::string, std::string, bool) function has been tested to work properly; testing was for: an outright false case, a case dependent on case (both conditions tested) and a case where the start of the target string was found toward the end of the search string (ie "insert" in "thin").

bool Editor::StringHandler::Contains(std::string target, std::vector<std::string> source, bool sensitive)
{
    for (std::string i : source)
    {
        if(Contains(target, i, sensitive)){return true;}
    }
    return false;
}

Any ideas on why the function always returns true?

Recommended Answers

All 4 Replies

You didn't provide enough code. Can you post a brief but complete program that exhibits the problem?

You should learn about passing by reference. As in:

static DATAEDITING_API bool Contains(const std::string& target, const std::string& source);

static DATAEDITING_API bool Contains(const std::string& target, const std::vector<std::string>& source);

static DATAEDITING_API bool Contains(const std::string& target, const std::string& source, bool sensitive);

static DATAEDITING_API bool Contains(const std::string& target, const std::vector<std::string>& source, bool sensitive);

And:

bool Editor::StringHandler::Contains(const std::string& target, const std::vector<std::string>& source, bool sensitive)
{
    for (auto i : source)
    {
        if(Contains(target, i, sensitive)) { return true; }
    }
    return false;
}

As for the problem, I can't tell what it is, there isn't enough code. The loop seems right, so the problem must be in the string-string "Contains()" function that is being called in it.

P.S.: What is DATAEDITING_API? It is a bit bizarre that you have both a static keyword, and what looks to me like a MACRO for something like extern "C" __declspec(dllexport). If the functions are static member functions, then OK, sort of. But if they are free functions, then it shouldn't work. Also, you should be aware that it is a bit tricky to export C++ constructs from a DLL, including both overloaded functions and standard library components like std::string or std::vector in the parameter lists of your functions. The name-mangling and the binary layout of these things are not portable between compilers, compiler options, and platforms, which more or less means that you'll have to recompile the DLL for every application that uses it, which kind of defeats the purpose of it all. It is preferrable to use a static library (.lib) for this kind of thing, otherwise, use a DLL but expose only C-style functions (with extern "C" and no C++ constructs as parameters (except pointers to objects)).

Primary Contains function:

bool Editor::StringHandler::Contains(std::string target, std::string source, bool sensitive)
{
    bool match=false;
    char schar, tchar;

    tchar = SetChar(target.c_str()[0], sensitive);


    for (int i=0;i<=source.length()-target.length();i++)
    {
        schar = SetChar(source.c_str()[i], sensitive);

        if (schar == tchar)
        {
            match = true;
            for (int j=1;j<target.length();j++)
            {
                schar = SetChar(source.c_str()[i+j], sensitive);
                tchar = SetChar(target.c_str()[j], sensitive);

                if (schar != tchar)
                {
                    tchar = SetChar(target.c_str()[0], sensitive);
                    match = false;
                    break;
                }
            }
            if (match)
            {
                return true;
            }
        }
    }
    return false;
}

SetChar function:

Header:
private:
        static char SetChar(char item, bool sensitive);

Source:
char Editor::StringHandler::SetChar(char item, bool sensitive)
{
    if (sensitive){return item;}
    return tolower(item);
}

A program that displays the problem:

std::string testString("It was... extrodinary");

//testIn was formed from another function I have made,
//contents are:
//  ["It","was","extrodinary"]

result = StringHandler::Contains(string("Ary"), testString);
OutputConsole("BASIC: " + ReturnResult(result));
result = StringHandler::Contains(string("Ary"), testString, true);
OutputConsole("CASE: " + ReturnResult(result));
result = StringHandler::Contains(string("Ary"), testIn);
OutputConsole("BASIC VECTOR: " + ReturnResult(result));
result = StringHandler::Contains(string("Ary"), testIn, true);
OutputConsole("CASE VECTOR: " + ReturnResult(result));

I hope you know that std::string has a find method in which you can use to find another string. So for your Contains function, you can simply so something like so:

bool contains(const std::string& target, const std::string& src, bool ignoreCasing = false){
   const std::string& adjustedSrc = ignoreCasing ? toLower( src ) : src;
   const std::string& adjustedTarget = ignoreCasing ? toLower( target ): target;
   return adjustedSrc.find( adjustedTarget ) != std::string::npos;
}

The toLower is a function you would have to create that lowers the whole string. Other than that suggestion, your code is fairly complicated, and I'm not sure why it needs to be that way.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.