C / C ++ Is there any cross-paid way to use relative paths?

I am programming a small game in SDL, and the files are structured as follows:

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

"data /" have game files such as maps, tiles, sprites, etc.

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

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

to convert this line to an absolute path, I have these 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 in this way the program is compiled only in liux, so ... if someone knows another way to do this, I would be grateful.

+4
source share
4 answers

A few points:

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

Also, how can the real way help you open your data? If

 fopen(converted,"r") 

Works in your case then

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

will work too. It is provided to eliminate all symbolic links, etc.

If you need similar functionality for realpath , you can use GetFullPathName on Windows, but it still behaves differently.

+3
source

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

+5
source

Just wrote a tiny class for him:

 #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 print:

 data\sprites\sprite-ghost.bmp data/sprites/sprite-ghost.bmp 
+1
source

My recommendation: first, your main program should take its own file name as an argument, which represents where the data for the program lives, for example,

 C:\program files\mycompany\mygame 

This is responsible for deciding what data to use in any other program (for example, a bash script or driver or something else).

Secondly, define the subcomponents of the directory space with the data in unix format so that all the literals in the file name in your program have this format. No ifs and buts, always Unix. For instance:

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

Now write a function that combines the one passed in the directory name (in native format) with the unix file name translated into the native format to get a suitable file name for access. You have already tried to do this, but use an OS-dependent function. Not. Write it yourself. Do you want to get this:

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

Method @ Industrial-antidepressant (previously blonde blonde stupid blonde) is also not bad, but it is a little more work.

0
source

Source: https://habr.com/ru/post/1333000/


All Articles