أمثلة رمز C ++ قبل وبعد النطاقات

مرحبا مرة اخرى تم إعداد ترجمة المواد التالية خصيصًا لطلاب الدورة التدريبية "C ++ Developer" ، الفصول التي ستبدأ في 27 يونيو.



تم اعتماد مكتبة النطاقات في C ++ 20 في اجتماع للجنة القياسية في سان دييغو في نوفمبر الماضي. توفر المكتبة مكونات لمعالجة نطاقات القيم المصممة لتبسيط التعليمات البرمجية الخاصة بنا. لسوء الحظ ، مكتبة Ranges غير موثقة جيدًا ، مما يجعل من الصعب فهمها بالنسبة لأولئك الذين يرغبون في تعلمها. يهدف هذا المنشور إلى تقديم أمثلة على الكود المكتوب باستخدام النطاقات وبدونها.

تطبيق مكتبة إريك نيبلر رينجز متوفر هنا . إنه يعمل مع Clang 3.6.2 أو الأحدث ، gcc 5.2 أو الأحدث ، و VC ++ 15.9 أو الأحدث. تمت كتابة أمثلة التعليمات البرمجية أدناه واختبارها باستخدام أحدث إصدارات المترجمات. تجدر الإشارة إلى أن هذه الأمثلة هي تطبيقات نموذجية وليست بالضرورة الحلول الوحيدة التي يمكنك التوصل إليها.

على الرغم من أن مساحة الاسم القياسية لمكتبة النطاقات هي std::ranges ، إلا أنه في تطبيق المكتبة الحالي هذا هو ranges::v3 .

يتم استخدام الأسماء المستعارة مساحة الاسم التالية في الأمثلة أدناه:

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

أيضًا ، للتبسيط ، سنشير إلى الكائنات والوظائف و 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; }; 

التاريخ : أود أن أشكر إريك نيبلر وأي شخص آخر علق أدناه ، مع اقتراحات لأمثلة الكود هذه. لقد قمت بتحديث عدد قليل بناءً على تقييماتهم.

اطبع كل عناصر النطاق:

إلى النطاقاتبعد رن
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); 


اطبع كل عناصر النطاق بالترتيب العكسي:

إلى النطاقاتبعد رن
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); }; 


قم بطباعة العناصر الزوجية للنطاق فقط ، لكن بترتيب عكسي:

إلى النطاقاتبعد رن
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); }; 


تخطي أول عنصرين من النطاق وطباعة فقط حتى من العناصر الثلاثة التالية:

إلى النطاقاتبعد رن
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); }; 


طباعة الأرقام من 101 إلى 200:

إلى النطاقاتبعد رن
C ++C ++
 for (int n = 101; n <= 200; ++n) { print_elem(n); } 
 for (auto n : rs::iota_view(101, 201)) { print_elem(n); } 


اطبع جميع الأرقام الرومانية من 101 إلى 200. لتحويل رقم إلى الرقم الروماني المقابل ، استخدم الدالة to_roman() الموضحة أعلاه.

إلى النطاقاتبعد رن
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); 


اطبع الأرقام الرومانية لآخر ثلاثة أرقام قابلة للقسمة على 7 في النطاق [101 ، 200] ، بترتيب عكسي.

إلى النطاقاتبعد رن
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); } 


أنشئ مجموعة من السلاسل التي تحتوي على الأرقام الرومانية للأرقام الثلاثة الأخيرة وهي مضاعفات 7 في النطاق [101 ، 200] ، بترتيب عكسي.

إلى النطاقاتبعد رن
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; 


قم بتغيير النطاق غير المصنف بحيث يحتفظ بقيم فريدة فقط ، ولكن بالترتيب العكسي.

إلى النطاقاتبعد رن
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; 


احذف القيمتين الأصغر والثاني في النطاق واترك الباقي مرتبًا في النطاق الثاني.

إلى النطاقاتبعد رن
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); 


الجمع بين جميع الصفوف في نطاق معين في قيمة واحدة.

إلى النطاقاتبعد رن
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; 


حساب عدد الكلمات (مفصولة بمسافة) في النص.

إلى النطاقاتبعد رن
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(' ')); 


هل كانت المقالة مفيدة لك؟ اكتب في التعليقات.

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


All Articles