我从文件夹中获取了文件名并将名称发送到vector<string>
,但是当我打印vector<string>
时,我发现订单与文件夹中的文件顺序不同。
我的代码如下所示:
#include <windows.h>
#include <iostream>
#include <vector>
using namespace std;
void searchFileInDirectroy( const string& dir, vector<string>& outList );
void searchFileInDirectroy( const string& dir, vector<string>& outList )
{
WIN32_FIND_DATA findData;
HANDLE hHandle;
string filePathName;
string fullPathName;
filePathName = dir;
filePathName += "\\*.*";
hHandle = FindFirstFile( filePathName.c_str(), &findData );
if( INVALID_HANDLE_VALUE == hHandle )
{
cout<<"Error"<<endl;
return ;
}
do
{
if( strcmp(".", findData.cFileName) == 0 || strcmp("..", findData.cFileName) == 0 )
{
continue;
}
fullPathName = dir;
fullPathName += "\\";
fullPathName += findData.cFileName;
if( findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
{
searchFileInDirectroy( fullPathName, outList );
}
else
{
outList.push_back(fullPathName);
}
} while( FindNextFile( hHandle, &findData ) );
FindClose( hHandle );
}
int main()
{
///get filenames from folder;
vector<string> pathList;
searchFileInDirectroy("D:/OpenCV/calculate laef area--cui.ver2.0/source", pathList);
for(unsigned int i=0;i<pathList.size();i++)
{
cout<<pathList[i]<<endl;
}
return 0;
}
结果是这样的:
我真正想要的是订单从1到12。
答案 0 :(得分:1)
我发现订单与文件夹中的文件订单不同。
你可能意味着它们不是自然命令的,即文件名中的数字似乎不受尊重。
这是因为 lexigraphical比较不尊重数学。 "12"
小于"2"
,因为"12"
已经&#34;胜出&#34;对于第一个字符,因为字符串逐字符进行比较,'1'
小于'2'
。
所以你首先需要一个自然排序的算法。 C ++不提供一个,但它提供了一种使用std::sort
对任何给定排序关系的范围进行排序的方法:
#include <algorithm>
// ...
struct NaturalOrdering
{
bool operator()(std::string const &lhs, std::string const &rhs) const
{
// ...
}
};
// ...
vector<string> pathList;
// ...
std::sort(pathList.begin(), pathList.end(), NaturalOrdering());
因此,目标变成找到一种算法,该算法定义两者之间的自然小于关系。如果你想覆盖每一个角落的情况,这不是一项微不足道的任务。如果您在Google上搜索&#34;字符串自然顺序&#34;,您会发现无数的算法可供使用。
这是一个快速自制的。它的想法是将字符串分成令牌,每个令牌只包含数字(例如&#34; 123&#34;)或根本没有数字(例如&#34;文件&#34;)。然后单独比较令牌。如果两者都是数字,则将它们转换为整数并进行数学比较,否则将按字典顺序进行比较。
如果它实际上太慢或有其他问题,请随意拿走这件事并改进它。它的意图比生产代码中的使用更具教育意义:
#include <iostream>
#include <string>
#include <vector>
#include <ctype.h>
#include <algorithm>
#include <sstream>
struct Token
{
bool is_number;
std::string string;
};
std::vector<Token> Tokenize(std::string const &input)
{
std::string const digits = "0123456789";
std::vector<Token> result;
if (!input.empty())
{
bool inside_number_token = isdigit(static_cast<unsigned char>(input[0])) != 0;
std::string::size_type start_current_token = 0;
std::string::size_type start_next_token = 0;
do
{
if (inside_number_token)
{
start_next_token = input.find_first_not_of(digits, start_current_token);
}
else
{
start_next_token = input.find_first_of(digits, start_current_token);
}
std::string const string = input.substr(start_current_token, start_next_token - start_current_token);
Token token;
token.is_number = inside_number_token;
token.string = string;
result.push_back(token);
start_current_token = start_next_token;
inside_number_token = !inside_number_token;
}
while (start_current_token != std::string::npos);
}
return result;
}
int ToInteger(std::string const &number_as_string)
{
std::istringstream converter(number_as_string);
int integer = 0;
converter >> integer;
return integer;
}
struct NaturalOrder
{
bool operator()(std::string const &lhs, std::string const &rhs) const
{
std::vector<Token> const tokens_lhs = Tokenize(lhs);
std::vector<Token> const tokens_rhs = Tokenize(rhs);
for (std::vector<Token>::size_type index = 0; index < tokens_lhs.size() && index < tokens_rhs.size(); ++index)
{
Token const &token_lhs = tokens_lhs[index];
Token const &token_rhs = tokens_rhs[index];
if (token_lhs.is_number && token_rhs.is_number)
{
int const number_lhs = ToInteger(token_lhs.string);
int const number_rhs = ToInteger(token_rhs.string);
if (number_lhs != number_rhs)
{
return number_lhs < number_rhs;
}
}
else
{
if (token_lhs.string != token_rhs.string)
{
return token_lhs.string < token_rhs.string;
}
}
}
return false;
}
};
int main()
{
std::vector<std::string> filenames;
filenames.push_back("file-10.txt");
filenames.push_back("file-2.txt");
filenames.push_back("file.txt");
filenames.push_back("100.txt");
filenames.push_back("100.txt");
filenames.push_back("file-23.txt");
filenames.push_back("file-11.txt");
filenames.push_back("test-01-a.txt");
filenames.push_back("test-022-b.txt");
filenames.push_back("test-03-c.txt");
filenames.push_back("aaa-10-2");
filenames.push_back("aaa-10-1");
std::sort(filenames.begin(), filenames.end(), NaturalOrder());
for (std::vector<std::string>::const_iterator iter = filenames.begin(); iter != filenames.end(); ++iter)
{
std::cout << *iter << "\n";
}
}
输出:
100.txt
100.txt
aaa-10-1
aaa-10-2
file-2.txt
file-10.txt
file-11.txt
file-23.txt
file.txt
test-01-a.txt
test-03-c.txt
test-022-b.txt