diff --git a/.gitignore b/.gitignore index e5a9a31..51463e7 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ /lab1.layout /unittest.layout /unittest.depend +/curl \ No newline at end of file diff --git a/histogram.cpp b/histogram.cpp index ca354e8..ecd05f1 100644 --- a/histogram.cpp +++ b/histogram.cpp @@ -2,23 +2,23 @@ #include #include -Input input_data() { - Input in; +Input input_data(std::istream& in, bool prompt) { + Input data; size_t number_count; - std::cerr << "Enter number count: "; - std::cin >> number_count; + if (prompt) std::cerr << "Enter number count: "; + in >> number_count; - in.numbers.resize(number_count); - std::cerr << "Enter " << number_count << " numbers: "; + data.numbers.resize(number_count); + if (prompt) std::cerr << "Enter " << number_count << " numbers: "; for (size_t i = 0; i < number_count; i++) { - std::cin >> in.numbers[i]; + in >> data.numbers[i]; } - std::cerr << "Enter bin count: "; - std::cin >> in.bin_count; + if (prompt) std::cerr << "Enter bin count: "; + in >> data.bin_count; - return in; + return data; } void find_minmax(const std::vector& numbers, double& min, double& max) { diff --git a/histogram.h b/histogram.h index 77e9998..0c70f10 100644 --- a/histogram.h +++ b/histogram.h @@ -1,12 +1,11 @@ #pragma once - #include +#include struct Input { std::vector numbers; size_t bin_count{}; }; -Input input_data(); +Input input_data(std::istream& in, bool prompt); std::vector make_histogram(const std::vector& numbers, size_t bin_count); -void show_histogram_text(const std::vector& bins); diff --git a/lab1.cbp b/lab1.cbp index c964ce2..cfda4fb 100644 --- a/lab1.cbp +++ b/lab1.cbp @@ -32,6 +32,9 @@ + + + + + diff --git a/main.cpp b/main.cpp index fd793a9..d97796e 100644 --- a/main.cpp +++ b/main.cpp @@ -1,9 +1,53 @@ #include "histogram.h" #include "svg.h" +#include +#include +#include -int main() { - auto in = input_data(); - auto bins = make_histogram(in.numbers, in.bin_count); + +size_t write_data(void* ptr, size_t size, size_t nmemb, std::stringstream* stream) { + size_t data_size = size * nmemb; + stream->write(static_cast(ptr), data_size); + return data_size; +} + + +Input download(const std::string& url) { + std::stringstream buffer; + + CURL* curl = curl_easy_init(); + if (!curl) { + std::cerr << "Failed to initialize cURL\n"; + exit(1); + } + + curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer); + + CURLcode res = curl_easy_perform(curl); + if (res != CURLE_OK) { + std::cerr << "cURL error: " << curl_easy_strerror(res) << "\n"; + exit(1); + } + + curl_easy_cleanup(curl); + return input_data(buffer, false); +} + +int main(int argc, char* argv[]) { + curl_global_init(CURL_GLOBAL_ALL); + + Input input; + if (argc > 1) { + input = download(argv[1]); // Загрузка из URL + } else { + input = input_data(std::cin, true); // Чтение из stdin + } + + auto bins = make_histogram(input.numbers, input.bin_count); show_histogram_svg(bins); + + curl_global_cleanup(); return 0; } diff --git a/svg.cpp b/svg.cpp index ed9bfed..f8c5ce1 100644 --- a/svg.cpp +++ b/svg.cpp @@ -23,7 +23,7 @@ void svg_rect(double x, double y, double width, double height, << "stroke='" << stroke << "' fill='" << fill << "' />\n"; } -void show_histogram_svg(const std::vector& bins) { +/*void show_histogram_svg(const std::vector& bins) { const size_t IMAGE_WIDTH = 400; const size_t IMAGE_HEIGHT = 300; const size_t TEXT_LEFT = 20; @@ -47,5 +47,28 @@ void show_histogram_svg(const std::vector& bins) { top += BIN_HEIGHT; } + svg_end(); +}*/ +void show_histogram_svg(const std::vector& bins) { + size_t max_count = 0; + for (size_t count : bins) { + if (count > max_count) max_count = count; + } + + const size_t IMAGE_HEIGHT = IMAGE_PADDING * 2 + max_count * 10 + TEXT_HEIGHT; + + svg_begin(IMAGE_WIDTH, IMAGE_HEIGHT); + + double x = IMAGE_PADDING; + const double y_base = IMAGE_HEIGHT - IMAGE_PADDING - TEXT_HEIGHT; + + for (size_t bin : bins) { + const double height = bin * 10; + svg_rect(x, y_base - height, BAR_WIDTH, height, "black", "#aaffaa"); + svg_text(x + BAR_WIDTH/2 - 5, y_base + TEXT_HEIGHT - 5, std::to_string(bin)); + + x += BAR_WIDTH + 10; + } + svg_end(); } diff --git a/svg.h b/svg.h index 62c8e73..3e71243 100644 --- a/svg.h +++ b/svg.h @@ -2,6 +2,10 @@ #include #include +const size_t IMAGE_WIDTH = 400; +const size_t IMAGE_PADDING = 20; +const size_t BAR_WIDTH = 30; +const size_t TEXT_HEIGHT = 20; void svg_begin(double width, double height); void svg_end(); void svg_text(double left, double baseline, const std::string& text); diff --git a/unittest.cbp b/unittest.cbp index 7f9621b..5a9c8c0 100644 --- a/unittest.cbp +++ b/unittest.cbp @@ -31,6 +31,10 @@ + + + + diff --git a/unittest.cpp b/unittest.cpp index a9ba7e5..a8a7dee 100644 --- a/unittest.cpp +++ b/unittest.cpp @@ -10,3 +10,36 @@ TEST_CASE("distinct positive numbers") { CHECK(min == 1); CHECK(max == 2); } + +TEST_CASE("empty vector") { + double min = 0; + double max = 0; + find_minmax({}, min, max); + CHECK(min == std::numeric_limits::max()); + CHECK(max == std::numeric_limits::lowest()); +} + +TEST_CASE("single element vector") { + double min = 0; + double max = 0; + find_minmax({42}, min, max); + CHECK(min == 42); + CHECK(max == 42); +} + +TEST_CASE("negative numbers") { + double min = 0; + double max = 0; + find_minmax({-5, -1, -3}, min, max); + CHECK(min == -5); + CHECK(max == -1); +} + +TEST_CASE("identical elements") { + double min = 0; + double max = 0; + find_minmax({7, 7, 7}, min, max); + CHECK(min == 7); + CHECK(max == 7); +} +//wewger