带有字母数字文件名的qsort dynamic 2d char数组 - C程序

时间:2018-02-22 17:50:05

标签: c sorting multidimensional-array alphanumeric qsort

我是新来的,所以这是我的第一篇文章。我已经挣扎了两个星期来解决这个问题。我正在尝试打开一个目录,捕获并存储找到的文件的名称,按升序对它们进行排序,然后打印结果。我的问题是qsort导致我的程序完全崩溃,或者qsort根本不对数组进行排序,因为这些文件是字母数字。我甚至尝试循环存储文件名来输出每个字符,只是为了看看我是否最终可以尝试比较两个数组位置之间的字符进行排序。但我注意到它似乎无法看到或识别字母数字文件名中的数字(例如:“f1.jpg”只会打印“f”,空白,然后是“j”,就是这样。我应该注意我无法更改文件名,因为我事先并不知道名称或总文件。我正在尝试使其成为动态。以下是我遇到问题的主要代码,因为它崩溃了'qsort'关键字:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <conio.h>
#include <ctype.h>
#include <time.h>
#include <dirent.h>
#include <math.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

int compare(const void *a, const void *b);
void readInFilenames();

int main
{
   readInFilenames();
   system("pause");
}

int compare(const void *a, const void *b)
{
  return strcmp(*(char **)a, *(char **)b);
}

void readInFilenames()
{
  char cwd[1024];
  DIR *dir = NULL;
  struct dirent *pent = NULL;
  struct stat info;
  char file_path[50] = "files/";
  int total_files = 0;
  int file_size;

  // Change directory to file location
  chdir(file_path);

  if((getcwd(cwd, sizeof(cwd))) != NULL)
  {
    printf("Current Directory: %s\n", cwd);
  }

  // Open directory and count the total number of files found
  dir = opendir(cwd);

  if(dir != NULL)
  {
    while((pent = readdir(dir)) != NULL)
    {
        if(stat(pent->d_name, &info))
        {
            printf("ERROR: stat%s: %s\n", pent->d_name, strerror(errno));
        }
        else
        {
            if(S_ISREG(info.st_mode))
            {
                if((strcmp(pent->d_name, ".cproject") == 0) || (strcmp(pent->d_name, ".project") == 0))
                {
                    continue;
                }
                else
                {
                    total_files++;
                    file_size = sizeof(pent->d_name);
                }
            }
        }
    }
    printf("# of files found: %d\n", total_files);
    rewinddir(dir);    //reset pointer back to beginning of file directory

    // Create character array to store file names;
    char *filenames_arr[total_files][file_size];
    int size = sizeof(filenames_arr)/sizeof(filenames_arr[total_files]);

    total_files = 0;   //reset file counter back to 0;

    // Read and store file names in the character array
    while((pent = readdir(dir)) != NULL)
    {
        if(stat(pent->d_name, &info))
        {
            printf("ERROR: stat%s: %s\n", pent->d_name, strerror(errno));
        }
        else
        {
            if(S_ISREG(info.st_mode))
            {
                if((strcmp(pent->d_name, ".cproject") == 0) || (strcmp(pent->d_name, ".project") == 0))
                {
                    continue;
                }
                else
                {
                    strcpy(filenames_arr[total_files], pent->d_name);
                    //printf("%s\n", filenames_arr[i]);
                    total_files++;
                }
            }
        }
    }
    closedir(dir);

    // Print original array contents
    printf("Original List of Files\n");
    printf("----------------------\n");
    for(int i = 0; i < total_files; i++)
    {
      printf("%s\n", filenames_arr[i]);
    }

    // Sort array in ascending order
    qsort(filenames_arr, total_files, size, compare);
    //qsort(filenames_arr, total_files, sizeof(filenames_arr[0]), (char (*)(const void*, const void*))strcmp);

    // Print organized array contents
    printf("Sorted List of Files\n");
    printf("----------------------\n");
    for(int i = 0; i < total_files; i++)
    {
      printf("%s\n", filenames_arr[i]);
    }
    printf("\nFinished!\n");
  }
}

这段代码是我试图打印每个角色的时候。这最初位于上一代码中进行最终阵列打印的位置:

    int i = 0;
    int j = 0;
    while(i < total_files)
    {
        printf("File Name: %s\n", filenames_arr[i]);
        printf("String Length: %d\n", strlen(filenames_arr[i]));
        while(filenames_arr[i] != '\0')
        {
            printf("Checking filenames_arr[%d][%d]\n", i, j);

            if(isalpha((unsigned char)filenames_arr[i][j]) != 0)
            {
                printf("In isalpha\n");
                printf("Found: %c\n", filenames_arr[i][j]);
            }
            else if(isdigit((unsigned char)filenames_arr[i][j]) != 0)
            {
                printf("In isdigit\n");
                printf("Found: %d\n", filenames_arr[i][j]);
            }
            j++;
        }
        printf("-------------------------------------------\n");
        i++;
        j = 0;
    }

如何使用qsort对字母数字字符串的2D数组进行排序?什么是qsort,甚至我的阵列设置导致我的程序崩溃?另外,qsort是如何工作的?我已经尝试搜索论坛和在线课程笔记,以确定qsort是否仅通过查看第一个字符,所有字符或数字有问题来排序。提前谢谢!

更新

我对我的代码进行了以下编辑。它工作得更好,因为qsort不再崩溃程序。但是,qsort仍然没有排序。以下是我所做的更新,后面是结果的屏幕截图:

typedef struct{
  char *filename;
}filedata;

int compare(const void *a, const void *b);
void readInFilenames();

int main(void){
  readInFilenames();
  system("pause");
}

int compare (const void *a, const void *b ) {
  filedata *ia = (filedata *)a;
  filedata *ib = (filedata *)b;
  return strcmp(ia->filename, ib->filename);
}

readInFilenames(){
.
.
.
  printf("# of files found: %d\n", total_files);
  rewinddir(dir);

  filedata fn_data[total_files];
  total_files = 0;

  printf("Original Array: \n");
  while((pent = readdir(dir)) != NULL)
  {
    .
    .
    .
    if((strcmp(pent->d_name, ".cproject") == 0) || (strcmp(pent->d_name, ".project") == 0))
    {
        continue;
    }
    else
    {
        fn_data[total_files].filename = malloc(file_size + 1);
        strcpy(fn_data[total_files].filename, pent->d_name);
        printf("%s\n", fn_data[total_files].filename);
        total_files++;
    }
  }
  closedir(dir);

  printf("\n");
  qsort(fn_data, total_files, sizeof(filedata), compare);

  printf("Sorted Array:\n");
  for(int i = 0; i < total_files; i++)
    printf("%s\n", fn_data[i].filename);

  printf("Finished!\n");
}

Click here to see sorting results

列表应打印:f0.dat,f1.dat,f2.dat,f3.dat,...,f20.dat。但它打印:f0.dat,f1.dat,f10.dat,f11.dat,...,f9.dat。

1 个答案:

答案 0 :(得分:1)

OP通过启用警告并使用@Snohdo建议来修复代码以应对“qsort dynamic 2d char array with filenames”。

然而,代码仍在与strcmp()进行比较,f1.dat, f2.dat, f3.dat,...,f20.dat仅将数字视为字符,而不是数字来实现int AdamsOrder(const char *s1, const char *s2) { // Compare as `unsigned char` as that is `strcmp()` behavior. C11 7.24.1 3 const unsigned char *us1 = (const unsigned char *) s1; const unsigned char *us2 = (const unsigned char *) s2; while (*us1 && *us2) { if (isdigit(*us1) && isdigit(*us2)) { char *end; // dummy unsigned long long l1 = strtoull(us1, &end, 10); // Parse for a number unsigned long long l2 = strtoull(us2, &end, 10); if (l1 > l2) return 1; if (l1 < l2) return -1; // Continue on treating as text. OP needs to decide how to handle ties: "0001" vs "1" } if (*us1 > *us2) return 1; if (*us1 < *us2) return -1; us1++; us2++; } // At this point, at least one string ended (i.e. points to '\0'). // The return statement below will behave as follows: // If a string ended, *us1/2 will be 0. Let an unfinished one be X > 0. // First string ended : ( 0 > X ) - ( 0 < X ) = false - true = 0 - 1 = -1 // Second string ended: ( X > 0 ) - ( X < 0 ) = true - false = 1 - 0 = 1 // Both strings ended : ( 0 > 0 ) - ( 0 < 0 ) = false - false = 0 - 0 = 0 return (*us1 > *us2) - (*us1 < *us2); } 次序。

以下是比较函数,它查找数字以调用数字子字符串的备用比较。可以通过OP进行此比较的变化以适应详细的编码目标。

Attempting to save one or more entities that have a non-nullable association with an unsaved transient entity. The unsaved transient entity must be saved in an operation prior to saving these dependent entities.