0

The code bellow extracts the file name of a file using its path.

#include <iostream>
#include <vector>

using namespace std;

int main() {
    cout << "Program operating..." << endl;

    string s = "C:\\Users\\user\\Pictures\\Strategic_Offense_Logo_1";
    string name;
    for (unsigned int i = s.size() - 1; i > 0; i--) {
        if (s[i] == '\\') {
            for (unsigned int j = i + 1; j < s.size(); j++) {
                if (s[j] == '.' || j == s.size() - 1) {
                    if (j == s.size() - 1)
                        j++;
                    vector<char> v(j - i - 1);
                    unsigned int l = 0;
                    for (unsigned int k = i + 1; k < j; k++) {
                        v[l++] = s[k];
                    }
                    char* vectorAsArray = &v[0];
                    name = vectorAsArray;
                    name.resize(v.size());
                    break;
                }
            }
            break;
        }
    }
    cout << name << endl;
}
#include <iostream>
#include <vector>

using namespace std;

int main() {
    cout << "Program operating..." << endl;

    string s = "C:\\Users\\user\\Pictures\\Strategic_Offense_Logo_1.png";
    string name;
    for (unsigned int i = s.size() - 1; i > 0; i--) {
        if (s[i] == '\\') {
            for (unsigned int j = i + 1; j < s.size(); j++) {
                if (s[j] == '.' || j == s.size() - 1) {
                    if (j == s.size() - 1)
                        j++;
                    vector<char> v(j - i - 1);
                    unsigned int l = 0;
                    for (unsigned int k = i + 1; k < j; k++) {
                        v[l++] = s[k];
                    }
                    char* vectorAsArray = &v[0];
                    name = vectorAsArray;
                    name.resize(v.size());
                    break;
                }
            }
            break;
        }
    }
    cout << name << endl;
}

Is there a more efficient way to do this?

Purpose: I am making a texture class and I want to refer the texture by its name instead of its path or a made up ID.

Note: library does not work at all with the visual studio compiler. If you know how to fix it or have an alternative solution, please post. enter image description here

  • Have you considered using the file system header? It is fully functional in VS2019 and 2022 – ChrisMM Jan 25 '22 at 22:21
  • You must set the langauge setting to use C++17 or later via: Project > Properties > C/C++ > Language > C++ Language Standard > C++17, C++20, or Preview C++ latest – Casey Jan 25 '22 at 22:43

3 Answers3

6

Use std::filesystem::path::filename.

That said, you should refer to the texture by its fully qualified path or a unique ID; otherwise, you will get collisions for textures with the same name in different folders.

Casey
  • 10,297
  • 11
  • 59
  • 88
  • No. This solution does not work because std::filesystem::path::filename is not even recognized by visual studio. Otherwise I would be using it. Also, the reason why I want to refer it by its name instead of by its path is because the header file for filesystem is not found when I try to include it. I looked into many examples online and everything I found on this header does not work. I am not the only one with this problem. – Christopher Barrios Agosto Jan 25 '22 at 22:25
  • What version of visual studio are you using? [You may need to instruct VS to use C++17.](https://stackoverflow.com/questions/41308933/how-to-enable-c17-compiling-in-visual-studio) – user4581301 Jan 25 '22 at 22:28
  • If C++17 really isn't available, [give this a try](https://learn.microsoft.com/en-us/windows/win32/api/shlwapi/nf-shlwapi-pathstrippatha). – user4581301 Jan 25 '22 at 22:29
  • I am using visual studio 2022. Visual Studio 2019 has the same issue. What are you doing different that filesystem works for you but does not work for me? – Christopher Barrios Agosto Jan 25 '22 at 22:31
  • You mentioned something that I answered lots of question. The version of C++. Apparently, Visual Studio defaults to C++ version 14. To be able to access all the features of the filesystem library one has to go into the solution properties and change the C++ version. So dumb. – Christopher Barrios Agosto Jan 25 '22 at 22:38
  • That's it: Project > Properties > Configuration Properties > General > C++ Language Standard > /std::c++17. – rturrado Jan 25 '22 at 23:27
2

The simplest solution is to use the <filesystem> library in C++17 onward, specifically the std::filesystem::path class and its stem() method:

Returns the filename identified by the generic-format path stripped of its extension.

#include <iostream>
#include <filesystem>

namespace fs = std::filesystem;
using namespace std;

int main() {
    cout << "Program operating..." << endl;

    //fs::path p = "C:" / "Users" / "user" / "Pictures" / "Strategic_Offense_Logo_1.png";
    fs::path p = "C:\\Users\\user\\Pictures\\Strategic_Offense_Logo_1.png";
    fs::path name = p.stem();

    cout << name << endl;
}

However, if that is not an option, there is a simple solution using the available methods of std::string, such as rfind() and substr():

#include <iostream>
#include <string>

using namespace std;

int main() {
    cout << "Program operating..." << endl;

    string s = "C:\\Users\\user\\Pictures\\Strategic_Offense_Logo_1.png";

    string name = s.substr(s.rfind('\\') /* or: s.find_last_of("\\/") */ + 1);
    name.resize(name.rfind('.'));

    cout << name << endl;
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
1

Visual Studio defaults to C++14. To be able to access <filesystem> and all of its features (like extracting file names), one has to go into the solution properties under C++ and change the version to the latest. Then, and only then, <filesystem> will work, as everyone in the Internet and StackOverflow talks about.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • Pre C++17 `boost::filesystem` provided something _nearly_ compatible with `std::filesystem` before C++17. In fact, it's `std::filesystem` _is_ what boost proposed, but with a few adjustments, got into `std`. – Ted Lyngmo Jan 26 '22 at 01:04