1

I have file names and I need to check if these files end with any extension of the vector extensions; I would like to use some of the algorithms that are in the library instead of how I have done it, is there any way?

#include <iostream>
#include <algorithm>
#include <vector>

std::string tail(const std::string &st, const size_t len)
{
    if (len >= st.size())
        return st;
    return st.substr(st.size() - len);
}

std::vector<std::string> filtered_files(const std::vector<std::string>& files, const std::vector<std::string>& extensions) {

    std::vector<std::string> re;
    for(const std::string f : files) {
        for(const std::string ex : extensions) {
            if(ex == tail(f,ex.size())) {
                re.push_back(std::move(f));
                break;
            }
        }
    }
    return re;
}

int main(int argc, char **argv) {

    std::vector<std::string> v{"main.cpp","main.c","main.py"};
    std::vector<std::string> re = filtered_files(v,{".c",".cpp"});
    for(const std::string s  :re) {
        std::cout << s << '\n';
    }

}
Ulrich Eckhardt
  • 16,572
  • 3
  • 28
  • 55
wiki2
  • 13
  • 2
  • That's kind of an open-ended question. Of course you can. As a first step, check out the algorithms and see if you reimplemented any of them. Then, replace your implementation with that from the standard library. – Ulrich Eckhardt Oct 02 '19 at 19:15
  • I think the [this answer](https://stackoverflow.com/a/874160/416574) on this question will be very helpful to you: https://stackoverflow.com/questions/874134/find-out-if-string-ends-with-another-string-in-c it is making use of the string::compare function and uses an index computation to calculate the end of the string for comparing. – pstrjds Oct 02 '19 at 19:20

2 Answers2

2

Have a look at the std::find_if() standard algorithm in place of the inner loop. You can use the std::string::compare() method to perform substring comparisons without having to actually allocate new std::string objects, as your loops and tail() function currently do. The only string allocations you need are for the strings pushed into re (and even that allocation can be avoided if you return a std::vector<std::string*> of pointers that point to the strings in te files vector).

Try this:

#include <iostream>
#include <algorithm>
#include <vector>

std::vector<std::string> filtered_files(const std::vector<std::string>& files, const std::vector<std::string>& extensions)
{
    std::vector<std::string> re;

    for(const std::string &f : files)
    {
        if (std::find_if(extensions.begin(), extensions.end(),
            [&](const std::string &ex){
                return (f.size() >= ex.size()) && (f.compare(f.size()-ex.size(), ex.size(), ex) == 0);
            }
        ) != extensions.end())
        {
            re.push_back(f);
        }
    }

    return re;
}

Live Demo

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
1

There are actually many ways of solving this, personally, this is the way I've achieved it before

#include <iostream>
#include <algorithm>
#include <string>
#include <functional>
#include <vector>

int main()
{
    std::vector<std::string> v{"main.cpp","main.c","main.py"};
    std::vector<std::string> ext{".cpp", ".c"};
    std::vector<std::string> res;

    for (auto& s : v) {
        auto pos = s.find_last_of('.');            
        if (pos != s.npos) {
            char* str = &s[pos];
            if (std::any_of(ext.begin(), ext.end(), 
                            [str](const string& a) { return str ==  a; })) {
                res.push_back(s);
            }
        }
    }

    for (auto& r : res)
        cout << r << endl;

    return 0;
}
Gerard097
  • 815
  • 4
  • 12