如何使用qsort根据字节对包含路径名/文件的char进行排序?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何使用qsort根据字节对包含路径名/文件的char进行排序?相关的知识,希望对你有一定的参考价值。
我基本上编写了一个代码,其中我接受两个命令行参数,一个是我想要在我的目录中搜索的文件类型,另一个是我想要的数量(尚未实现,但我可以修复)代码是这样的:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#define sizeFileName 500
#define filesMax 5000
int cmpfunc( const void *a, const void *b) {
return *(char*)a + *(char*)b;
}
int main( int argc, char ** argv) {
FILE * fp = popen( "find . -type f", "r");
char * type = argv[1];
char * extension = ".";
char* tExtension;
tExtension = malloc(strlen(type)+1+4);
strcpy(tExtension, extension);
strcat(tExtension, type);
// printf("%s
",tExtension);
int amount = atoi(argv[2]);
//printf("%d
",amount);
char buff[sizeFileName];
int nFiles = 0;
char * files[filesMax];
while(fgets(buff,sizeFileName,fp)) {
int leng = strlen(buff) - 1;
if (strncmp(buff + leng - 4, tExtension, 4) == 0){
files[nFiles] = strndup(buff,leng);
//printf(" %s
", files[nFiles]);
nFiles ++;
}
}
fclose(fp);
printf("Found %d files
", nFiles);
long long totalBytes = 0;
struct stat st;
// sorting based on byte size from greatest to least
qsort(files, (size_t) strlen(files), (size_t) sizeof(char), cmpfunc);
for(int i = 0;i< nFiles; i ++) {
if(0!= stat(files[i],&st)){
perror("stat failed:");
exit(-1);
}
totalBytes += st.st_size;
printf("%s : %ld
",files[i],st.st_size);
}
printf("Total size: %lld
", totalBytes);
// clean up
for(int i = 0; i < nFiles ; i ++ ) {
free(files[i]);
}
return 0;
}
到目前为止,我已经正确设置了每个部分,在运行代码时说$./find ini 5,
它将打印出所有ini files
,然后是字节大小(它当前忽略了5)。然而,对于qsort()
,我不确定如何排序char * files
的内容,因为它保存路径名,我不得不使用stat
来获取字节大小,我将如何打印出我的打印语句的排序版本第一个语句是最多字节,最少字节完成?
如果我们假设您的输入有效,您的问题可以通过以下方式简化:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define filesMax 5000
int cmpfunc(const void const *a, const void *b) { return *(char *)a + *(char *)b; }
int main(void) {
int nFiles = 4;
char *files[filesMax] = {"amazing", "hello", "this is a file", "I'm a bad file"};
qsort(files, strlen(files), sizeof(char), cmpfunc);
for (int i = 0; i < nFiles;; i++) {
printf("%s
", files[i]);
}
}
如果您使用警告进行编译,则可以:
source_file.c:11:23: warning: incompatible pointer types passing 'char *[5000]' to parameter of type 'const char *' [-Wincompatible-pointer-types]
qsort(files, strlen(files), sizeof(char), cmpfunc);
^~~~~
qsort()
期望你的数组的大小(或者在你的情况下是一个子类),它也期望你的数组的一个元素的大小。你错误地把它给了它。此外,您的比较函数不会比较任何东西,您当前正在添加char的两个指针的第一个字节,这没有多大意义。
要修复您的代码,您必须写:
qsort(files, nFiles, sizeof *files, &cmpfunc);
并修复比较功能:
int cmpfunc_aux(char * const *a, char * const *b) { return strcmp(*a, *b); }
int cmpfunc(void const *a, void const *b) { return cmpfunc_aux(a, b); }
也应该是size_t
类型的大小:
size_t nFiles = 0;
不要忘记有关如何使用函数的所有信息都写在他们的doc中。
我将如何打印出我的打印语句的排序版本,其中第一个语句是最多字节并以最少字节结束?
您的代码没有显示您尝试这样做的任何线索,您当前正在存储名称文件而且只存储该文件。您如何期望使用未获得的信息对文件进行排序?
但是,简单地创建一个包含文件名和大小的结构,获取对其进行排序和排序所需的信息:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <inttypes.h>
struct file {
off_t size;
char *name;
};
int cmpfunc_aux(struct file const *a, struct file const *b) {
if (a->size > b->size) {
return -1;
} else if (a->size < b->size) {
return 1;
} else {
return 0;
}
}
int cmpfunc(void const *a, void const *b) { return cmpfunc_aux(a, b); }
#define filesMax 5000
int main(void) {
size_t nFiles = 4;
struct file files[filesMax] = {{42, "amazing"},
{21, "hello"},
{168, "this is a file"},
{84, "I'm a bad file"}};
qsort(files, nFiles, sizeof *files, &cmpfunc);
for (size_t i = 0; i < nFiles; i++) {
printf("%s, %" PRId64 "
", files[i].name, (intmax_t)files[i].size);
}
}
函数cmpfunc()
提供了每个字符串的第一个字符,并且这不是一个正确的比较函数(当你切换参数时它应该给出一个相反的符号值,例如,如果"a"
和"b"
是要比较的字符串,它会添加前两个字符两个字符串,给97+98 == 195
,在unsigned char
s上是积极的,然后用"b"
和"a"
调用应该给出一个负数(并且它再次给你98 + 97 == 195
),更多的是,它总是给出相同的结果---即使用signed char
s-- - 所以它不能用作排序比较器)
在比较字符串时,为什么不使用标准库函数strcmp(3)
这是一个有效的比较函数?如果第一个字符串在字典上比第二个字符串更少,则给出负数,如果两者相等则为0
,如果第一个字符串在字典上比第二个字符串更大,则给出正数。
如果您的函数必须按文件名的长度检查(和排序),那么您可以将其定义为:
int cmpfunc(char *a, char *b) /* yes, you can define parameters as char * */
{
return strlen(a) - strlen(b);
}
或者,首先根据文件长度,然后按字典顺序:
int cmpfunc(char *a, char *b)
{
int la = strlen(a), lb = strlen(b);
if (la != lb) return la - lb;
/* la == lb, so we must check lexicographycally */
return strcmp(a, b);
}
现在,为了继续帮助你,我需要知道为什么你需要对任何东西进行排序,就像你说你想在目录中搜索文件一样,问题在哪里进行排序?
以上是关于如何使用qsort根据字节对包含路径名/文件的char进行排序?的主要内容,如果未能解决你的问题,请参考以下文章