Извлечь все имена каталогов из текстового файла - PullRequest
0 голосов
/ 02 апреля 2020

У меня есть текстовый файл, в котором имена файлов вместе с именами их подкаталогов могут появляться в любых случайных местах. Например,

input_file.txt

This is a text file. This line has a file name and location Folder1/file1.dat appearing here.

This is another line: Folder2/file2.txt

Here is yet another line with ../Folder3/Folder4/file3.doc filename and location.

Это будет в системе Linux; отсюда косая черта.

Мне нужен код C ++, который может извлечь все имена / местоположения каталогов из этого типа файлов. В приведенном выше примере извлекаемые строки будут иметь вид:

Folder1
Folder2
../Folder3/Folder4

Учитывая приведенный выше формат входного файла, я предполагаю, что алгоритм должен выглядеть примерно так:

  1. Go через каждую строку в файле и посмотреть, есть ли в строке вперед-sla sh (/) где-либо в нем.

  2. Если forward-sla sh находится в строке, извлеките подстроку между последним вхождением forward-sla sh (/) в этой строке и последним пробелом, который появился перед ней.

Я пробовал несколько разных способов, например, приведенных ниже, но, боюсь, просто не могу заставить его работать.

#include <iostream>
#include <string>

int main(int argc, char* argv[])
{
    using std::cout; using std::endl;
    unsigned first, last;

    if(argc < 2)
    {
        cout << "\nPlease give valid file name!"<<endl;
        exit(1);
    }

    std::string para_file_name = argv[1];      //The name of the input file.
    std::ifstream configfile(para_file_name);

    while (getline(configfile, line)) {
       if (line.find(" ")) {
          if (line.find(" ")!=std::string::npos) first = line.find(" ");
          if (line.find("/")!=std::string::npos) last = line.find("/");
          std::string DirName = line.substr (first,last-first);
          cout << " DirName = " << DirName << endl;
       }
    }

Код должен быть совместим с версиями старше C ++ 11 и не может используйте модные внешние библиотеки, такие как Boost. Просто родной C ++, пожалуйста.

Ответы [ 2 ]

1 голос
/ 02 апреля 2020

Не самый лаконичный, но более производительный, чем <regex> и работает с C ++ 98.

#include <cstdlib>  // exit
#include <fstream>  // fstream
#include <iostream> // cout
#include <sstream>  // istringstream
#include <string>   // getline

int main(int argc, char **argv)
{
    if (argc < 2)
    {
        std::cout << "\nPlease give valid file name!\n";
        exit(1);
    }

    // Load the file in
    std::string line;
    std::fstream file(argv[1]);

    // For each line of file...
    while (std::getline(file, line))
    {
        std::istringstream iss(line);
        std::string word;
        char delim = ' ';

        // For each word of line...
        while (std::getline(iss, word, delim))
        {
            size_t pos = word.find_last_of('/');

            // Word includes '/'
            if (pos != std::string::npos)
            {
                std::string dir_name = word.substr(0, pos);

                std::cout << dir_name << "\n";
            }
        }
    }
}

Вывод

Folder1
Folder2
../Folder3/Folder4
1 голос
/ 02 апреля 2020

Может быть, излишним, но вы можете использовать регулярное выражение.

#include <iostream>
#include <regex>
#include <string>

int main() {
  std::cmatch m;
  std::regex_match("This is another line: Folder2/file2.txt", m,
                   std::regex(".*?([^/ ]+/)+.*"));

  std::cout << m.str(1) << std::endl;
  return 0;
}

Выход

Folder2/
...