C++. Сборник рецептов - Д. Стефенс
Шрифт:
Интервал:
Закладка:
directory_iterator end;
Затем вы можете создать итератор для вашего пути и следующим образом сравнивать его с маркером конца.
for (directory_iterator it(fullPath); it != end; ++it) {
// выполнить любые действия с *it
std::cout << it->leaf();
}
Функция-член leaf возвращает строку, представляющую конечный элемент пути, а не весь путь, который вы можете получить, вызывая функцию-член string.
Если вам требуется обеспечить переносимость, но по каким-то причинам вы не можете использовать библиотеки Boost, обратите внимание на исходный код Boost. Он содержит операторы #ifdef, которые учитывают (по большей части) отличия среды Windows и ОС, использующих интерфейс Posix, и в частности отличия в представлении путей, например буквы дисководов и имена устройств.
Смотри такжеРецепты 10.10 и 10.11.
10.13. Извлечение расширения файла из строки
ПроблемаИмеется имя файла или полный путь и требуется получить расширение файла, которое является частью имени файла, расположенной за последней точкой. Например, в именах файлов src.cpp, Window.class и Resume.doc расширениями файла являются соответственно .cpp, .class и .doc.
РешениеПреобразуйте имя файла или путь к нему в строку string, используйте функцию-член rfind для определения позиции последней точки и возвратите то, что находится за ней. Пример 10.20 показывает, как это можно сделать.
Пример 10.20. Получение расширения файла из его имени
#include <iostream>
#include <string>
using std::string;
string getFileExt(const string& s) {
size_t i = s.rfind('.', s.length());
if (i ! = string::npos) {
return(s.substr(i+1, s.length() - i));
}
return("");
}
int main(int argc, char** argv) {
string path = argv[1];
std::cout << "The extension is "" << getFileExt(path) << ""n";
}
ОбсуждениеДля получения расширения из имени файла достаточно лишь найти позицию последней точки «.» и выделить все, что находится справа от нее. Стандартный класс string, определенный в <string>, содержит функции, которые могут выполнить обе эти операции: rfind и substr.
rfind выполнит поиск (в обратном направлении) того, что вы передаете ей в первом аргументе (символ типа char в данном случае), начиная с позиции, указанной вторым аргументом, и возвращает позицию, в которой найден указанный объект. Если поиск завершился неудачей, rfind возвратит string::npos. Функция substr также имеет два аргумента. Первый аргумент содержит позицию первого копируемого элемента, а второй аргумент — количество копируемых символов.
Стандартный класс строки содержит несколько функций-членов, выполняющих поиск. См. рецепт 4.9, в котором более детально обсуждается поиск строк.
Смотри такжеРецепты 4.9 и 10.12.
10.14. Извлечение имени файла из полного пути
ПроблемаИмеется полный путь к файлу, например d:appssrcfoo.с, и требуется получить имя файлa, foo.с.
РешениеПримените подход, который использовался в предыдущем рецепте, и используйте функции rfind и substr для поиска и получения из полного пути то, что вам нужно. Пример 10.21 показывает, как это можно сделать.
Пример 10.21. Извлечение имени файла из полного пути
#include <iostream>
#include <string>
using std::string;
string getFileName(const string& s) {
char sep = '/';
#ifdef _WIN32
sep = '\';
#endif
size_t i = s.rfind(sep.s.length());
if (i ! = string::npos) {
return(s.substr(i+1, s.length( ) - i));
}
return("");
}
int main(int argc, char** argv) {
string path = argv[1];
std::cout << "The file name is "" << getFileName(path) << ""n";
}
ОбсуждениеСм. предыдущий рецепт, в котором приводится детальное описание функций rfind и substr. Стоит отметить только то, что вы уже, по-видимому, заметили в примере 10.21: в Windows в качестве разделителя используется обратный слеш вместо прямого, поэтому я добавил оператор #ifdef для установки требуемого разделителя элементов пути.
Класс path из библиотеки Boost Filesystem позволяет легко получить с помощью функции-члена path::leaf последний элемент полного пути, которым может быть имя файла или каталога. В примере 10.22 приводится простая программа, которая использует эту функцию, чтобы показать, к чему относится этот путь: к файлу или к каталогу.
Пример 10.22. Получение имени файла из пути
#include <iostream>
#include <cstdlib>
#include <boost/filesystem/operations.hpp>
using namespace std;
using namespace boost::filesystem;
int main(int argc, char** argv) {
// Проверка параметров
try {
path p = complete(path(argv[1], native));
cout << p.leaf() << " is a "
<< (is_directory(p) ? "directory" : "file") << endl;
} catch (exception& e) {
cerr << e.what() << endl;
}
return(EXIT_SUCCESS);
}
См. обсуждение рецепта 10.7, где более детально рассматривается класс path.
Смотри такжеРецепт 10.15.
10.15. Извлечение пути из полного имени файла
ПроблемаИмеется полное имя файла (имя файла и путь доступа к нему), например d:appssrcfoo.с, и требуется получить путь к файлу, d:appssrc.
РешениеПримените подход, который использовался в предыдущих двух рецептах, и используйте функции rfind и substr для поиска и получения из полного пути то, что вам нужно. В примере 10.23 приводится короткая программа, показывающая, как это можно сделать.
Пример 10.23. Получение пути из полного имени файла
#include <iostream>
#include <string>
using std::string;
string getPathName(const string& s) {
char sep = '/';
#ifdef _WIN32
sep = '\';
#endif
size_t i = s.rfind(sep, s.length());
if (i != string::npos) {
return(s.substr(0, !));
}
return("");
}
int main(int argc, char** argv) {
string path = argv[1];
std::cout << "The path name is "" << getPathName(path) << ""n";
}
ОбсуждениеПример 10.23 тривиален, особенно если вы уже знакомы с двумя предыдущими рецептами, поэтому дополнительные пояснения не требуются. Однако, как и во многих других рецептах, библиотека Boost Filesystem позволяет извлекать с помощью функции branch_path все, что угодно, кроме последней части имени файла. Пример 10.24 показывает, как можно использовать эту функцию.
Пример 10.24. Получение базового пути
#include <iostream>
#include <cstdlib>
#include <boost/filesystem/operations.hpp>
using namespace std;
using namespace boost::filesystem;
int main(int argc, char** argv) {
// Проверка параметров...
try {
path p = complete(path(argv[1], native));
cout << p.branch_path().string() << endl;
} catch (exception& e) {
cerr << e.what() << endl;
}
return(EXIT_SUCCESS);
}
Результат выполнения примера 10.24 может выглядеть следующим образом.
D:srcccbc10>binGetPathBoost.exe с:windowssystem321033
с:/windows/system32
Смотри такжеРецепты 10.13 и 10.14.
10.16. Замена расширения файла
ПроблемаИмеется имя файла (возможно, с путем доступа к нему) и требуется заменить расширение файла. Например, имя файла thesis.tex требуется преобразовать в thesis.txt.
РешениеИспользуйте функции-члены rfind и replace класса string для поиска расширения и его замены. Пример 10.25 показывает, как это можно сделать.
Пример 10.25. Замена расширения файла
#include <iostream>
#include <string>
using std::string;
void replaceExt(string& s, const string& newExt) {
string::size_type i = s.rfind('.', s.length());
if (i != string::npos) {
s.replace(i+1, newExt.length(), newExt);
}
}
int main(int argc, char** argv) {
string path = argv[1];
replaceExt(path, "foobar");
std::cout << "The new name is "" << path << ""n";
}
ОбсуждениеЗдесь используется подход, аналогичный тому, который применялся в предыдущих рецептах, однако в данном случае я использовал функцию replace для замены части строки новой подстрокой. Функция replace имеет три параметра. Первый параметр задает позицию, в которую вставляется новая подстрока, а второй параметр определяет количество символов, которые необходимо удалить в формируемой строке. Третий параметр — это значение, которое будет использовано для замены удаляемой части строки.