Read N Characters Given Read4
Problem
You are given a file and an API read4(buf) that reads up to 4 characters from the file into buf and returns the number actually read. Implement read(buf, n) that reads exactly n characters (or until end of file) using read4 only.
file = "abcdefg", n = 55 (buf = "abcde")def read(buf, n):
total = 0
tmp = [''] * 4
while total < n:
ret = read4(tmp)
copy = min(ret, n - total)
for i in range(copy):
buf[total + i] = tmp[i]
total += copy
if ret < 4:
break
return total
function read(buf, n) {
let total = 0;
const tmp = new Array(4);
while (total < n) {
const ret = read4(tmp);
const copy = Math.min(ret, n - total);
for (let i = 0; i < copy; i++) buf[total + i] = tmp[i];
total += copy;
if (ret < 4) break;
}
return total;
}
public class Solution extends Reader4 {
public int read(char[] buf, int n) {
int total = 0;
char[] tmp = new char[4];
while (total < n) {
int ret = read4(tmp);
int copy = Math.min(ret, n - total);
for (int i = 0; i < copy; i++) buf[total + i] = tmp[i];
total += copy;
if (ret < 4) break;
}
return total;
}
}
int read(char* buf, int n) {
int total = 0;
char tmp[4];
while (total < n) {
int ret = read4(tmp);
int copy = min(ret, n - total);
for (int i = 0; i < copy; i++) buf[total + i] = tmp[i];
total += copy;
if (ret < 4) break;
}
return total;
}
Explanation
You can only pull characters through read4, which fills a small 4-char scratch buffer and returns how many it actually got. The plan is to call it repeatedly and copy the useful part into buf until we have n characters or the file runs out.
We track total, the number of characters delivered so far. Each loop calls ret = read4(tmp). Then we copy only what we still need: copy = min(ret, n - total), so we never overshoot past n.
After copying those copy characters into buf at offset total, we add them to total. The loop stops in two ways: when ret < 4 (the file is exhausted, so we break) or when total reaches n.
Example: file "abcdefg", n = 5. The first read4 returns 4 ("abcd"), all copied (total = 4). The second returns 3 ("efg"), but we only need 1 more, so we copy just "e" and stop with total = 5 and buf = "abcde".