You can use boost::filesystem. However, this is not a header only library and you may have requirements not to link with external libraries or it may be very inconvenient to do so.
On Windows (which looks like you are) I like to use this class to get all the filenames matching given pattern.
#pragma once
#include <string>
#include <vector>
#include <windows.h>
#pragma comment(lib, "User32.lib")
#undef tstring
#undef tcout
#if defined(_UNICODE) || defined(UNICODE)
#define tstring std::wstring
#define tcout std::wcout
#else
#define tstring std::string
#define tcout std::cout
#endif
class FileFinder {
  WIN32_FIND_DATA ffd;
  HANDLE _handle;
public:
  FileFinder(LPCTSTR pattern) { _handle = FindFirstFile(pattern, &ffd); }
  ~FileFinder() { FindClose(_handle); }
  const TCHAR *FindFirst() const {
    return _handle != INVALID_HANDLE_VALUE ? ffd.cFileName : nullptr;
  }
  const TCHAR *FindNext() {
    return FindNextFile(_handle, &ffd) ? ffd.cFileName : nullptr;
  }
  std::vector<tstring> GetAllNames() {
    std::vector<tstring> result;
    for (auto name = FindFirst(); name; name = FindNext())
      result.push_back(name);
    return result;
  }
};
It follows RAII paradigm and will not leak resources due to an exception.
Example of it's usage could be like this.
#include <tchar.h>
#include <iostream>
#include "FileFinder.h"
int _tmain(int argc, TCHAR *argv[]) {
  DWORD dwError = 0;
  if (argc != 2) {
    _tprintf(TEXT("\nUsage: %s <directory name>\n"), argv[0]);
    return -1;
  }
  tstring pattern(argv[1]);
  pattern.erase(pattern.find_last_not_of(TEXT("\\")) + 1);
  pattern += TEXT("\\*.pgm");
  if (pattern.length() > MAX_PATH) {
    _tprintf(TEXT("\nDirectory path is too long.\n"));
    return -1;
  }
  FileFinder finder(pattern.c_str());
  auto files = finder.GetAllNames();
  for (const auto &f : files)
    tcout << f << std::endl;
  return 0;
}