initial commit
This commit is contained in:
73
cplusplus/geminitutorial/tutorial2/src/CsvParser.cpp
Normal file
73
cplusplus/geminitutorial/tutorial2/src/CsvParser.cpp
Normal file
@@ -0,0 +1,73 @@
|
||||
#include "CsvParser.h"
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <iostream>
|
||||
#include <algorithm> // For std::remove_if
|
||||
|
||||
namespace CsvParser {
|
||||
|
||||
TickData parseTickCsvLine(std::string_view line) {
|
||||
TickData tick;
|
||||
std::string s_line(line); // Convert string_view to string for stringstream
|
||||
std::stringstream ss(s_line);
|
||||
std::string segment;
|
||||
std::vector<std::string> seglist;
|
||||
|
||||
while(std::getline(ss, segment, ',')) {
|
||||
seglist.push_back(segment);
|
||||
}
|
||||
|
||||
if (seglist.size() != 3) {
|
||||
throw std::runtime_error("CSV line does not have 3 segments: " + std::string(line));
|
||||
}
|
||||
|
||||
// Parse timestamp (simplified for now, assumes epoch seconds)
|
||||
// In a real scenario, this would involve more robust date/time parsing
|
||||
try {
|
||||
long long timestamp_sec = std::stoll(seglist[0]);
|
||||
tick.timestamp = std::chrono::system_clock::from_time_t(timestamp_sec);
|
||||
} catch (const std::exception& e) {
|
||||
throw std::runtime_error("Failed to parse timestamp: " + seglist[0] + " - " + e.what());
|
||||
}
|
||||
|
||||
// Parse price
|
||||
try {
|
||||
tick.price = std::stod(seglist[1]);
|
||||
} catch (const std::exception& e) {
|
||||
throw std::runtime_error("Failed to parse price: " + seglist[1] + " - " + e.what());
|
||||
}
|
||||
|
||||
// Parse volume
|
||||
try {
|
||||
tick.volume = std::stol(seglist[2]);
|
||||
} catch (const std::exception& e) {
|
||||
throw std::runtime_error("Failed to parse volume: " + seglist[2] + " - " + e.what());
|
||||
}
|
||||
|
||||
return tick;
|
||||
}
|
||||
|
||||
std::vector<TickData> parseTickCsvFile(std::string_view filename)
|
||||
{
|
||||
std::vector<TickData> ticks;
|
||||
std::ifstream file(std::string{filename}); // Convert string_view to string for ifstream
|
||||
|
||||
if (!file.is_open()) {
|
||||
throw std::runtime_error("Could not open file: " + std::string(filename));
|
||||
}
|
||||
|
||||
std::string line;
|
||||
while (std::getline(file, line)) {
|
||||
if (line.empty()) continue; // Skip empty lines
|
||||
try {
|
||||
ticks.push_back(parseTickCsvLine(line));
|
||||
} catch (const std::runtime_error& e) {
|
||||
std::cerr << "Error parsing line: \"" << line << "\" - " << e.what() << std::endl;
|
||||
// Depending on requirements, could rethrow or continue
|
||||
}
|
||||
}
|
||||
return ticks;
|
||||
}
|
||||
|
||||
} // namespace CsvParser
|
||||
11
cplusplus/geminitutorial/tutorial2/src/CsvParser.h
Normal file
11
cplusplus/geminitutorial/tutorial2/src/CsvParser.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include "TickData.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <string_view> // For std::string_view
|
||||
|
||||
namespace CsvParser {
|
||||
TickData parseTickCsvLine(std::string_view line);
|
||||
std::vector<TickData> parseTickCsvFile(std::string_view filename);
|
||||
} // namespace CsvParser
|
||||
@@ -0,0 +1,9 @@
|
||||
#include "StockData_Modern.h"
|
||||
|
||||
// Constructor: Initialize the vector with a given size
|
||||
StockData_Modern::StockData_Modern(size_t size) : data_(size) {}
|
||||
|
||||
// Public method to access data (with bounds checking provided by std::vector::at)
|
||||
double& StockData_Modern::at(size_t index) {
|
||||
return data_.at(index);
|
||||
}
|
||||
19
cplusplus/geminitutorial/tutorial2/src/StockData_Modern.h
Normal file
19
cplusplus/geminitutorial/tutorial2/src/StockData_Modern.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
#include <cstddef> // For size_t
|
||||
|
||||
#include <vector>
|
||||
|
||||
class StockData_Modern {
|
||||
public:
|
||||
// Constructor
|
||||
StockData_Modern(size_t size);
|
||||
|
||||
// No Copy Constructor, Copy Assignment, or Destructor needed!
|
||||
// The compiler-generated versions work perfectly because `std::vector` handles itself.
|
||||
|
||||
// Public method to access data
|
||||
double& at(size_t index);
|
||||
|
||||
private:
|
||||
std::vector<double> data_;
|
||||
};
|
||||
37
cplusplus/geminitutorial/tutorial2/src/StockData_Old.cpp
Normal file
37
cplusplus/geminitutorial/tutorial2/src/StockData_Old.cpp
Normal file
@@ -0,0 +1,37 @@
|
||||
#include "StockData_Old.h"
|
||||
#include <algorithm> // For std::copy
|
||||
|
||||
// Constructor: Allocate memory for the array
|
||||
StockData_Old::StockData_Old(size_t size) : size_(size) {
|
||||
data_ = new double[size_];
|
||||
}
|
||||
|
||||
// Destructor: Free the allocated memory
|
||||
StockData_Old::~StockData_Old() {
|
||||
delete[] data_;
|
||||
}
|
||||
|
||||
// Copy Constructor: Perform a deep copy
|
||||
StockData_Old::StockData_Old(const StockData_Old& other) : size_(other.size_) {
|
||||
data_ = new double[size_];
|
||||
std::copy(other.data_, other.data_ + size_, data_);
|
||||
}
|
||||
|
||||
// Copy Assignment Operator: Handle self-assignment and perform a deep copy
|
||||
StockData_Old& StockData_Old::operator=(const StockData_Old& other) {
|
||||
if (this != &other) { // Protect against self-assignment
|
||||
// Free the old memory
|
||||
delete[] data_;
|
||||
|
||||
// Allocate new memory and copy data
|
||||
size_ = other.size_;
|
||||
data_ = new double[size_];
|
||||
std::copy(other.data_, other.data_ + size_, data_);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Public method to access data (no bounds checking for simplicity)
|
||||
double& StockData_Old::at(size_t index) {
|
||||
return data_[index];
|
||||
}
|
||||
25
cplusplus/geminitutorial/tutorial2/src/StockData_Old.h
Normal file
25
cplusplus/geminitutorial/tutorial2/src/StockData_Old.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#pragma once // Use modern include guard
|
||||
|
||||
#include <cstddef> // For size_t
|
||||
|
||||
class StockData_Old {
|
||||
public:
|
||||
// Constructor
|
||||
StockData_Old(size_t size);
|
||||
|
||||
// Copy Constructor (Rule 1 of 3)
|
||||
StockData_Old(const StockData_Old& other);
|
||||
|
||||
// Copy Assignment Operator (Rule 2 of 3)
|
||||
StockData_Old& operator=(const StockData_Old& other);
|
||||
|
||||
// Destructor (Rule 3 of 3)
|
||||
~StockData_Old();
|
||||
|
||||
// Public method to access data
|
||||
double& at(size_t index);
|
||||
|
||||
private:
|
||||
double* data_;
|
||||
size_t size_;
|
||||
};
|
||||
25
cplusplus/geminitutorial/tutorial2/src/TickData.h
Normal file
25
cplusplus/geminitutorial/tutorial2/src/TickData.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <chrono>
|
||||
#include <sstream> // For std::ostringstream
|
||||
|
||||
struct TickData {
|
||||
std::chrono::system_clock::time_point timestamp;
|
||||
double price;
|
||||
long volume;
|
||||
|
||||
// Optional: for easy printing/debugging
|
||||
std::string toString() const {
|
||||
std::ostringstream oss;
|
||||
// Convert timestamp to a readable format (simple example)
|
||||
std::time_t time = std::chrono::system_clock::to_time_t(timestamp);
|
||||
std::string time_str = std::ctime(&time);
|
||||
time_str.pop_back(); // Remove trailing newline
|
||||
|
||||
oss << "Timestamp: " << time_str
|
||||
<< ", Price: " << price
|
||||
<< ", Volume: " << volume;
|
||||
return oss.str();
|
||||
}
|
||||
};
|
||||
26
cplusplus/geminitutorial/tutorial2/src/Trade.h
Normal file
26
cplusplus/geminitutorial/tutorial2/src/Trade.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include "spdlog/spdlog.h"
|
||||
|
||||
|
||||
class Trade {
|
||||
public:
|
||||
Trade(const std::string& instrument, double price)
|
||||
: instrument_(instrument), price_(price) {
|
||||
spdlog::info("Trade constructor: {} @ {}", instrument_, price_);
|
||||
}
|
||||
|
||||
~Trade() {
|
||||
spdlog::info("Trade destructor: {} @ {}", instrument_, price_);
|
||||
}
|
||||
|
||||
void print() const {
|
||||
spdlog::info("Executing trade: {} for ${}", instrument_, price_);
|
||||
}
|
||||
|
||||
private:
|
||||
std::string instrument_;
|
||||
double price_;
|
||||
};
|
||||
202
cplusplus/geminitutorial/tutorial2/src/main.cpp
Normal file
202
cplusplus/geminitutorial/tutorial2/src/main.cpp
Normal file
@@ -0,0 +1,202 @@
|
||||
#include "spdlog/spdlog.h"
|
||||
#include "StockData_Old.h"
|
||||
#include "StockData_Modern.h"
|
||||
#include "Trade.h"
|
||||
#include "TickData.h"
|
||||
#include "CsvParser.h"
|
||||
|
||||
#include <memory> // For smart pointers
|
||||
#include <iostream> // For std::cout, std::cerr
|
||||
#include <vector> // For std::vector
|
||||
#include <numeric> // For std::accumulate
|
||||
#include <algorithm> // For std::max_element, std::for_each, std::count_if
|
||||
#include <map> // For std::map (instead of unordered_map for simplicity in example)
|
||||
#include <string_view> // For std::string_view
|
||||
#include <fstream> // For std::ofstream
|
||||
|
||||
// --- Existing Tutorial 2.1 Demonstrations ---
|
||||
|
||||
void demonstrate_old_way() {
|
||||
spdlog::info("--- Demonstrating the Old Way (Manual Memory Management) ---");
|
||||
StockData_Old prices(5);
|
||||
for (size_t i = 0; i < 5; ++i) {
|
||||
prices.at(i) = 100.0 + i;
|
||||
}
|
||||
|
||||
spdlog::info("Copied prices_copy1(prices)");
|
||||
StockData_Old prices_copy1(prices); // Copy constructor
|
||||
prices_copy1.at(0) = 999.0;
|
||||
|
||||
spdlog::info("prices.at(0) = {}", prices.at(0));
|
||||
spdlog::info("prices_copy1.at(0) = {}", prices_copy1.at(0));
|
||||
|
||||
spdlog::info("Copied prices_copy2 = prices");
|
||||
StockData_Old prices_copy2(1);
|
||||
prices_copy2 = prices; // Copy assignment
|
||||
prices_copy2.at(1) = 888.0;
|
||||
|
||||
spdlog::info("prices.at(1) = {}", prices.at(1));
|
||||
spdlog::info("prices_copy2.at(1) = {}", prices_copy2.at(1));
|
||||
|
||||
spdlog::info("--- Leaving scope for Old Way demo ---");
|
||||
}
|
||||
|
||||
void demonstrate_modern_way() {
|
||||
spdlog::info("--- Demonstrating the Modern Way (RAII with std::vector) ---");
|
||||
StockData_Modern prices(5);
|
||||
for (size_t i = 0; i < 5; ++i) {
|
||||
prices.at(i) = 100.0 + i;
|
||||
}
|
||||
|
||||
spdlog::info("Copied prices_copy1(prices)");
|
||||
StockData_Modern prices_copy1(prices); // Copy constructor (compiler-generated)
|
||||
prices_copy1.at(0) = 999.0;
|
||||
|
||||
spdlog::info("prices.at(0) = {}", prices.at(0));
|
||||
spdlog::info("prices_copy1.at(0) = {}", prices_copy1.at(0));
|
||||
|
||||
spdlog::info("Copied prices_copy2 = prices");
|
||||
StockData_Modern prices_copy2(1);
|
||||
prices_copy2 = prices; // Copy assignment (compiler-generated)
|
||||
prices_copy2.at(1) = 888.0;
|
||||
|
||||
spdlog::info("prices.at(1) = {}", prices.at(1));
|
||||
spdlog::info("prices_copy2.at(1) = {}", prices_copy2.at(1));
|
||||
spdlog::info("--- Leaving scope for Modern Way demo ---");
|
||||
}
|
||||
|
||||
void demonstrate_smart_pointers() {
|
||||
spdlog::info("--- Demonstrating Smart Pointers ---");
|
||||
|
||||
// Demonstrate unique_ptr for exclusive ownership
|
||||
{
|
||||
spdlog::info("Creating a unique_ptr-managed Trade");
|
||||
auto unique_trade = std::make_unique<Trade>("AAPL", 150.0);
|
||||
unique_trade->print();
|
||||
// unique_trade is automatically destroyed when this scope ends
|
||||
} // ~Trade() is called here
|
||||
|
||||
// Demonstrate shared_ptr for shared ownership
|
||||
{
|
||||
spdlog::info("Creating a shared_ptr-managed Trade");
|
||||
std::shared_ptr<Trade> shared_trade1;
|
||||
{
|
||||
auto shared_trade2 = std::make_shared<Trade>("GOOG", 2800.0);
|
||||
shared_trade1 = shared_trade2; // Both pointers now share ownership
|
||||
spdlog::info("shared_ptr use_count: {}", shared_trade1.use_count());
|
||||
shared_trade2->print();
|
||||
} // shared_trade2 goes out of scope, but the object is not destroyed
|
||||
|
||||
spdlog::info("shared_ptr use_count after inner scope: {}", shared_trade1.use_count());
|
||||
shared_trade1->print();
|
||||
// shared_trade1 is automatically destroyed when this scope ends
|
||||
} // ~Trade() is called here
|
||||
spdlog::info("--- Leaving scope for Smart Pointers demo ---");
|
||||
}
|
||||
|
||||
// --- New Tutorial 2.2 Demonstrations ---
|
||||
|
||||
void generate_mock_csv_file(std::string_view filename, int num_lines) {
|
||||
spdlog::info("Generating mock CSV file: {}", std::string(filename));
|
||||
std::ofstream ofs(std::string{filename});
|
||||
if (!ofs.is_open()) {
|
||||
throw std::runtime_error("Could not create mock CSV file.");
|
||||
}
|
||||
|
||||
for (int i = 0; i < num_lines; ++i) {
|
||||
long long timestamp = std::chrono::system_clock::now().time_since_epoch().count() / 1000000000LL + i;
|
||||
double price = 100.0 + (i * 0.5);
|
||||
long volume = 100 + (i * 10);
|
||||
ofs << timestamp << "," << price << "," << volume << "\n";
|
||||
}
|
||||
ofs.close();
|
||||
}
|
||||
|
||||
|
||||
void demonstrate_stl_containers_algorithms() {
|
||||
spdlog::info("--- Demonstrating Modern STL Containers & Algorithms (Tutorial 2.2) ---");
|
||||
|
||||
const std::string_view csv_filename = "mock_tick_data.csv";
|
||||
generate_mock_csv_file(csv_filename, 10);
|
||||
|
||||
std::vector<TickData> ticks;
|
||||
try {
|
||||
ticks = CsvParser::parseTickCsvFile(csv_filename);
|
||||
spdlog::info("Successfully parsed {} ticks.", ticks.size());
|
||||
} catch (const std::runtime_error& e) {
|
||||
spdlog::error("Error parsing CSV file: {}", e.what());
|
||||
return;
|
||||
}
|
||||
|
||||
// Example 1: Find the highest price
|
||||
auto max_price_it = std::max_element(ticks.begin(), ticks.end(),
|
||||
[](const TickData& a, const TickData& b) {
|
||||
return a.price < b.price;
|
||||
});
|
||||
if (max_price_it != ticks.end()) {
|
||||
spdlog::info("Highest price found: {}", max_price_it->price);
|
||||
}
|
||||
|
||||
// Example 2: Calculate total volume
|
||||
long total_volume = std::accumulate(ticks.begin(), ticks.end(), 0LL,
|
||||
[](long sum, const TickData& tick) {
|
||||
return sum + tick.volume;
|
||||
});
|
||||
spdlog::info("Total volume: {}", total_volume);
|
||||
|
||||
// Example 3: Filter ticks above a certain price (e.g., > 102.0)
|
||||
std::vector<TickData> high_price_ticks;
|
||||
std::copy_if(ticks.begin(), ticks.end(), std::back_inserter(high_price_ticks),
|
||||
[](const TickData& tick) {
|
||||
return tick.price > 102.0;
|
||||
});
|
||||
spdlog::info("Number of ticks with price > 102.0: {}", high_price_ticks.size());
|
||||
// std::for_each(high_price_ticks.begin(), high_price_ticks.end(),
|
||||
// [](const TickData& tick) { spdlog::info(" {}", tick.toString()); });
|
||||
|
||||
// Example 4: Average price using a lambda
|
||||
double sum_prices = 0.0;
|
||||
std::for_each(ticks.begin(), ticks.end(),
|
||||
[&sum_prices](const TickData& tick) {
|
||||
sum_prices += tick.price;
|
||||
});
|
||||
if (!ticks.empty()) {
|
||||
spdlog::info("Average price: {}", sum_prices / ticks.size());
|
||||
}
|
||||
|
||||
// Example 5: Aggregate volume by second (using std::map for simplicity)
|
||||
// For high performance, a custom hash map or a more direct time-series approach would be used.
|
||||
std::map<long long, long> volume_by_second;
|
||||
for (const auto& tick : ticks) {
|
||||
long long sec = std::chrono::duration_cast<std::chrono::seconds>(tick.timestamp.time_since_epoch()).count();
|
||||
volume_by_second[sec] += tick.volume;
|
||||
}
|
||||
|
||||
spdlog::info("Volume by second (first 3 entries):");
|
||||
int count = 0;
|
||||
for (const auto& entry : volume_by_second) {
|
||||
if (count >= 3) break;
|
||||
spdlog::info(" Timestamp (sec): {}, Volume: {}", entry.first, entry.second);
|
||||
count++;
|
||||
}
|
||||
|
||||
spdlog::info("--- Leaving scope for STL Containers & Algorithms demo ---");
|
||||
}
|
||||
|
||||
|
||||
int main() {
|
||||
spdlog::set_level(spdlog::level::info);
|
||||
spdlog::info("Starting Tutorial 2: Core Language, Libraries, and Concepts");
|
||||
|
||||
demonstrate_old_way();
|
||||
std::cout << "\n";
|
||||
demonstrate_modern_way();
|
||||
std::cout << "\n";
|
||||
demonstrate_smart_pointers();
|
||||
std::cout << "\n";
|
||||
demonstrate_stl_containers_algorithms();
|
||||
|
||||
|
||||
spdlog::info("Tutorial 2 finished.");
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user