Google Interview Question Software Engineer / Developers
0of 0 votesGiven API:
int Read4096(char* buf);
It reads data from a file and records the position so that the next time when it is called it read the next 4k chars (or the rest of the file, whichever is smaller) from the file.
The return is the number of chars read.
Todo: Use above API to Implement API
"int Read(char* buf, int n)" which reads any number of chars from the file.
Country: United States
Interview Type: In-Person
since this read API 'int Read(char *buf)' doesn't take any arg to say the number of bytes to be read, should we assume to read the whole file?
Any reasonable API would tell you how many bites to read, after all the buffer may not be large enough to hold the entire file, so I think there shouldn't be any problem if you take another integer input as no. of bytes to be read.
#define FOURKB 4096
int Read(char* buf, int count)
{
int bytesToRead=count,bytesRead=0,min;
while(bytesToRead>0)
{
if(bytesToRead<FOURKB)
{
//last read, take care of the potential buffer overflow
char temp[FOURKB];
bytesRead=Read4096(temp);
min = bytesRead<bytesToRead?bytesRead:bytesToRead;
memcpy(buf,temp, min);
bytesToRead -=min;
break;
}
bytesRead = Read4096(buf);
bytesToRead -= bytesRead;
if(bytesRead<FOURKB)
//file ended
break;
}
return count-bytesToRead;
}
I haven't modified the original Read4096 API and haven't assumed anything about what happens if you try calling Read4096 on a file after Read4096 has read it completely.
sorry to miss that. There is another argument to say how may chars need to be read in Read().
int Read(char* buf){
int cnt=0,total=0;
char tmpbuf[4096]={0};
do{
cnt = Read4096(tmpbuf);
total = +cnt;
strcat(buf,tmpbuf);
}while(cnt<=4096);
return total;
}
This sln seems to read all the data out of the file, and return the total number of bytes. However, I am not sure whether the question is asking for reading a specified number of bytes ( reads any number of chars from the file).
Anyway, the suggested API doesn't contain any argument taking in the desired number of bytes to read.
int Read4096(char* buf);
char* g_buf[4096];
int g_idxCur = 0;
int g_idxEnd = -1;
int Read(char* buf, int n)
{
//argument validation
if (n==0) return 0;
int idxbuf = 0;
int cReadFromFile = INT_MAX;
//if more to read, call Read4096
while(idxbuf<n && cReadFromFile>0)
{
int cCh = g_idxEnd - g_idxCur + 1;
if(cCh > 0)
{
int cRead = (n-idxbuf < cCh ) ? n-idxbuf : cCh;
for (int i=0; i<cRead; ++i)
{
buf[idxbuf++]=g_buf[g_idxCur++];
}
if (cReadFromFile<4096)
{
break;
}
}
else
{
cReadFromFile = Read4096(g_buf);
g_idxCur = 0;
g_idxEnd = cReadFromFile-1;
}
}
return idxbuf;
}
Another solution:
int ReadChar4096(char *buf);
char g_buf[4096]; //global buffer to save the data read by ReadChar4096.
int ReadChar(char *buf, int n)
{
int n1,n2;
bool isEnd=false;
n1=(int)n/4096;
n2=n%4096;
int pos = 0;
for(int i=0;i<n1;++i)
{
int cRead = ReadChar4096(g_buf);
copy(buf, g_buf, pos, cRead);
pos+=cRead;
if(cRead<4096)
{
isEnd = true;
break;
}
}
if(!isEnd && n2)
{
int cRead = ReadChar4096(g_buf);
int cNeeded = cRead < n2 ? cRead : n2;
copy(buf, g_buf, pos, cNeeded);
pos+=cNeeded;
}
return pos;
}
Given:
int Read4096(char *buf);
Solution:
We Assume that Main Program Has char buf[n] to store Read data
int Read(char *buf, int n){
static char temp[4096], *ptr= temp-1;
int r, l=0;
if(ptr>= temp){
if(n> 4096- ptr){
strcat(buf, ptr);
n-= 4096- ptr;
l+= 4096- ptr;
ptr= temp;
}else{
strncat(buf, ptr, n);
ptr+= n;
l= n;
n= 0;
return l;
}
}
while(n>= 4096){
r= Read4096(temp);
strncat(buf, temp, r);
l+= r;
n= n-r;
}
if(n){
r= Read4096(temp);
strncat(buf, temp, n);
l+= n;
ptr= temp+ n;
}
return l;
}
void copy(char* buf, char*des, int n)
{
if( n <= 0 ) return n;
while( *buf && n > 0 )
{
*des++ = *buf++;
n--;
}
}
int Read(char* buf, int n)
{
int count = 0;
int remain = n;
char* buf = new char[n+1];
buf[n] = '\0';
while( remain <= count )
{
char* buf = new char[4096];
int res = Read4096(tmp);
if( res < 4096 )
{
if( res > remain )
{
copy(tmp, buf+count, remain);
count += remain;
break;
}
else
{
copy(tmp, buf+count, res);
count += res;
buf[count+1] = '\0';
break;
}
}
else
{
if( res > remain )
{
copy(tmp, buf+count, remain);
count += remain;
break;
}
else
{
copy(tmp, buf+count, 4096);
count += 4096;
remain -= 4096;
}
}
}
return count;
}
int Read(char* buf)
{
int cnt=0,total=0;
char tmpbuf[4096]={0};
do
{
cnt = Read4096(tmpbuf);
total = +cnt;
strcat(buf,tmpbuf);
}while(cnt == 4096); // break when we read less than 4096 chars (including 0)
return total;
}
To avoid extra copy cost here, while n >= 4096, Read4096 must be called on the input buffer and not on a temp buffer. each time Read4096 is called, n should be decreased as the read amount (read amont can be less than 4096 if eof reached).
if n gets less than 4906 after some k reads. then an internal buffer should be used otherwise, using Read4096 on input buffer will cause overflow..
int read(char* buf, int n){
int num_it = n / 4096;
int remain = n % 4096;
int total = 0;
while(num_it--){
int num_read = read4096(buf);
if(num_read == 0) break;
buf += num_read;
total += num_read;
}
if(total != n-remain) return total;
char readbuf[4096];
int num_read = read4096(readbuf);
int num_copy = min(num_read, remain);
copy(readbuf, readbuf + num_copy, buf);
total += num_copy;
return total;
}

we will need to keep an internal buffer as well as a pointer indicating up to which position the internal buffer is used:
Note that the following code most likely won't compile, especially considering I am not entirely sure if memcpy works that way, but the logic should be correct, and you should be able to see what I am trying to achieve with the memcpy calls
- airfang613 on August 21, 2012 Edit | Flag Replyclass GenericReader { Reader4k reader4k_; int buf_ptr_; char* internal_buf_; public: int Read(int n, char* buf) { int count = 0; int remain = n; int buf_ptr = 0; while (remain > 0) { if (buf_ptr_ == -1) { int bytes_read = reader4k.Read(internal_buf_); if (bytes_read == 0) // we have exhausted the buffer break; buf_ptr_ = 0; if (bytes_read > remain) { memcpy(buf + buf_ptr, internal_buf_, remain); count += remain; buf_ptr_ += remain; return count; } else { remain -= bytes_read; count += bytes_read; buf_ptr_ = -1; memcpy(buf + buf_ptr, internal_buf_, bytes_read); buf_ptr += bytes_read; } } else { // we still have stuff in internal_buf_, read those first if (4096 - buf_ptr_ > remain) { memcpy(buf + buf_ptr, internal_buf_ + buf_ptr_, remain); buf_ptr_ += remain; count += remain; return count; } else { remain -= (4096 - buf_ptr_); count += (4096 - buf_ptr_); memcpy(but + buf_ptr, internal_buf_ + buf_ptr_, 4096 - buf_ptr_); buf_ptr += (4096 - buf_ptr_); buf_ptr_ = -1; } } } return count; } };