C ++ - Codebeispiele vor und nach Bereichen

Hallo nochmal. Die Übersetzung des folgenden Materials wurde speziell für Studenten des Kurses "C ++ Developer" erstellt , dessen Unterricht am 27. Juni beginnt.



Die Ranges-Bibliothek wurde im November letzten Jahres auf einer Sitzung des Standardausschusses in San Diego in C ++ 20 übernommen. Die Bibliothek enthält Komponenten für die Verarbeitung von Wertebereichen, die unseren Code vereinfachen sollen. Leider ist die Ranges-Bibliothek nicht sehr gut dokumentiert, was es für diejenigen, die sie beherrschen möchten, schwieriger macht, sie zu verstehen. Dieser Beitrag soll Beispiele für Code enthalten, der mit und ohne Bereiche geschrieben wurde.

Die Implementierung der Ranges-Bibliothek von Eric Niebler finden Sie hier . Es funktioniert mit Clang 3.6.2 oder höher, gcc 5.2 oder höher und VC ++ 15.9 oder höher. Die folgenden Codebeispiele wurden mit den neuesten Versionen von Compilern geschrieben und getestet. Es ist erwähnenswert, dass diese Beispiele typische Implementierungen sind und nicht unbedingt die einzigen Lösungen sind, die Sie finden können.

Obwohl der Standard-Namespace für die Ranges-Bibliothek std::ranges , ist es in dieser aktuellen Bibliotheksimplementierung ranges::v3 .

Die folgenden Namespace-Aliase werden in den folgenden Beispielen verwendet:

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

Zur Vereinfachung werden wir auch auf die folgenden Objekte, Funktionen und Lambdas verweisen:

 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 : Ich möchte Eric Nibler und allen anderen, die unten kommentiert haben, mit Vorschlägen für diese Codebeispiele danken. Ich habe einige basierend auf ihren Bewertungen aktualisiert.

Drucken Sie alle Elemente des Bereichs:

Zu den BereichenNach klingelt
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); 


Drucken Sie alle Elemente des Bereichs in umgekehrter Reihenfolge:

Zu den BereichenNach klingelt
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); }; 


Drucken Sie nur die geraden Elemente des Bereichs, jedoch in umgekehrter Reihenfolge:

Zu den BereichenNach klingelt
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); }; 


Überspringen Sie die ersten beiden Elemente des Bereichs und drucken Sie nur die folgenden drei aus:

Zu den BereichenNach klingelt
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); }; 


Drucknummern von 101 bis 200:

Zu den BereichenNach klingelt
C ++C ++
 for (int n = 101; n <= 200; ++n) { print_elem(n); } 
 for (auto n : rs::iota_view(101, 201)) { print_elem(n); } 


Drucken Sie alle römischen Ziffern von 101 bis 200 aus. Um eine Zahl in die entsprechende römische Zahl umzuwandeln, verwenden Sie die to_roman() gezeigte Funktion to_roman() .

Zu den BereichenNach klingelt
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); 


Drucken Sie die römischen Ziffern der letzten drei durch 7 teilbaren Zahlen im Bereich [101, 200] in umgekehrter Reihenfolge.

Zu den BereichenNach klingelt
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); } 


Erstellen Sie eine Reihe von Zeichenfolgen, die die römischen Ziffern der letzten drei Zahlen enthalten, die in umgekehrter Reihenfolge Vielfache von 7 im Bereich [101, 200] sind.

Zu den BereichenNach klingelt
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; 


Ändern Sie den unsortierten Bereich so, dass nur eindeutige Werte in umgekehrter Reihenfolge erhalten bleiben.

Zu den BereichenNach klingelt
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; 


Löschen Sie die zwei kleinsten und die zwei größten Werte des Bereichs und lassen Sie den Rest im zweiten Bereich.

Zu den BereichenNach klingelt
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); 


Kombinieren Sie alle Zeilen in einem bestimmten Bereich zu einem einzigen Wert.

Zu den BereichenNach klingelt
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; 


Zählen Sie die Anzahl der Wörter (durch ein Leerzeichen getrennt) im Text.

Zu den BereichenNach klingelt
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(' ')); 


War der Artikel für Sie hilfreich? Schreiben Sie in die Kommentare.

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


All Articles