-
Notifications
You must be signed in to change notification settings - Fork 4.9k
/
readNCharactersGivenRead4.II.cpp
181 lines (153 loc) · 4.77 KB
/
readNCharactersGivenRead4.II.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
// Source : https://oj.leetcode.com/problems/read-n-characters-given-read4-ii-call-multiple-times/
// Author : Hao Chen
// Date : 2014-12-01
/*
* The API: int read4(char *buf) reads 4 characters at a time from a file.
*
* The return value is the actual number of characters read.
* For example, it returns 3 if there is only 3 characters left in the file.
*
* By using the read4 API, implement the function int read(char *buf, int n) that reads n characters from the file.
*
* Note:
* The read function may be called multiple times.
*/
/*
* The key to solve this problem is:
*
* You have to buffer the extra data return from `read4()` API, which is for next call for `read()` .
*/
#include <stdio.h>
#include <string.h>
// Forward declaration of the read4 API.
static char input[64];
static char *p = input;
int read4(char *buf) {
int s=0;
for (; s<4 && *p!='\0'; s++){
buf[s] = *p;
p++;
}
return s;
}
class RingBuffer {
public:
RingBuffer(int cap=4): _capacity(cap) {
_size = 0;
_pbuf = new char[_capacity];
_p = _pbuf;
_pend = _pbuf + _capacity - 1;
}
~RingBuffer(){
delete _pbuf;
}
int read(char* buf, int n){
//empty, nothing can read
if (_size==0) return 0;
//read `n` or all
int s;
for (s=0; s<n && s<_size; s++){
buf[s] = *_p;
_p = (_p < _pend) ? _p + 1 : _pbuf;
}
_size -= s;
return s;
}
int write(char* buf, int n) {
//full, cannot write
if (_size >= _capacity) return 0;
//write `n` or all
int s;
char *p = _p + _size;
for (s=0; s < _capacity - _size && s < n; s++){
*p = buf[s];
p = (p < _pend) ? p + 1 : _pbuf;
}
_size += s;
return s;
}
private:
const int _capacity;
int _size;
char* _pbuf;
char* _p;
char* _pend;
};
class Solution {
public:
/**
* @param buf Destination buffer
* @param n Maximum number of characters to read
* @return The number of characters read
*/
int read(char *buf, int n) {
int buf_size = 0;
int api_size = 0;
//read the data from the RingBuffer at first
buf_size = _ring_buffer.read(buf, n);
if (buf_size == n) {
return n;
}
n = n - buf_size;
//read the data from the API at second
api_size = read1(buf + buf_size, n);
return buf_size + api_size;
}
// The read1 implementation is from the `Read N Characters Given Read4` problem
// Add the feature - write the extra char(s) into RingBuffer
int read1(char *buf, int n) {
char _buf[4]; // the buffer for read4()
int _n = 0; // the return for read4()
int len = 0; // total buffer read from read4()
int size = 0; // how many bytes need be copied from `_buf` to `buf`
while((_n = read4(_buf)) > 0){
//check the space of `buf` whether full or not
size = len + _n > n ? n-len : _n;
//write the extra char(s) into RingBuffer
if (len + _n > n ){
_ring_buffer.write(_buf + size, _n - size);
}
strncpy(buf+len, _buf, size);
len += size;
//buffer is full
if (len>=n){
break;
}
}
return len;
}
private:
RingBuffer _ring_buffer;
};
int main()
{
Solution s;
const int buf_len = 10;
char buf[buf_len]={0};
#define SET_INPUT(s) strcpy(input, s); p=input; printf("input data = \"%s\"\n", p);
#define CLEAR_BUFFER() memset(buf, 0, sizeof(buf)/sizeof(buf[0]) )
#define READ(s, buf, n) CLEAR_BUFFER(); printf("read(%d) => ",n); s.read(buf, n); printf("%s\n", buf);
printf("-----------------------------\n");
SET_INPUT("1234abcd1234abcdxyz");
for(int i=0; i<5; i++){
READ(s, buf, 4);
}
printf("-----------------------------\n");
SET_INPUT("ab");
READ(s, buf, 1);
READ(s, buf, 2);
printf("-----------------------------\n");
SET_INPUT("abcde");
for(int i=0; i<5; i++){
READ(s, buf, 1);
}
printf("-----------------------------\n");
SET_INPUT("1234xyzabcd00");
READ(s, buf, 4);
for(int i=0; i<3; i++){
READ(s, buf, 1);
}
READ(s, buf, 4);
printf("-----------------------------\n");
return 0;
}