C++ Direct3D Sarmalayıcı [Source Code]

Durum
Üzgünüz bu konu cevaplar için kapatılmıştır...
Banlı Üye
Katılım
10 Eki 2016
Mesajlar
1,402
Çözümler
36
Tepki puanı
631
Yaş
26
9 HİZMET YILI
defines.h yapıp bu kodu yapıştırın :
Kod:
#ifndef __DEFINES_H_INCLUDED__ 
#define __DEFINES_H_INCLUDED__ 

#if defined (_MSC_VER) && (_MSC_VER >= 1020) 
#pragma once 
#endif 

#include <Windows.h> 
#include <fstream> 
#include <iostream> 
#include <list> 
#include <map> 
#include <regex> 
#include <sstream> 
#include <string> 

/** 
 * 
 * Regular expressions used to locate information. 
 * 
 */ 
const std::wregex g_vRegexInterface(L"^DECLARE_INTERFACE_\\(([a-zA-Z0-9]+), IUnknown\\)$"); 
const std::wregex g_vRegexFunctions(L"^[\\s]+?STDMETHOD\\(([a-zA-Z0-9]+)\\)\\((.*)\\) PURE;$|^[\\s]+?STDMETHOD_\\(([a-zA-Z0-9]+)[,\\s]+?([a-zA-Z0-9]+)\\)\\((.*)\\) PURE;$"); 

/** 
 * 
 * Regular expression iterator ends. 
 * 
 */ 
const std::wsregex_iterator            g_vRegexIteratorEnd; 
const std::wsregex_token_iterator    g_vRegexTokenIteratorEnd; 

/** 
 * 
 * Function entry structure. 
 * 
 */ 
typedef struct _FUNCTION_ENTRY { 
    std::wstring Parent; 
    std::wstring RawFunction; 
    std::wstring Return; 
    std::wstring Function; 
    std::wstring RawArguments; 
    std::wstring FixedArguments; 
} functionentry_t; 

/** 
 * 
 * Base interface header template. 
 * 
 */ 
const wchar_t* g_vHeaderTemplate[] = 
{ 
    L"", 
    L"/**", 
    L" * new{INTERFACE}.h - {INTERFACE} Wrapper Header", 
    L" *", 
    L" * This file was generated using d3dxgen!atom0s.cpp", 
    L" * (c) 2011-2013 atom0s [atom0s@live.com]", 
    L" */", 
    L"", 
    L"#pragma once", 
    L"", 
    L"#ifndef __{INTERFACEUPPER}_H_INCLUDED__", 
    L"#define __{INTERFACEUPPER}_H_INCLUDED__", 
    L"", 
    L"#include <Windows.h>", 
    L"#include <d3d9.h>", 
    L"", 
    L"interface new{INTERFACE} : public {INTERFACE}", 
    L"{", 
    L"public:", 
    L"{CLASS_DATA}", 
    L"", 
    L"public:", 
    L"   new{INTERFACE}( {INTERFACE}** ppOrigInterface );", 
    L"   virtual ~new{INTERFACE}( void );", 
    L"", 
    L"private:", 
    L"   {INTERFACE}* m_vOrigInterface;", 
    L"};", 
    L"", 
    L"#endif // __{INTERFACEUPPER}_H_INCLUDED__" 
}; 


/** 
 * 
 * Base interface source template. 
 * 
 */ 
const wchar_t* g_vSourceTemplate[] = 
{ 
    L"", 
    L"/**", 
    L" * new{INTERFACE}.cpp - {INTERFACE} Wrapper Source File", 
    L" *", 
    L" * This file was generated using d3dxgen!atom0s.cpp", 
    L" * (c) 2011-2013 atom0s [atom0s@live.com]", 
    L" */", 
    L"", 
    L"#include \"new{INTERFACE}.h\"", 
    L"", 
    L"new{INTERFACE}::new{INTERFACE}( {INTERFACE}** ppOrigInterface )", 
    L"{", 
    L"    this->m_vOrigInterface = *ppOrigInterface;", 
    L"}", 
    L"new{INTERFACE}::~new{INTERFACE}( void )", 
    L"{", 
    L"}", 
    L"" 
}; 

/** 
 * 
 * Function definition template (header file). 
 * 
 */ 
const std::wstring g_vFunctionTemplate = L"virtual __declspec( nothrow ) {RETURN} __stdcall {FUNCTION}({ARGUMENTS});"; 

/** 
 * 
 * Function definition templates (source file). 
 * 
 */ 
const std::wstring g_vSouceFunctionTemplate = L"{RETURN} new{INTERFACE}::{FUNCTION}( {ARGUMENTS} )"; 
const std::wstring g_vReturnTemplateVoid = L"m_vOrigInterface->{FUNCTION}( {ARGUMENTS_CALL} );"; 
const std::wstring g_vReturnTemplate = L"return " + g_vReturnTemplateVoid; 

/** 
 * Wide String Replace 
 * 
 * Used for easily modifing template strings with tokens. 
 */ 
static inline DWORD WStrRep(std::wstring& wstrInput, const std::wstring& wstrWhat, const std::wstring& wstrWith) 
{ 
    size_t    nPosition = wstrInput.find(wstrWhat, 0); 
    int        nMatches = 0; 

    while (nPosition != std::wstring::npos) 
    { 
        wstrInput.replace(nPosition, wstrWhat.size(), wstrWith); 
        nPosition = wstrInput.find(wstrWhat, nPosition); 
        nMatches++; 
    } 

    return nMatches; 
} 

/** 
 * Converts the input string to lower-case. 
 */ 
static inline std::wstring& WStrLower(std::wstring& wstrInput) 
{ 
    std::transform(wstrInput.begin(), wstrInput.end(), wstrInput.begin(), ::tolower); 
    return wstrInput; 
} 

/** 
 * Converts the input string to upper-case. 
 */ 
static inline std::wstring& WStrUpper(std::wstring& wstrInput) 
{ 
    std::transform(wstrInput.begin(), wstrInput.end(), wstrInput.begin(), ::toupper); 
    return wstrInput; 
} 


/** 
 * Trim  
 * 
 * Removes whitespace from the strings beginning/end. 
 */ 
static inline std::wstring& trim(std::wstring& input) 
{ 
    input.erase(0, input.find_first_not_of(L' ')); 
    input.erase(input.find_last_not_of(L' ') + 1); 
    return input; 
} 

/** 
 * RemoveSpecialChars 
 * 
 * Removes special characters from the input string. 
 */ 
static inline std::wstring& RemoveSpecialChars(std::wstring& input) 
{ 
    std::wstring wstrNewString; 
    static const wchar_t wszInvalidChars[] = { L'*', L'&' }; 

    for (unsigned int x = 0; x < input.size(); x++) 
    { 
        if (input.at(x) != wszInvalidChars[0] && 
            input.at(x) != wszInvalidChars[1]) 
            wstrNewString += input.at(x); 
    } 

    input = wstrNewString; 
    return input; 
} 

/** 
 * BuildFunctionCall 
 * 
 * Builds a function based on the input information given. 
 */ 
static inline std::wstring BuildFunctionCall(functionentry_t& f) 
{ 
    // 
    // Invalid Argument Variables 
    // 
    static const std::wstring wstrInvalidArgument = L"INVALID_ARG"; 
    int nInvalidCount = 0; 

    // 
    // Parse for function arguments.. 
    // 
    std::list< std::wstring > listArguments; 
    std::wstring::size_type start = 0; 
    std::wstring::size_type end = f.RawArguments.find(L","); 
    while (end != std::wstring::npos) 
    { 
        listArguments.push_back(trim(f.RawArguments.substr(start, end - start))); 
        start = end + 1; 
        end = f.RawArguments.find(L",", start); 
    } 
    listArguments.push_back(trim(f.RawArguments.substr(start))); 

    // 
    // Parse for argument variables... 
    // 
    std::list< std::wstring > listFuncArgs; 
    for (std::list< std::wstring >::iterator iter = listArguments.begin(), iterend = listArguments.end(); iter != iterend; ++iter) 
    { 
        // Cleanup argument whitespace.. 
        const std::wstring wstrRawArgument = *iter; 
        std::wstring wstrArgument = trim(std::wstring(*iter)); 

        // Determine space count.. 
        std::wstring::size_type numSpaces = std::count_if(wstrArgument.begin(), wstrArgument.end(), 
            [](const wchar_t wch) { return (wch == L' '); } 
        ); 

        // Determine how many keywords we have (ex. const, class, struct) 
        std::wstring::size_type numKeywords = 0; 
        numKeywords += (WStrLower(wstrArgument).find(L"class ") == -1) ? 0 : 1; 
        numKeywords += (WStrLower(wstrArgument).find(L"const ") == -1) ? 0 : 1; 
        numKeywords += (WStrLower(wstrArgument).find(L"struct ") == -1) ? 0 : 1; 

        // Are we a normal argument with no keywords? 
        if (numSpaces == 1 && numKeywords == 0) 
        { 
            std::wstring wstrArg = wstrRawArgument.substr(wstrRawArgument.find_last_of(L" ") + 1); 
            listFuncArgs.push_back(RemoveSpecialChars(wstrArg)); 
        } 

        // Are we an argument with keywords? 
        else if (numSpaces >= 2 && numKeywords > 0) 
        { 
            std::wstring wstrArg = wstrRawArgument.substr(wstrRawArgument.find_last_of(L" ") + 1); 
            listFuncArgs.push_back(RemoveSpecialChars(wstrArg)); 
        } 

        // Is there a space between an astrisk? 
        else if (numSpaces == 2 && numKeywords == 0) 
        { 
            std::wstring wstrArg = wstrRawArgument.substr(wstrRawArgument.find_last_of(L" ") + 1); 
            listFuncArgs.push_back(RemoveSpecialChars(wstrArg)); 
        } 

        else if ((numSpaces == 1 || numSpaces == 2) && numKeywords > 0) 
        { 
            ++nInvalidCount; 

            // Create a temp argument for this invalid arg. 
            std::wstringstream wstrStreamFuncArg(wstrInvalidArgument, std::ios_base::in | std::ios_base::out | std::ios_base::ate); 
            wstrStreamFuncArg << (nInvalidCount - 1); 
            listFuncArgs.push_back(wstrStreamFuncArg.str()); 

            // Fix the original functions argument list.. 
            std::wstringstream wstrStreamArg(wstrRawArgument, std::ios_base::in | std::ios_base::out | std::ios_base::ate); 
            wstrStreamArg << L" " << wstrInvalidArgument << (nInvalidCount - 1); 
            *iter = wstrStreamArg.str(); 
        } 

        // Are we just the word void? 
        else if (numSpaces == 0 && numKeywords == 0 && wstrArgument.length() == 4 && wstrArgument == L"void") 
        { 
            // Don't push anything or we will create invalid calls.. 
        } 

        // Are we just a single word.. 
        else if (numSpaces == 0 && numKeywords == 0 && wstrArgument.length() > 0) 
        { 
            ++nInvalidCount; 

            // Create a temp argument for this invalid arg. 
            std::wstringstream wstrStreamFuncArg(wstrInvalidArgument, std::ios_base::in | std::ios_base::out | std::ios_base::ate); 
            wstrStreamFuncArg << (nInvalidCount - 1); 
            listFuncArgs.push_back(wstrStreamFuncArg.str()); 

            // Fix the original functions argument list.. 
            std::wstringstream wstrStreamArg(wstrRawArgument, std::ios_base::in | std::ios_base::out | std::ios_base::ate); 
            wstrStreamArg << L" " << wstrInvalidArgument << (nInvalidCount - 1); 
            *iter = wstrStreamArg.str(); 
        } 

        // Completely invalid argument not recognized yet.. 
        else 
        { 
            std::wcout << L"=================================================" << std::endl; 
            std::wcout << L"Could not find a valid argument while parsing: " << f.Function << L", debug info:" << std::endl; 
            std::wcout << L"=================================================" << std::endl; 
            std::wcout << f.RawFunction << std::endl; 
            std::wcout << L"    Argument: " << wstrRawArgument << std::endl; 
            std::wcout << L"    Space count: " << numSpaces << std::endl << L"    Keyword count: " << numKeywords << std::endl; 
            std::wcout << L"    Arguments: " << f.RawArguments << std::endl; 
        } 
    } 

    // 
    // Build the full function with parsed data.. 
    // 
    std::wstringstream wstrFullFunction; 
    wstrFullFunction << f.Return << L" __stdcall new{INTERFACE}::" << f.Function << L"( "; 

    int nCommaCount = listArguments.size() - 1; 
    std::for_each(listArguments.begin(), listArguments.end(), 
        [&](const std::wstring& wstr) 
    { 
        wstrFullFunction << wstr; 
        f.FixedArguments += wstr; 
        if (nCommaCount) 
        { 
            wstrFullFunction << L", "; 
            f.FixedArguments += L", "; 
        } 
        --nCommaCount; 
    }); 
    wstrFullFunction << L" )" << std::endl << L"{" << std::endl; 

    if (f.Return == L"void") 
        wstrFullFunction << L"    m_vOrigInterface->" << f.Function << L"("; 
    else 
        wstrFullFunction << L"    return m_vOrigInterface->" << f.Function << L"( "; 

    nCommaCount = listFuncArgs.size() - 1; 
    std::for_each(listFuncArgs.begin(), listFuncArgs.end(), 
        [&](const std::wstring& wstr) 
    { 
        wstrFullFunction << wstr; 
        if (nCommaCount) 
            wstrFullFunction << L", "; 
        --nCommaCount; 
    }); 
    wstrFullFunction << L" );" << std::endl << L"}" << std::endl; 

    return wstrFullFunction.str(); 
} 

#endif // __DEFINES_H_INCLUDED__  


main.cpp kodu :

Kod:
#include <Windows.h> 
#include "defines.h" 

#include <cmath> 
#include <functional> 
#include <list> 
#include <map> 

int __cdecl main(int argc, wchar_t* argv[]) 
{ 
    // Ensure a target header was given.. 
    if (argc != 2 || strlen((char*)argv[1]) == 0) 
    { 
        std::wcout << L"ERROR: No input file was given!" << std::endl; 
        std::wcout << L"Usage: dxgen.exe [input_file]" << std::endl; 
        return 0; 
    } 

    // Attempt to load target header file.. 
    std::wifstream wifs((char*)argv[1]); 
    if (!wifs.is_open()) 
    { 
        std::wcout << L"ERROR: Failed to open target file, " << (char*)argv[1] << std::endl; 
        return 0; 
    } 

    // Read and close file.. 
    std::wstring wstrFileData((std::istreambuf_iterator< wchar_t >(wifs)), std::istreambuf_iterator< wchar_t >()); 
    wifs.close(); 

    // Scan and dump all interfaces.. 
    std::wcout << std::endl; 
    std::wcout << L"=====================================================" << std::endl; 
    std::wcout << L"Parsing header file for interfaces..." << std::endl; 
    std::wcout << L"=====================================================" << std::endl; 

    std::map< std::wstring, std::wstring > mapInterfaces; 
    for (std::wsregex_iterator iter_interfaces(wstrFileData.begin(), wstrFileData.end(), g_vRegexInterface); iter_interfaces != g_vRegexIteratorEnd; ++iter_interfaces) 
    { 
        // Copy full interface from file contents.. 
        int nStartPos = iter_interfaces->position(); 
        int nBracePos = (wstrFileData.find(L"}", nStartPos)) + 2; 
        std::wstring wstrInterface(wstrFileData.substr(nStartPos, (nBracePos - nStartPos))); 

        // Store this interface.. 
        mapInterfaces[(*iter_interfaces)[1]] = wstrInterface; 
        std::wcout << L"Found interface: " << (*iter_interfaces)[1] << std::endl; 
    } 

    // Assure we found some interfaces.. 
    if (mapInterfaces.size() == 0) 
    { 
        std::wcout << L"ERROR: Failed to parse for any interfaces." << std::endl; 
        return 0; 
    } 

    // Parse each interface for functions.. 
    std::wcout << std::endl; 
    std::wcout << L"=====================================================" << std::endl; 
    std::wcout << L"Parsing interfaces for functions..." << std::endl; 
    std::wcout << L"=====================================================" << std::endl; 

    std::map< std::pair< std::wstring, std::wstring >, std::list< functionentry_t > > mapFunctions; 
    std::for_each(mapInterfaces.begin(), mapInterfaces.end(), 
        [&](const std::pair< std::wstring, std::wstring >& p) 
    { 
        std::wcout << L"Parsing interface: " << p.first << std::endl; 
        std::list< functionentry_t > listFunctions; 

        for (std::wsregex_iterator iter_functions(p.second.begin(), p.second.end(), g_vRegexFunctions); iter_functions != g_vRegexIteratorEnd; ++iter_functions) 
        { 
            int nGroups = std::count_if(iter_functions->begin(), iter_functions->end(), [](const std::wssub_match& smatch) { return (smatch.matched == true); }); 

            // Create function entry.. 
            functionentry_t functionEntry; 
            functionEntry.RawFunction = (*iter_functions)[0].str(); 
            functionEntry.Return = (nGroups == 3) ? L"HRESULT" : (*iter_functions)[3].str(); 
            functionEntry.Function = (nGroups == 3) ? (*iter_functions)[1].str() : (*iter_functions)[4].str(); 
            functionEntry.RawArguments = (nGroups == 3) ? (*iter_functions)[2].str() : (*iter_functions)[5].str(); 

            // Cleanup unneeded macros.. 
            WStrRep(functionEntry.RawArguments, L"THIS_", L""); 
            WStrRep(functionEntry.RawArguments, L"THIS", L"void"); 

            // Cleanup double-spaces.. 
            WStrRep(functionEntry.RawArguments, L"  ", L" "); 

            // Store this function entry.. 
            listFunctions.push_back(functionEntry); 
            std::wcout << L"    Found function: " << functionEntry.Function << std::endl; 
        } 

        // Store functions. 
        mapFunctions[p] = listFunctions; 
    }); 

    // Ensure all maps have functions.. 
    std::wcout << std::endl; 
    std::wcout << L"=====================================================" << std::endl; 
    std::wcout << L"Validating interface function lists..." << std::endl; 
    std::wcout << L"=====================================================" << std::endl; 

    std::map< std::pair< std::wstring, std::wstring >, std::list< functionentry_t > >::iterator iter_func = mapFunctions.begin(); 
    while (iter_func != mapFunctions.end()) 
    { 
        std::wcout << L"Validating interface: " << (*iter_func).first.first << " ... "; 

        if ((*iter_func).second.size() == 0) 
        { 
            std::wcout << L"Invalid! Removing.." << std::endl; 
            mapFunctions.erase(iter_func++); 
        } 
        else 
        { 
            std::wcout << L"Ok!" << std::endl; 
            ++iter_func; 
        } 
    } 

    // Prepare path information.. 
    wchar_t wszCurrentDirectory[MAX_PATH] = { 0 }; 
    GetCurrentDirectory(MAX_PATH, wszCurrentDirectory); 
    std::wstring wstrOutputPath = std::wstring(wszCurrentDirectory) + L"\\includes\\"; 

    if (GetFileAttributes(wstrOutputPath.c_str()) == 0xFFFFFFFF) 
        CreateDirectory(wstrOutputPath.c_str(), NULL); 

    // Create source files for each found interface.. 
    std::wcout << std::endl; 
    std::wcout << L"=====================================================" << std::endl; 
    std::wcout << L"Creating source files for found interfaces..." << std::endl; 
    std::wcout << L"=====================================================" << std::endl; 

    for (auto iter = mapFunctions.begin(), iterend = mapFunctions.end(); iter != iterend; ++iter) 
    { 
        std::wcout << L"Creating source file: " << (*iter).first.first << L".cpp" << std::endl; 

        // Iterate and create each function body.. 
        std::list< std::wstring > listFuncBodies; 
        for (auto fiter = (*iter).second.begin(), fiterend = (*iter).second.end(); fiter != fiterend; ++fiter) 
        { 
            std::wcout << L"    Building function: " << (*fiter).Function << std::endl; 
            std::wstring wstrFunctionBody = BuildFunctionCall(*fiter); 
            WStrRep(wstrFunctionBody, L"{INTERFACE}", (*iter).first.first); 
            listFuncBodies.push_back(wstrFunctionBody); 
        } 

        // Create our output file.. 
        std::wofstream wofs(std::wstring(wstrOutputPath + L"new" + (*iter).first.first + L".cpp"), std::ios_base::binary); 
        if (!wofs.is_open()) 
        { 
            std::wcout << L"Failed to create file: " << (*iter).first.first << L".cpp" << std::endl; 
        } 
        else 
        { 
            std::wstring wstrSourceFile; 
            std::for_each(g_vSourceTemplate, g_vSourceTemplate + (sizeof(g_vSourceTemplate) / sizeof(g_vSourceTemplate[0])), 
                [&](const std::wstring& wstr) 
            { 
                std::wstring wstrLine = wstr; 
                std::wstring wstrLower = (*iter).first.first; 
                std::wstring wstrUpper = (*iter).first.first; 

                std::transform(wstrLower.begin(), wstrLower.end(), wstrLower.begin(), ::tolower); 
                std::transform(wstrUpper.begin(), wstrUpper.end(), wstrUpper.begin(), ::toupper); 

                WStrRep(wstrLine, L"{INTERFACE}", (*iter).first.first); 
                WStrRep(wstrLine, L"{INTERFACELOWER}", wstrLower); 
                WStrRep(wstrLine, L"{INTERFACEUPPER}", wstrUpper); 

                wstrSourceFile += wstrLine + L"\r\n"; 
            }); 

            wofs << wstrSourceFile; 

            std::ostream_iterator< std::wstring, wchar_t > ositer(wofs, L"\r\n"); 
            std::copy(listFuncBodies.begin(), listFuncBodies.end(), 
                std::ostream_iterator< std::wstring, wchar_t >(wofs, L"\r\n") 
                ); 

            wofs.close(); 
        } 
    } 

    // Create header files for each found interface.. 
    std::wcout << std::endl; 
    std::wcout << L"=====================================================" << std::endl; 
    std::wcout << L"Creating header files for found interfaces..." << std::endl; 
    std::wcout << L"=====================================================" << std::endl; 

    std::for_each(mapFunctions.begin(), mapFunctions.end(), 
        [&](const std::pair< std::pair< std::wstring, std::wstring >, std::list< functionentry_t > >& p) 
    { 
        std::wcout << L"Creating header file: " << p.first.first << L".h ... "; 

        std::wofstream wofs(std::wstring(wstrOutputPath + L"new" + p.first.first + L".h"), std::ios_base::binary); 
        if (!wofs.is_open()) 
        { 
            std::wcout << L"Failed!" << std::endl; 
        } 
        else 
        { 
            // Generate header file.. 
            std::wstring wstrHeader; 
            std::for_each(g_vHeaderTemplate, g_vHeaderTemplate + (sizeof(g_vHeaderTemplate) / sizeof(g_vHeaderTemplate[0])), 
                [&](const std::wstring& wstr) 
            { 
                std::wstring wstrLine = wstr; 
                std::wstring wstrLower = p.first.first; 
                std::wstring wstrUpper = p.first.first; 

                std::transform(wstrLower.begin(), wstrLower.end(), wstrLower.begin(), ::tolower); 
                std::transform(wstrUpper.begin(), wstrUpper.end(), wstrUpper.begin(), ::toupper); 

                WStrRep(wstrLine, L"{INTERFACE}", p.first.first); 
                WStrRep(wstrLine, L"{INTERFACELOWER}", wstrLower); 
                WStrRep(wstrLine, L"{INTERFACEUPPER}", wstrUpper); 

                wstrHeader += wstrLine + L"\r\n"; 
            }); 

            // Generate class data.. 
            std::wstring wstrClassData; 
            std::for_each(p.second.begin(), p.second.end(), 
                [&](const functionentry_t& f) 
            { 
                std::wstring wstrReturn = f.Return; 
                std::wstring wstrFunction = f.Function; 
                std::wstring wstrArguments = f.FixedArguments; 

                WStrRep(wstrArguments, L"THIS_", L""); 
                WStrRep(wstrArguments, L"THIS", L""); 
                trim(wstrArguments); 

                if (wstrArguments.size() == 0) 
                    wstrArguments = L"void"; 

                wstrArguments.insert(wstrArguments.cbegin(), L' '); 
                wstrArguments.insert(wstrArguments.cend(), L' '); 

                std::wstring wstrFullFunction = g_vFunctionTemplate; 
                WStrRep(wstrFullFunction, L"{RETURN}", wstrReturn); 
                WStrRep(wstrFullFunction, L"{FUNCTION}", wstrFunction); 
                WStrRep(wstrFullFunction, L"{ARGUMENTS}", wstrArguments); 

                wstrClassData += L"    " + wstrFullFunction + L"\r\n"; 
            }); 

            WStrRep(wstrHeader, L"{CLASS_DATA}", wstrClassData); 

            wofs << wstrHeader; 
            wofs.close(); 

            std::wcout << L"Ok!" << std::endl; 
        } 
    }); 

    std::cin.sync(); 
    std::cin.ignore(); 

    return 0; 
}
 
Durum
Üzgünüz bu konu cevaplar için kapatılmıştır...