用C++实现split/startswith/endswith/trim

本文介绍了四个常用的C++字符串操作函数:split用于按分隔符分割字符串;startswith和endswith分别用于判断字符串是否以特定子串开头或结尾;trim用于去除字符串两端的空白字符。
部署运行你感兴趣的模型镜像

一.split函数

1.python演示
这里写图片描述
2.C++函数原型

vector<string> split(const string& srcstr, const string& delimeter = ";");//split the string by delimeter

3.实现思路
用delimeter分割符将字符串srcstr分割开,结果保存到向量中,默认的分割符为”;”。思路是,

(1)find_first_not_of(delimeter)即为开始切割的位置pos_begin
(2)随后find(delimeter),找到第一个分隔符的位置dlm_pos
(3)那么加在dlm_pos和pos_begin中间的字符串为第一个结果,保存在vector中
(4)以此循环,更新pos_begin和dlm_pos,直到pos_begin超出srcstr的范围,即到达string::npos

4.源码展示

//strutils.cpp
vector<string> split(const string& srcstr, const string& delimeter)
{
    vector<string> ret(0);//use ret save the spilted reault
    if(srcstr.empty())    //judge the arguments
    {
        return ret;
    }
    string::size_type pos_begin = srcstr.find_first_not_of(delimeter);//find first element of srcstr

    string::size_type dlm_pos;//the delimeter postion
    string temp;              //use third-party temp to save splited element
    while(pos_begin != string::npos)//if not a next of end, continue spliting
    {
        dlm_pos = srcstr.find(delimeter, pos_begin);//find the delimeter symbol
        if(dlm_pos != string::npos)
        {
            temp = srcstr.substr(pos_begin, dlm_pos - pos_begin);
            pos_begin = dlm_pos + delimeter.length();
        }
        else
        {
            temp = srcstr.substr(pos_begin);
            pos_begin = dlm_pos;
        }
        if(!temp.empty())
            ret.push_back(temp);
    }
    return ret;
}

二.startswith函数

1.python展示
这里写图片描述
2.C++函数原型

bool startswith(const std::string& str, const std::string& start)

3.实现思路

str截取出前len个字符与start比较(len为start字符串的长度)

4.代码展示

//strutils.cpp
bool startswith(const std::string& str, const std::string& start)
{
    int srclen = str.size();
    int startlen = start.size();
    if(srclen >= startlen)
    {
        string temp = str.substr(0, startlen);
        if(temp == start)
            return true;
    }

    return false;
}

三.endswith函数

1.python展示
这里写图片描述
2.C++函数原型

bool endswith(const std::string& str, const std::string& end)

3.实现思路

str截取出最后len个字符与start比较(len为start字符串的长度)

4.代码展示

bool endswith(const std::string& str, const std::string& end)
{
    int srclen = str.size();
    int endlen = end.size();
    if(srclen >= endlen)
    {
        string temp = str.substr(srclen - endlen, endlen);
        if(temp == end)
            return true;
    }

    return false;
}

四.trim函数

1.python演示
这里写图片描述
注:python中strip是trim掉字符串两边的空格。
lstrip, trim掉左边的空格
rstrip, trim掉右边的空格
2.C++函数原型

string trim(const std::string& str)

3.实现思路

查找第一个不是空格或者制表符的位置pos_begin,查找最后一个不是空格和制表符的位置pos_end,那么夹在两者之间的即为trim掉字符串两边空格和\t的新字符串

4.代码展示

string trim(const std::string& str)
{
    string ret;
    //find the first position of not start with space or '\t'
    string::size_type pos_begin = str.find_first_not_of(" \t");
    if(pos_begin == string::npos)
        return str;

    //find the last position of end with space or '\t'
    string::size_type pos_end = str.find_last_not_of(" \t");
    if(pos_end == string::npos)
        return str;

    ret = str.substr(pos_begin, pos_end-pos_begin);

    return ret;
}

您可能感兴趣的与本文相关的镜像

Python3.11

Python3.11

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

不是,而是修改下面的源代码 /****************************************************************************** * SystemC DLL Modifier for VS2015 (C++11) - Ultimate Template API Fix * Completely fixed template class DLL API marker position issue * Enhanced to support .cpp file class definitions and comment formats ******************************************************************************/ #include <iostream> #include <fstream> #include <string> #include <vector> #include <algorithm> #include <set> #include <cctype> #include <windows.h> // VS2015 Check #ifdef _MSC_VER #if _MSC_VER < 1900 #error "This program requires Visual Studio 2015 or later" #endif #endif // Configuration structure struct Config { std::string systemcDllApi = "SYSTEMC_DLL_API"; std::string tlmDllApi = "TLM_DLL_API"; std::string includeConfig = "#include \"config.hpp\""; std::set<std::string> headerExtensions = { ".h", ".hpp", ".hxx" }; std::set<std::string> sourceExtensions = { ".cpp", ".cxx", ".cc" }; std::set<std::string> excludeFiles = { "config.hpp", "Makefile", "CMakeLists.txt" }; std::set<std::string> excludeDirs = { ".git", ".svn", ".vs", "Debug", "Release", "build", "x64", "x86" }; }; // Statistics struct Statistics { int totalFiles = 0; int processedFiles = 0; int modifiedFiles = 0; int skippedFiles = 0; int errorFiles = 0; }; // String Utilities Class class StringUtils { public: static std::string trim(const std::string& str) { if (str.empty()) return str; size_t start = 0; while (start < str.length() && std::isspace(static_cast<unsigned char>(str[start]))) { ++start; } if (start >= str.length()) return ""; size_t end = str.length() - 1; while (end > start && std::isspace(static_cast<unsigned char>(str[end]))) { --end; } return str.substr(start, end - start + 1); } static bool startsWith(const std::string& str, const std::string& prefix) { if (str.length() < prefix.length()) return false; return str.compare(0, prefix.length(), prefix) == 0; } static bool endsWith(const std::string& str, const std::string& suffix) { if (str.length() < suffix.length()) return false; return str.compare(str.length() - suffix.length(), suffix.length(), suffix) == 0; } static bool contains(const std::string& str, const std::string& substr) { if (substr.empty()) return true; if (str.empty()) return false; return str.find(substr) != std::string::npos; } static std::string replace(const std::string& str, const std::string& from, const std::string& to) { if (from.empty() || str.empty()) return str; std::string result = str; size_t pos = 0; while ((pos = result.find(from, pos)) != std::string::npos) { result.replace(pos, from.length(), to); pos += to.length(); } return result; } static std::string toLower(const std::string& str) { std::string result = str; std::transform(result.begin(), result.end(), result.begin(), [](unsigned char c) { return static_cast<char>(std::tolower(c)); }); return result; } static std::string toUpper(const std::string& str) { std::string result = str; std::transform(result.begin(), result.end(), result.begin(), [](unsigned char c) { return static_cast<char>(std::toupper(c)); }); return result; } static std::string getFileName(const std::string& path) { if (path.empty()) return ""; size_t pos = path.find_last_of("\\/"); if (pos == std::string::npos) return path; return path.substr(pos + 1); } static std::string getExtension(const std::string& path) { if (path.empty()) return ""; size_t pos = path.find_last_of("."); if (pos == std::string::npos) return ""; return path.substr(pos); } static std::string getDirectory(const std::string& path) { if (path.empty()) return ""; size_t pos = path.find_last_of("\\/"); if (pos == std::string::npos) return ""; return path.substr(0, pos); } static std::vector<std::string> split(const std::string& str, char delimiter) { std::vector<std::string> tokens; if (str.empty()) return tokens; size_t start = 0; size_t end = 0; while ((end = str.find(delimiter, start)) != std::string::npos) { if (end != start) { tokens.push_back(str.substr(start, end - start)); } start = end + 1; } if (start < str.length()) { tokens.push_back(str.substr(start)); } return tokens; } // Check if line is a comment separator static bool isCommentSeparator(const std::string& str) { std::string trimmed = trim(str); return startsWith(trimmed, "// ---") || startsWith(trimmed, "/* ---") || (contains(trimmed, "---") && (startsWith(trimmed, "//") || startsWith(trimmed, "/*"))); } // Check if line is a class comment header static bool isClassCommentHeader(const std::string& str) { std::string trimmed = trim(str); return (contains(trimmed, "CLASS :") || contains(trimmed, "class")) && (startsWith(trimmed, "//") || startsWith(trimmed, "/*")); } }; // File System Utilities Class class FileSystemUtils { public: static bool fileExists(const std::string& path) { if (path.empty()) return false; DWORD attrs = GetFileAttributesA(path.c_str()); if (attrs == INVALID_FILE_ATTRIBUTES) return false; return (attrs & FILE_ATTRIBUTE_DIRECTORY) == 0; } static bool directoryExists(const std::string& path) { if (path.empty()) return false; DWORD attrs = GetFileAttributesA(path.c_str()); if (attrs == INVALID_FILE_ATTRIBUTES) return false; return (attrs & FILE_ATTRIBUTE_DIRECTORY) != 0; } static bool createDirectory(const std::string& path) { if (path.empty()) return false; if (directoryExists(path)) return true; return CreateDirectoryA(path.c_str(), NULL) != 0; } static bool createDirectoryRecursive(const std::string& path) { if (path.empty()) return false; if (directoryExists(path)) return true; std::string normalizedPath = path; std::replace(normalizedPath.begin(), normalizedPath.end(), '/', '\\'); std::vector<std::string> components = StringUtils::split(normalizedPath, '\\'); if (components.empty()) return false; std::string currentPath; if (components[0].find(':') != std::string::npos) { currentPath = components[0] + "\\"; components.erase(components.begin()); } for (const auto& component : components) { if (component.empty()) continue; if (!currentPath.empty() && currentPath.back() != '\\') { currentPath += "\\"; } currentPath += component; if (!createDirectory(currentPath)) { return false; } } return true; } static bool copyFile(const std::string& from, const std::string& to) { if (from.empty() || to.empty()) return false; if (!fileExists(from)) return false; std::string targetDir = StringUtils::getDirectory(to); if (!targetDir.empty() && !createDirectoryRecursive(targetDir)) { return false; } return ::CopyFileA(from.c_str(), to.c_str(), FALSE) != 0; } static bool findFiles(const std::string& directory, std::vector<std::string>& files, std::vector<std::string>& directories, bool recursive = true) { if (!directoryExists(directory)) return false; std::string searchPath = directory + "\\*"; WIN32_FIND_DATAA findData; HANDLE hFind = FindFirstFileA(searchPath.c_str(), &findData); if (hFind == INVALID_HANDLE_VALUE) { return false; } do { if (strcmp(findData.cFileName, ".") == 0 || strcmp(findData.cFileName, "..") == 0) { continue; } std::string fullPath = directory + "\\" + findData.cFileName; if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { std::string dirName = findData.cFileName; if (isDirectoryExcluded(dirName)) continue; directories.push_back(fullPath); if (recursive) { findFiles(fullPath, files, directories, recursive); } } else { files.push_back(fullPath); } } while (FindNextFileA(hFind, &findData) != 0); FindClose(hFind); return true; } private: static bool isDirectoryExcluded(const std::string& dirName) { static std::set<std::string> excludedDirs = { ".git", ".svn", ".vs", "Debug", "Release", "build", "x64", "x86", "obj", "bin" }; std::string lowerName = StringUtils::toLower(dirName); return excludedDirs.find(lowerName) != excludedDirs.end(); } }; // Main Processor Class - Ultimate Template API Fix class SystemCDLLModifier { private: Config config; Statistics stats; bool dryRun; bool createBackup; std::string backupDir; public: SystemCDLLModifier(bool dryRunMode = false, bool backup = false) : dryRun(dryRunMode), createBackup(backup) {} bool processDirectory(const std::string& sourceDir) { std::cout << "Processing directory: " << sourceDir << std::endl; if (!FileSystemUtils::directoryExists(sourceDir)) { std::cerr << "Error: Directory does not exist: " << sourceDir << std::endl; return false; } // Create backup if (createBackup && !dryRun) { std::cout << "\nCreating backup..." << std::endl; if (!createBackupDirectory(sourceDir)) { std::cout << "Backup creation had issues!" << std::endl; std::cout << "Do you want to continue without backup? (y/n): "; char response; std::cin >> response; if (response != 'y' && response != 'Y') { return false; } } } // Process files std::vector<std::string> files; std::vector<std::string> directories; if (!FileSystemUtils::findFiles(sourceDir, files, directories, true)) { std::cerr << "Failed to enumerate files" << std::endl; return false; } stats.totalFiles = static_cast<int>(files.size()); std::cout << "Found " << stats.totalFiles << " files to process" << std::endl; for (int i = 0; i < stats.totalFiles; ++i) { processFile(files[i]); if ((i + 1) % 10 == 0 || (i + 1) == stats.totalFiles) { int percent = (i + 1) * 100 / stats.totalFiles; std::cout << "Processing: " << (i + 1) << "/" << stats.totalFiles << " files (" << percent << "%)" << std::endl; } } // Generate config.hpp if (!dryRun) { generateConfigFile(sourceDir); } return true; } const Statistics& getStatistics() const { return stats; } const std::string& getBackupDir() const { return backupDir; } private: void processFile(const std::string& filePath) { if (!FileSystemUtils::fileExists(filePath)) { stats.skippedFiles++; return; } std::string filename = StringUtils::getFileName(filePath); std::string ext = StringUtils::getExtension(filePath); // Check excluded files if (config.excludeFiles.find(StringUtils::toLower(filename)) != config.excludeFiles.end()) { stats.skippedFiles++; return; } // Check extension bool isHeader = config.headerExtensions.find(ext) != config.headerExtensions.end(); bool isSource = config.sourceExtensions.find(ext) != config.sourceExtensions.end(); if (!isHeader && !isSource) { stats.skippedFiles++; return; } stats.processedFiles++; if (isHeader) { processHeaderFile(filePath); } else { processSourceFile(filePath); } } void processHeaderFile(const std::string& filePath) { std::vector<std::string> lines; if (!readFile(filePath, lines)) { stats.errorFiles++; return; } bool isSystemcFile = false; bool isTlmFile = false; std::string filename = StringUtils::getFileName(filePath); // Check file type if (filename == "systemc.h" || StringUtils::startsWith(filename, "sc_") || StringUtils::contains(StringUtils::toLower(filename), "vcd") || StringUtils::contains(StringUtils::toLower(filename), "trace")) { isSystemcFile = true; } else if (filename == "tlm.h" || StringUtils::contains(StringUtils::toLower(filename), "tlm")) { isTlmFile = true; } else { // Check content for (const auto& line : lines) { std::string trimmed = StringUtils::trim(line); if (StringUtils::contains(trimmed, "namespace sc_core") || StringUtils::contains(trimmed, "SC_MODULE") || StringUtils::contains(trimmed, "class sc_") || StringUtils::contains(trimmed, "class vcd_") || StringUtils::contains(trimmed, "vcd_trace")) { isSystemcFile = true; break; } else if (StringUtils::contains(trimmed, "namespace tlm") || StringUtils::contains(trimmed, "class tlm_")) { isTlmFile = true; break; } } } if (!isSystemcFile && !isTlmFile) { stats.skippedFiles++; return; } std::string dllApi = isTlmFile ? config.tlmDllApi : config.systemcDllApi; bool modified = false; // Check if config.hpp is already included bool hasConfigInclude = false; for (size_t i = 0; i < lines.size(); ++i) { std::string trimmed = StringUtils::trim(lines[i]); if (StringUtils::contains(trimmed, "#include \"config.hpp\"") || StringUtils::contains(trimmed, "#include <config.hpp>")) { hasConfigInclude = true; break; } } // Add config.hpp include if (!hasConfigInclude) { bool inserted = false; for (size_t i = 0; i < lines.size(); ++i) { std::string trimmed = StringUtils::trim(lines[i]); if (StringUtils::startsWith(trimmed, "#include")) { lines.insert(lines.begin() + i, config.includeConfig); inserted = true; modified = true; break; } } if (!inserted) { lines.insert(lines.begin(), config.includeConfig); modified = true; } } // Process class declarations and templates with enhanced pattern matching for (size_t i = 0; i < lines.size(); ++i) { std::string line = lines[i]; std::string trimmed = StringUtils::trim(line); // Skip preprocessor directives and comments if (StringUtils::startsWith(trimmed, "#") || StringUtils::startsWith(trimmed, "//") || StringUtils::startsWith(trimmed, "/*")) { continue; } // Process regular classes (including those with comment headers) if (isClassDeclarationLine(trimmed)) { if (!StringUtils::contains(trimmed, config.systemcDllApi) && !StringUtils::contains(trimmed, config.tlmDllApi)) { // Check if this class has a comment header above it if (i > 0 && hasCommentHeader(lines, i)) { // Find the start of the comment block size_t commentStart = findCommentBlockStart(lines, i); if (commentStart != std::string::npos && commentStart < i) { // Insert API after the comment block, before the class declaration lines[i] = addAPIToClassDeclaration(trimmed, dllApi); modified = true; } } else { // No comment header, just add API to the class line lines[i] = addAPIToClassDeclaration(trimmed, dllApi); modified = true; } } } // ULTIMATE FIX: Template class API placement with inheritance support if (isTemplateClassDeclaration(trimmed)) { modified = ultimateTemplateFix(lines, i, dllApi, filePath) || modified; } } if (modified) { if (dryRun) { std::cout << "[DRY RUN] Would modify header: " << filePath << std::endl; stats.modifiedFiles++; } else { if (writeFile(filePath, lines)) { std::cout << "Modified header: " << filePath << std::endl; stats.modifiedFiles++; } else { std::cerr << "Failed to write header: " << filePath << std::endl; stats.errorFiles++; } } } } // Check if line is a class declaration bool isClassDeclarationLine(const std::string& line) { std::string trimmed = StringUtils::trim(line); // Match patterns like: // class class_name // class class_name { // class class_name : if (StringUtils::startsWith(trimmed, "class ") && !StringUtils::contains(trimmed, "template")) { // Extract class name part (after "class ") size_t classPos = trimmed.find("class "); size_t afterClass = classPos + 6; if (afterClass >= trimmed.length()) return false; std::string afterClassStr = trimmed.substr(afterClass); StringUtils::trim(afterClassStr); // Check if it's a real class name (not a template parameter) if (afterClassStr.empty()) return false; // Exclude single-letter template parameters if (afterClassStr.length() == 1 && (afterClassStr[0] == 'T' || afterClassStr[0] == 'U' || afterClassStr[0] == 'V' || afterClassStr[0] == 'W')) { return false; } return true; } return false; } // Check if line is a template class declaration bool isTemplateClassDeclaration(const std::string& line) { std::string trimmed = StringUtils::trim(line); // Match patterns like: // template <class T> class class_name // template <typename T> class class_name // template <class T> class class_name : if (StringUtils::startsWith(trimmed, "template") && (StringUtils::contains(trimmed, "class") || StringUtils::contains(trimmed, "typename")) && StringUtils::contains(trimmed, "class ")) { // Check if it's a template parameter declaration (like template<class T>) if (isTemplateParameterDeclaration(trimmed)) { return false; } return true; } return false; } // Check if line is a template parameter declaration bool isTemplateParameterDeclaration(const std::string& line) { std::string trimmed = StringUtils::trim(line); // Template parameter declarations end with > and don't have a second class keyword if (!StringUtils::contains(trimmed, ">")) return false; // Check if it's a simple template parameter like template<class T> size_t templatePos = trimmed.find("template"); size_t angleBracketPos = trimmed.find(">", templatePos); if (angleBracketPos == std::string::npos) return false; // Check if there's content after the > that indicates it's a real class std::string afterAngleBracket = trimmed.substr(angleBracketPos + 1); StringUtils::trim(afterAngleBracket); // If there's no content after >, it's likely a template parameter declaration if (afterAngleBracket.empty()) return true; // If there's content but it doesn't contain "class", it's probably not a class declaration return !StringUtils::contains(afterAngleBracket, "class"); } // Check if class has a comment header above it bool hasCommentHeader(const std::vector<std::string>& lines, size_t currentLine) { if (currentLine == 0) return false; // Check previous lines for comment patterns for (int i = static_cast<int>(currentLine) - 1; i >= 0 && i >= static_cast<int>(currentLine) - 10; --i) { std::string line = lines[i]; std::string trimmed = StringUtils::trim(line); if (trimmed.empty()) continue; // Check for comment separators or class comment headers if (StringUtils::isCommentSeparator(trimmed) || StringUtils::isClassCommentHeader(trimmed)) { return true; } // If we hit a non-comment, non-empty line, stop searching if (!StringUtils::startsWith(trimmed, "//") && !StringUtils::startsWith(trimmed, "/*") && !trimmed.empty()) { break; } } return false; } // Find the start of a comment block before a class declaration size_t findCommentBlockStart(const std::vector<std::string>& lines, size_t currentLine) { if (currentLine == 0) return std::string::npos; for (int i = static_cast<int>(currentLine) - 1; i >= 0; --i) { std::string line = lines[i]; std::string trimmed = StringUtils::trim(line); if (trimmed.empty()) continue; // Look for the start of the comment block (first comment line) if (StringUtils::startsWith(trimmed, "//") || StringUtils::startsWith(trimmed, "/*")) { // Check if this is the first comment in the block if (i == 0 || !StringUtils::startsWith(StringUtils::trim(lines[i - 1]), "//") && !StringUtils::startsWith(StringUtils::trim(lines[i - 1]), "/*")) { return i; } } else { // Non-comment line, stop searching break; } } return std::string::npos; } // Add API to class declaration (handles inheritance) std::string addAPIToClassDeclaration(const std::string& line, const std::string& dllApi) { std::string result = line; // Find "class " position size_t classPos = result.find("class "); if (classPos == std::string::npos) return line; // Position after "class " size_t afterClass = classPos + 6; while (afterClass < result.length() && std::isspace(result[afterClass])) { afterClass++; } if (afterClass >= result.length()) return line; // Insert API after "class " but before the class name result = result.substr(0, afterClass) + dllApi + " " + result.substr(afterClass); return result; } void processSourceFile(const std::string& filePath) { std::vector<std::string> lines; if (!readFile(filePath, lines)) { stats.errorFiles++; return; } bool isSystemcFile = false; bool isTlmFile = false; std::string filename = StringUtils::getFileName(filePath); // Check file type if (StringUtils::startsWith(filename, "sc_") || StringUtils::contains(filename, "tlm") || StringUtils::contains(filename, "vcd") || StringUtils::contains(filename, "trace")) { isSystemcFile = true; } else { // Check content for SystemC/TLM indicators for (const auto& line : lines) { std::string trimmed = StringUtils::trim(line); if (StringUtils::contains(trimmed, "namespace sc_core") || StringUtils::contains(trimmed, "SC_MODULE") || StringUtils::contains(trimmed, "class sc_") || StringUtils::contains(trimmed, "sc_vcd_trace") || StringUtils::contains(trimmed, "vcd_trace") || StringUtils::contains(trimmed, "sc_main")) { isSystemcFile = true; break; } else if (StringUtils::contains(trimmed, "namespace tlm") || StringUtils::contains(trimmed, "class tlm_")) { isTlmFile = true; break; } } } if (!isSystemcFile && !isTlmFile) { stats.skippedFiles++; return; } std::string dllApi = isTlmFile ? config.tlmDllApi : config.systemcDllApi; bool modified = false; // Check if config.hpp is already included bool hasConfigInclude = false; for (size_t i = 0; i < lines.size(); ++i) { std::string trimmed = StringUtils::trim(lines[i]); if (StringUtils::contains(trimmed, "#include \"config.hpp\"") || StringUtils::contains(trimmed, "#include <config.hpp>")) { hasConfigInclude = true; break; } } // Add config.hpp include to source files if (!hasConfigInclude) { bool inserted = false; for (size_t i = 0; i < lines.size(); ++i) { std::string trimmed = StringUtils::trim(lines[i]); if (StringUtils::startsWith(trimmed, "#include")) { lines.insert(lines.begin() + i, config.includeConfig); inserted = true; modified = true; break; } } if (!inserted) { // If no #include found, add at the beginning lines.insert(lines.begin(), config.includeConfig); modified = true; } } // Process class definitions in .cpp files for (size_t i = 0; i < lines.size(); ++i) { std::string line = lines[i]; std::string trimmed = StringUtils::trim(line); // Skip preprocessor directives and comments if (StringUtils::startsWith(trimmed, "#") || StringUtils::startsWith(trimmed, "//") || StringUtils::startsWith(trimmed, "/*")) { continue; } // Process class member function definitions in .cpp files if (isClassMemberFunctionDefinition(trimmed)) { modified = processClassMemberFunction(lines, i, dllApi, filePath) || modified; } // Process template specializations in .cpp files if (isTemplateSpecialization(trimmed)) { modified = processTemplateSpecialization(lines, i, dllApi, filePath) || modified; } // Process static member definitions in .cpp files if (isStaticMemberDefinition(trimmed)) { modified = processStaticMemberDefinition(lines, i, dllApi, filePath) || modified; } } if (modified) { if (dryRun) { std::cout << "[DRY RUN] Would modify source: " << filePath << std::endl; stats.modifiedFiles++; } else { if (writeFile(filePath, lines)) { std::cout << "Modified source: " << filePath << std::endl; stats.modifiedFiles++; } else { std::cerr << "Failed to write source: " << filePath << std::endl; stats.errorFiles++; } } } } // Check if line is a class member function definition bool isClassMemberFunctionDefinition(const std::string& line) { std::string trimmed = StringUtils::trim(line); // Pattern: return_type class_name::function_name if (!StringUtils::contains(trimmed, "::")) return false; if (!StringUtils::contains(trimmed, "(")) return false; if (!StringUtils::contains(trimmed, ")")) return false; if (StringUtils::contains(trimmed, ";")) return false; // Not a declaration // Check if it's a SystemC related class std::vector<std::string> systemcClasses = { "sc_", "tlm_", "vcd_", "wif_", "signal_", "module_", "port_" }; for (const auto& className : systemcClasses) { if (StringUtils::contains(trimmed, className) && StringUtils::contains(trimmed, "::")) { return true; } } return false; } // Process class member function definition bool processClassMemberFunction(std::vector<std::string>& lines, size_t currentLine, const std::string& dllApi, const std::string& filePath) { std::string line = lines[currentLine]; std::string trimmed = StringUtils::trim(line); // Check if already has API if (StringUtils::contains(trimmed, dllApi)) { return false; } // Add API to function definition std::string fixedLine = addAPIToFunctionDefinition(trimmed, dllApi); if (fixedLine != line) { lines[currentLine] = fixedLine; std::cout << "ADDED API to function definition in " << filePath << ":\n"; std::cout << " BEFORE: " << trimmed << "\n"; std::cout << " AFTER: " << fixedLine << std::endl; return true; } return false; } // Check if line is a template specialization bool isTemplateSpecialization(const std::string& line) { std::string trimmed = StringUtils::trim(line); // Pattern: template class ClassName<Args>; if (!StringUtils::contains(trimmed, "template class")) return false; if (!StringUtils::contains(trimmed, ";")) return false; // Check if it's a SystemC related class std::vector<std::string> systemcClasses = { "sc_", "tlm_", "vcd_", "signal_" }; for (const auto& className : systemcClasses) { if (StringUtils::contains(trimmed, className)) { return true; } } return false; } // Process template specialization bool processTemplateSpecialization(std::vector<std::string>& lines, size_t currentLine, const std::string& dllApi, const std::string& filePath) { std::string line = lines[currentLine]; std::string trimmed = StringUtils::trim(line); // Check if already has API if (StringUtils::contains(trimmed, dllApi)) { return false; } // Add API to template specialization std::string fixedLine = addAPIToTemplateSpecialization(trimmed, dllApi); if (fixedLine != line) { lines[currentLine] = fixedLine; std::cout << "ADDED API to template specialization in " << filePath << ":\n"; std::cout << " BEFORE: " << trimmed << "\n"; std::cout << " AFTER: " << fixedLine << std::endl; return true; } return false; } // Check if line is a static member definition bool isStaticMemberDefinition(const std::string& line) { std::string trimmed = StringUtils::trim(line); // Pattern: type class_name::member = value; if (!StringUtils::contains(trimmed, "::")) return false; if (!StringUtils::contains(trimmed, "=")) return false; if (!StringUtils::contains(trimmed, ";")) return false; // Check if it's a SystemC related class std::vector<std::string> systemcClasses = { "sc_", "tlm_", "vcd_", "signal_" }; for (const auto& className : systemcClasses) { if (StringUtils::contains(trimmed, className) && StringUtils::contains(trimmed, "::")) { return true; } } return false; } // Process static member definition bool processStaticMemberDefinition(std::vector<std::string>& lines, size_t currentLine, const std::string& dllApi, const std::string& filePath) { std::string line = lines[currentLine]; std::string trimmed = StringUtils::trim(line); // Check if already has API if (StringUtils::contains(trimmed, dllApi)) { return false; } // Add API to static member definition std::string fixedLine = addAPIToStaticMemberDefinition(trimmed, dllApi); if (fixedLine != line) { lines[currentLine] = fixedLine; std::cout << "ADDED API to static member definition in " << filePath << ":\n"; std::cout << " BEFORE: " << trimmed << "\n"; std::cout << " AFTER: " << fixedLine << std::endl; return true; } return false; } // Add API to function definition std::string addAPIToFunctionDefinition(const std::string& line, const std::string& dllApi) { // Add API at the beginning of function definition return dllApi + " " + line; } // Add API to template specialization std::string addAPIToTemplateSpecialization(const std::string& line, const std::string& dllApi) { // Pattern: template class ClassName<Args>; // Change to: template class SYSTEMC_DLL_API ClassName<Args>; return StringUtils::replace(line, "template class", "template class " + dllApi); } // Add API to static member definition std::string addAPIToStaticMemberDefinition(const std::string& line, const std::string& dllApi) { // Add API at the beginning of static member definition return dllApi + " " + line; } // ULTIMATE FIX: Template class API placement for header files with inheritance support bool ultimateTemplateFix(std::vector<std::string>& lines, size_t currentLine, const std::string& dllApi, const std::string& filePath) { std::string line = lines[currentLine]; std::string trimmed = StringUtils::trim(line); // Debug output std::cout << "DEBUG Processing template: " << trimmed << std::endl; // Basic checks if (!StringUtils::contains(trimmed, "template") || (!StringUtils::contains(trimmed, "class") && !StringUtils::contains(trimmed, "typename"))) { return false; } // Skip if already has API if (StringUtils::contains(trimmed, dllApi)) { std::cout << "DEBUG: Already has API, skipping" << std::endl; return false; } // Check if this is a template parameter declaration (like template<class T>) if (isTemplateParameterDeclaration(trimmed)) { std::cout << "DEBUG: Skipping template parameter declaration" << std::endl; return false; } // For all other cases, add API std::string fixedLine = addAPIToTemplateClass(trimmed, dllApi); if (fixedLine != line) { lines[currentLine] = fixedLine; std::cout << "SUCCESS: Added API to template in " << filePath << ":\n"; std::cout << " BEFORE: " << trimmed << "\n"; std::cout << " AFTER: " << fixedLine << std::endl; return true; } return false; } // Add API to template class (handles inheritance) std::string addAPIToTemplateClass(const std::string& line, const std::string& dllApi) { std::string result = line; // Find the class keyword after template size_t templatePos = result.find("template"); if (templatePos == std::string::npos) return line; // Find the second "class" keyword (the actual class declaration) size_t firstClassPos = result.find("class", templatePos); if (firstClassPos == std::string::npos) { firstClassPos = result.find("typename", templatePos); if (firstClassPos == std::string::npos) return line; } // Find the actual class declaration (second "class" keyword) size_t secondClassPos = result.find("class", firstClassPos + 5); if (secondClassPos == std::string::npos) { // If no second class, it might be a template alias or other construct return line; } // Position after second "class" size_t afterClass = secondClassPos + 5; while (afterClass < result.length() && std::isspace(result[afterClass])) { afterClass++; } if (afterClass >= result.length()) return line; // Insert API after the second "class" keyword result = result.substr(0, afterClass) + dllApi + " " + result.substr(afterClass); return result; } void generateConfigFile(const std::string& outputDir) { std::string configPath = outputDir + "\\config.hpp"; if (FileSystemUtils::fileExists(configPath)) { std::cout << "config.hpp already exists, skipping generation" << std::endl; return; } std::string content = "#ifndef __CONFIG_HPP__\r\n" "#define __CONFIG_HPP__\r\n" "\r\n" "#undef SYSTEMC_DLL_API\r\n" "#undef TLM_DLL_API\r\n" "\r\n" "// C++11 Configuration for VS2015\r\n" "#if defined(_MSC_VER) && (_MSC_VER < 1900)\r\n" " #error \"Visual Studio 2015 (VC++ 14.0) or later is required for C++11 support\"\r\n" "#endif\r\n" "\r\n" "// DLL Configuration\r\n" "#define SYSTEMC_DLL // Enable DLL support\r\n" "#define SYSTEMC_DLL_EXPORT // Define this to export DLL symbols\r\n" "\r\n" "#if defined(_WIN32) || defined(WIN32) || defined(WINDOWS) || defined(_WINDOWS)\r\n" " #ifdef SYSTEMC_DLL\r\n" " #ifdef SYSTEMC_DLL_EXPORT\r\n" " #define SYSTEMC_DLL_API __declspec(dllexport)\r\n" " #else\r\n" " #define SYSTEMC_DLL_API __declspec(dllimport)\r\n" " #endif\r\n" "\r\n" " // Disable VS2015 warnings for DLL exports\r\n" " #ifdef _MSC_VER\r\n" " #pragma warning(push)\r\n" " #pragma warning(disable: 4251) // class needs dll-interface\r\n" " #pragma warning(disable: 4275) // non dll-interface base class\r\n" " #endif\r\n" "\r\n" " #else\r\n" " #define SYSTEMC_DLL_API\r\n" " #endif\r\n" "#else\r\n" " #define SYSTEMC_DLL_API\r\n" "#endif\r\n" "\r\n" "// TLM DLL API definition\r\n" "#define TLM_DLL_API SYSTEMC_DLL_API\r\n" "\r\n" "// C++11 standard library includes\r\n" "#include <cstdint>\r\n" "#include <memory>\r\n" "#include <string>\r\n" "#include <vector>\r\n" "\r\n" "#endif // __CONFIG_HPP__\r\n"; std::ofstream file(configPath, std::ios::binary); if (file.is_open()) { file.write(content.c_str(), content.length()); file.close(); std::cout << "Generated config.hpp at: " << configPath << std::endl; } else { std::cerr << "Failed to generate config.hpp" << std::endl; } } bool readFile(const std::string& filePath, std::vector<std::string>& lines) { std::ifstream file(filePath, std::ios::binary); if (!file.is_open()) { std::cerr << "Cannot open file for reading: " << filePath << std::endl; return false; } lines.clear(); std::string line; while (std::getline(file, line)) { // Handle Windows line endings if (!line.empty() && line.back() == '\r') { line.pop_back(); } lines.push_back(line); } if (file.bad()) { std::cerr << "Error reading file: " << filePath << std::endl; file.close(); return false; } file.close(); return true; } bool writeFile(const std::string& filePath, const std::vector<std::string>& lines) { std::ofstream file(filePath, std::ios::binary); if (!file.is_open()) { std::cerr << "Cannot open file for writing: " << filePath << std::endl; return false; } for (const auto& line : lines) { file << line << "\r\n"; } if (file.bad()) { std::cerr << "Error writing file: " << filePath << std::endl; file.close(); return false; } file.close(); return true; } bool createBackupDirectory(const std::string& sourceDir) { if (!FileSystemUtils::directoryExists(sourceDir)) { std::cerr << "Source directory does not exist: " << sourceDir << std::endl; return false; } // Generate timestamped backup directory name SYSTEMTIME st; GetLocalTime(&st); char timeBuffer[256]; sprintf_s(timeBuffer, "SystemC_Backup_%04d%02d%02d_%02d%02d%02d", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond); backupDir = timeBuffer; std::cout << "Creating backup: " << backupDir << std::endl; // Create backup directory if (!FileSystemUtils::createDirectoryRecursive(backupDir)) { std::cerr << "Failed to create backup directory: " << backupDir << std::endl; return false; } // Copy files std::vector<std::string> files; std::vector<std::string> directories; if (!FileSystemUtils::findFiles(sourceDir, files, directories, true)) { std::cerr << "Failed to enumerate files for backup" << std::endl; return false; } int copiedFiles = 0; int failedFiles = 0; int totalFiles = static_cast<int>(files.size()); std::cout << "Found " << totalFiles << " files to backup" << std::endl; for (int i = 0; i < totalFiles; ++i) { const auto& file = files[i]; // Calculate relative path std::string relativePath = getRelativePath(sourceDir, file); if (relativePath.empty()) { failedFiles++; continue; } std::string targetPath = backupDir + "\\" + relativePath; if (FileSystemUtils::copyFile(file, targetPath)) { copiedFiles++; } else { failedFiles++; std::cerr << "Failed to copy: " << file << std::endl; } // Show progress if ((i + 1) % 100 == 0 || (i + 1) == totalFiles) { int percent = (i + 1) * 100 / totalFiles; std::cout << "Backup progress: " << (i + 1) << "/" << totalFiles << " files (" << percent << "%)" << std::endl; } } std::cout << "\nBackup completed:" << std::endl; std::cout << " Successfully copied: " << copiedFiles << " files" << std::endl; std::cout << " Failed: " << failedFiles << " files" << std::endl; std::cout << " Backup location: " << backupDir << std::endl; if (failedFiles > 0) { std::cout << "WARNING: " << failedFiles << " files failed to backup!" << std::endl; } return failedFiles == 0; } std::string getRelativePath(const std::string& baseDir, const std::string& fullPath) { if (fullPath.find(baseDir) != 0) { return fullPath; } std::string relative = fullPath.substr(baseDir.length()); // Remove leading path separators while (!relative.empty() && (relative[0] == '\\' || relative[0] == '/')) { relative = relative.substr(1); } return relative; } }; // Help information void printHelp() { std::cout << R"( ======================================================================== SystemC DLL Modifier for VS2015 (C++11) - Ultimate Template API Fix ================================================================ ENHANCED VERSION: Now supports .cpp file class definitions and comment headers! ULTIMATE FIX: - Completely fixed template class DLL API placement error - Now supports .cpp file class definitions - Handles comment headers above class declarations - Supports template class inheritance patterns ================================================================ Usage: systemc_modifier_ultimate.exe <SystemC_directory> [options] Options: /dryrun Dry run mode (test without modifying files) /backup Create backup directory before modifications /help Display this help information /force Force processing even if backup fails Examples: systemc_modifier_ultimate.exe C:\systemc-2.3.1a systemc_modifier_ultimate.exe C:\systemc-2.3.1a /dryrun systemc_modifier_ultimate.exe C:\systemc-2.3.1a /backup systemc_modifier_ultimate.exe /help NEW FEATURES: 1. Support for .cpp file class member function definitions 2. Support for template specializations in .cpp files 3. Support for static member definitions in .cpp files 4. Enhanced pattern matching for comment headers 5. Improved template class API placement Supported Patterns in .cpp files: Pattern 1: Class member function definitions void sc_vcd_trace::write_comment(const std::string& comment) { // implementation } Pattern 2: Template specializations template class vcd_T_trace<bool>; template class vcd_T_trace<sc_dt::sc_logic>; Pattern 3: Static member definitions int sc_vcd_trace::instance_count = 0; Fixed Output for .cpp files: SYSTEMC_DLL_API void sc_vcd_trace::write_comment(const std::string& comment) { // implementation } template class SYSTEMC_DLL_API vcd_T_trace<bool>; template class SYSTEMC_DLL_API vcd_T_trace<sc_dt::sc_logic>; SYSTEMC_DLL_API int sc_vcd_trace::instance_count = 0; Supported Patterns in .h files: Pattern 1: Comment headers // ---------------------------------------------------------------------------- // CLASS : vcd_trace // // Base class for VCD traces. // ---------------------------------------------------------------------------- class vcd_trace { Pattern 2: Template class inheritance template <class T> class vcd_T_trace : public vcd_trace { Fixed Output for .h files: // ---------------------------------------------------------------------------- // CLASS : vcd_trace // // Base class for VCD traces. // ---------------------------------------------------------------------------- class SYSTEMC_DLL_API vcd_trace { template <class T> class SYSTEMC_DLL_API vcd_T_trace : public vcd_trace { Enhanced Features: 1. Automatically add #include "config.hpp" to SystemC headers AND source files 2. Add SYSTEMC_DLL_API or TLM_DLL_API export macros to classes 3. Generate config.hpp configuration file 4. Create timestamped backup directories 5. Process .h and .cpp files recursively 6. Skip build directories and version control directories 7. Retry mechanism for file operations 8. Detailed progress reporting 9. ULTIMATE template API placement fix 10. .cpp file class definition support 11. Comment header support 12. Template inheritance support Important Notes: 1. Always backup your important code before making modifications! 2. Test with /dryrun first to see what will be modified 3. The program will ask for confirmation if backup fails 4. Generated config.hpp includes proper warning suppression 5. Run as Administrator for system-protected directories ================================================================ )" << std::endl; } // Print statistics void printStatistics(const Statistics& stats, bool dryRun, const std::string& backupDir) { std::cout << "\n" << std::string(60, '=') << "\n"; std::cout << "PROCESSING COMPLETED\n"; std::cout << std::string(60, '=') << "\n"; std::cout << "Total files: " << stats.totalFiles << "\n"; std::cout << "Processed files: " << stats.processedFiles << "\n"; std::cout << "Modified files: " << stats.modifiedFiles << "\n"; std::cout << "Skipped files: " << stats.skippedFiles << "\n"; std::cout << "Error files: " << stats.errorFiles << "\n"; if (!backupDir.empty()) { std::cout << "\nBackup created: " << backupDir << "\n"; } if (dryRun) { std::cout << "\nMODE: DRY RUN - No files were actually modified\n"; std::cout << "To actually modify files, run without /dryrun option\n"; } std::cout << std::string(60, '=') << "\n"; } // Main function int main(int argc, char* argv[]) { std::cout << "========================================================================\n"; std::cout << " SystemC DLL Modifier for VS2015 (C++11) - Ultimate Template API Fix\n"; std::cout << " ================================================================\n"; std::cout << " Enhanced Version: Now supports .cpp file class definitions!\n"; std::cout << " Completely fixed template class DLL API position error\n"; std::cout << "========================================================================\n\n"; if (argc < 2) { printHelp(); return 1; } std::string sourceDir = argv[1]; bool dryRun = false; bool createBackup = false; bool forceMode = false; // Parse command line arguments for (int i = 2; i < argc; ++i) { std::string arg = argv[i]; std::string lowerArg = arg; std::transform(lowerArg.begin(), lowerArg.end(), lowerArg.begin(), ::tolower); if (lowerArg == "/dryrun" || lowerArg == "-dryrun" || lowerArg == "/d") { dryRun = true; } else if (lowerArg == "/backup" || lowerArg == "-backup" || lowerArg == "/b") { createBackup = true; } else if (lowerArg == "/help" || lowerArg == "-help" || lowerArg == "/h" || lowerArg == "/?") { printHelp(); return 0; } else if (lowerArg == "/force" || lowerArg == "-force" || lowerArg == "/f") { forceMode = true; } else { std::cout << "Unknown option: " << arg << "\n"; std::cout << "Use /help for usage information\n"; return 1; } } // Display mode information std::cout << "Mode: " << (dryRun ? "Dry Run (no modifications)" : createBackup ? "Normal with Backup" : "Normal") << "\n"; std::cout << "Target: " << sourceDir << "\n"; std::cout << "Force mode: " << (forceMode ? "Yes" : "No") << "\n"; std::cout << "C++ Standard: C++11\n"; std::cout << "Compiler: Visual Studio 2015\n"; std::cout << "Fix: Ultimate template API placement fix\n"; std::cout << "Enhanced: .cpp file class definition support\n"; std::cout << std::string(60, '-') << "\n\n"; // Create processor SystemCDLLModifier modifier(dryRun, createBackup); try { if (modifier.processDirectory(sourceDir)) { Statistics stats = modifier.getStatistics(); std::string backupDir = modifier.getBackupDir(); printStatistics(stats, dryRun, backupDir); std::cout << "\nNEXT STEPS:\n"; std::cout << "1. Review modified files for any issues\n"; std::cout << "2. Create a new DLL project in Visual Studio 2015\n"; std::cout << "3. Add SYSTEMC_DLL_EXPORT to preprocessor definitions\n"; std::cout << "4. Add all SystemC source files to the project\n"; std::cout << "5. Build the systemc.dll\n"; std::cout << "6. Test with your SystemC applications\n"; if (!dryRun && backupDir.empty() && createBackup) { std::cout << "\nWARNING: Backup was not created!\n"; std::cout << "Consider creating a manual backup before proceeding.\n"; } std::cout << "\nProcessing completed " << (dryRun ? "in dry run mode" : "successfully") << "!\n"; } else { std::cout << "\nERROR: Processing failed!\n"; std::cout << "Possible reasons:\n"; std::cout << "1. Invalid SystemC directory\n"; std::cout << "2. Permission issues\n"; std::cout << "3. Disk space problems\n"; std::cout << "4. File system errors\n"; return 1; } } catch (const std::exception& e) { std::cerr << "\nFATAL ERROR: " << e.what() << "\n"; std::cerr << "Please check:\n"; std::cerr << "1. Directory permissions\n"; std::cerr << "2. Disk space\n"; std::cerr << "3. File system integrity\n"; return 1; } return 0; }
最新发布
01-02
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值