C/C++有没有使用相对路径的跨平台方式?

发布于 2024-10-08 20:55:07 字数 499 浏览 3 评论 0原文

我正在用 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 下编译,所以...如果有人知道另一种方法,我将不胜感激。

I'm programming a little game in SDL and the files are structured like this:

"src/game/" have both .h and .cpp source files.

"data/" have the game files like maps, tilesets, sprites and so on...

to load a sprite for example I would use the following code.

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

to convert this string to an absolute path I have those lines in the first 4 lines of the function:

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

But this way the program only compiles under liux so... if anyone knows another way to do that I would be grateful.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

dawn曙光 2024-10-15 20:55:07

提升是你的朋友。以下是 Boost 文件系统 教程的链接。

Boost is your friend. Here's a link to the Boost Filesystem tutorial.

我乃一代侩神 2024-10-15 20:55:07

几点:

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

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

fopen(converted,"r")

适用于您的情况,那么

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

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

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

Few points:

char converted[128];
realpath(file.c_str(),converted);
  1. First of all realpath on some operating systems (Solaris) may still return the relative path.
  2. Your code contains buffer overflow, it is better to use canonicalize_file_name or char *m=realpath(file.c_str(),0); ... free(m); - however this is Linux specific. See man realpath to see how to use it more or less correctly.

Also how would realpath help you to open your data? If

fopen(converted,"r")

Works in your case then

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

would work as well. It is provided to help removing all symbolic links, etc.

If you need some similar functionality to realpath, you may use GetFullPathName under Windows, but
it still behaves differently.

街角卖回忆 2024-10-15 20:55:07

刚刚为其编写了一个小类:

#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

Just wrote a tiny class for it:

#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;
}

will prints:

data\sprites\sprite-ghost.bmp
data/sprites/sprite-ghost.bmp
〗斷ホ乔殘χμё〖 2024-10-15 20:55:07

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

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

@Induscial-antidepressant(以前是@nice金发蠢女孩)的方法也很好,但是需要更多的工作。

My recommendation is: first, your main program should accept a native filename as an argument that represents where the data for the program live eg

C:\program files\mycompany\mygame

This passes the responsibility of deciding which data to use off to some other program (such as a bash script or driver or whatever).

Second, define the subparts of the directory space with the data in unix format so all filename literals in your program have this format. No ifs and buts, always Unix. Eg:

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

Now write a function which combines the passed in directory name (in native format) with the unix filename translated to native format to get a suitable filename for access. You have already tried to do this but you're using an OS dependent function. Don't. Write it yourself. You want to get this out:

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

The method of @Industrial-antidepressant (previously @nice blonde stupid girl) is quite good too, but it's a bit more work.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文