簡體   English   中英

帶有字母數字文件名的 qsort 動態二維字符數組 - C 程序

[英]qsort dynamic 2d char array with alphanumeric filenames - C program

我是新來的,所以這是我的第一篇文章。 我一直在努力解決這個問題 2 周。 我正在嘗試打開一個目錄,捕獲並存儲找到的文件的名稱,按升序對它們進行排序,然后打印結果。 我的問題是 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 對字母數字字符串的二維數組進行排序? 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");
}

單擊此處查看排序結果

該列表應打印:f0.dat、f1.dat、f2.dat、f3.dat、...、f20.dat。 但它會打印:f0.dat、f1.dat、f10.dat、f11.dat、...、f9.dat。

OP 通過啟用警告和使用@Snohdo建議來處理“帶有文件名的 qsort 動態二維字符數組”的固定代碼。

然而代碼仍在與strcmp()進行比較,它只將數字視為字符而不是數字來實現f1.dat, f2.dat, f3.dat,...,f20.dat順序。


以下是查找數字以調用數字子字符串的替代比較的比較函數。 OP 可以對此比較進行更改,以適應詳細的編碼目標。

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);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM