1

我需要将字符串向量转换为小写,但我需要保留文件名的大小写。它们由先前的字符串标记“file”或“out”标识。

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

template <class T>
void print(const T& v) {
    std::copy(v.begin(), v.end(), 
            std::ostream_iterator<typename T::value_type>(std::cout, "\n"));
}

std::string lowercase(const std::string& s) 
{
    std::string result(s);
    std::transform(result.begin(), result.end(), result.begin(), ::tolower);
    return result;
}

int main() {

    std::vector<std::string> tokens {"Col1", "Col2", "File", "FileIn.dat", "Out", "FileOut.dat"};
    std::transform(tokens.begin(), tokens.end(), tokens.begin(), lowercase);

    // how to replace lowercase() with a lambda that will take the previous
    // element into account while converting an element into lowercase
    print(tokens);

    return 0;
}

在上面的代码中,结果应该是

{"col1", "col2", "file", "FileIn.dat", "out", "FileOut.dat"};

在“file”和“out”之后保留字符串的大小写。

有没有办法使用std::transformlambda函数来做到这一点?

4

3 回答 3

2

就在这里。您可以像这样使用捕获 lambda:

bool is_filename = false;
std::transform(tokens.begin(), tokens.end(), tokens.begin(),
    [&is_filename] (auto &s) {
        if (is_filename)
            is_filename = false;
        else  
        {
            s = lowercase (s);
            is_filename = s == "file" || s == "out";
        }
        return s;
    });

输出:

col1
col2
file
FileIn.dat
out
FileOut.dat

现场演示

于 2019-05-17T16:14:16.510 回答
2

是的。您可以捕获一些状态,并根据您所看到的进行设置。但是您不应该使用std::transform,因为它不能保证按顺序遍历。你必须使用std::for_each.

int main() {

    std::vector<std::string> tokens {"Col1", "Col2", "File", "FileIn.dat", "Out", "FileOut.dat"};

    bool toggle = true;
    auto lowercase = [&toggle](std::string & s) 
    {
        if (toggle)
        {
            std::transform(s.begin(), s.end(), s.begin(), ::tolower);
        }

        toggle = (s == "file") || (s == "out");
    }

    std::for_each(tokens.begin(), tokens.end(), tokens.begin(), lowercase);
    print(tokens);

    return 0;
}
于 2019-05-17T16:17:06.133 回答
1

有没有办法使用 std::transform 和 lambda 函数来做到这一点?

std::transform不保证运算符的有序应用。因此,如果我们需要std::transform解决这个问题,二元运算符的重载会更可取:

现场演示

std::vector<std::string> tokens {"Col1", "Col2", "File", "FileIn.dat", "Out", "FileOut.dat"};

{    
    // The first element must not be file name.
    tokens[0] = lowercase(tokens[0]);

    std::vector<std::string> dummy;        
    std::transform(
        std::next(tokens.begin()), tokens.end(), tokens.begin(),
        std::back_inserter(dummy),
        [](auto& target, const auto& prev)
        {            
            const auto prevLower  = lowercase(prev);
            const auto isFileName = (prevLower == "file") || (prevLower == "out");

            if(!isFileName){
                target = lowercase(target);
            }

            return "";
        });
}

print(tokens);
于 2019-05-17T17:58:24.563 回答