@编辑 看起来 fread 函数读取的字符比 record_size 参数多;x
我有两个函数可以按记录对文件进行排序(冒泡排序)(键是第一个字符)。第一个是使用系统函数(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()
readsnmemb
elements of data, eachsize
bytes long, from the stream pointed to bystream
, storing them at the location given byptr
.The function
fwrite()
writesnmemb
elements of data, eachsize
bytes long, to the stream pointed to bystream
, obtaining them from the location given byptr
.
您告诉 fread()
和 fwrite()
您的记录或项目的长度是 1 个字节长,并且您要求 5000 条记录。
Return Value
On success,
fread()
andfwrite()
return the number of items read or written. This number equals the number of bytes transferred only when size is1
. 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/