在C中使用随机整数对MMMAPAPE进行排序

发布于 2025-02-09 05:07:32 字数 2318 浏览 2 评论 0原文

我正在尝试创建一个C程序,该程序使用随机整数创建TXT文件,然后MMAP上述文件和QSort IT。创建TXT和映射顺利进行,但是我无法弄清楚为什么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个随机整数,并没有问题。但是我猜Qsort不喜欢给出的内容。 我尝试使用mmap作为int,但这创造了其他问题,例如数组中的数字不正确,数量不正确和一些0(也许我错误地处理了输出)。我不确定我在做什么错。如果需要,这是完整的代码:

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

Quickie: 阵列和指针在实践中的行为是否相同(如字符串)?说我们声明: int *x = {10,20,30,40}; 我们可以fprint(“%d \ t”,x [i]); 还是必须将这种类型的数组声明为int [] = {10,20 ...};而不是指针? (如果没有答案,我可以并且将自己测试并编辑“ Quickie”,直到我能够进行测试和研究之后)

I'm trying to create a C program that creates a txt file with random integers, and then mmap the said file and qsort it. Creating the txt and mapping goes smoothly, but I can't figure out why qsort just destroys it. My guess, it's something to do with data types, but even after playing around with them, I get more or less the same result.

compar:

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

mmap and 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]);

output example:

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

So 20 random integers are created in txt and mapped with no problems. But I guess qsort doesn't like what's given to it.
I tried having mmap as int, but that created other problems like incorrect numbers in the array and incorrect amount of numbers and some 0s (perhaps I handled the output incorrectly). I'm not exactly sure what I'm doing wrong. here is the full code in case if it's needed:

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

Also a quickie:
Do the arrays and pointers behave in the same way in practice(like strings)? say we declare:
int *x = { 10, 20, 30, 40 };
can we just fprint("%d\t", x[i]);
or such type of arrays must be declared as int[] = { 10, 20... }; and not with pointers?
(I can and will test it myself and edit the "quickie" out if there is no answer until after I am able to test and study it)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

凤舞天涯 2025-02-16 05:07:32

您无法通过在内存中映射文件并使用比较函数来对具有不同尺寸的数字进行分类,但出于多种原因:

  • QSort需要一个数组条目具有相同的大小,这不是文本表示的情况。
  • 比较函数假定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);
}

You cannot sort a text file with numbers of different sizes by mapping the file in memory and calling qsort() with the comparison function for multiple reasons:

  • qsort needs an array where all entries have the same size, which is not the case of textual representations.
  • the comparison function assumes an array of int, not an array of textual representations
  • even for an array of int, the comparison function would be inappropriate for large absolute values as the subtraction might overflow.

To sort the text file, the classic approach is to allocate an array of int and load the values from the file, converting from text representation to int values, sort the array with qsort with an appropriate comparison function, and write the sorted array converting back to string representations.

Here is a comparison function you can use:

int cmp(const void *p1, const void *p2) {
    const int *i1 = p1;
    const int *i2 = p2;
    return (*i1 > *i2) - (*i1 < *i2);
}
稀香 2025-02-16 05:07:32

您的代码所做的是您写的。没有QSORT“喜欢”或功能“思考”。

您按行编写文本,如下所示。请注意,线字符的结尾:

  10 \ n
19 \ n
9 \ n
 

以下功能

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

需要两个指针,将它们解释为int*,然后比较两个int s。类型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语言?

What your code does is what you wrote. There is no qsort "likes", or function "thinks".

You write text line by line, like below. Do notice the end of line characters:

10\n
19\n
9\n

The below function

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

Takes two pointers, interprets them as int* and compares two ints being pointed to. Type int has typically 32-bit length.
I will write your text in one line and see what will cmp function do.

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

The comparator will get bytes 10\n1, interpret them as an int.
Then it will get bytes 9\n9\n, interpret them as an int. And compare those ints.

As others have pointed out in comments section, qsort may access past the data that you wrote to the file. That case, comparator will compare bytes values, that it finds in a mmaped memory.

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

Turn on compiler warnings and see what will it tell you. Maybe try to print x[0], x[1]. Why are you asking that quickey? Do you trip into imaginary C language?

眼泪都笑了 2025-02-16 05:07:32

您应该为字符串设置格式(持续的长度且左填充零):

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

然后在qsort函数中使用相同的长度+1在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;
}

You should set format for your strings(with constant length and zero left padding):

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

and then use same length+1 at size argument in qsort function.

You should also change the ‍‍cmp function as follows so that it converts the string into a number by atoi:

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

My suggested code is:

#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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文