diff --git a/README.md b/README.md index cdedfac..0c2819e 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,8 @@ Examples include (and will expand to): * Parallelism * [parallel-transform](./parallel-transform/) * Performance‑oriented C++ idioms +* STL and ranges: + * [ranges-find-in-vector-string](./ranges-find-in-vector-string/) * Algorithms * [integer-factorization](./integer-factorization/) * Encoding diff --git a/map-with-unknown-key/main.cpp b/map-with-unknown-key/main.cpp index f905788..5ae114e 100644 --- a/map-with-unknown-key/main.cpp +++ b/map-with-unknown-key/main.cpp @@ -3,17 +3,48 @@ What happens if you access an unknown key in the std::map, std::unordered_map? */ #include #include +#include #include -#include #include +#include int main() { + // Example with std::map value type int std::map my_map; std::print("Accessing unknown key 'unknown_key' in std::map:\n"); int value = my_map["unknown_key"]; std::print("Value: {}\n", value); // Should print 0, as default-constructed int is 0 std::print("Map size after access: {}\n", my_map.size()); // Should print 1 + assert(value == 0); // Default-constructed int is 0 + assert(my_map.size() == 1); // The map now contains one entry for 'unknown_key' + + // Example with std::unordered_map value type int + std::unordered_map my_unordered_map; + std::print("Accessing unknown key 'unknown_key' in std::unordered_map:\n"); + int unordered_value = my_unordered_map["unknown_key"]; + std::print("Value: {}\n", unordered_value); // Should print 0 + std::print("Unordered map size after access: {}\n", my_unordered_map.size()); // Should print 1 + assert(unordered_value == 0); // Default-constructed int is 0 + assert(my_unordered_map.size() == 1); // The unordered_map now contains one entry for 'unknown_key' + + // Example with std::map value type std::string + std::map my_string_map; + std::print("Accessing unknown key 'unknown_key' in std::map with string values:\n"); + std::string str_value = my_string_map["unknown_key"]; + std::print("Value: '{}'\n", str_value); // Should print empty string + std::print("Map size after access: {}\n", my_string_map.size()); // Should print 1 + assert(str_value.empty()); // Default-constructed string is empty + assert(my_string_map.size() == 1); // The map now contains one entry for + + // Example with std::unordered_map value type std::string + std::unordered_map my_string_unordered_map; + std::print("Accessing unknown key 'unknown_key' in std::unordered_map with string values:\n"); + std::string str_unordered_value = my_string_unordered_map["unknown_key"]; + std::print("Value: '{}'\n", str_unordered_value); // Should print empty string + std::print("Unordered map size after access: {}\n", my_string_unordered_map.size()); // Should print 1 + assert(str_unordered_value.empty()); // Default-constructed string is empty + assert(my_string_unordered_map.size() == 1); // The unordered_map now contains one entry for 'unknown_key' return 0; } diff --git a/ranges-find-in-vector-string/Makefile b/ranges-find-in-vector-string/Makefile new file mode 100644 index 0000000..ab8b3c0 --- /dev/null +++ b/ranges-find-in-vector-string/Makefile @@ -0,0 +1,31 @@ +# pull in shared compiler settings +include ../common.mk + +# per-example flags +# CXXFLAGS += -pthread + +## get it from the folder name +TARGET := $(notdir $(CURDIR)) +## all *.cpp files in this folder +SRCS := $(wildcard *.cpp) +OBJS := $(SRCS:.cpp=.o) + +all: $(TARGET) + +$(TARGET): $(OBJS) + $(CXX) $(CXXFLAGS) -o $@ $^ + +%.o: %.cpp + $(CXX) $(CXXFLAGS) -c $< -o $@ + +run: $(TARGET) + ./$(TARGET) $(ARGS) + +clean: + rm -f $(OBJS) $(TARGET) + +# Delegates to top-level Makefile +check-format: + $(MAKE) -f ../Makefile check-format DIR=$(CURDIR) + +.PHONY: all clean run check-format diff --git a/ranges-find-in-vector-string/main.cpp b/ranges-find-in-vector-string/main.cpp new file mode 100644 index 0000000..5b479e6 --- /dev/null +++ b/ranges-find-in-vector-string/main.cpp @@ -0,0 +1,133 @@ +/** +This demonstrates different ways to find an element in a vector of strings +*/ +#include +#include +#include +#include +#include +#include +#include + +int +main() +{ + std::vector vec = {"apple", "banana", "cherry", "date", "elderberry"}; + std::string target = "cherry"; + + // Method 1: Using a loop + bool found = false; + for (size_t i = 0; i < vec.size(); ++i) { + if (vec[i] == target) { + std::print("loop: Found '{}' using loop at index {}\n", target, i); + found = true; + break; + } + } + if (!found) { + std::print("loop: '{}' not found using loop\n", target); + } + + // Method 2: Using std::find_if with a lambda + auto it_if = std::find_if(vec.begin(), vec.end(), [&target](const std::string& s) { return s == target; }); + if (it_if != vec.end()) { + std::print( + "std::find_if: Found '{}' using std::find_if at index {}\n", target, std::distance(vec.begin(), it_if)); + } else { + std::print("std::find_if: '{}' not found using std::find_if\n", target); + } + + // Method 3: Using std::find + auto it = std::find(vec.begin(), vec.end(), target); + if (it != vec.end()) { + std::print("std::find: Found '{}' using std::find at index {}\n", target, std::distance(vec.begin(), it)); + } else { + std::print("std::find: '{}' not found using std::find\n", target); + } + + // Method 4: std::count (pre C++20) + auto count_std = std::count(vec.begin(), vec.end(), target); + std::print("std::count: Vector contains '{}' {} time(s) using std::count\n", target, count_std); + + // Method 5: std::count_if (pre C++20) + auto count_if_std = std::count_if(vec.begin(), vec.end(), [&target](const std::string& s) { return s == target; }); + std::print("std::count_if: Vector contains '{}' {} time(s) using std::count_if\n", target, count_if_std); + + // Method 6: std::any_of + bool any_of_std = std::any_of(vec.begin(), vec.end(), [&target](const std::string& s) { return s == target; }); + if (any_of_std) { + std::print("std::any_of: Vector contains '{}' using std::any_of\n", target); + } else { + std::print("std::any_of: Vector does not contain '{}' using std::any_of\n", target); + } + + // Method 7: Using std::ranges::find (C++20) + auto range_it = std::ranges::find(vec, target); + if (range_it != vec.end()) { + std::print( + "std::ranges::find: Found '{}' using std::ranges::find at index {}\n", + target, + std::distance(vec.begin(), range_it)); + } else { + std::print("std::ranges::find: '{}' not found using std::ranges::find\n", target); + } + + // Method 8: Using std::ranges::find_if with a lambda (C++20) + auto range_it_if = std::ranges::find_if(vec, [&target](const std::string& s) { return s == target; }); + if (range_it_if != vec.end()) { + std::print( + "std::ranges::find_if: Found '{}' using std::ranges::find_if at index {}\n", + target, + std::distance(vec.begin(), range_it_if)); + } else { + std::print("std::ranges::find_if: '{}' not found using std::ranges::find_if\n", target); + } + + // Method 9: std::ranges::contains (C++23) + auto contains = std::ranges::contains(vec, target); + if (contains) { + std::print("std::ranges::contains: Vector contains '{}' using std::ranges::contains\n", target); + } else { + std::print("std::ranges::contains: Vector does not contain '{}' using std::ranges::contains\n", target); + } + + // Method 10: std::ranges::any_of (C++20) + bool any_of = std::ranges::any_of(vec, [&target](const std::string& s) { return s == target; }); + if (any_of) { + std::print("std::ranges::any_of: Vector contains '{}' using std::ranges::any_of\n", target); + } else { + std::print("std::ranges::any_of: Vector does not contain '{}' using std::ranges::any_of\n", target); + } + + // Method 11: std::ranges::count (C++20) + auto count = std::ranges::count(vec, target); + std::print("std::ranges::count: Vector contains '{}' {} time(s) using std::ranges::count\n", target, count); + + // Method 12: std::ranges::count_if (C++20) + auto count_if = std::ranges::count_if(vec, [&target](const std::string& s) { return s == target; }); + std::print( + "std::ranges::count_if: Vector contains '{}' {} time(s) using std::ranges::count_if\n", target, count_if); + + // Method 13: via std::ranges::views (C++20) + auto view = vec | std::ranges::views::filter([&target](const std::string& s) { return s == target; }); + for (const auto& s : view) { + std::print("std::ranges::views::filter: Found '{}' using std::ranges::views::filter\n", s); + } + + // Assertions to verify correctness + assert(it != vec.end() && *it == target); + assert(found); + assert(range_it != vec.end() && *range_it == target); + assert(it_if != vec.end() && *it_if == target); + assert(range_it_if != vec.end() && *range_it_if == target); + assert(contains); + assert(any_of); + assert(count == 1); + assert(count_std == 1); + assert(count_if == 1); + assert(count_if_std == 1); + assert(std::ranges::distance(view) == 1); + assert(any_of_std); + + return 0; +} diff --git a/ranges-find-in-vector-string/tests.sh b/ranges-find-in-vector-string/tests.sh new file mode 100755 index 0000000..0ecc2d2 --- /dev/null +++ b/ranges-find-in-vector-string/tests.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +set -ex + +./ranges-find-in-vector-string