Windows C++ Fehlerbehandlung Beispiele

Windows C++ Fehlerbehandlungsbeispiele einschließlich Ausnahmebehandlung, Protokollierung und Parametervalidierung

💻 Ausnahmebehandlung cpp

🟢 simple ⭐⭐

Try-Catch-Ausnahmebehandlung mit benutzerdefinierten Ausnahmeklassen für Windows-Anwendungen implementieren

⏱️ 20 min 🏷️ cpp, exception, error handling, windows
Prerequisites: Basic C++, Exception handling concepts
// Windows C++ Exception Handling Examples

#include <iostream>
#include <string>
#include <vector>
#include <exception>
#include <stdexcept>
#include <windows.h>

// 1. Custom Exception Classes
class WindowsException : public std::exception {
private:
    DWORD m_errorCode;
    std::string m_message;
    std::string m_function;
    std::string m_file;
    int m_line;

public:
    WindowsException(DWORD errorCode, const std::string& message,
                     const std::string& function, const std::string& file, int line)
        : m_errorCode(errorCode), m_message(message), m_function(function),
          m_file(file), m_line(line) {
        m_description = formatDescription();
    }

    const char* what() const noexcept override {
        return m_description.c_str();
    }

    DWORD getErrorCode() const { return m_errorCode; }
    const std::string& getFunction() const { return m_function; }
    const std::string& getFile() const { return m_file; }
    int getLine() const { return m_line; }

private:
    std::string m_description;

    std::string formatDescription() const {
        char buffer[256];
        sprintf_s(buffer, "Error 0x%08X in %s (%s:%d): %s",
                 m_errorCode, m_function.c_str(), m_file.c_str(), m_line, m_message.c_str());
        return buffer;
    }
};

// Macro for throwing exceptions with file/line info
#define THROW_WINDOWS_ERROR(msg, errorCode) \
    throw WindowsException(errorCode, msg, __FUNCTION__, __FILE__, __LINE__)

#define THROW_IF_FAILED(hr, msg) \
    if (FAILED(hr)) { \
        THROW_WINDOWS_ERROR(msg, hr); \
    }

// 2. File Operation Exception
class FileException : public std::runtime_error {
public:
    enum class ErrorType {
        NotFound,
        AccessDenied,
        AlreadyExists,
        InvalidPath,
        ReadError,
        WriteError
    };

private:
    ErrorType m_errorType;
    std::string m_filePath;

public:
    FileException(ErrorType type, const std::string& filePath)
        : std::runtime_error(formatMessage(type, filePath)),
          m_errorType(type), m_filePath(filePath) {}

    ErrorType getErrorType() const { return m_errorType; }
    const std::string& getFilePath() const { return m_filePath; }

private:
    static std::string formatMessage(ErrorType type, const std::string& path) {
        std::string typeName;
        switch (type) {
            case ErrorType::NotFound: typeName = "File not found"; break;
            case ErrorType::AccessDenied: typeName = "Access denied"; break;
            case ErrorType::AlreadyExists: typeName = "File already exists"; break;
            case ErrorType::InvalidPath: typeName = "Invalid path"; break;
            case ErrorType::ReadError: typeName = "Read error"; break;
            case ErrorType::WriteError: typeName = "Write error"; break;
        }
        return typeName + ": " + path;
    }
};

// 3. Validation Exception
class ValidationException : public std::runtime_error {
public:
    enum class ErrorType {
        NullPointer,
        EmptyString,
        OutOfRange,
        InvalidFormat,
        NegativeValue,
        ExceedsMaximum
    };

private:
    ErrorType m_errorType;
    std::string m_parameterName;

public:
    ValidationException(ErrorType type, const std::string& paramName)
        : std::runtime_error(formatMessage(type, paramName)),
          m_errorType(type), m_parameterName(paramName) {}

    ErrorType getErrorType() const { return m_errorType; }
    const std::string& getParameterName() const { return m_parameterName; }

private:
    static std::string formatMessage(ErrorType type, const std::string& param) {
        std::string typeName;
        switch (type) {
            case ErrorType::NullPointer: typeName = "Null pointer"; break;
            case ErrorType::EmptyString: typeName = "Empty string"; break;
            case ErrorType::OutOfRange: typeName = "Out of range"; break;
            case ErrorType::InvalidFormat: typeName = "Invalid format"; break;
            case ErrorType::NegativeValue: typeName = "Negative value"; break;
            case ErrorType::ExceedsMaximum: typeName = "Exceeds maximum"; break;
        }
        return "Validation failed [" + typeName + "]: " + param;
    }
};

// 4. Network Exception
class NetworkException : public std::runtime_error {
public:
    enum class ErrorType {
        ConnectionFailed,
        Timeout,
        DnsError,
        HttpError,
        SslError
    };

private:
    ErrorType m_errorType;
    int m_errorCode;

public:
    NetworkException(ErrorType type, int errorCode, const std::string& message)
        : std::runtime_error(message), m_errorType(type), m_errorCode(errorCode) {}

    ErrorType getErrorType() const { return m_errorType; }
    int getErrorCode() const { return m_errorCode; }
};

// 5. Database Exception
class DatabaseException : public std::runtime_error {
private:
    std::string m_sqlState;
    int m_nativeError;

public:
    DatabaseException(const std::string& message, const std::string& sqlState, int nativeError)
        : std::runtime_error(message), m_sqlState(sqlState), m_nativeError(nativeError) {}

    const std::string& getSQLState() const { return m_sqlState; }
    int getNativeError() const { return m_nativeError; }
};

// 6. Exception Handler with Logging
class ExceptionHandler {
public:
    static void handleException(const std::exception& e) {
        std::cerr << "\n=== Exception Caught ===" << std::endl;
        std::cerr << "Type: " << typeid(e).name() << std::endl;
        std::cerr << "Message: " << e.what() << std::endl;

        // Try to handle specific exception types
        try {
            dynamic_cast<const WindowsException&>(e);
            std::cerr << "This is a Windows exception" << std::endl;
        } catch (...) {}

        try {
            const FileException& fe = dynamic_cast<const FileException&>(e);
            std::cerr << "File: " << fe.getFilePath() << std::endl;
            std::cerr << "Error Type: " << static_cast<int>(fe.getErrorType()) << std::endl;
        } catch (...) {}
    }

    static void handleUnknownException() {
        std::cerr << "\n=== Unknown Exception Caught ===" << std::endl;
        std::cerr << "An unknown exception was caught" << std::endl;
    }

    static std::string getLastErrorString() {
        DWORD errorCode = GetLastError();
        if (errorCode == 0) {
            return "No error";
        }

        LPSTR messageBuffer = nullptr;
        size_t size = FormatMessageA(
            FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
            nullptr,
            errorCode,
            MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
            (LPSTR)&messageBuffer,
            0,
            nullptr
        );

        std::string message(messageBuffer, size);
        LocalFree(messageBuffer);

        return message;
    }
};

// 7. RAII Exception-Safe Wrapper
class ExceptionSafeFile {
private:
    HANDLE m_hFile;
    std::string m_filename;

public:
    ExceptionSafeFile(const std::string& filename, bool forRead = true)
        : m_hFile(INVALID_HANDLE_VALUE), m_filename(filename) {

        DWORD access = forRead ? GENERIC_READ : GENERIC_WRITE;
        DWORD disposition = forRead ? OPEN_EXISTING : CREATE_ALWAYS;

        m_hFile = CreateFileA(
            filename.c_str(),
            access,
            FILE_SHARE_READ,
            nullptr,
            disposition,
            FILE_ATTRIBUTE_NORMAL,
            nullptr
        );

        if (m_hFile == INVALID_HANDLE_VALUE) {
            DWORD error = GetLastError();

            FileException::ErrorType errorType;
            if (error == ERROR_FILE_NOT_FOUND) {
                errorType = FileException::ErrorType::NotFound;
            } else if (error == ERROR_ACCESS_DENIED) {
                errorType = FileException::ErrorType::AccessDenied;
            } else {
                errorType = FileException::ErrorType::InvalidPath;
            }

            throw FileException(errorType, filename);
        }

        std::cout << "File opened successfully: " << filename << std::endl;
    }

    ~ExceptionSafeFile() {
        close();
    }

    void close() {
        if (m_hFile != INVALID_HANDLE_VALUE) {
            CloseHandle(m_hFile);
            m_hFile = INVALID_HANDLE_VALUE;
            std::cout << "File closed: " << m_filename << std::endl;
        }
    }

    HANDLE getHandle() const { return m_hFile; }
};

// 8. Try-Catch Examples
void demonstrateTryCatch() {
    std::cout << "\n--- Basic Try-Catch ---" << std::endl;

    try {
        // Code that might throw
        std::string str = "test";
        if (str.empty()) {
            throw ValidationException(
                ValidationException::ErrorType::EmptyString,
                "str"
            );
        }
        std::cout << "String validation passed" << std::endl;

    } catch (const ValidationException& e) {
        ExceptionHandler::handleException(e);
    } catch (const std::exception& e) {
        ExceptionHandler::handleException(e);
    }
}

// 9. Nested Try-Catch
void demonstrateNestedTryCatch() {
    std::cout << "\n--- Nested Try-Catch ---" << std::endl;

    try {
        std::cout << "Outer try block" << std::endl;

        try {
            std::cout << "Inner try block" << std::endl;

            // Simulate error
            throw std::runtime_error("Inner error");

        } catch (const std::exception& inner) {
            std::cout << "Inner catch: " << inner.what() << std::endl;
            // Re-throw to outer handler
            throw;
        }

    } catch (const std::exception& outer) {
        std::cout << "Outer catch: " << outer.what() << std::endl;
    }
}

// 10. Exception Specifications and noexcept
class SafeOperation {
public:
    // Function that doesn't throw exceptions
    void safeFunction() noexcept {
        std::cout << "This function guarantees not to throw" << std::endl;
        // If an exception occurs, program will terminate
    }

    // Function with exception specification
    void riskyFunction() throw(std::runtime_error) {
        throw std::runtime_error("This function only throws runtime_error");
    }

    void demonstrateNoExcept() {
        safeFunction();

        try {
            riskyFunction();
        } catch (const std::runtime_error& e) {
            std::cout << "Caught expected error: " << e.what() << std::endl;
        }
    }
};

// 11. Multiple Catch Blocks
void demonstrateMultipleCatches() {
    std::cout << "\n--- Multiple Catch Blocks ---" << std::endl;

    try {
        // Simulate different types of errors
        int choice = 2; // Change to test different exceptions

        switch (choice) {
            case 1:
                throw std::invalid_argument("Invalid argument");
            case 2:
                throw std::runtime_error("Runtime error");
            case 3:
                throw std::out_of_range("Out of range");
            case 4:
                throw "C-style string exception";
            default:
                std::cout << "No exception" << std::endl;
        }

    } catch (const std::invalid_argument& e) {
        std::cout << "Invalid argument: " << e.what() << std::endl;
    } catch (const std::runtime_error& e) {
        std::cout << "Runtime error: " << e.what() << std::endl;
    } catch (const std::out_of_range& e) {
        std::cout << "Out of range: " << e.what() << std::endl;
    } catch (const std::exception& e) {
        std::cout << "Standard exception: " << e.what() << std::endl;
    } catch (...) {
        std::cout << "Unknown exception caught" << std::endl;
    }
}

// 12. Exception Propagation
void level3Function() {
    throw std::runtime_error("Error in level 3");
}

void level2Function() {
    level3Function();
}

void level1Function() {
    try {
        level2Function();
    } catch (const std::exception& e) {
        std::cout << "Caught at level 1: " << e.what() << std::endl;
        throw; // Re-throw
    }
}

void demonstrateExceptionPropagation() {
    std::cout << "\n--- Exception Propagation ---" << std::endl;

    try {
        level1Function();
    } catch (const std::exception& e) {
        std::cout << "Caught at main: " << e.what() << std::endl;
    }
}

// 13. Standard Exception Usage
void divideNumbers(int a, int b) {
    if (b == 0) {
        throw std::invalid_argument("Division by zero is not allowed");
    }

    double result = static_cast<double>(a) / b;
    std::cout << a << " / " << b << " = " << result << std::endl;
}

void demonstrateStandardExceptions() {
    std::cout << "\n--- Standard Exceptions ---" << std::endl;

    try {
        divideNumbers(10, 2);
        divideNumbers(10, 0); // This will throw
    } catch (const std::invalid_argument& e) {
        std::cout << "Caught: " << e.what() << std::endl;
    }
}

// Main demonstration
int main() {
    std::cout << "=== Windows C++ Exception Handling Examples ===" << std::endl;

    // 1. Basic try-catch
    demonstrateTryCatch();

    // 2. Nested try-catch
    demonstrateNestedTryCatch();

    // 3. Multiple catch blocks
    demonstrateMultipleCatches();

    // 4. Exception propagation
    demonstrateExceptionPropagation();

    // 5. Standard exceptions
    demonstrateStandardExceptions();

    // 6. Safe operations
    std::cout << "\n--- Exception-Safe Operations ---" << std::endl;
    try {
        ExceptionSafeFile file("test_exception.txt", false);
        std::cout << "File operation completed" << std::endl;
    } catch (const FileException& e) {
        ExceptionHandler::handleException(e);
    }

    // 7. Noexcept demonstration
    std::cout << "\n--- Noexcept Demonstration ---" << std::endl;
    SafeOperation safeOp;
    safeOp.demonstrateNoExcept();

    std::cout << "\n=== All Exception Handling Examples Completed ===" << std::endl;
    return 0;
}

💻 Parametervalidierung cpp

🟢 simple ⭐⭐⭐

Funktionsparameter validieren einschließlich Nullzeiger-Prüfung, Bereichsprüfung und benutzerdefinierte Validierungsregeln

⏱️ 20 min 🏷️ cpp, validation, error handling, windows
Prerequisites: Basic C++, Exception handling
// Windows C++ Parameter Validation Examples

#include <iostream>
#include <string>
#include <vector>
#include <stdexcept>
#include <regex>
#include <algorithm>
#include <windows.h>

// 1. Basic Validation Functions
class ParameterValidator {
public:
    // Null pointer validation
    template<typename T>
    static void notNull(T* ptr, const std::string& paramName = "pointer") {
        if (ptr == nullptr) {
            throw std::invalid_argument(paramName + " cannot be null");
        }
    }

    // String validation
    static void notEmpty(const std::string& str, const std::string& paramName = "string") {
        if (str.empty()) {
            throw std::invalid_argument(paramName + " cannot be empty");
        }
    }

    static void maxLength(const std::string& str, size_t maxLen, const std::string& paramName = "string") {
        if (str.length() > maxLen) {
            throw std::invalid_argument(paramName + " exceeds maximum length of " + std::to_string(maxLen));
        }
    }

    static void minLength(const std::string& str, size_t minLen, const std::string& paramName = "string") {
        if (str.length() < minLen) {
            throw std::invalid_argument(paramName + " is shorter than minimum length of " + std::to_string(minLen));
        }
    }

    // Numeric validation
    static void notNegative(int value, const std::string& paramName = "value") {
        if (value < 0) {
            throw std::invalid_argument(paramName + " cannot be negative (got: " + std::to_string(value) + ")");
        }
    }

    static void inRange(int value, int min, int max, const std::string& paramName = "value") {
        if (value < min || value > max) {
            throw std::out_of_range(paramName + " must be between " + std::to_string(min) +
                                   " and " + std::to_string(max) + " (got: " + std::to_string(value) + ")");
        }
    }

    static void positive(double value, const std::string& paramName = "value") {
        if (value <= 0.0) {
            throw std::invalid_argument(paramName + " must be positive (got: " + std::to_string(value) + ")");
        }
    }

    // Array/Container validation
    template<typename T>
    static void notEmpty(const std::vector<T>& vec, const std::string& paramName = "vector") {
        if (vec.empty()) {
            throw std::invalid_argument(paramName + " cannot be empty");
        }
    }

    template<typename T>
    static void inBounds(size_t index, const std::vector<T>& vec, const std::string& indexName = "index") {
        if (index >= vec.size()) {
            throw std::out_of_range(indexName + " out of bounds (size: " +
                                   std::to_string(vec.size()) + ", index: " + std::to_string(index) + ")");
        }
    }

    static void maxSize(const std::vector<int>& vec, size_t max, const std::string& paramName = "vector") {
        if (vec.size() > max) {
            throw std::invalid_argument(paramName + " exceeds maximum size of " + std::to_string(max));
        }
    }
};

// 2. File Path Validation
class PathValidator {
public:
    static bool isValidPath(const std::string& path) {
        if (path.empty()) {
            return false;
        }

        // Check for invalid characters
        const std::string invalidChars = "<>"|?*";
        for (char c : invalidChars) {
            if (path.find(c) != std::string::npos) {
                return false;
            }
        }

        return true;
    }

    static void validatePath(const std::string& path, const std::string& paramName = "path") {
        if (!isValidPath(path)) {
            throw std::invalid_argument(paramName + " contains invalid characters: " + path);
        }
    }

    static void validateFileExtension(const std::string& filename,
                                      const std::vector<std::string>& allowedExtensions,
                                      const std::string& paramName = "filename") {
        size_t dotPos = filename.find_last_of('.');
        if (dotPos == std::string::npos) {
            throw std::invalid_argument(paramName + " has no file extension");
        }

        std::string ext = filename.substr(dotPos);
        std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower);

        for (const auto& allowedExt : allowedExtensions) {
            std::string lowerAllowed = allowedExt;
            std::transform(lowerAllowed.begin(), lowerAllowed.end(), lowerAllowed.begin(), ::tolower);

            if (ext == lowerAllowed || ext == "." + lowerAllowed) {
                return; // Valid extension
            }
        }

        throw std::invalid_argument(paramName + " has invalid extension: " + ext);
    }
};

// 3. String Format Validation
class FormatValidator {
public:
    static void validateEmail(const std::string& email) {
        // Basic email validation regex
        std::regex emailRegex(R"([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,})");
        if (!std::regex_match(email, emailRegex)) {
            throw std::invalid_argument("Invalid email format: " + email);
        }
    }

    static void validatePhoneNumber(const std::string& phone) {
        // Remove common formatting characters
        std::string cleaned = phone;
        cleaned.erase(std::remove(cleaned.begin(), cleaned.end(), '('), cleaned.end());
        cleaned.erase(std::remove(cleaned.begin(), cleaned.end(), ')'), cleaned.end());
        cleaned.erase(std::remove(cleaned.begin(), cleaned.end(), '-'), cleaned.end());
        cleaned.erase(std::remove(cleaned.begin(), cleaned.end(), ' '), cleaned.end());

        // Check if all remaining characters are digits
        if (!std::all_of(cleaned.begin(), cleaned.end(), ::isdigit)) {
            throw std::invalid_argument("Invalid phone number format: " + phone);
        }

        // Check length (typical US phone numbers)
        if (cleaned.length() != 10 && cleaned.length() != 11) {
            throw std::invalid_argument("Invalid phone number length: " + phone);
        }
    }

    static void validateURL(const std::string& url) {
        std::regex urlRegex(R"(https?://[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}(/.*)?)");
        if (!std::regex_match(url, urlRegex)) {
            throw std::invalid_argument("Invalid URL format: " + url);
        }
    }

    static void validateIPAddress(const std::string& ip) {
        std::regex ipRegex(R"(^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$)");
        if (!std::regex_match(ip, ipRegex)) {
            throw std::invalid_argument("Invalid IP address format: " + ip);
        }
    }

    static void validateDateFormat(const std::string& date) {
        // Check YYYY-MM-DD format
        std::regex dateRegex(R"(^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$)");
        if (!std::regex_match(date, dateRegex)) {
            throw std::invalid_argument("Invalid date format (expected YYYY-MM-DD): " + date);
        }
    }
};

// 4. Business Rule Validation
class BusinessValidator {
public:
    static void validateAge(int age, const std::string& paramName = "age") {
        ParameterValidator::inRange(age, 0, 150, paramName);
    }

    static void validateUsername(const std::string& username) {
        ParameterValidator::notEmpty(username, "username");
        ParameterValidator::minLength(username, 3, "username");
        ParameterValidator::maxLength(username, 20, "username");

        // Username must contain only alphanumeric characters and underscore
        std::regex usernameRegex(R"(^[a-zA-Z0-9_]+$)");
        if (!std::regex_match(username, usernameRegex)) {
            throw std::invalid_argument("Username can only contain letters, numbers, and underscores");
        }
    }

    static void validatePassword(const std::string& password) {
        ParameterValidator::minLength(password, 8, "password");

        bool hasUpper = false, hasLower = false, hasDigit = false, hasSpecial = false;

        for (char c : password) {
            if (isupper(c)) hasUpper = true;
            else if (islower(c)) hasLower = true;
            else if (isdigit(c)) hasDigit = true;
            else if (ispunct(c)) hasSpecial = true;
        }

        if (!hasUpper) {
            throw std::invalid_argument("Password must contain at least one uppercase letter");
        }
        if (!hasLower) {
            throw std::invalid_argument("Password must contain at least one lowercase letter");
        }
        if (!hasDigit) {
            throw std::invalid_argument("Password must contain at least one digit");
        }
        if (!hasSpecial) {
            throw std::invalid_argument("Password must contain at least one special character");
        }
    }

    static void validatePort(int port) {
        ParameterValidator::inRange(port, 1, 65535, "port");
    }

    static void validatePercentage(double value, const std::string& paramName = "percentage") {
        if (value < 0.0 || value > 100.0) {
            throw std::invalid_argument(paramName + " must be between 0 and 100 (got: " +
                                   std::to_string(value) + ")");
        }
    }
};

// 5. Batch Validation
class BatchValidator {
private:
    std::vector<std::string> m_errors;

public:
    template<typename Func>
    void validateAll(const std::vector<std::pair<Func, std::string>>& validations) {
        for (const auto& [validation, description] : validations) {
            try {
                validation();
            } catch (const std::exception& e) {
                m_errors.push_back(description + ": " + e.what());
            }
        }
    }

    bool hasErrors() const {
        return !m_errors.empty();
    }

    const std::vector<std::string>& getErrors() const {
        return m_errors;
    }

    void throwIfErrors() const {
        if (!m_errors.empty()) {
            std::string message = "Validation failed:\n";
            for (const auto& error : m_errors) {
                message += "  - " + error + "\n";
            }
            throw std::invalid_argument(message);
        }
    }
};

// 6. Precondition and Postcondition Checks
class Contract {
public:
    template<typename T>
    static void requires(T* ptr, const std::string& message = "Precondition failed") {
        if (ptr == nullptr) {
            throw std::runtime_error(message);
        }
    }

    static void requires(bool condition, const std::string& message = "Precondition failed") {
        if (!condition) {
            throw std::runtime_error(message);
        }
    }

    static void ensures(bool condition, const std::string& message = "Postcondition failed") {
        if (!condition) {
            throw std::runtime_error(message);
        }
    }
};

// 7. Validation Helper Macros
#define VALIDATE_NOT_NULL(ptr) ParameterValidator::notNull(ptr, #ptr)
#define VALIDATE_NOT_EMPTY(str) ParameterValidator::notEmpty(str, #str)
#define VALIDATE_NOT_NEGATIVE(val) ParameterValidator::notNegative(val, #val)
#define VALIDATE_RANGE(val, min, max) ParameterValidator::inRange(val, min, max, #val)
#define VALIDATE_EMAIL(email) FormatValidator::validateEmail(email)
#define VALIDATE_PATH(path) PathValidator::validatePath(path, #path)

// 8. Practical Usage Examples
class UserService {
public:
    struct User {
        std::string username;
        std::string email;
        std::string password;
        int age;
    };

    void createUser(const User& user) {
        std::cout << "\n--- Creating User ---" << std::endl;

        // Validate all fields
        BatchValidator validator;

        validator.validateAll({
            {[&]() { BusinessValidator::validateUsername(user.username); }, "username"},
            {[&]() { FormatValidator::validateEmail(user.email); }, "email"},
            {[&]() { BusinessValidator::validatePassword(user.password); }, "password"},
            {[&]() { BusinessValidator::validateAge(user.age); }, "age"}
        });

        validator.throwIfErrors();

        std::cout << "User validation passed!" << std::endl;
        std::cout << "Username: " << user.username << std::endl;
        std::cout << "Email: " << user.email << std::endl;
        std::cout << "Age: " << user.age << std::endl;
    }
};

class NetworkConfig {
public:
    std::string host;
    int port;
    std::string url;
    int timeout;

    void validate() const {
        Contract::requires(!host.empty(), "Host cannot be empty");
        Contract::requires(port > 0, "Port must be positive");
        BusinessValidator::validatePort(port);
        FormatValidator::validateIPAddress(host);
        ParameterValidator::positive(timeout, "timeout");
    }
};

// 9. Function with Preconditions and Postconditions
std::vector<int> processArray(const std::vector<int>& input, int multiplier) {
    // Preconditions
    VALIDATE_NOT_EMPTY(input);
    VALIDATE_NOT_NEGATIVE(multiplier);

    std::vector<int> result;

    for (int value : input) {
        result.push_back(value * multiplier);
    }

    // Postcondition
    Contract::ensures(result.size() == input.size(), "Output size must match input size");

    return result;
}

// Main demonstration
int main() {
    std::cout << "=== Windows C++ Parameter Validation Examples ===" << std::endl;

    // 1. Basic validation
    std::cout << "\n--- Basic Validation ---" << std::endl;
    try {
        ParameterValidator::notEmpty("test", "myString");
        ParameterValidator::inRange(50, 0, 100, "score");
        ParameterValidator::notNegative(42, "count");
        std::cout << "All validations passed!" << std::endl;
    } catch (const std::exception& e) {
        std::cerr << "Validation error: " << e.what() << std::endl;
    }

    // 2. Format validation
    std::cout << "\n--- Format Validation ---" << std::endl;
    try {
        FormatValidator::validateEmail("[email protected]");
        FormatValidator::validatePhoneNumber("123-456-7890");
        FormatValidator::validateURL("https://example.com");
        FormatValidator::validateIPAddress("192.168.1.1");
        std::cout << "All format validations passed!" << std::endl;
    } catch (const std::exception& e) {
        std::cerr << "Format error: " << e.what() << std::endl;
    }

    // 3. User creation with validation
    std::cout << "\n--- User Creation with Validation ---" << std::endl;
    UserService userService;

    try {
        UserService::User user;
        user.username = "john_doe";
        user.email = "[email protected]";
        user.password = "SecurePass123";
        user.age = 25;

        userService.createUser(user);
    } catch (const std::exception& e) {
        std::cerr << "User creation failed: " << e.what() << std::endl;
    }

    // 4. Contract usage
    std::cout << "\n--- Contract Usage ---" << std::endl;
    try {
        std::vector<int> data = {1, 2, 3, 4, 5};
        std::vector<int> result = processArray(data, 2);
        std::cout << "Array processed successfully" << std::endl;
    } catch (const std::exception& e) {
        std::cerr << "Contract error: " << e.what() << std::endl;
    }

    // 5. Path validation
    std::cout << "\n--- Path Validation ---" << std::endl;
    try {
        PathValidator::validatePath("C:\\Valid\\Path\\file.txt");
        PathValidator::validateFileExtension("document.pdf", {".pdf", ".doc", ".docx"});
        std::cout << "Path validation passed!" << std::endl;
    } catch (const std::exception& e) {
        std::cerr << "Path error: " << e.what() << std::endl;
    }

    std::cout << "\n=== All Parameter Validation Examples Completed ===" << std::endl;
    return 0;
}

💻 Protokollierungssystem cpp

🟡 intermediate ⭐⭐⭐

Umfassendes Protokollierungssystem mit mehreren Protokollebenen, Dateiprotokollierung und Rotation implementieren

⏱️ 30 min 🏷️ cpp, logging, error handling, windows
Prerequisites: Intermediate C++, File I/O
// Windows C++ Logging System Examples

#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <chrono>
#include <iomanip>
#include <vector>
#include <mutex>
#include <windows.h>

// 1. Log Level Enumeration
enum class LogLevel {
    TRACE = 0,
    DEBUG = 1,
    INFO = 2,
    WARNING = 3,
    ERROR = 4,
    CRITICAL = 5,
    OFF = 6
};

std::string logLevelToString(LogLevel level) {
    switch (level) {
        case LogLevel::TRACE: return "TRACE";
        case LogLevel::DEBUG: return "DEBUG";
        case LogLevel::INFO: return "INFO";
        case LogLevel::WARNING: return "WARNING";
        case LogLevel::ERROR: return "ERROR";
        case LogLevel::CRITICAL: return "CRITICAL";
        case LogLevel::OFF: return "OFF";
        default: return "UNKNOWN";
    }
}

// 2. Logger Class
class Logger {
private:
    static Logger* s_instance;
    static std::mutex s_mutex;

    LogLevel m_minLevel;
    std::vector<std::ofstream*> m_fileStreams;
    std::mutex m_logMutex;
    bool m_consoleOutput;
    bool m_includeTimestamp;
    bool m_includeThreadId;

    Logger()
        : m_minLevel(LogLevel::INFO)
        , m_consoleOutput(true)
        , m_includeTimestamp(true)
        , m_includeThreadId(false) {
    }

    std::string getCurrentTimestamp() const {
        auto now = std::chrono::system_clock::now();
        auto time = std::chrono::system_clock::to_time_t(now);

        std::stringstream ss;
        ss << std::put_time(std::localtime(&time), "%Y-%m-%d %H:%M:%S");
        return ss.str();
    }

    DWORD getCurrentThreadId() const {
        return GetCurrentThreadId();
    }

public:
    static Logger& getInstance() {
        std::lock_guard<std::mutex> lock(s_mutex);
        if (s_instance == nullptr) {
            s_instance = new Logger();
        }
        return *s_instance;
    }

    Logger(const Logger&) = delete;
    Logger& operator=(const Logger&) = delete;

    void setMinLevel(LogLevel level) {
        m_minLevel = level;
    }

    void enableConsoleOutput(bool enable) {
        m_consoleOutput = enable;
    }

    void enableTimestamp(bool enable) {
        m_includeTimestamp = enable;
    }

    void enableThreadId(bool enable) {
        m_includeThreadId = enable;
    }

    bool addLogFile(const std::string& filename) {
        std::lock_guard<std::mutex> lock(m_logMutex);

        std::ofstream* file = new std::ofstream(filename, std::ios::app);
        if (!file->is_open()) {
            delete file;
            return false;
        }

        m_fileStreams.push_back(file);
        return true;
    }

    void closeAllLogFiles() {
        std::lock_guard<std::mutex> lock(m_logMutex);

        for (auto* file : m_fileStreams) {
            if (file->is_open()) {
                file->close();
            }
            delete file;
        }

        m_fileStreams.clear();
    }

    void log(LogLevel level, const std::string& message, const char* file = nullptr, int line = 0) {
        if (level < m_minLevel) {
            return;
        }

        std::lock_guard<std::mutex> lock(m_logMutex);

        std::stringstream logEntry;

        // Add timestamp
        if (m_includeTimestamp) {
            logEntry << "[" << getCurrentTimestamp() << "] ";
        }

        // Add log level
        logEntry << "[" << logLevelToString(level) << "] ";

        // Add thread ID
        if (m_includeThreadId) {
            logEntry << "[TID:" << getCurrentThreadId() << "] ";
        }

        // Add message
        logEntry << message;

        // Add file and line if provided
        if (file && line > 0) {
            logEntry << " (" << file << ":" << line << ")";
        }

        logEntry << std::endl;

        std::string logString = logEntry.str();

        // Output to console
        if (m_consoleOutput) {
            // Color code the output
            HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
            if (hConsole != INVALID_HANDLE_VALUE) {
                CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
                GetConsoleScreenBufferInfo(hConsole, &consoleInfo);

                WORD color = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
                switch (level) {
                    case LogLevel::ERROR:
                    case LogLevel::CRITICAL:
                        color = FOREGROUND_RED | FOREGROUND_INTENSITY;
                        break;
                    case LogLevel::WARNING:
                        color = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY;
                        break;
                    case LogLevel::INFO:
                        color = FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY;
                        break;
                    case LogLevel::DEBUG:
                    case LogLevel::TRACE:
                        color = FOREGROUND_INTENSITY;
                        break;
                }

                SetConsoleTextAttribute(hConsole, color);
                std::cout << logString;
                SetConsoleTextAttribute(hConsole, consoleInfo.wAttributes);
            } else {
                std::cout << logString;
            }
        }

        // Output to files
        for (auto* file : m_fileStreams) {
            if (file->is_open()) {
                *file << logString;
                file->flush();
            }
        }
    }

    // Convenience methods
    void trace(const std::string& message, const char* file = nullptr, int line = 0) {
        log(LogLevel::TRACE, message, file, line);
    }

    void debug(const std::string& message, const char* file = nullptr, int line = 0) {
        log(LogLevel::DEBUG, message, file, line);
    }

    void info(const std::string& message, const char* file = nullptr, int line = 0) {
        log(LogLevel::INFO, message, file, line);
    }

    void warning(const std::string& message, const char* file = nullptr, int line = 0) {
        log(LogLevel::WARNING, message, file, line);
    }

    void error(const std::string& message, const char* file = nullptr, int line = 0) {
        log(LogLevel::ERROR, message, file, line);
    }

    void critical(const std::string& message, const char* file = nullptr, int line = 0) {
        log(LogLevel::CRITICAL, message, file, line);
    }
};

Logger* Logger::s_instance = nullptr;
std::mutex Logger::s_mutex;

// 3. Logging Macros
#define LOG_TRACE(msg) Logger::getInstance().trace(msg, __FILE__, __LINE__)
#define LOG_DEBUG(msg) Logger::getInstance().debug(msg, __FILE__, __LINE__)
#define LOG_INFO(msg) Logger::getInstance().info(msg, __FILE__, __LINE__)
#define LOG_WARNING(msg) Logger::getInstance().warning(msg, __FILE__, __LINE__)
#define LOG_ERROR(msg) Logger::getInstance().error(msg, __FILE__, __LINE__)
#define LOG_CRITICAL(msg) Logger::getInstance().critical(msg, __FILE__, __LINE__)

// 4. Scoped Logger (RAII for timing)
class ScopedLogger {
private:
    std::string m_name;
    std::chrono::steady_clock::time_point m_start;

public:
    explicit ScopedLogger(const std::string& name)
        : m_name(name), m_start(std::chrono::steady_clock::now()) {
        LOG_INFO("Entering: " + m_name);
    }

    ~ScopedLogger() {
        auto end = std::chrono::steady_clock::now();
        auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - m_start);

        std::stringstream ss;
        ss << "Exiting: " << m_name << " (took " << duration.count() << "ms)";
        LOG_INFO(ss.str());
    }
};

#define LOG_SCOPE(name) ScopedLogger _logger(name)

// 5. Conditional Logging
class ConditionalLogger {
public:
    static void logIf(bool condition, const std::string& message, LogLevel level = LogLevel::INFO) {
        if (condition) {
            Logger::getInstance().log(level, message);
        }
    }

    static void logOnce(int& flag, const std::string& message, LogLevel level = LogLevel::INFO) {
        if (flag == 0) {
            Logger::getInstance().log(level, message);
            flag = 1;
        }
    }
};

// 6. Performance Logger
class PerformanceLogger {
private:
    std::string m_operation;
    std::chrono::steady_clock::time_point m_start;

public:
    explicit PerformanceLogger(const std::string& operation)
        : m_operation(operation), m_start(std::chrono::steady_clock::now()) {}

    ~PerformanceLogger() {
        auto end = std::chrono::steady_clock::now();
        auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - m_start);

        std::stringstream ss;
        ss << "Performance: " << m_operation << " took " << duration.count() << " microseconds";
        LOG_DEBUG(ss.str());
    }

    void checkpoint(const std::string& checkpointName) {
        auto now = std::chrono::steady_clock::now();
        auto duration = std::chrono::duration_cast<std::chrono::microseconds>(now - m_start);

        std::stringstream ss;
        ss << "Checkpoint [" << checkpointName << "]: " << duration.count() << " microseconds";
        LOG_DEBUG(ss.str());
    }
};

#define LOG_PERFORMANCE(name) PerformanceLogger _perf(name)

// 7. Structured Logging
class StructuredLogger {
public:
    struct LogEntry {
        LogLevel level;
        std::string message;
        std::string category;
        std::map<std::string, std::string> properties;
    };

    static void logStructured(const LogEntry& entry) {
        std::stringstream ss;
        ss << "[" << entry.category << "] " << entry.message;

        if (!entry.properties.empty()) {
            ss << " {";
            bool first = true;
            for (const auto& prop : entry.properties) {
                if (!first) ss << ", ";
                ss << prop.first << "=" << prop.second;
                first = false;
            }
            ss << "}";
        }

        Logger::getInstance().log(entry.level, ss.str());
    }

    static void logEvent(const std::string& eventName, const std::map<std::string, std::string>& data) {
        LogEntry entry;
        entry.level = LogLevel::INFO;
        entry.category = "EVENT";
        entry.message = eventName;
        entry.properties = data;

        logStructured(entry);
    }
};

// 8. Error Logging with Context
class ErrorLogger {
public:
    static void logLastError(const std::string& context) {
        DWORD error = GetLastError();
        if (error == 0) return;

        LPSTR messageBuffer = nullptr;
        FormatMessageA(
            FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
            nullptr,
            error,
            0,
            (LPSTR)&messageBuffer,
            0,
            nullptr
        );

        std::stringstream ss;
        ss << context << " - Error " << error << ": " << messageBuffer;

        Logger::getInstance().error(ss.str());

        LocalFree(messageBuffer);
    }

    static void logException(const std::exception& e, const std::string& context = "") {
        std::stringstream ss;
        if (!context.empty()) {
            ss << context << " - ";
        }
        ss << "Exception: " << e.what();

        Logger::getInstance().error(ss.str());
    }
};

// 9. Log Rotation (Simple)
class LogRotator {
private:
    std::string m_baseFilename;
    size_t m_maxFileSize;
    int m_maxBackupCount;

public:
    LogRotator(const std::string& filename, size_t maxSize = 1024 * 1024, int maxBackups = 5)
        : m_baseFilename(filename), m_maxFileSize(maxSize), m_maxBackupCount(maxBackups) {}

    bool shouldRotate() const {
        std::ifstream file(m_baseFilename, std::ios::ate | std::ios::binary);
        return file.is_open() && file.tellg() > m_maxFileSize;
    }

    void rotate() {
        // Remove oldest backup if it exists
        std::string oldestBackup = m_baseFilename + "." + std::to_string(m_maxBackupCount);
        _unlink(oldestBackup.c_str());

        // Rotate existing backups
        for (int i = m_maxBackupCount - 1; i >= 1; i--) {
            std::string oldName = m_baseFilename + "." + std::to_string(i);
            std::string newName = m_baseFilename + "." + std::to_string(i + 1);

            std::ifstream oldFile(oldName);
            if (oldFile.good()) {
                std::ofstream newFile(newName);
                newFile << oldFile.rdbuf();
            }
        }

        // Rename current log to .1
        std::rename(m_baseFilename.c_str(), (m_baseFilename + ".1").c_str());

        LOG_INFO("Log file rotated");
    }
};

// Main demonstration
int main() {
    std::cout << "=== Windows C++ Logging System Examples ===" << std::endl;

    Logger& logger = Logger::getInstance();

    // Configure logger
    logger.setMinLevel(LogLevel::DEBUG);
    logger.addLogFile("application.log");
    logger.enableConsoleOutput(true);
    logger.enableTimestamp(true);
    logger.enableThreadId(false);

    std::cout << "\n--- Basic Logging ---" << std::endl;
    LOG_TRACE("This is a trace message");
    LOG_DEBUG("This is a debug message");
    LOG_INFO("This is an info message");
    LOG_WARNING("This is a warning message");
    LOG_ERROR("This is an error message");
    LOG_CRITICAL("This is a critical message");

    // 2. Scoped logging
    std::cout << "\n--- Scoped Logging ---" << std::endl;
    {
        LOG_SCOPE("processData");
        // Simulate work
        Sleep(100);
    }

    // 3. Performance logging
    std::cout << "\n--- Performance Logging ---" << std::endl;
    {
        LOG_PERFORMANCE("complexOperation");
        Sleep(150);
    }

    // 4. Structured logging
    std::cout << "\n--- Structured Logging ---" << std::endl;
    std::map<std::string, std::string> eventData = {
        {"userId", "12345"},
        {"action", "login"},
        {"ip", "192.168.1.1"}
    };
    StructuredLogger::logEvent("UserLogin", eventData);

    // 5. Error logging
    std::cout << "\n--- Error Logging ---" << std::endl;
    try {
        throw std::runtime_error("Simulated error");
    } catch (const std::exception& e) {
        ErrorLogger::logException(e, "During operation");
    }

    // 6. Conditional logging
    std::cout << "\n--- Conditional Logging ---" << std::endl;
    bool debugMode = true;
    ConditionalLogger::logIf(debugMode, "Debug mode is enabled", LogLevel::DEBUG);

    static int flag = 0;
    ConditionalLogger::logOnce(flag, "This message will only appear once", LogLevel::INFO);

    // Cleanup
    logger.closeAllLogFiles();

    std::cout << "\n=== All Logging Examples Completed ===" << std::endl;
    return 0;
}