如何在C中按顺序对数字和字母排序文件名?

ind*_*ira 12 c c++ sorting

我使用以下代码按字母顺序对文件进行排序,并对文件进行排序,如图所示:

for(int i = 0;i < maxcnt;i++) 
{
    for(int j = i+1;j < maxcnt;j++)
    {           
        if(strcmp(Array[i],Array[j]) > 0)
        {            
            strcpy(temp,Array[i]);      
            strcpy(Array[i],Array[j]);      
            strcpy(Array[j],temp);    
        }    
    } 
}
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

但我需要按照Windows资源管理器中的顺序对其进行排序

在此输入图像描述

怎么这样排序?请帮忙

Jos*_*sey 7

作为C答案,以下是替代strcasecmp().此函数recurses处理包含交替数字和非数字子字符串的字符串.您可以使用它qsort():

int strcasecmp_withNumbers(const void *void_a, const void *void_b) {
   const char *a = void_a;
   const char *b = void_b;

   if (!a || !b) { // if one doesn't exist, other wins by default
      return a ? 1 : b ? -1 : 0;
   }
   if (isdigit(*a) && isdigit(*b)) { // if both start with numbers
      char *remainderA;
      char *remainderB;
      long valA = strtol(a, &remainderA, 10);
      long valB = strtol(b, &remainderB, 10);
      if (valA != valB)
         return valA - valB;
      // if you wish 7 == 007, comment out the next two lines
      else if (remainderB - b != remainderA - a) // equal with diff lengths
         return (remainderB - b) - (remainderA - a); // set 007 before 7
      else // if numerical parts equal, recurse
         return strcasecmp_withNumbers(remainderA, remainderB);
   }
   if (isdigit(*a) || isdigit(*b)) { // if just one is a number
      return isdigit(*a) ? -1 : 1; // numbers always come first
   }
   while (*a && *b) { // non-numeric characters
      if (isdigit(*a) || isdigit(*b))
         return strcasecmp_withNumbers(a, b); // recurse
      if (tolower(*a) != tolower(*b))
         return tolower(*a) - tolower(*b);
      a++;
      b++;
   }
   return *a ? 1 : *b ? -1 : 0;
}
Run Code Online (Sandbox Code Playgroud)

笔记:

  • Windows需要stricmp()而不是Unix等价物strcasecmp().
  • 如果数字非常大,上面的代码(显然)会给出不正确的结果.
  • 这里忽略前导零.在我的区域,这是一个功能,而不是一个错误:我们通常希望UAL0123匹配UAL123.但这可能是也可能不是你所需要的.
  • 另请参阅对可能包含数字的字符串进行排序以及如何在c ++中实现自然排序算法?虽然那里的答案,或者在它们的链接中,与上述代码相比,肯定是漫长而漫无目的的,大约至少四倍.


The*_*ght 6

自然分拣是你必须在这里采取的方式.我的方案有一个工作代码.你可以根据自己的需要改变它来利用它:

    #ifndef JSW_NATURAL_COMPARE
    #define JSW_NATURAL_COMPARE
    #include <string>
    int natural_compare(const char *a, const char *b);
    int natural_compare(const std::string& a, const std::string& b);
    #endif
    #include <cctype>
    namespace {
      // Note: This is a convenience for the natural_compare 
      // function, it is *not* designed for general use
      class int_span {
        int _ws;
        int _zeros;
        const char *_value;
        const char *_end;
      public:
        int_span(const char *src)
        {
          const char *start = src;
          // Save and skip leading whitespace
          while (std::isspace(*(unsigned char*)src)) ++src;
          _ws = src - start;
          // Save and skip leading zeros
          start = src;
          while (*src == '0') ++src;
          _zeros = src - start;
          // Save the edges of the value
          _value = src;
          while (std::isdigit(*(unsigned char*)src)) ++src;
          _end = src;
        }
        bool is_int() const { return _value != _end; }
        const char *value() const { return _value; }
        int whitespace() const { return _ws; }
        int zeros() const { return _zeros; }
        int digits() const { return _end - _value; }
        int non_value() const { return whitespace() + zeros(); }
      };
      inline int safe_compare(int a, int b)
      {
        return a < b ? -1 : a > b;
      }
    }
    int natural_compare(const char *a, const char *b)
    {
      int cmp = 0;
      while (cmp == 0 && *a != '\0' && *b != '\0') {
        int_span lhs(a), rhs(b);
        if (lhs.is_int() && rhs.is_int()) {
          if (lhs.digits() != rhs.digits()) {
            // For differing widths (excluding leading characters),
            // the value with fewer digits takes priority
            cmp = safe_compare(lhs.digits(), rhs.digits());
          }
          else {
            int digits = lhs.digits();
            a = lhs.value();
            b = rhs.value();
            // For matching widths (excluding leading characters),
            // search from MSD to LSD for the larger value
            while (--digits >= 0 && cmp == 0)
              cmp = safe_compare(*a++, *b++);
          }
          if (cmp == 0) {
            // If the values are equal, we need a tie   
            // breaker using leading whitespace and zeros
            if (lhs.non_value() != rhs.non_value()) {
              // For differing widths of combined whitespace and 
              // leading zeros, the smaller width takes priority
              cmp = safe_compare(lhs.non_value(), rhs.non_value());
            }
            else {
              // For matching widths of combined whitespace 
              // and leading zeros, more whitespace takes priority
              cmp = safe_compare(rhs.whitespace(), lhs.whitespace());
            }
          }
        }
        else {
          // No special logic unless both spans are integers
          cmp = safe_compare(*a++, *b++);
        }
      }
      // All else being equal so far, the shorter string takes priority
      return cmp == 0 ? safe_compare(*a, *b) : cmp;
    }
    #include <string>
    int natural_compare(const std::string& a, const std::string& b)
    {
      return natural_compare(a.c_str(), b.c_str());
    }
Run Code Online (Sandbox Code Playgroud)


Kar*_*k T 5

你想要做的是执行"自然排序".这是一篇关于它的博客文章,我相信在python中解释实现.是一个完成它的perl模块.在如何在c ++中实现自然排序算法似乎也存在类似的问题


Ken*_*ski 5

考虑到它有一个c++标签,你可以详细说明@Joseph Quinsey的答案并创建一个natural_less函数传递给标准库.

using namespace std;

bool natural_less(const string& lhs, const string& rhs)
{
    return strcasecmp_withNumbers(lhs.c_str(), rhs.c_str()) < 0;
}

void example(vector<string>& data)
{
    std::sort(data.begin(), data.end(), natural_less);
}
Run Code Online (Sandbox Code Playgroud)

我花时间写了一些工作代码作为练习 https://github.com/kennethlaskoski/natural_less