Tôi hiện đang có mã này lên và chạy:Kết hợp C++ thuật toán tiêu chuẩn bằng cách lặp chỉ một lần
string word="test,";
string::iterator it = word.begin();
for (; it != word.end(); it++)
{
if (!isalpha(*it)) {
break;
}
else {
*it = toupper(*it);
}
}
word.erase(it, word.end());
// word should now be: TEST
Tôi muốn làm cho nó nhỏ gọn hơn và có thể đọc được nó bằng cách:
- Soạn tiêu chuẩn hiện hành C++ thuật toán (*)
- Thực hiện các vòng lặp chỉ một lần
(*) tôi giả định rằng c ombining thuật toán hiện làm cho mã của tôi dễ đọc hơn ...
Một giải pháp thay thế
Ngoài việc xác định một thuật toán tùy chỉnh transform_until
, theo đề nghị của jrok, nó có thể là có thể xác định một adapter tùy chỉnh iterator rằng sẽ lặp sử dụng trình lặp cơ bản nhưng xác định lại toán tử *() bằng cách sửa đổi tham chiếu cơ bản trước khi trả về nó. Một cái gì đó như thế:
template <typename Iterator, typename UnaryFunction = typename Iterator::value_type (*)(typename Iterator::value_type)>
class sidefx_iterator: public std::iterator<
typename std::forward_iterator_tag,
typename std::iterator_traits<Iterator>::value_type,
typename std::iterator_traits<Iterator>::difference_type,
typename std::iterator_traits<Iterator>::pointer,
typename std::iterator_traits<Iterator>::reference >
{
public:
explicit sidefx_iterator(Iterator x, UnaryFunction fx) : current_(x), fx_(fx) {}
typename Iterator::reference operator*() const { *current_ = fx_(*current_); return *current_; }
typename Iterator::pointer operator->() const { return current_.operator->(); }
Iterator& operator++() { return ++current_; }
Iterator& operator++(int) { return current_++; }
bool operator==(const sidefx_iterator<Iterator>& other) const { return current_ == other.current_; }
bool operator==(const Iterator& other) const { return current_ == other; }
bool operator!=(const sidefx_iterator<Iterator>& other) const { return current_ != other.current_; }
bool operator!=(const Iterator& other) const { return current_ != other; }
operator Iterator() const { return current_; }
private:
Iterator current_;
UnaryFunction fx_;
};
Tất nhiên điều này vẫn còn rất thô, nhưng nên đưa ra ý tưởng. Với adapter trên, tôi sau đó có thể viết như sau:
word.erase(std::find_if(it, it_end, std::not1(std::ref(::isalpha))), word.end());
với những điều sau đây được xác định trước (có thể được đơn giản hóa bằng một số mẫu-magic):
using TransformIterator = sidefx_iterator<typename std::string::iterator>;
TransformIterator it(word.begin(), reinterpret_cast<typename std::string::value_type(*)(typename std::string::value_type)>(static_cast<int(*)(int)>(std::toupper)));
TransformIterator it_end(word.end(), nullptr);
Nếu tiêu chuẩn sẽ bao gồm một bộ chuyển đổi như vậy tôi sẽ sử dụng nó, bởi vì nó có nghĩa là nó hoàn hảo, nhưng vì đây không phải là trường hợp tôi có lẽ sẽ giữ cho vòng lặp của tôi như vậy.
Như một bộ chuyển đổi sẽ cho phép tái sử dụng các thuật toán hiện hành và trộn chúng theo nhiều cách khác nhau không thể ngày hôm nay, nhưng nó có thể có nhược điểm là tốt, mà tôi có thể nhìn vào lúc này ...
Trong mã hiện tại của tôi, có một vòng lặp đơn. Quan điểm của tôi là sau khi viết lại sẽ vẫn có một vòng lặp đơn. –
Cuộc di cư sớm dựa trên '! Isalpha (* it)' là điều duy nhất tôi thấy có khả năng ngăn cản bạn đạt được những gì tôi nghĩ bạn đang tìm kiếm, và thành thật, bất cứ điều gì có thể làm điều đó cho bạn (và tôi không thể thấy bất cứ điều gì ngay lập tức mà sẽ) có khả năng sẽ được như vậy phức tạp bạn rõ ràng-yếu tố sẽ đi ra ngoài cửa sổ. Tôi có thể gắn bó với những gì bạn có. – WhozCraig
Cảm ơn tất cả vì những câu trả lời đầy cảm hứng của bạn. Tôi sẽ gắn bó với mã hiện tại của tôi bây giờ. Tôi tin rằng 'boost :: transform_iterator' là điều gần nhất tôi đang tìm kiếm. Trường hợp sử dụng này sẽ được bao phủ bởi một bộ điều hợp vòng lặp "tác dụng phụ", một cái gì đó sẽ được sử dụng như thế này: 'word.erase (std :: find_if (sidefx_iterator (word.begin(), :: toupper), word.end (), std :: not1 (:: isalpha)), word.end()); ' –