在C中使用随机整数对mmaped文件进行排序

vsikbqxv  于 2023-11-16  发布在  其他
关注(0)|答案(3)|浏览(99)

我试图创建一个C程序,它用随机整数创建一个txt文件,然后mmap上述文件,qsort它。创建txt和Map顺利进行,但我不明白为什么qsort只是破坏了它。我的猜测,这与数据类型有关,但即使在玩弄它们之后,我还是得到了或多或少相同的结果。
比较:

int cmp(const void *p1, const void *p2)
{
    return (*(const int *)p1 - *(const int *)p2);
}

字符串
mmap和qsort:

char *addr = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, myFile, 0); 
    for (int i = 0; i < size; i++)
         printf("%c", addr[i]);
    qsort(addr, 20, sizeof(char), cmp);
    printf("\n-------------\n");
    for (int i = 0; i < size; i++)
         printf("%c", addr[i]);


输出示例:

10
19
9
8
18
2
9
6
3
7
15
12
12
14
6
2
4
3
15
13

-------------

296

1
9
93818
1
0

7
15
12
12
14
6
2
4
3
15
13


所以在txt中创建了20个随机整数,并没有任何问题地Map。但我猜qsort不喜欢给它的东西。我试着让mmap作为int,但这也带来了其他问题,比如数组中的数字不正确,数字数量不正确,(也许我错误地处理了输出).我不确定我做错了什么.这里是完整的代码,如果需要的话:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <time.h>
#include <stdlib.h>

int cmp(const void *p1, const void *p2);
void rand_txt(int size);

int main() {

    rand_txt(20);

    int myFile = open("rand.txt", O_RDWR);
    struct stat myStat = {};
    fstat(myFile, &myStat);
    off_t size = myStat.st_size;

    char *addr = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, myFile, 0);

    for (int i = 0; i < size; i++)
        printf("%c", addr[i]);

    qsort(addr, 20, sizeof(char), cmp);
    printf("\n-------------\n");
    for (int i = 0; i < size; i++)
        printf("%c", addr[i]);

    return 0;
}

int cmp(const void *p1, const void *p2) {
    return (*(const int*)p1 - *(const int*)p2);
}

//Function to create a txt with random integers in given size
void rand_txt(int size) {
    FILE *fp = fopen("rand.txt", "w");
    srand(time(0));
    for (int i = 0; i < size; i++)
        fprintf(fp, "%d\n", (rand() % size) + 1);
    fclose(fp);
}


还有一个快速:数组和指针在实践中的行为是一样的吗(就像字符串一样)?比如我们声明:int *x = { 10, 20, 30, 40 };,我们可以只声明fprint("%d\t", x[i]);吗?或者这种类型的数组必须声明为int[] = { 10, 20... };,而不是指针?(我可以也会自己测试它,如果没有答案,我会编辑“quickie”,直到我能够测试和研究它)

qeeaahzv

qeeaahzv1#

由于多种原因,您无法通过在内存中Map文件并使用比较函数调用qsort()来对具有不同大小的数字的文本文件进行排序:

  • qsort需要一个数组,其中所有条目都具有相同的大小,这不是文本表示的情况。
  • 比较函数假定一个int数组,而不是一个文本表示数组
  • 即使对于int的阵列,由于减法可能溢出,所以比较函数对于大的绝对值也是不合适的。

要对文本文件进行排序,经典的方法是分配一个int数组并从文件中加载值,将文本表示转换为int值,使用qsort和适当的比较函数对数组进行排序,并将排序后的数组转换回字符串表示。
这里有一个比较函数,你可以用途:

int cmp(const void *p1, const void *p2) {
    const int *i1 = p1;
    const int *i2 = p2;
    return (*i1 > *i2) - (*i1 < *i2);
}

字符串

kgsdhlau

kgsdhlau2#

你的代码做的就是你写的。没有qsort“喜欢”,或者函数“认为”。
你一行一行地写文本,就像下面这样。注意行尾字符:

10\n
19\n
9\n

字符串
下面的函数

int cmp(const void *p1, const void *p2)
{
    return (*(const int*)p1 - *(const int*)p2);
}


获取两个指针,将它们解释为int*并比较两个int所指向的。类型int通常具有32位长度。我将在一行中编写您的文本,看看cmp函数会做什么。

p1        p2
  |         |
  v         v
 10\n1   9\n9\n


比较器将得到字节10\n1,将它们解释为int。然后它将得到字节9\n9\n,将它们解释为int。并比较这些int s。
正如其他人在评论部分指出的那样,qsort可能会访问您写入文件的数据。这种情况下,比较器将比较它在mmap ed内存中找到的字节值。

*int x = {10,20,30,40};

打开编译器警告,看看它会告诉你什么。也许试着打印x[0], x[1]。你为什么问这个quickey?你是在想象C吗?

2uluyalo

2uluyalo3#

你应该为你的字符串设置格式(使用常量长度和零左填充):

fprintf(fp, "%015d\n", (rand() % size*5) + 1)

字符串
然后在qsort函数中使用相同的length+1 at size参数。
您还应该按如下方式更改cmp函数,以便它将字符串转换为atoi的数字:‍‍

int cmp(const void *p1, const void *p2)
{
    const int i1 = atoi((char*)p1);
    const int i2 = atoi((char*)p2);
    return (i1 - i2);
}


我的建议代码是:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <time.h>
#include <stdlib.h>

#include <stdlib.h>
#include <unistd.h>

int cmp(const void *p1, const void *p2)
{
    const int i1 = atoi((char*)p1);
    const int i2 = atoi((char*)p2);
    return (i1 - i2);
}
//Function to create a txt with random integers in given size
void rand_txt(int size)
{
    srand(time(0));
    FILE *fp = fopen("rand.txt", "w");
    for (int i = 0; i < size; i++)
        fprintf(fp, "%015d\n", (rand() % size*5) + 1);
    fclose(fp);
}

int main()
{
    int COUNT=20;
    rand_txt(COUNT);
    int myFile = open("rand.txt", O_RDWR);
    struct stat myStat = {};
    fstat(myFile, &myStat);
    off_t size = myStat.st_size;

    char *addr =(char*) mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, myFile, 0);
    close(myFile);
    for (int i = 0; i < size; i++)
        printf("%c", addr[i]);

    qsort(addr, COUNT, 16, cmp);
    printf("\n-------------\n");
    for (int i = 0; i < size; i++)
        printf("%c", addr[i]);
    munmap(NULL, size);
    return 0;
}

相关问题