我想对我拥有的代码提出一些建议。
我设法完成了想要完成的任务,但是我认为这不是在程序员世界中“正确”的实现方式。
您能否以任何方式帮助我改进代码,如果还有更好的方法,也请与他们分享。
我有以下格式的文件:
501.236.pcd
501.372.pcd
...
612.248.pcd等
我想使用C ++根据文件名按升序排列文件名。
这是我使用的代码:
#include <string>
#include <iostream>
#include <boost/filesystem.hpp>
#include <sstream>
using namespace std;
using namespace boost::filesystem;
int main()
{
vector <string> str,parsed_str;
path p("./fake_pcd");
string delimiter = ".";
string token,parsed_filename;
size_t pos = 0;
int int_filename;
vector <int> int_dir;
//insert filenames in the directory to a string vector
for (auto i = directory_iterator(p); i != directory_iterator(); i++)
{
if (!is_directory(i->path())) //we eliminate directories in a list
{
str.insert(str.end(),i->path().filename().string());
}
else
continue;
}
//parse each string element in the vector, split from each delimiter
//add each token together and convert to integer
//put inside a integer vector
parsed_str = str;
for (std::vector<string>::iterator i=parsed_str.begin(); i != parsed_str.end(); ++i)
{
cout << *i << endl;
while ((pos = i->find(delimiter)) != string::npos) {
token = i->substr(0,pos);
parsed_filename += token;
i->erase(0, pos + delimiter.length());
}
int_filename = stoi(parsed_filename);
int_dir.push_back(int_filename);
parsed_filename = "";
}
cout << endl;
parsed_str.clear();
sort(int_dir.begin(), int_dir.end());
//print the sorted integers
for(vector<int>::const_iterator i=int_dir.begin(); i != int_dir.end(); i++) {
cout << *i << endl;
}
//convert sorted integers to string and put them back into string vector
for (auto &x : int_dir) {
stringstream ss;
ss << x;
string y;
ss >> y;
parsed_str.push_back(y);
}
cout << endl;
//change the strings so that they are like the original filenames
for(vector<string>::iterator i=parsed_str.begin(); i != parsed_str.end(); i++) {
*i = i->substr(0,3) + "." + i->substr(3,3) + ".pcd";
cout << *i << endl;
}
}
这是输出,第一部分是由directory_iterator获取它的顺序,第二部分是以整数排序的文件名,最后一部分是将整数改回原始文件名格式的字符串的地方。
612.948.pcd
612.247.pcd
501.567.pcd
501.346.pcd
501.236.pcd
512.567.pcd
613.008.pcd
502.567.pcd
612.237.pcd
612.248.pcd
501236
501346
501567
502567
512567
612237
612247
612248
612948
613008
501.236.pcd
501.346.pcd
501.567.pcd
502.567.pcd
512.567.pcd
612.237.pcd
612.247.pcd
612.248.pcd
612.948.pcd
613.008.pcd
从Boost Filesystem中的Filtering文件夹中获取一些提示,以防万一:
Live On Coliru使用Boost(也在Wandbox.org上)
#include <boost/range/adaptors.hpp>
#include <boost/spirit/home/x3.hpp>
#include <boost/filesystem.hpp>
#include <iostream>
#include <optional>
#include <set>
namespace fs = boost::filesystem;
namespace {
using Path = fs::path;
struct Ranked {
std::optional<int> rank;
Path path;
explicit operator bool() const { return rank.has_value(); }
bool operator<(Ranked const& rhs) const { return rank < rhs.rank; }
};
static Ranked rank(Path const& p) {
if (p.extension() == ".pcd") {
auto stem = p.stem().native();
std::string digits;
using namespace boost::spirit::x3;
if (phrase_parse(begin(stem), end(stem), +digit >> eoi, punct, digits))
return { std::stoul(digits), p };
}
return { {}, p };
}
}
int main() {
using namespace boost::adaptors;
auto dir = boost::make_iterator_range(fs::directory_iterator("."), {})
| transformed(std::mem_fn(&fs::directory_entry::path))
| transformed(rank)
;
std::multiset<Ranked> index(begin(dir), end(dir));
for (auto& [rank, path] : index) {
std::cout << rank.value_or(-1) << "\t" << path << "\n";
}
}
印刷品:
-1 "./main.cpp"
-1 "./a.out"
501008 "./501.008.pcd"
501236 "./501.236.pcd"
501237 "./501.237.pcd"
501247 "./501.247.pcd"
501248 "./501.248.pcd"
501346 "./501.346.pcd"
501567 "./501.567.pcd"
501948 "./501.948.pcd"
502008 "./502.008.pcd"
502236 "./502.236.pcd"
502237 "./502.237.pcd"
502247 "./502.247.pcd"
502248 "./502.248.pcd"
502346 "./502.346.pcd"
502567 "./502.567.pcd"
502948 "./502.948.pcd"
512008 "./512.008.pcd"
512236 "./512.236.pcd"
512237 "./512.237.pcd"
512247 "./512.247.pcd"
512248 "./512.248.pcd"
512346 "./512.346.pcd"
512567 "./512.567.pcd"
512948 "./512.948.pcd"
612008 "./612.008.pcd"
612236 "./612.236.pcd"
612237 "./612.237.pcd"
612247 "./612.247.pcd"
612248 "./612.248.pcd"
612346 "./612.346.pcd"
612567 "./612.567.pcd"
612948 "./612.948.pcd"
613008 "./613.008.pcd"
613236 "./613.236.pcd"
613237 "./613.237.pcd"
613247 "./613.247.pcd"
613248 "./613.248.pcd"
613346 "./613.346.pcd"
613567 "./613.567.pcd"
613948 "./613.948.pcd"
由于文件系统库已经标准化并使用Rangev3,因此:
#include <filesystem>
#include <iostream>
#include <map>
#include <optional>
#include <range/v3/action/remove_if.hpp>
#include <range/v3/range/conversion.hpp>
#include <range/v3/view/filter.hpp>
#include <range/v3/view/subrange.hpp>
#include <range/v3/view/transform.hpp>
namespace fs = std::filesystem;
namespace {
using namespace ranges;
using Ranked = std::pair<std::optional<int>, fs::path>;
bool has_rank(Ranked const& v) { return v.first.has_value(); }
static Ranked ranking(fs::path const& p) {
if (p.extension() == ".pcd") {
auto stem = p.stem().native();
auto non_digit = [](uint8_t ch) { return !std::isdigit(ch); };
stem |= actions::remove_if(non_digit);
return { std::stoul(stem), p };
}
return { {}, p };
}
}
int main() {
using It = fs::directory_iterator;
for (auto&& [rank, path] : subrange(It("."), It())
| views::transform(std::mem_fn(&fs::directory_entry::path))
| views::transform(ranking)
| views::filter(has_rank)
| to<std::multimap>())
{
std::cout << rank.value_or(-1) << "\t" << path << "\n";
}
}
打印例如
501236 "./501.236.pcd"
501346 "./501.346.pcd"
501567 "./501.567.pcd"
502567 "./502.567.pcd"
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句