Ejemplos de código C ++ antes y después de Rangos

Hola de nuevo La traducción del siguiente material fue preparada específicamente para los estudiantes del curso "C ++ Developer" , clases en las que comenzará el 27 de junio.



La biblioteca Ranges fue adoptada en C ++ 20 en una reunión del comité estándar en San Diego en noviembre pasado. La biblioteca proporciona componentes para procesar rangos de valores diseñados para simplificar nuestro código. Desafortunadamente, la biblioteca Ranges no está muy bien documentada, lo que hace que sea más difícil de entender para aquellos que desean dominarla. Esta publicación está destinada a proporcionar ejemplos de código escrito usando y sin rangos.

La implementación de la biblioteca Ranges de Eric Niebler está disponible aquí . Funciona con Clang 3.6.2 o posterior, gcc 5.2 o posterior y VC ++ 15.9 o posterior. Los ejemplos de código a continuación se han escrito y probado con las últimas versiones de compiladores. Vale la pena señalar que estos ejemplos son implementaciones típicas y no son necesariamente las únicas soluciones que puede encontrar.

Aunque el espacio de nombres estándar para la biblioteca de Rangos es std::ranges , en esta implementación actual de la biblioteca es ranges::v3 .

Los siguientes alias de espacio de nombres se utilizan en los ejemplos a continuación:

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

Además, para simplificar, nos referiremos a los siguientes objetos, funciones y 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 : Me gustaría agradecer a Eric Nibler y a todos los que comentaron a continuación, con sugerencias para estos ejemplos de código. Actualicé algunos en función de sus comentarios.

Imprima todos los elementos de la gama:

A los rangosDespués sonó
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 los elementos del rango en el orden inverso:

A los rangosDespués sonó
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 solo los elementos pares del rango, pero en el orden inverso:

A los rangosDespués sonó
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); }; 


Omita los dos primeros elementos del rango e imprima solo los pares de los siguientes tres:

A los rangosDespués sonó
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 del 101 al 200:

A los rangosDespués sonó
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 los números romanos del 101 al 200. Para convertir un número al número romano correspondiente, use la función to_roman() que se muestra arriba.

A los rangosDespués sonó
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 los números romanos de los últimos tres números divisibles por 7 en el rango [101, 200], en orden inverso.

A los rangosDespués sonó
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); } 


Cree un rango de cadenas que contenga los números romanos de los últimos tres números que sean múltiplos de 7 en el rango [101, 200], en orden inverso.

A los rangosDespués sonó
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; 


Cambie el rango sin clasificar para que conserve solo valores únicos, pero en el orden inverso.

A los rangosDespués sonó
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; 


Elimine los dos valores más pequeños y los dos más grandes del rango y deje el resto ordenado en el segundo rango.

A los rangosDespués sonó
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); 


Combina todas las filas en un rango dado en un solo valor.

A los rangosDespués sonó
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; 


Cuente la cantidad de palabras (separadas por un espacio) en el texto.

A los rangosDespués sonó
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(' ')); 


¿Te fue útil el artículo? Escribe en los comentarios.

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


All Articles