c - 使用系统和库函数对文件进行排序

标签 c sorting

@编辑 看起来 fread 函数读取的字符比 record_size 参数多;x

PICTURE

我有两个函数可以按记录对文件进行排序(冒泡排序)(键是第一个字符)。第一个是使用系统函数(read、write 等),第二个是使用库函数(fread、fwrite 等)。对于较小的 record_size 参数,两者都可以正常工作,但例如对于 record_size = 5000,只有 sys_sort 可以正常工作。通过lib_sort排序的文件行数较少且长度不同。为什么?不知道是什么问题。

void lib_sort(const char *filename, long long int record_size, long long int num_of_lines) {
    record_size++;  // '\n' char at the end of line
    FILE *file;

    if (!(file = fopen(filename, "r+"))) {
        printf("Cannot open %s file.\n", filename);
        fclose(file);
        exit(EXIT_FAILURE);
    }

    char *buffer1 = malloc(sizeof(char) * record_size);
    char *buffer2 = malloc(sizeof(char) * record_size);

    bool flag = true;

    while (flag) {
        flag = false;
        if(fseek(file, 0, SEEK_SET) != 0) {
            printf("fseek failed.\n");
        }
        if((fread(buffer1, sizeof(char), (size_t) record_size, file)) != record_size) {
            printf("fread failed.\n");
        }

        for (int i = 1; i < num_of_lines; ++i) {
            if((fread(buffer2, sizeof(char), (size_t) record_size, file)) != record_size) {
                printf("fread failed.\n");
            }
            if (buffer1[0] > buffer2[0]) {
                if(fseek(file, record_size * (-2), SEEK_CUR) != 0) {
                    printf("fseek failed.\n");
                }
                if((fwrite(buffer2, sizeof(char), (size_t) record_size, file)) != record_size) {
                    printf("fwrite failed.\n");
                }

                if((fwrite(buffer1, sizeof(char), (size_t) record_size, file)) != record_size) {
                    printf("write failed.\n");
                }
                flag = true;
            } else {
                char *tmp = buffer2;
                buffer2 = buffer1;
                buffer1 = tmp;
            }
        }
        num_of_lines--;
    }
    fclose(file);
    free(buffer1);
    free(buffer2);
}

这是正确的:

void sys_sort(const char *filename, long long int record_size, long long int num_of_records) {
    record_size++;  // '\n' char at the end of line
    int file;

    if ((file = open(filename, O_RDWR)) < 0) {
        printf("Cannot open %s file.\n", filename);
        close(file);
        exit(EXIT_FAILURE);
    }

    char *buffer1 = malloc(sizeof(char) * record_size);
    char *buffer2 = malloc(sizeof(char) * record_size);

    bool flag = true;

    while (flag) {
        flag = false;
        lseek(file, 0, SEEK_SET);
        read(file, buffer1, (size_t) record_size);

        for (int i = 1; i < num_of_records; ++i) {
            read(file, buffer2, (size_t) record_size);
            if (buffer1[0] > buffer2[0]) {
                lseek(file, record_size * (-2), SEEK_CUR);
                write(file, buffer2, (size_t) record_size);
                write(file, buffer1, (size_t) record_size);
                flag = true;
            } else {
                char *tmp = buffer2;
                buffer2 = buffer1;
                buffer1 = tmp;
            }
        }
        num_of_records--;
    }
    close(file);
    free(buffer1);
    free(buffer2);
}

我使用 ubuntu 16.04 和标准 C99

最佳答案

您错误地使用了 fread()fwrite()

size_t fread(void *ptr, size_t size, size_t nmemb, FILE * stream );

size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);

Description

The function fread() reads nmemb elements of data, each size bytes long, from the stream pointed to by stream, storing them at the location given by ptr.

The function fwrite() writes nmemb elements of data, each size bytes long, to the stream pointed to by stream, obtaining them from the location given by ptr.

您告诉 fread()fwrite() 您的记录或项目的长度是 1 个字节长,并且您要求 5000 条记录。

Return Value

On success, fread() and fwrite() return the number of items read or written. This number equals the number of bytes transferred only when size is 1. If an error occurs, or the end of the file is reached, the return value is a short item count (or zero).

当您在代码中明确表示记录大小(项目的长度)时,传递给 fread()fwrites() 的参数顺序错误在您的失败场景中,为 record_size 或 5000。

您应该编写代码以这种方式调用 fread():

fread(buffer1, (size_t) record_size, 1, file)

并以这种方式调用fwrite():

fwrite(buffer2, (size_t) record_size, 1, file)

还应该注意的是,fread()fwrite() 适用于二进制流。这意味着字符串不会自动以 null 结尾,并且读取将读取过去的换行符和过去的 null \0 字节。写入时,换行符不会自动转换为操作系统支持的换行符,例如 Linux 上的 LF 和 Windows 上的 CRLF

对于字符串操作,请使用 fgets()fputs()

你忘了提及,我错误地认为你正在 Linux 上运行。根据您的评论,您毕竟是在 Windows 上运行。在 Windows 上,当以 text 模式打开文件时,由于操作系统相关编码的转换,fread()fwrite() 将无法正常工作。您需要以二进制模式打开该文件。

关于c - 使用系统和库函数对文件进行排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42960043/

相关文章:

c - 反转字符串是段错误

sorting - Erlang ETS 带有袋型元素排序

jquery - 如何以 yyyy-mm-dd 格式对日期进行排序。通过使用数据表[js]?

c# - 与 C# 中的现有列表相比,如何对列表进行排序?

c++ - 为什么链接器看不到我的函数(定义宏来替代系统日志)?

c - 程序在 Linux 用户空间的 FD_SET 宏处挂起

c++ - 如何从 C 或 C++ 语言级别安全地访问内存映射硬件寄存器?

c - 为什么这个 C 数组算法在第二次迭代时失败?

ios - Swift 设置数组自定义排序

c++ - "Locking"两个 vector 并对它们进行排序