无法按字母顺序对数组进行排序

Can't sort array in alphabetical order

我正在尝试制作一个模拟 ls 命令的程序,然后按照不区分大小写的字母顺序对文件进行排序。到目前为止,所有的文件名都进入了单词数组,但是当我尝试编译时,出现了问题。

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <dirent.h>

// This program is pretty much a simulation of the ls command. Find out how to scan all of the files
// in the directory it's being run in and print out all the file names. Has to be in order.

int main(int argc, char* argv[])
{
    char **words = calloc(1000, sizeof(*words));
    char **words2 = calloc(1000, sizeof(*words2));
    
    DIR *d;
    struct dirent *dir;  // Pointer for directory entry 
    d = opendir(".");
    char* a = ".";
    char* b = "..";
    char* c = "ls";
    int ret1, ret2, ret3, count = 0;
    
    
    if (d)  // opendir returns NULL if couldn't open directory
    {
        while ((dir = readdir(d)) != NULL)
        {
            ret1 = strcmp(dir->d_name, a); // Compare with the parent directory.
            ret2 = strcmp(dir->d_name, b); // Compare with the parent directory.
            ret3 = strcmp(dir->d_name, c); // Compare with the ls
            
            if (ret1 == 0 || ret2 == 0 || ret3 == 0)
            {
                // Skip the ., .., and ls
            }
            else
            {
                words[count] = dir->d_name; // Put the file name in the array.
                count++;
            }
        }
        
        for (int i = 1; i < 10; i++) // Start readjusting the array in alphabetical order.
        {
            for (int j = 1; j < 10; j++)
            {
                if (strcmp(words[j - 1], words[j]) > 0)
                {
                    strcpy(words2, words[j - 1]);
                    strcpy(words[j - 1], words[j]);
                    strcpy(words[j], words2);
                }
            }
        }
        
        // Print every word in the array.
        while (count != 0)
        {
            printf("%s\n", words[count - 1]);
            count--;
        }
        
    }   
    // Closing and freeing
    closedir(d);
    for (int a = 0; a < 1000; ++a)
    {
        free(words[a]);
    }
    for (int a = 0; a < 1000; ++a)
    {
        free(words2[a]);
    }
    free(words);
    free(words2);
   
    return 0;
}

当我编译时,这是我在下面得到的错误信息。当我尝试对数组进行排序时,它发生在序列中。我可以做些什么来解决这个问题吗?

ls.c: In function ‘main’:
ls.c:52:13: warning: passing argument 1 of ‘strcpy’ from incompatible pointer type [-Wincompatible-pointer-types]
   52 |      strcpy(words2, words[j - 1]);
      |             ^~~~~~
      |             |
      |             char **
In file included from ls.c:3:
/usr/include/string.h:122:14: note: expected ‘char * restrict’ but argument is of type ‘char **’
  122 | extern char *strcpy (char *__restrict __dest, const char *__restrict __src)
      |              ^~~~~~
ls.c:54:23: warning: passing argument 2 of ‘strcpy’ from incompatible pointer type [-Wincompatible-pointer-types]
   54 |      strcpy(words[j], words2);
      |                       ^~~~~~
      |                       |
      |                       char **
In file included from ls.c:3:
/usr/include/string.h:122:14: note: expected ‘const char * restrict’ but argument is of type ‘char **’
  122 | extern char *strcpy (char *__restrict __dest, const char *__restrict __src)
      |              ^~~~~~

在此if语句中调用strcpy

if (strcmp(words[j - 1], words[j]) > 0)
{
    strcpy(words2, words[j - 1]);
    strcpy(words[j - 1], words[j]);
    strcpy(words[j], words2);
}

参数 words 和 words2 具有 char ** 类型,但函数需要 char *.

类型的参数
char **words = calloc(1000, sizeof(*words));
char **words2 = calloc(1000, sizeof(*words2));

似乎变量words2被用作临时变量来存储字符串。在这种情况下,它应该用 char * 类型声明并且足够大以存储指针指向的动态分配数组中指针指向的任何字符串 words.

也不清楚为什么在 for 循环中使用幻数 10 而不是变量 count 例如

for (int i = 1; i < 10; i++)

注意比较函数strcmp区分大小写

莫斯科Vlad的回答说到点子上了。我补充一下,你的代码中还有一个非常讨厌的错误:DIR结构的d_name字段不是新分配的,所以你真的需要分配和复制 名称进入 words 序列:

words[count] = strdup(dir->d_name); // Put the file name in the array.

此外,count 对您的序列非常重要。用它来排序,打印数组内容时不要乱动它:

        // Print every word in the array.
        for (int i = 0; i < count; ++i) {
            printf("%s\n", words[i]);
        }

最后,您假设所有 words 的长度都相同,但这是不对的。所以你想要交换的是指针,而不是它们指向的字符。如果您想要一种易于实现的排序,请使用 selection sort:它与冒泡排序一样慢,但交换更少。顺便说一下,你的冒泡排序是错误的,因为你没有跟踪交换,所以你失去了冒泡排序的唯一优势,那就是提前停止。 在您的情况下,选择排序的可能实现可能是:

for (int i = 0; i < count; ++i) {
    int imin = i;
    for (int j = i + 1; j < count; ++j) {
        if (strcmp(words[j], words[imin]) < 0) {
            imin = j;
        }
    }
    char *tmp = words[i];
    words[i] = words[imin];
    words[imin] = tmp;
}

那么,就不要再使用words2了,免费最多只能到count