Exemplos de código C ++ antes e depois de intervalos

Olá novamente. A tradução do material a seguir foi preparada especificamente para os alunos do curso "Desenvolvedor C ++" , cujas aulas começarão em 27 de junho.



A biblioteca Ranges foi adotada em C ++ 20 em uma reunião do comitê padrão em San Diego em novembro passado. A biblioteca fornece componentes para o processamento de intervalos de valores projetados para simplificar nosso código. Infelizmente, a biblioteca Ranges não está muito bem documentada, o que dificulta o entendimento para quem deseja dominá-la. Esta publicação pretende fornecer exemplos de código escrito usando e sem intervalos.

A implementação da biblioteca de Eric Niebler Ranges está disponível aqui . Ele funciona com o Clang 3.6.2 ou posterior, gcc 5.2 ou posterior e VC ++ 15.9 ou posterior. Os exemplos de código abaixo foram escritos e testados com as versões mais recentes dos compiladores. Vale ressaltar que esses exemplos são implementações típicas e não são necessariamente as únicas soluções que você pode apresentar.

Embora o espaço de nomes padrão para a biblioteca Ranges seja std::ranges , nessa implementação atual da biblioteca, ele é ranges::v3 .

Os aliases de namespace a seguir são usados ​​nos exemplos abaixo:

 namespace rs = ranges::v3; namespace rv = ranges::v3::view; namespace ra = ranges::v3::action; 

Além disso, para simplificação, vamos nos referir aos seguintes objetos, funções e lambdas:

 std::string to_roman(int value) { std::vector<std::pair<int, char const*>> roman { { 1000, "M" },{ 900, "CM" }, { 500, "D" },{ 400, "CD" }, { 100, "C" },{ 90, "XC" }, { 50, "L" },{ 40, "XL" }, { 10, "X" },{ 9, "IX" }, { 5, "V" },{ 4, "IV" }, { 1, "I" } }; std::string result; for (auto const & [d, r]: roman) { while (value >= d) { result += r; value -= d; } } return result; } std::vector<int> v{1,1,2,3,5,8,13,21,34}; auto print_elem = [](auto const e) {std::cout << e << '\n'; }; auto is_even = [](auto const i) {return i % 2 == 0; }; 

APDATE : Gostaria de agradecer a Eric Nibler e a todos os outros que comentaram abaixo, com sugestões para esses exemplos de código. Eu atualizei alguns com base em seus comentários.

Imprima todos os elementos do intervalo:

Para os intervalosDepois dos toques
C ++C ++
 std::for_each( std::cbegin(v), std::cend(v), print_elem); // or for(auto const i : v) { print_elem(i); }; 
 rs::for_each( std::cbegin(v), std::cend(v), print_elem); // or rs::for_each(std::as_const(v), print_elem); 


Imprima todos os elementos do intervalo na ordem inversa:

Para os intervalosDepois dos toques
C ++C ++
 std::for_each( std::crbegin(v), std::crend(v), print_elem); 
 rs::for_each( std::crbegin(v), std::crend(v), print_elem); // or for (auto const i : v | rv::reverse) { print_elem(i); }; 


Imprima apenas os elementos pares do intervalo, mas na ordem inversa:

Para os intervalosDepois dos toques
C ++C ++
 std::for_each( std::crbegin(v), std::crend(v), [print_elem](auto const i) { if(i % 2 == 0) print_elem(i); }); 
 for (auto const i : v | rv::reverse | rv::filter(is_even)) { print_elem(i); }; 


Pule os dois primeiros elementos do intervalo e imprima apenas pares dos três seguintes:

Para os intervalosDepois dos toques
C ++C ++
 auto it = std::cbegin(v); std::advance(it, 2); auto ix = 0; while (it != std::cend(v) && ix++ < 3) { if (is_even(*it)) print_elem(*it); it++; } 
 for (auto const i : v | rv::drop(2) | rv::take(3) | rv::filter(is_even)) { print_elem(i); }; 


Imprima números de 101 a 200:

Para os intervalosDepois dos toques
C ++C ++
 for (int n = 101; n <= 200; ++n) { print_elem(n); } 
 for (auto n : rs::iota_view(101, 201)) { print_elem(n); } 


Imprima todos os números romanos de 101 a 200. Para converter um número no número romano correspondente, use a função to_roman() mostrada acima.

Para os intervalosDepois dos toques
C ++C ++
 for (int i = 101; i <= 200; ++i) { print_elem(to_roman(i)); } 
 for (auto n : rs::iota_view(101, 201) | rv::transform(to_roman)) { print_elem(n); } // or rs::for_each(rv::iota(101, 201), print_element, to_roman); 


Imprima os algarismos romanos dos três últimos números divisíveis por 7 no intervalo [101, 200], na ordem inversa.

Para os intervalosDepois dos toques
C ++C ++
 for (int n = 200, count=0; n >= 101 && count < 3; --n) { if (n % 7 == 0) { print_elem(to_roman(n)); count++; } } 
 for (auto n : rs::iota_view(101, 201) | rv::reverse | rv::filter([](auto v) { return v % 7 == 0; }) | rv::transform(to_roman) | rv::take(3)) { print_elem(n); } 


Crie um intervalo de cadeias contendo os algarismos romanos dos últimos três números que são múltiplos de 7 no intervalo [101, 200], na ordem inversa.

Para os intervalosDepois dos toques
C ++C ++
 std::vector<std::string> v; for (int n = 200, count = 0; n >= 101 && count < 3; --n) { if (n % 7 == 0) { v.push_back(to_roman(n)); count++; } } 
 auto v = rs::iota_view(101, 201) | rv::reverse | rv::filter([](auto v) {return v % 7 == 0; }) | rv::transform(to_roman) | rv::take(3) | rs::to_vector; 


Altere o intervalo não classificado para que ele retenha apenas valores exclusivos, mas na ordem inversa.

Para os intervalosDepois dos toques
C ++C ++
 std::vector<int> v{ 21, 1, 3, 8, 13, 1, 5, 2 }; std::sort(std::begin(v), std::end(v)); v.erase( std::unique(std::begin(v), std::end(v)), std::end(v)); std::reverse(std::begin(v), std::end(v)); 
 std::vector<int> v{ 21, 1, 3, 8, 13, 1, 5, 2 }; v = std::move(v) | ra::sort | ra::unique | ra::reverse; 


Exclua os dois menores e os dois maiores valores do intervalo e deixe o restante ordenado no segundo intervalo.

Para os intervalosDepois dos toques
C ++C ++
 std::vector<int> v{ 21, 1, 3, 8, 13, 1, 5, 2 }; std::vector<int> v2 = v; std::sort(std::begin(v2), std::end(v2)); auto first = std::begin(v2); std::advance(first, 2); auto last = first; std::advance(last, std::size(v2) - 4); v2.erase(last, std::end(v2)); v2.erase(std::begin(v2), first); 
 std::vector<int> v{ 21, 1, 3, 8, 13, 1, 5, 2 }; auto v2 = v | rs::copy | ra::sort | ra::slice(2, rs::end - 2); 


Combine todas as linhas em um determinado intervalo em um único valor.

Para os intervalosDepois dos toques
C ++C ++
 std::vector<std::string> words { "Lorem", " ", "ipsum", " ", "dolor", " ", "sit", " ", "amet"}; std::string text; for (auto const & word : words) text += word; 
 std::vector<std::string> words { "Lorem", " ", "ipsum", " ", "dolor", " ", "sit", " ", "amet"}; std::string text = words | rs::move | ra::join; 


Conte o número de palavras (separadas por um espaço) no texto.

Para os intervalosDepois dos toques
C ++C ++
 auto text = "Lorem ipsum dolor sit amet"; std::istringstream iss(text); std::vector<std::string> words( std::istream_iterator<std::string>{iss}, std::istream_iterator<std::string>()); auto count = words.size(); // or size_t count = 0; std::vector<std::string> words; std::string token; std::istringstream tokenStream(text); while (std::getline(tokenStream, token, ' ')) { ++count; } 
 auto text = "Lorem ipsum dolor sit amet"; auto count = rs::distance( rv::c_str(text) | rv::split(' ')); 


O artigo foi útil para você? Escreva nos comentários.

Source: https://habr.com/ru/post/pt456452/


All Articles