我一直在为求职面试做一些练习问题,而且我遇到了一个我无法解决如何解决问题的功能。我们的想法是创建一个函数,该函数采用两个文件的名称,允许的缓冲区大小从file1读取,允许的缓冲区大小用于写入file2。如果缓冲区大小相同,我知道如何解决这个问题,但是当我确定如何在大小不同时在缓冲区之间移动数据时遇到问题。部分约束是我们必须在将写缓冲区写入文件之前始终填充写缓冲区。如果file1不是file2的倍数,我们用零填充最后一次缓冲区传输。
// input: name of two files made for copy, and their limited buffer sizes
// output: number of bytes copied
int fileCopy(char* file1,char* file2, int bufferSize1, int bufferSize2){
int bytesTransfered=0;
int bytesMoved=o;
char* buffer1, *buffer2;
FILE *fp1, *fp2;
fp1 = fopen(file1, "r");
if (fp1 == NULL) {
printf ("Not able to open this file");
return -1;
}
fp2 = fopen(file2, "w");
if (fp2 == NULL) {
printf ("Not able to open this file");
fclose(fp1);
return -1;
}
buffer1 = (char*) malloc (sizeof(char)*bufferSize1);
if (buffer1 == NULL) {
printf ("Memory error");
return -1;
}
buffer2 = (char*) malloc (sizeof(char)*bufferSize2);
if (buffer2 == NULL) {
printf ("Memory error");
return -1;
}
bytesMoved=fread(buffer1, sizeof(buffer1),1,fp1);
//TODO: Fill buffer2 with maximum amount, either when buffer1 <= buffer2 or buffer1 > buffer2
//How do I iterate trough file1 and ensuring to always fill buffer 2 before writing?
bytesTransfered+=fwrite(buffer2, sizeof(buffer2),1,fp2);
fclose(fp1);
fclose(fp2);
return bytesTransfered;
}
如何在fwrites之前为缓冲区传输编写while循环?
答案 0 :(得分:1)
我在确定如何在大小不同的情况下在缓冲区之间移动数据时遇到问题
制定计划。对于“求职面试的一些实践问题”,一个好的计划和能力来证明这一点很重要。编码虽然很重要,但却是次要的。
given valid: 2 FILE *, 2 buffers and their sizes
while write active && read active
while write buffer not full && reading active
if read buffer empty
read
update read active
append min(read buffer length, write buffer available space) of read to write buffer
if write buffer not empty
pad write buffer
write
update write active
return file status
现在编码吧。更强大的解决方案是使用struct
对FILE*, buffer, size, offset, length, active
变量进行分组。
// Return true on problem
static bool rw(FILE *in_s, void *in_buf, size_t in_sz, FILE *out_s,
void *out_buf, size_t out_sz) {
size_t in_offset = 0;
size_t in_length = 0;
bool in_active = true;
size_t out_length = 0;
bool out_active = true;
while (in_active && out_active) {
// While room for more data
while (out_length < out_sz && in_active) {
if (in_length == 0) {
in_offset = 0;
in_length = fread(in_buf, in_sz, 1, in_s);
in_active = in_length > 0;
}
// Append a portion of `in` to `out`
size_t chunk = min(in_length, out_sz - out_length);
memcpy((char*) out_buf + out_length, (char*) in_buf + in_offset, chunk);
out_length += chunk;
in_length -= chunk;
in_offset += chunk;
}
if (out_length > 0) {
// Padding only occurs, maybe, on last write
memset((char*) out_buf + out_length, 0, out_sz - out_length);
out_active = fwrite(out_buf, out_sz, 1, out_s) == out_sz;
out_length = 0;
}
}
return ferror(in_s) || ferror(out_s);
}
其他说明;
不需要投射malloc()
个结果。 @Gerhardh
// buffer1 = (char*) malloc (sizeof(char)*bufferSize1);
buffer1 = malloc (sizeof *buffer1 * bufferSize1);
使用stderr
获取错误消息。 @Jonathan Leffler
以二进制文件打开文件。
size_t
对于数组/缓冲区大小比int
更强大。
将sizeof buffer1
与sizeof (buffer1)
视为sizeof object
答案 1 :(得分:0)
while(bytesMoved > 0) {
for(i=0; i<bytesMoved && i<bufferSize2; i++)
buffer2[i]=buffer1[i];
bytesTransfered+=fwrite(buffer2, i,1,fp2);
bytesMoved-=i;
}
如果bufferSize1小于filesize,则需要外部循环。
答案 2 :(得分:0)
正如您的问题的评论所示,此解决方案不是将数据从1个文件传输到另一个文件的最佳方式。但是,您的案例有一些限制,此解决方案可以解决这个问题。
(1)由于您使用的是缓冲区,因此您不需要一次读取和写入1
个字符,而是可以尽可能少地调用这些函数
size_t fread(void * ptr,size_t size,size_t nmemb,FILE * stream);
:在fread
的手册页中,nmemb
可以= bufferSize1
(2)您需要检查fread()
的回报(即bytesMoved
)并将其与bufferSize
1和2进行比较。如果(a) bytesMoved
(即从fread()
返回)等于bufferSize1
或(b) {{1} }小于bufferSize2
或从bufferSize1
返回,那么您就知道仍有数据需要读取(或写入)。因此,您应该开始下一次数据传输,当完成后返回上一步时,您就停止了。
注意:如果数据大于bufferSizes,则fread()
和fread()
中指向文件流的指针将从停止的位置开始。
<强>伪代码:强>
fwrite()