【问题标题】:C/C++ Is there any cross plataform way of using relative paths?C/C++ 有没有使用相对路径的跨平台方式?
【发布时间】:2011-05-29 05:28:00
【问题描述】:

我正在用 SDL 编写一个小游戏,文件的结构如下:

“src/game/”同时拥有 .h 和 .cpp 源文件。

"data/" 包含游戏文件,如地图、图块集、精灵等...

以加载精灵为例,我将使用以下代码。

spriteLib.loadSprite("data/sprites/sprite-ghost.bmp");

要将此字符串转换为绝对路径,我在函数的前 4 行中有这些行:

SSprite CSpriteLib::loadSprite(std::string file)
{
    //Converting the file path
    char converted[128];
    realpath(file.c_str(),converted);
    file = converted;

但是这种方式程序只能在 liux 下编译,所以......如果有人知道另一种方法,我将不胜感激。

【问题讨论】:

    标签: c++ cross-platform sdl relative-path


    【解决方案1】:

    Boost 是您的朋友。这是Boost Filesystem 教程的链接。

    【讨论】:

    • 哇,答案很快,我得稍后测试一下,因为现在是凌晨 3:30。
    【解决方案2】:

    几点:

    char converted[128];
    realpath(file.c_str(),converted);
    
    1. 首先,某些操作系统 (Solaris) 上的 realpath 可能仍会返回相对路径。
    2. 您的代码包含缓冲区溢出,最好使用canonicalize_file_name 或char *m=realpath(file.c_str(),0); ... free(m); - 但这是特定于Linux 的。请参阅 man realpath 了解如何或多或少地正确使用它。

    另外,realpath 将如何帮助您打开数据?如果

    fopen(converted,"r")
    

    然后在你的情况下工作

    fopen(file.c_str(),"r")
    

    也可以。提供它是为了帮助删除所有符号链接等。

    如果你需要一些与realpath类似的功能,你可以在Windows下使用GetFullPathName,但是 它的行为仍然不同。

    【讨论】:

    • 我不知道 fopen 会使用相对路径,谢谢你的提示,但是 IMG_Load() 和 SDL_LoadBMP() 怎么样,它们只适用于绝对路径?
    【解决方案3】:

    刚刚为它写了一个小类:

    #include <string>
    #include <vector>
    #include <iostream>
    
    class CFilePath
    {
            typedef std::vector<std::string> TPath;
        public:
            enum EPlatform
            {  
                Windows,
                Unix
            };
            CFilePath(EPlatform p_platform) : m_platform(p_platform) {}
            CFilePath& operator/(const char* p_path)
            {  
                m_path.push_back(p_path);
                return *this;
            }
    
            std::string GetPath()
            {  
                std::string ret;
                if (m_path.empty())
                    return ret;
                for (unsigned i = 0; i < m_path.size();)
                {
                    ret+=m_path[i];
                    i++;
                    if (i < m_path.size())
                    {  
                        switch (m_platform)
                        {  
                            case Windows:
                                ret+="\\";
                                break;
                            case Unix:
                                ret+="/";
                                break;
                        }
                    }
                }
                return ret;
            }
            operator const char*()
            {
                return GetPath().c_str();
            }
            EPlatform m_platform;
    
        private:
            std::vector<std::string> m_path;
    };
    
    int main(int argc, char* argv[])
    {
        CFilePath::EPlatform platform = CFilePath::Windows; // variable
        CFilePath path(platform);
        path/"data"/"sprites"/"sprite-ghost.bmp";
        std::cout << path << std::endl;
        path.m_platform = CFilePath::Unix;
        std::cout << path << std::endl;
    
        return 0;
    }
    

    将打印:

    data\sprites\sprite-ghost.bmp
    data/sprites/sprite-ghost.bmp
    

    【讨论】:

      【解决方案4】:

      我的建议是:首先,您的主程序应该接受本机文件名作为参数,表示程序的数据所在的位置,例如

      C:\program files\mycompany\mygame
      

      这会将决定使用哪些数据的职责转交给其他程序(例如 bash 脚本或驱动程序等)。

      其次,使用 unix 格式的数据定义目录空间的子部分,以便程序中的所有文件名文字都具有这种格式。没有如果和但是,总是 Unix。例如:

      spriteLib.loadSprite("data/sprites/sprite-ghost.bmp");
      

      现在编写一个函数,它将传入的目录名称(以本机格式)与转换为本机格式的 unix 文件名相结合,以获得适合访问的文件名。您已经尝试过这样做,但您正在使用依赖于操作系统的函数。别。自己写吧。你想把它弄出来:

      C:\program files\mycompany\mygame\data\sprites\sprite-ghost.bmp
      

      @Industrial-antidepressant(以前是@nice 金发傻姑娘)的方法也不错,但工作量有点大。

      【讨论】:

        猜你喜欢
        • 2011-03-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-03-12
        • 1970-01-01
        • 2011-10-05
        相关资源
        最近更新 更多