Google Interview Question Software Engineer / Developers

  • google-interview-questions
    0
    of 0 votes
    19
    Answers

    Given 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.

    - jiangok2006 on July 26, 2012 in United States Report Duplicate | Flag
    Google Software Engineer / Developer Coding

Country: United States
Interview Type: In-Person


Comment hidden because of low score. Click to expand.
2
of 2 vote

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

class 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;
  }  
};

- airfang613 on August 21, 2012 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

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?

- Anonymous on July 26, 2012 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

yep, there is something missing from this question.

- dtx on July 26, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

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.

- Anonymous on July 26, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

sorry to miss that. There is another argument to say how may chars need to be read in Read().

- jiangok2006 on July 27, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

This solution will only fill in the first 4096 bytes with the last 4096 bytes of the file (or a partial mix of the last bytes with the previous 4096) since you keep passing in buf to Read4096. Any file larger then 4096 will not read correctly.

- Robert on September 19, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 2 vote

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;
}

- fenghhk on July 26, 2012 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

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.

- Daru on July 29, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

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;
}

- jiangok2006 on July 27, 2012 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

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;
}

- jiangok2006 on May 28, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

int Read(char* buf){
    int cnt = 0;
    char* start = buf;
    while(cnt = Read4096(buf))
    {
        buf += cnt; // forward the buffer by the amount read
        if (cnt < 4096) break;
    }
  return buf-start;
}

The other solution here does not handle binary data containing nulls.

- Matthew Parlane on July 31, 2012 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

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;
}

- Abhijeet Rokade on August 07, 2012 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

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;
}

- haoyu.hust on August 18, 2012 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 2 vote

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;
}

- Dilbert Einstein on September 02, 2012 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

This will make it slow, better keep the pointer to first and keep doing memcpy from last position.

- aayush.raina21 on September 04, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

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..

- noname on November 25, 2012 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

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;
}

- tmc on February 03, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
-1
of 1 vote

can we use any other file APIs like fgets(), fread()? or should we use only this API?

- Anonymous on July 26, 2012 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

no other api is allowed.

- jiangok2006 on July 27, 2012 | Flag


Add a Comment
Name:

Writing Code? Surround your code with {{{ and }}} to preserve whitespace.

Books

is a comprehensive book walking you through every aspect of getting a job at a top tech company, while focuses on software engineering interviews.

Learn More

Videos

CareerCup's interview videos give you a real-life look at technical interviews. In these unscripted videos, watch how other candidates handle tough questions and how the interviewer thinks about their performance.

Learn More

Resume Review

Most engineers make critical mistakes on their resumes -- we can fix your resume with our custom resume review service. And, we use fellow engineers as our resume reviewers, so you can be sure that we "get" what you're saying.

Learn More

Mock Interviews

Our Mock Interviews will be conducted "in character" just like a real interview, and can focus on whatever topics you want. All our interviewers have worked for Microsoft, Google or Amazon, you know you'll get a true-to-life experience.

Learn More